曾經講過計算斐波那契數列的幾種方法,其中基於遞歸的方法是速度最慢的,例如計算第40項的值,需要36秒。如下圖所示:
要提高運算速度,根本辦法當然是改進算法。不過算法的提高是一個長期積累加上靈機一動的過程。我們今天要講的,是一個不費腦筋,立竿見影的方法——把 Python 代碼編譯成 C 語言代碼。通過 C 語言的運行效率來加速計算過程。
這個過程看起來很複雜,但實際上你並不需要編寫一行 C 語言代碼。你需要做的只是使用一個叫做 Cython 的庫把 Python 代碼編譯爲 C 語言代碼即可。
首先我們來安裝 Cython,就像安裝普通的第三方庫一樣:
python3 -m pip install cython
安裝完成以後,我們單獨寫計算斐波那契數列的函數:
def fib(n):
if n in [1, 2]:
return 1
return fib(n - 1) + fib(n - 2)
非常簡單的遞歸寫法。然後關鍵來了,我們要把這個文件保存爲fast_fib.pyx
。注意後綴是.pyx
。如下圖所示:
然後我們創建一個setup.py
文件,文件內容如下:
from setuptools import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize('fast_fib.pyx'))
如下圖所示:
這個文件的作用,就是調用 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}秒')
運行效果如下圖所示:
計算斐波那契數列第40項只需要5秒鐘,速度妥妥變成 Python 版本的7倍。
使用 Cython,不僅可以提高程序的運行速度,還可以把你的核心代碼轉換爲.so
文件,防止別人反編譯看到你的代碼。
關於 Cython 的更多介紹,請閱讀它的官方文檔[1]
有同學可能會問,當前文件夾下面既然有fast_fib.pyx
文件,爲什麼當我們執行from fast_fib import fib
的時候,不會從這個文件裏面導入 Python 版本的代碼?
這是因爲,import
只會從後綴爲.py
/.pyc
/.pyo
/.so
的文件中導入模塊,不會進入.pyx
文件中尋找。
參考資料
[1]
官方文檔: https://cython.readthedocs.io/