Python 新提案:“廢除”全域性直譯器鎖 GIL | CPython 直譯器或許會變得更快

MissD發表於2022-05-24

近日,開發者 Alex Waygood 在 Python 基金會部落格中提到了上週剛剛舉辦的Python 語言峰會上關於 Python 語言的重大議題 —— “廢除” Python 語言的全域性直譯器鎖(GIL)。

“雙刃劍”:CPython —— 直譯器和編譯器

眾所周知,Python 動態語言的靈活性是把“雙刃劍”。這意味著可以有不同的執行時,例如 Pyston、Cinder、MicroPython、pypypy 等,它們可能支援整個語言、特定版本或子集。但如果你使用的是 Python,那麼你可能正在執行 CPython。

CPython 是用 C 語言編寫的標準 Python 直譯器,它同時還充當著編譯器,因為它的任務是在實際的解釋階段之前以位元組碼的形式編譯 Python 程式碼。

CPython 有一種稱為全域性直譯器鎖 GIL(Global Interpreter Lock)的東西,可以影響執行緒程式碼,即一次只能在直譯器中執行一個執行緒。因此,GIL 一直被看做是該語言發展的固有限制。

之前,也一直有提案想要解決這個問題,例如將效能關鍵部分移到 C 或使用多個直譯器。但要滿足以上期望,直譯器使用者的受眾可能會擴大。目前有幾種替代方案,例如通過專用於 JVM(Java 虛擬機器)和 CLR(公共語言執行時)的方案,但以上多數現有的解決方案都有相當大的缺點。

所以基於以上背景,“不帶全域性直譯器鎖的 Python” 的支援聲逐漸受到關注。

多次嘗試被廢除:GIL 究竟該如何擺脫掉

直到此次的 Python 語言峰會上,Meta 高階工程總監 Sam Gross 在有關 “nogil”專案的主題中,提出了“廢除 GIL ”的相關議題。

據悉,該提議是基於之前在 Python 中廢除 GIL 的想法。Gross 最初在使用第三方程式碼的 Python 專案中遇到了問題,因此開始思考“如果沒有 GIL”的話如何使得執行緒安全的進行。

前面提到過,全域性直譯器鎖 GIL 一次只能在直譯器中執行一個執行緒,所以當你可以保證一次只執行一個執行緒時,程式狀態或許會更容易推理。但如果沒有 GIL,引用計數、記憶體分配、方法解析順序快取和垃圾收集執行緒則會變得不安全。

那麼,該如何擺脫 GIL 呢?

據報導,早前 Sam Gross 就專門對這一演變進行了討論。由於 CPython 中的設計是“執行緒安全”,但它依賴於 GIL。想要擺脫 GIL,首先,就要對參考計數進行重大更改。

為了知道垃圾收集器是否可以釋放記憶體中的物件,它會統計對該物件的所有引用。目前,引用計數是非原子性的,將所有引用計數操作更改為原子性操作會對效能造成巨大影響。

Sam Gross 在該提案中使用了一種稱為“有偏引用計數”(biased reference counting )的技術,用於獲取本地和共享引用。本地引用可以利用非原子性操作,擁有執行緒將本地引用和共享引用結合起來以跟蹤所有權。這種方法非常適用於單執行緒物件,或者只被幾個執行緒少量使用的物件。

在程式的生命週期中存在幾個物件,如插入字串、True、False 和 None,它們可以被標記為“不朽”(immortal),從而將它們的引用計數開銷減少到零。通過利用引用計數字段中的最低有效位,物件被標記為“不朽”。經常訪問但不能保證“不朽”的物件延遲了引用計數,這意味著唯一需要的引用計數是當引用儲存在堆上時,此更改的一個副作用是無法立即回收物件,因為需要掃描堆疊以查詢任何剩餘的引用。

Sam Gross 用 mimalloc 替換了標準的 pymalloc 記憶體分配器,mimalloc 是 malloc 的一個替代品,提供了執行緒安全和效能。這種交換的好處是,這個分配器允許執行時在沒有顯式列表的情況下查詢 GC 跟蹤的物件。這是一個顯著的效能提升,但這意味著不能只交換另一個與 malloc 相容的分配器,而期望垃圾收集和收集具有相同的執行緒安全性。

Python 尚未決定是否刪除 GIL

關於為何要刪除 GIL 的問題,Python 基金會部落格中解釋稱,“為了讓 Python 在沒有 GIL 的情況下有效地工作,必須向大多數程式碼中新增新鎖,以確保其保持執行緒安全,但向現有程式碼中新增新鎖可能非常困難,因為在某些領域可能會出現大幅放緩。”

此次,Sam Gross “刪除 GIL”的新提議似乎已經受到了 Python 核心開發團隊其他成員的“熱情”歡迎。現在,要解決的主要問題是如何在 CPython 上實施如此巨大的變革。

據悉,CPython 的下一個版本(或為 CPython 3.11)預計將於 2022 年 10 月釋出,不知道屆時會不會有大更新,但報導稱開發人員們尤其希望通過此更新獲得更高的效能和對在 web 瀏覽器上下文中執行的支援的整合。

過去的一段時間裡,由於 GIL 阻礙了語言的進發,開發者曾多次嘗試在標準實現 CPython 中廢除這種技術。此次,“刪除 GIL”的新提議終於來了,儘管 Python 官方尚未就實施作出最終決定,但一切依舊值得期待。

相關文章