Cythonとは
Cythonは、PythonをC言語にコンパイルして高速化するツール。
Pythonの構文を維持しながら、C言語の速度を得られる。「Python遅い」問題の切り札だよ。
Python → Cython → C → コンパイル → 高速な拡張モジュール
インストール
pip install cython
基本的な使い方
1. .pyxファイルを作成
# example.pyx
def python_style(n):
"""普通のPython関数"""
total = 0
for i in range(n):
total += i
return total
cpdef long cython_style(long n):
"""型宣言した高速版"""
cdef long total = 0
cdef long i
for i in range(n):
total += i
return total
2. setup.pyでビルド
# setup.py
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize("example.pyx")
)
3. コンパイル
python setup.py build_ext --inplace
4. 使用
from example import cython_style
result = cython_style(100_000_000)
型宣言
Cythonの高速化の鍵は型宣言です。
変数の型宣言
# cdef で型を宣言
cdef int x = 10
cdef double y = 3.14
cdef long z = 1000000000
# 配列
cdef int arr[100]
# ポインタ
cdef int* ptr
関数の型宣言
# def: Pythonから呼べる(遅い)
def python_func(x):
return x * 2
# cdef: Cython/Cからのみ呼べる(速い)
cdef int c_func(int x):
return x * 2
# cpdef: 両方から呼べる(中間)
cpdef int hybrid_func(int x):
return x * 2
型一覧
| Cython型 | C型 | 用途 |
|---|---|---|
int |
int |
整数 |
long |
long |
長整数 |
float |
float |
浮動小数点 |
double |
double |
倍精度 |
bint |
int |
ブール値 |
char |
char |
文字 |
str |
PyObject* |
文字列 |
パフォーマンス比較
Pure Python vs Cython
| 処理 | Pure Python | Cython | 高速化 |
|---|---|---|---|
| 単純ループ(1億回) | 3.87秒 | 0.08秒 | 48x |
| フィボナッチ(35) | 1.39秒 | 0.02秒 | 70x |
| 素数カウント | 0.11秒 | 0.005秒 | 22x |
実践例
フィボナッチ
# fib.pyx
# Pure Python(遅い)
def fib_python(n):
if n <= 1:
return n
return fib_python(n-1) + fib_python(n-2)
# Cython(速い)
cpdef long fib_cython(int n):
if n <= 1:
return n
return fib_cython(n-1) + fib_cython(n-2)
素数判定
# primes.pyx
cpdef bint is_prime(int n):
cdef int i
if n < 2:
return False
for i in range(2, <int>(n**0.5) + 1):
if n % i == 0:
return False
return True
cpdef list get_primes(int limit):
cdef int n
cdef list primes = []
for n in range(2, limit):
if is_prime(n):
primes.append(n)
return primes
NumPy連携
# numpy_example.pyx
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False) # 境界チェック無効
@cython.wraparound(False) # 負のインデックス無効
cpdef double array_sum(np.ndarray[np.float64_t, ndim=1] arr):
cdef Py_ssize_t i
cdef double total = 0.0
for i in range(arr.shape[0]):
total += arr[i]
return total
Pure Pythonモード
.pyファイルでも型ヒントでCython高速化:
# example.py
import cython
@cython.cfunc
@cython.locals(n=cython.int, total=cython.long, i=cython.long)
def fast_sum(n: int) -> int:
total: int = 0
for i in range(n):
total += i
return total
コンパイルオプション
ディレクティブ
# cython: boundscheck=False
# cython: wraparound=False
# cython: cdivision=True
# cython: profile=True
または関数単位で:
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef int fast_func(int n):
...
| ディレクティブ | 効果 |
|---|---|
boundscheck(False) |
配列境界チェック無効 |
wraparound(False) |
負のインデックス無効 |
cdivision(True) |
Cスタイル除算 |
profile(True) |
プロファイリング有効 |
pyximport
開発中は自動コンパイル:
import pyximport
pyximport.install()
import my_module # .pyxを自動コンパイル
いつCythonを使うか
✓ 適している場面
- 数値計算のループ
- 再帰関数
- NumPy配列の要素単位操作
- C言語ライブラリのラッパー
✗ 向いていない場面
- I/O処理(ファイル、ネットワーク)
- 文字列操作が多い処理
- Pythonオブジェクトを多用する処理
まとめ
Pure Python → Cython変換の手順:
1. .pyx ファイルを作成
2. 変数に cdef で型を付ける
3. 関数を cpdef に変更
4. setup.py でビルド
5. import して使用
型宣言するだけで10〜100倍の高速化!
ボトルネックの関数だけCython化するのが効率的です。