SciPy 中的執行緒安全#

SciPy 支援在多執行緒環境中使用,透過標準函式庫中的 threading 模組。許多 SciPy 操作會釋放 GIL,NumPy 也是如此 (且許多 SciPy 功能是以呼叫 NumPy 函數實作) - 因此與 Python 中的許多情況不同,透過利用 Python 中的多執行緒平行處理,有可能提高平行效能。

當每個工作執行緒擁有自己的陣列或一組陣列物件,且執行緒之間沒有直接共享資料時,最容易獲得效能提升。大部分時間花費在底層程式碼的執行緒通常會平行執行。

可以在執行緒之間共享 NumPy 陣列,但必須極其小心,以避免在修改多個執行緒之間共享的陣列時產生執行緒安全問題 - 有關更多詳細資訊,請參閱 NumPy 關於執行緒安全的文檔。SciPy 函數不會修改使用者傳入的陣列,除非函數明確說明會這樣做 (這種情況很少見)。因此,在多執行緒環境中對同一個 NumPy 陣列呼叫 SciPy 函數是安全的。

雖然 SciPy 的大部分是由函數組成,但對於類別資料結構需要更加小心。

具有狀態的類別,例如 scipy.integratescipy.interpolate 中的一些積分和內插物件,通常對於平行呼叫具有穩健性。它們要么接受平行呼叫,要么引發資訊豐富的錯誤。例如,scipy.integrate.ode 對於不支援平行執行的積分方法,可能會引發 IntegratorConcurrencyError

SciPy 提供了一些資料結構,即 scipy.sparse 中的稀疏陣列和矩陣,以及 scipy.spatial 中的 k-D 樹。這些資料結構目前不是執行緒安全的。請特別避免在多個執行緒之間共享資料時,對資料結構進行變更的操作,例如在稀疏陣列上使用項目或切片賦值。這可能會導致資料損壞、崩潰或其他不良行為。

請注意,釋放 GIL 的操作從使用 threading 模組中不會看到效能提升,相反地,使用 multiprocessing 可能會更好。

自由執行緒 Python#

在版本 1.15.0 中新增。

從 SciPy 1.15.0 和 CPython 3.13 開始,SciPy 實驗性地支援在所有平台上禁用 GIL 的 Python 運行時環境。有關安裝和使用自由執行緒 Python 的更多資訊,請參閱 https://py-free-threading.github.io

由於自由執行緒 Python 沒有全域直譯器鎖 (GIL) 來序列化對 Python 物件的存取,因此執行緒有更多機會修改共享狀態並產生執行緒安全問題。所有 SciPy 功能都經過平行執行緒使用的測試,但我們預期會有一些尚未發現的問題 - 如果您遇到問題,請查看 帶有 free-threading 標籤的 GitHub 問題,如果對於行為異常的函數還不存在相關問題,請開啟新的問題。