1. 程式人生 > 實用技巧 >嫌Python太慢但又不想學C/C++?來了解下JIT技術

嫌Python太慢但又不想學C/C++?來了解下JIT技術

什麼是 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。


歡迎關注: