Cython:加速你的 Python code

1 minute read

Cython: Speeding up your Python code

Python 是一種直譯式的動態語言,它的優點是可讀性高、彈性大、開發快⋯⋯等很多優點啦(This is why I like it!)。但是,身為直譯式語言(Interpreted language)的一員,在執行速度上當然會比編譯式語言(Compiled language)慢一點啦。

試想一種情境,當你用 Python 快速開發出一個 prototype 後,卻發現執行速度有點慢,如果你希望它跑的和 C/C++ 一樣快的時候,應該怎麼做勒?

這時候 Cython 就可以幫你啦,Cython 可以讓你稍微修改原始的 Python code 後,就可以讓你從機車變成高鐵。

以下參考官方的教學 Basic Tutorial,紀錄使用過程。

OS Information: 由於編譯過程會與系統相依,所以這邊顯示我使用的系統資訊。

macOS Mojave Version 10.14.3
Python 3.6

1. Write a simple Python code

這邊先寫一個簡單的階乘 function,檔名叫做 run_as_python.py

def factorial(n):
    ans = 1
    for i in range(1, n + 1):
        ans *= i
    return ans

2. Modify your Python code

然後再新增一個檔案,檔名叫做 run_as_cython.pyx,然後稍微修改前一個階乘 function。

cpdef int factorial(int n):
    cdef int ans
    ans = 1
    cdef int i
    for i in range(1, n + 1):
        ans *= i
    return ans

所謂的稍微,也就是將原本的 Python code 裡面的物件都宣告成 C 的型態 (Cython type reference)。

這邊把 ans i n 都宣告成 cdef int,由於計算完的結果也是 int,所以在 factorial() 前面宣告 cpdef intcdefcpdef 的差異可以 參考,如果要讓編譯後的 function 可以在 Python 裡面使用的話,就必須要將該 function 宣告成 cpdef

3. Setup the setup.py

接著建立 setup.py,然後在裡面寫

from distutils.core import setup
from Cython.Build import cythonize


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

4. Compile

經過前面的步驟後,你的檔案結構應該會長這樣。

.
├── run_as_cython.pyx
├── run_as_python.py
└── setup.py

最後,在 terminal 裡面下

python setup.py build_ext --inplace

如果編譯成功的話,你的檔案結構應該會變成這樣。

.
├── run_as_cython.c
├── run_as_cython.cpython-36m-darwin.so
├── run_as_cython.pyx
├── run_as_python.py
└── setup.py

如果你的系統是 Unix 會產生 .so 檔,如果是 Windows 則會產生 .pyd

使用方式就只要簡單的 import 該檔案就好啦。

5. Try it

萬事俱備,直接在 Jupyter Notebook 中測試一下速度是不是真的從機車變成高鐵吧。

import run_as_python
import run_as_cython

%%timeit
run_as_python.factorial(5)
# output
# 629 ns ± 32.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%%timeit
run_as_cython.factorial(5)
# output
# 79.4 ns ± 1.46 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

利用 Jupyter 的 %%timeit 測試,可以發現一樣的程式碼,速度提升接近 8 倍。


完整的 sample code 請參考 cython-basic

如果你要直接下載執行的話,由於機器的不同,可能需要重新編譯。

Leave a comment