當前位置: 妍妍網 > 碼農

PyPy為什麽能讓Python比C還快?一文了解內在機制

2024-04-22碼農

源:機器之心

「如果想讓程式碼執行得更快,您應該使用 PyPy。」—— Python 之父 Guido van Rossum

對於研究人員來說,迅速把想法程式碼化並檢視其是否行得通至關重要。Python 是能夠實作這一目標的出色語言,它能夠讓人們專註於想法本身,而不必過度為程式碼格式等無聊的事情困擾。

但是,Python 有一個致命的缺點:速度比 C、C ++ 等語言慢很多。那麽,構建一個 Python 原型測試想法之後,如何將其轉變為快速且高效能的工具?通常來說,人們還要再進行一步工作:將 Python 程式碼手動轉換為 C 語言的程式碼。但如果 Python 原型本身就可以執行得很快,那麽轉換程式碼的時間就可以做一些更有意義的事情。

而 PyPy,恰好可以解決這一問題。它能夠讓 Python 程式碼執行得比 C 還快。

import timefrom termcolor import coloredstart = time.time()number = 0for i in range(100000000): number += iprint(colored("FINISHED", "green"))print(f"Ellapsed time: {time.time() - start} s")

為了證明 PyPy 的速度,使用預設的 Python 直譯器和 PyPy 執行上述程式碼,執行一個從整數 0 加到 100,000,000 的迴圈, 然後打印出執行時間。執行結果如下:

執行時間 Python vs PyPy

這不是學術意義上的評估,但該結果是令人驚嘆的。與大約需要 10 秒鐘的預設 Python 直譯器相比,PyPy 僅用 0.22 秒就完成了執行。而且無需進行任何更改就可以直接將 Python 程式碼放到 PyPy 上。而同一台電腦上,等效的 C 語言實作需要 0.32 秒,PyPy 甚至擊敗了最快的 C 語言。

為什麽 PyPy 這麽快?

盡管程式碼完全相同,但程式碼的執行方式卻大不相同。PyPy 提升速度的秘訣是「即時編譯( just-in-time compilation)」,即 JIT 編譯。

提前編譯

C、C ++、Swift、Haskell、Rust 等程式語言通常是提前編譯(AOT 編譯)的。這意味著用這些語言編寫程式碼之後,編譯器會將原始碼轉換成特定電腦架構可讀的機器碼。也就是說在執行程式時,執行的並不是原始原始碼,而是機器碼。

提前編譯把原始碼轉化為機器碼

解釋語言

與 C 語言等上述語言不同,Python、JavaScript、PHP 等語言采用另一種方法——解釋語言。與將原始碼轉換為機器碼相比,解釋的過程中原始碼是保持不變的。每次運行程式時,直譯器都會逐行檢視程式碼並執行。例如,每個 Web 瀏覽器都內建了 JavaScript 直譯器。

直譯器逐行運行程式

即時編譯

PyPy 是利用即時編譯來執行 Python 程式碼的。即 PyPy 不同於直譯器,它並不會逐行執行程式碼,而是在執行程式前先將部份程式碼編譯成機器碼。

JIT 編譯綜合了提前編譯和解釋

如上圖所示,而 PyPy 使用的 JIT 編譯是解釋和提前編譯的結合,可以利用提前編譯來提高效能,並提高解釋型語言的靈活性和跨平台可用性。

1