In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)
GIL官方解釋:
In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)
簡單說GIL就是一把全域性排他鎖 ,全域性鎖的存在會對多執行緒的效率有不小影響。甚至就幾乎等於Python是個單執行緒的程式。
另一個角度全域性鎖只要釋放的勤快效率也不會差啊。只要在進行耗時的IO操作的時候,能釋放GIL,這樣也還是可以提升執行效率的嘛。或者說再差也不會比單執行緒的效率差吧。理論上是這樣,而實際上呢?Python比你想的更糟。
拿例項驗證一下:
一個迴圈1億次的計數器函式。一個透過單執行緒執行兩次,一個多執行緒執行。最後比較執行總時間,測試機器是雙核:
下面我們執行一下,看下最後結果:
可以看到python在多執行緒的情況下居然比單執行緒整整慢了45%。按照之前的分析,即使是有GIL全域性鎖的存在,序列化的多執行緒也應該和單執行緒有一樣的效率才對。實際更糟糕。
可選最佳化方案:
多程序用multiprocessing替代Thread
multiprocessing庫可以彌補thread庫因為GIL而低效的缺陷。它完整的複製了一套thread所提供的介面方便重構遷移,方便快速轉換。唯一的不同就是它使用了多程序而不是多執行緒。犧牲了一些資源,每個程序有自己的獨立的GIL,因此也不會出現程序之間的GIL爭搶。
如果對平行計算效能較高的程式可以考慮把核心部分也成C模組,或者索性用其他語言實現