Open4
Cython学習
1章 Cythonの基本
Cythonとは
- Python-C/C++間の橋渡し(インターフェース)
- Pythonライクな構文にC/C++ の静的型付けシステムを追加した言語
- CythonコードをC/C++コードに変換するコンパイラ
- Python拡張モジュールや実行可能ファイルに変換できる
簡単な比較
Python
fib.py
def fib(n):
a, b = 0.0, 1.0
for _ in range(n):
a, b = a + b, a
return a
Cython
cyfib.pyx
def cyfib(n):
cdef double a = 0.0, b = 1.0
for _ in range(n):
a, b = a + b, a
return a
セットアップファイルとコンパイル方法
setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize(['cyfib.pyx']))
python3 setup.py build_ext --inplace
処理時間計測コード
fibtime.py
from fib import fib
from cyfib import cyfib
import time
time_start = time.time()
n = 100000000
fib(n)
time_end = time.time()
time_gap = time_end - time_start
print(f"fib : process_time = {time_gap}")
time_start = time.time()
cyfib(n)
time_end = time.time()
time_gap = time_end - time_start
print(f"cyfib : process_time = {time_gap}")
計測結果
python3 fibtime.py
fib : process_time = 1.8234779834747314
cyfib : process_time = 0.8040680885314941
約2.25倍の改善
性能が向上する理由
- 関数呼び出しのオーバーヘッド
- Cythonでは、遅いPython/C APIコールを一部省略できるから
- ループ処理
- Pythonはコンパイル言語と比べて非常に遅い
- 数値計算
- Pythonでは実行時にa,bの型を調べてから加算メソッドを行う
- ヒープメモリからスタックメモリ使うようになった
- Python上での動的オブジェクトはCレイヤーだとヒープメモリに置かれる
- さらに、イミュータブルオブジェクトなので、生成と破棄が計算の度に実行されメモリに再配置される(オーバーヘッド)
- Cython上だとスタックメモリに置かれる
- ミュータブルオブジェクトなので、効率的に使われる
- Python上での動的オブジェクトはCレイヤーだとヒープメモリに置かれる
性能改善できる箇所(ボトルネックによって改善できない場合も)
- CPUバウンドなら改善できる余地あり
- I/Oバウンド・ネットワークバウンドだと改善が難しい
- まずはプロファイリングツールでボトルネックを探すこと
3章 Cythonの深層
インタプリターによる実行とコンパイラによる実行
- Python
- 実行前に自動的にPythonバイトコードにコンパイルされる
- バイトコード=Python仮想マシン:VM
- VMにより、プラットフォームの違いを吸収する
- 仮想マシンの実行はコンパイラされた機械語より遅い
- C
- VMやインタプリタは存在せず、高水準のバイトコードもない
- コンパイラによって直接機械語に翻訳される
2章 Cythonコードのコンパイルと実行
Cythonをコンパイルする方法一覧
- IPythonで対話的にコンパイル&実行(Google Colabでも可)
- インポート時に自動コンパイル
- Pythonのdistutilsのようなビルドツールを使う
- make,cmakeなどの標準ビルドシステムに統合する
PurePython
Python文法のまま、Cython固有の宣言を使うことができる。
Pythonインタプリタで実行もコンパイルして実行することもできる。
Cython コンパイルパイプライン
- cythonコンパイラがプラットフォームに依存しないC/C++ソースコードに変換する
- 標準C/C++コンパイラでC/C++ソースコードを共有ライブラリに変換する
- Linux/MacOSなら
*.so
ファイル、Windowsなら*.pxd
ファイル - コンパイラ済みモジュールを拡張モジュールとも言う
- Linux/MacOSなら