python 為什么不能利用多核 CPU
GIL 其實是因為在 python中有一個 GIL( Global Interpreter Lock),中文為:全局解釋器鎖。
1、最開始時候設計GIL是為了數據安全
python為了數據安全設計了這個 GIL。
2、每個 CPU在同一時間只能執行一個線程:
(在單核 CPU下的多線程其實都只是並發,不是並行,並發和並行從宏觀上來講都是同時處理多路請求的概念。 但並發和並行又有區別,並行是指兩個或者多個事件在同一時刻發生;而並發是指兩個或多個事件在同一時間間隔內發生(
2)在 python多線程下,每個線程的執行方式如下:
1、獲取GIL
2、執行代碼直到sleep或者是 python虛擬機將其掛起。
3、釋放 GIL
為什么有時候多線程效率低於單線程?
1、如上我們可以知道,在 python中想要某個線程要執行必須先拿到
GIL這把鎖,且 python只有一個 GIL,拿到這個 GIL才能進入 CPU執行,
在遇到
I/O 操作時會釋放這把鎖。如果是純計算的程序,沒有 I/O 操作,解釋器會每隔
100次操作就釋放這把鎖,讓別的線程有機會 執行(這個次數可以通sys.setcheckinterval
來調整)。所以雖然 CPython 的線程庫直接封裝操作系統的原生線程,但 CPython
進程做為一個整體,同一時間只會有一個獲得了
GIL 的線程在跑,其它的線程都處於等待狀態等着
GIL 的釋放。
2、而每次釋放 GIL鎖,線程進行鎖競爭、切換線程,會消耗資源。並且由於
GIL鎖存在,python里一個進程永遠只能同時執行一個線程 (拿到 GIL的線程才能執行
),這就是為什么在多核
CPU上, python的多線程效率並不高。
python的多線程是否就完全沒有用了呢?
相同的代碼,為何有時候多線程會比單線程慢,有時又會比單線程快?
這主要跟運行的代碼有關:
1、 CPU密集型代碼
(各種循環處理、計數等等 ),在這種情況下,由於計算工作多, ticks計數很快就會達到
100閾值,然后觸發 GIL的釋放與再競爭 (多個線程來回切換當然是需要消耗資源的),所以 python下的多線程遇到 CPU密集型代碼時,單線程比多線程效率高。
IO密集型代碼 (文件處理、網絡爬蟲等 ),多線程能夠有效提升效率
(單線程下有 IO操作會進行 IO等待,造成不必要的時間浪費,而開啟多線程能在
線程
A等待時,自動切換到線程
B,可以不浪費
CPU的資源,從而能提升程序執行效率
)。
進行 IO密集型的時候可以進行分時切換 所有這個時候多線程快過單線程(
5)如果 python想充分利用多核 CPU,可以采用多進程, 每個進程有各自獨立的
GIL,互不干擾,這樣就可以真正意義上的並行執行,所以在
python中,多進程的執行效率優於多線程
(僅僅針對多核 CPU而言 )。
所以在多核 CPU下,想做並行提升效率,比較通用的方法是使用多進程,能夠有效提高執行效率。