作者sustainer123 (溫水佳樹的兄長大人)
看板Marginalman
標題py
時間Mon Sep 30 22:54:12 2024
全局鎖(global interpreter lock,GIL)
討論python的thread 我們就不得不提到GIL
這邊必須先聲明 GIL不是python的特性
這是cpython的產物
cpython是python的直譯器
假如您想避開GIL 您可以考慮其他直譯器 諸如jpython
但cpython是大多數情況的默認環境
所以大多數python使用者還是得面對GIL
GIL創立的目的是為了解決多線程的安全問題
這邊要先介紹cpython的記憶體管理機制
cpython有一種管理方式叫引用記數
cpython的object的struct裡面有個東西叫ob_refcnt
當你創建或引用變數時 ob_refcnt會+1
反之-1
當我們使用多線程時 線程會共用記憶體
這意味著線程會共用全局變數
當不同線程同時修改同個變數的引用記數
這就可能導致內存洩漏或內存提前被釋放
總之 cpython考慮線程安全 才會引進GIL
GIL的具體運作方式
線程執行前 必須取得GIL 取得後才能開始執行任務
如果線程進入IO任務或執行超過一定時間(通常15毫秒)或執行完成
釋放GIL
所以一個線程會經歷三個步驟:
1.爭取GIL
2.執行任務
3.釋放GIL
因為只有一個GIL 所以一段時間內只會有一個線程運行
假設是多核心的情況 其他進程本來能在其他核心運行
因為GIL的緣故 其他核心只能在一旁閒置
所以python的多線程才會被說實際是單線程
從執行的效率來說 有GIL的多線程甚至不如單線程
因為每當GIL釋放 系統需要執行線程切換
線程切換是保存線程的狀態 並載入下一個執行的線程
再者 GIL釋放時 線程會被喚醒競爭GIL
當GIL頻繁被釋出 上述行為重複執行
這耗費了大量的CPU資源
反觀單線程就不需要執行上述行為
所以在CPU密集型任務 單線程優於多線程
PY:
import time
def countdown(n):
while (n > 0):
n = n - 1
start = time.time()
countdown(100000000)
end = time.time()
print('總時間:', end - start)
result:
總時間: 2.3528549671173096
py:
import time
import threading
def countdown(n):
while (n > 0):
n = n - 1
t1 = threading.Thread(target=countdown, args=(100000000/2,))
t2 = threading.Thread(target=countdown, args=(100000000/2,))
start = time.time()
t1.start()
t2.start()
t1.join()
t2.join()
end = time.time()
print('總時間:', end - start)
result:
總時間: 2.818242073059082
上述結果可以證明在cpu密集型任務 單線程優於多線程
先這樣 後面應該會寫gil爭搶的可能問題 gil實際並沒有線程安全
怎解決gil問題ㄅ
累了 剩下明天再寫
參考資料:
https://wiki.python.org/moin/GlobalInterpreterLock
https://yhtechnote.com/global-interpreter-lock/
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.136.174.252 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/Marginalman/M.1727708059.A.EA7.html
→ handfox: 大師 09/30 22:54
→ sustainer123: 好久不見 手狐你是112大老 09/30 22:55
推 HGK: 證明了 intel核心臭打遊戲強 09/30 22:56
推 Lilchicken: 別打了 我腦子要炸了 09/30 22:57
推 Kroner: 甘露糖功效 09/30 22:57 推 cities516: 什麼! 09/30 22:57
→ sustainer123: 懶人包:python請用multiprocessing 09/30 22:58
推 enmeitiryous: 跟user level 和kernel level 的thread 的概念很像 09/30 23:01
推 Kroner: 魚油推薦 09/30 23:01 → enmeitiryous: 嗎 09/30 23:01
推 DJYOSHITAKA: 大師 09/30 23:09
→ sustainer123: 概念上我感覺類似 但具體上可能要再研究 09/30 23:12
推 enmeitiryous: 想起來了 多對一模式 多個使用者空間thread 其實 09/30 23:19
→ enmeitiryous: 對應同個kernel thread 09/30 23:19
→ sustainer123: 大師 我os還沒讀完 研究中 09/30 23:22
推 Chricey: 葉黃素 09/30 23:22