Open4

Cython学習

MasaHeroMasaHero

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上だとスタックメモリに置かれる
      • ミュータブルオブジェクトなので、効率的に使われる

性能改善できる箇所(ボトルネックによって改善できない場合も)

  • CPUバウンドなら改善できる余地あり
  • I/Oバウンド・ネットワークバウンドだと改善が難しい
  • まずはプロファイリングツールでボトルネックを探すこと
MasaHeroMasaHero

3章 Cythonの深層

インタプリターによる実行とコンパイラによる実行

  • Python
    • 実行前に自動的にPythonバイトコードにコンパイルされる
    • バイトコード=Python仮想マシン:VM
    • VMにより、プラットフォームの違いを吸収する
    • 仮想マシンの実行はコンパイラされた機械語より遅い
  • C
    • VMやインタプリタは存在せず、高水準のバイトコードもない
    • コンパイラによって直接機械語に翻訳される
MasaHeroMasaHero

2章 Cythonコードのコンパイルと実行

Cythonをコンパイルする方法一覧

  • IPythonで対話的にコンパイル&実行(Google Colabでも可)
  • インポート時に自動コンパイル
  • Pythonのdistutilsのようなビルドツールを使う
  • make,cmakeなどの標準ビルドシステムに統合する

PurePython

Python文法のまま、Cython固有の宣言を使うことができる。
Pythonインタプリタで実行もコンパイルして実行することもできる。

https://cython.readthedocs.io/en/latest/src/tutorial/pure.html

Cython コンパイルパイプライン

  1. cythonコンパイラがプラットフォームに依存しないC/C++ソースコードに変換する
  2. 標準C/C++コンパイラでC/C++ソースコードを共有ライブラリに変換する
    • Linux/MacOSなら*.soファイル、Windowsなら*.pxdファイル
    • コンパイラ済みモジュールを拡張モジュールとも言う