什么是 JIT
Python 是門多才多藝的語言,既可以寫后端,也可以做數據分析,既可以智能化運維,也可以搞滲透,既可以寫爬蟲,又可以做機器學習深度學習。然而,Python 的缺點也很明顯,它的速度有點慢。
我們從官方網站下載到的版本,默認是采用了 CPython 解釋器,它也是用得最廣的解釋器。以 CPython 為例,看看它的執行過程。 Pyhton 代碼(.py 文件)在運行時,解釋器把源代碼變為一組虛擬機指令,也就是“字節碼”(.pyc 文件)。這些字節碼指令,是運行在 Python 虛擬機上的。因為這些是運行在虛擬機的,自然而然就比 C/C++ 等可以編譯為機器碼的語言慢很多。當然,影響執行效率的因素還有很多,這里就不敘述。

如果對高性能有非常迫切的需求,最好的解決方案是用 C/C++ 。不過,C/C++ 的學習難度比 Python 大很多,不是那么容易。除了換編程語言外,還有個更為容易的方法,那就是 JIT。
Just-In-Time(JIT),也就是即時編譯,它為解釋語言提供了一種優化。通俗地來說,就是代碼在運行時,實時編譯為機器碼。這樣,程序就可以跳過虛擬機直接在硬件上運行,執行速度大幅提高。
JIT 技術在 Java 中使用非常廣泛。不過在 Python 中,以往 JIT 並不完善,聽說過的人很少。
下面就介紹兩種 Python 的解決方案。
Numba
Numba 是一個 開源的 JIT編譯器,采用了 LLVM。它支持 Python 的原生函數和 Numpy,可以在 x86、x86_64、ppc64、armv7l、armv8l 等架構上運行,支持 Windows、MacOS 和 Linux。
Numba 的使用非常簡單,無需更換 Python 的解釋器。舉一個簡單的例子,只需要在函數上加上一個裝飾器,Numba 就會自動將這些代碼編譯成機器碼:
from numba import jit
import random
@jit(nopython=True)def monte_carlo_pi(nsamples):
acc = 0
for i in range(nsamples):
x = random.random()
y = random.random()
if (x ** 2 + y ** 2) < 1.0:
acc += 1
return 4.0 * acc / nsamples
PyPy
PyPy 是 Armin Rigo開發的動態編譯器,基於 Trace 的 JIT 技術,對源碼進行動態編譯(不是動態解釋),可以顯著提高執行速度。它歷史非常悠久,1.0 版本在 2007 年發布。目前支持大多數標准庫,在 Python 2.7 和 3.6 上都能使用。它可以在 x86、x86_64、ARMv6、ARMv7、AArch64PowerPC 64bit、System Z 等架構上運行,支持 Linux、MacOS、Windows、OpenBSD、FreeBSD 等系統。不過,在非 x86 架構上,它只能支持 Linux。
但它有個缺點,那就是不支持支持官方的 CPython,因而無法使用 Numpy、Scipy 等常用的重要第三方庫。另外,PyPy 在使用上與 CPython有些不同,具體可看 https://doc.pypy.org/en/latest/cpython_differences.html ,需要注意。
總結
Python 的 JIT 技術還不是很完善,但 Numba 已經可以滿足一大部分的計算需要。至於 PyPy,個人而言不太推薦。感興趣的不妨試試 Numba。
