立竿見影地把你的 Python 程式碼提速7倍

進擊的Coder發表於2020-04-17

之前曾經測試計算斐波那契數列的幾種方法,其中基於遞迴的方法是速度最慢的,例如計算第 40 項的值,需要 36 秒。如下圖所示。

立竿見影地把你的 Python 程式碼提速7倍

要提高運算速度,根本辦法當然是改進演算法。不過演算法的提高是一個長期積累加上靈機一動的過程。我們今天要講的,是一個不費腦筋,立竿見影的方法——把 Python 程式碼編譯成 C 語言程式碼。透過 C 語言的執行效率來加速計算過程。

這個過程看起來很複雜,但實際上你並不需要編寫一行 C 語言程式碼。你需要做的只是使用一個叫做 Cython 的庫把 Python 程式碼編譯為 C 語言程式碼即可。

首先我們來安裝 Cython,就像安裝普通的第三方庫一樣:

python3 -m pip install cython

安裝完成以後,我們單獨寫計算斐波那契數列的函式:

def fib(n):
    if n in [12]:
        return 1
    return fib(n - 1) + fib(n - 2)

非常簡單的遞迴寫法。然後關鍵來了,我們要把這個檔案儲存為fast_fib.pyx。注意字尾是.pyx。如下圖所示:

立竿見影地把你的 Python 程式碼提速7倍

然後我們建立一個setup.py檔案,檔案內容如下:

from setuptools import setup
from Cython.Build import cythonize

setup(ext_modules=cythonize('fast_fib.pyx'))

如下圖所示:

立竿見影地把你的 Python 程式碼提速7倍

這個檔案的作用,就是呼叫 Cython 的cythonize函式把 Python 程式碼轉換為 C 程式碼。

接下來,開始編譯程式碼,執行如下命令:

python3 setup.py build_ext --inplace

我的 Python 是 Python3.7,所以執行完成以後,會生成一個fast_fib.cpython-37m-darwin.so,如果你的 Python 是3.8,這個檔名可能是fast_fib.cpython-38m-darwin.so。這個檔案你可以改名字,例如改成fast_fib.so

還有一個檔案叫做fast_fib.c。不過你不用開啟這個檔案,因為它有3200多行。並且你甚至可以直接把它刪掉。真正有用的只有這個fast_fib.cpython-38m-darwin.so檔案。

你需要做的,僅僅是直接呼叫你的函式。我們另外建立一個檔案test_fast_fib.py,內容如下:

import time
from fast_fib import fib

start = time.time()
result = fib(40)
end = time.time()
print(f'斐波拉契數列第40項為:{result},耗時:{end - start}秒')

執行效果如下圖所示:

立竿見影地把你的 Python 程式碼提速7倍

計算斐波那契數列第40項只需要5秒鐘,速度妥妥變成 Python 版本的7倍。

使用 Cython,不僅可以提高程式的執行速度,還可以把你的核心程式碼轉換為.so檔案,防止別人反編譯看到你的程式碼。

關於 Cython 的更多介紹,請閱讀它的官方文件[1]

有同學可能會問,當前資料夾下面既然有fast_fib.pyx檔案,為什麼當我們執行from fast_fib import fib的時候,不會從這個檔案裡面匯入 Python 版本的程式碼?

這是因為,import只會從字尾為.py/.pyc/.pyo/.so的檔案中匯入模組,不會進入.pyx檔案中尋找。

參考資料

[1]

官方文件:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31557738/viewspace-2686668/,如需轉載,請註明出處,否則將追究法律責任。

相關文章