繞過 GIL

Python SELF TW
等級 26 , 課堂 4
開放

11.1 Global Interpreter Lock

Global Interpreter Lock (GIL) 是在 CPython 解釋器中的一個機制,確保僅有一個執行緒 能在任何時候執行 Python 的 bytecode。GIL 阻止 執行緒的平行執行,這可能會對多執行緒程式的 效能產生負面影響,特別是在多核心處理器上。

為什麼 GIL 會存在

簡化記憶體管理GIL 簡化了 記憶體管理和垃圾回收,使 Python 更容易實現。

執行緒安全GIL 防止競態條件, 使得程式的執行對執行緒是安全的,無需使用鎖。

GIL 帶來的問題

受限的效能:多執行緒的程式進行計算密集的 任務時,無法充分利用多核心處理器的優勢,由於 GIL 的限制。

效能扭曲:使用大量執行緒執行任務的程式可能會 因為執行緒間的 context switching 而導致效能下降。

目前有四個主要方法來「繞過 GIL」:

11.2 使用多重處理 (multiprocessing)

模組 multiprocessing 允許創建 平行執行且不受 GIL 限制的進程,因為每個進程都有自己獨立的 Python 解釋器和 記憶體。

範例:


import multiprocessing

def worker(num):
    print(f'Worker: {num}')
            
def main():
    processes = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,))
        processes.append(p)
        p.start()
            
    for p in processes:
        p.join()
            
main()

11.3 非同步編程

使用 asyncio 的非同步編程允許在不 阻塞主線程的情況下平行執行任務。雖然這不能直接繞過 GIL, 但它允許在等待的時間內有效地執行其他任務。

範例:


import asyncio

async def main():
    await asyncio.sleep(1)
    print('Hello')
            
asyncio.run(main())

11.4 使用自主管理執行緒的函式庫

一些函式庫,例如 NumPy 和 SciPy,是用 C 編寫的並 使用自主管理執行緒的機制,使其能夠繞過 GIL 並有效 利用多核心處理器進行計算。

這其實是 Python 成功的原因之一,無論其本身有多慢。所有複雜的計算都用 C/C++ 語言重寫並 在處理器的所有核心甚至圖形卡的所有核心上執行。在現代圖形卡上有數千個核心。

這樣一來,無論語言本身快或慢都不再重要,因為所有資源密集的計算都是由外部函式庫進行的 或者完全放在遠端的數據中心。

11.5 在 Python 解釋器外執行計算

使用在 C/C++ 或其他語言上的擴展來執行計算,然後返回 結果。這允許在計算密集的運行期間避免被 GIL 阻塞。

使用 Cython 的範例:


# example.pyx

def compute(int n):
    cdef int i, result = 0
    for i in range(n):
        result += i
    return result

編譯和使用:


cythonize -i example.pyx

import example
print(example.compute(1000000))
1
Опрос
非同步性,  26 уровень,  4 лекция
недоступен
非同步性
非同步性
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION