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

轉自:機器之心,編輯:杜偉、陳萍

大家好,我是東哥。

Python 之父 Guido van Rossum 曾經說過:如果想讓代碼運行得更快,應該使用 PyPy。

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

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

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

import time
from termcolor import colored

start = time.time()
number = 0
for i in range(100000000):
    number += i
    
print(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 編譯是解釋和提前編譯的結合,可以利用提前編譯來提高性能,並提高解釋型語言的靈活性和跨平臺可用性。

這也就是爲什麼 PyPy 可以讓 Python 有這麼快的執行速度了。目前,大部分的使用者還保持使用着默認的 Python 編譯器,如果對速度有要求不妨可以試試 PyPy 編譯器

原文鏈接:https://towardsdatascience.com/run-your-python-code-as-fast-as-c-4ae49935a826

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/g-77Lodf0-fYAfETOiVzCg