参考文献
- 『Cython ―Cとの融合によるPythonの高速化』, オライリー・ジャパン, ISBN978-4-87311-727-0
- 以下では、Cython本と呼ぶ
- Cython ドキュメント(和訳) — Cython 0.17.1 documentation
Cython概要
- Cythonは、PythonとCもしくはC++の静的型システムを融合したプログラミング言語
- クレオール型プログラミング言語
- クレオール言語(creole languag) - wikipedia : 複数の言語の混成語のこと。
- クレオール型プログラミング言語
- cython(cが小文字)は、CythonコードをCまたはC++コードに変換するコンパイラ
- Cythonの長所 = Pythonの表現力 + 動的性格 + C言語の性能
- Pythonコードは、そのままCythonコード (いくつかの例外はある)
- Cythonキーワード追加で、cythonが効率的なCコードを生成
##Cythonの2面性
- 陽 : PythonをCにコンパイル
- 陰 : C/C++とPythonのインターフェース
- Cythonが効果を発揮する領域のひとつに、「CライブラリをPythonでラップする」がある
(これがCython本を読んでいる理由)
##プロファリングの重要性
-
プロファイリングにより、I/Oバウンド/ネットワークバウンドだとわかったらCythonは第一の有効な手段でない
-
Cythonが有効なのはCPUバウンドな問題である。
-
パレートの法則
-
プログラム実行時間の80%はコードのわずか20%で費やされる。
-
20%はプロファリングをしなければ見つからない
-
Python組み込みのプロファイリングツールを活用する
-
メモリバウンド、I/Oバウンド、ネットワークバウンドな処理が主の場合、CythonとPythonの差は小さい
- メモリバウンド : 巨大な配列の要素の加算など
- I/Oバウンド : ファイルをディスクから読み出すなど
- ネットワークバウンド : ネットワークからデータを受信するなど
##型について
- Cの型システムをPythonに持ち込む ⊃ Cのデータ型が持つ制約を持ち込む
- Python → 無限精度、C → 固定精度
- CはPythonよりも高速 ←→ Pythonより柔軟性/一般性で劣る
Cythonコードのコンパイルと実行
- IPythonで対話的に
- インポート時に自動コンパイル
- Pythonのdistutilsを使って別途コンパイル
- make, CMake, SConsの標準ビルドシステムに統合する
- 標準的な方法は、「Pythonのdistutilsを使って別途コンパイル」(distutlisとcythonizeを使う方法)とされていた。
- 今でも本当にそうなのかは調べてみる必要あり
IPythonで対話的に
-
Cython本の通りに
%load_ext cythonmagic
とやると以下のエラーが出た
%load_ext cythonmagic
...\extensions\cythonmagic.py:21: UserWarning: The Cython magic has been moved to the Cython package
warnings.warn("""The Cython magic has been moved to the Cython package""")
- Stack overflowを見たら解決方法が載っていた
Cython in Ipython: ERROR: Cell magic %%cython
not found - Stack Overflow
you should do:
%load_ext Cython
After that, the cython magic should work as expected.
- また、Cython本では、
2回続け[Return]キーを押下してブロックを抜けると
となっているが,抜けられなかった。↓のように延々と改行になる。
In [6]: %%cython
...: def fib(int n):
...: cdef int i
...: for i in range(n):
...: print(i)
...:
...:
...:
...:
...:
...:
...:
- [Shift] + [Return]で抜けられた
In [7]: %load_ext Cython
In [8]: %%cython
...: def fib(int n):
...: cdef int i
...: for i in range(n):
...: print(i)
...: # [Shift] + [Return]
- [Shift] + [Return]を押下したあと待たされるのは、IPythonがコードブロックをコンパイル~ロードしているため。
- 生成されたソース
....ipython\cython_cython_magic_ed5cb5261ba45739ef3878fbe8610564.c
/* "_cython_magic_ed5cb5261ba45739ef3878fbe8610564.pyx":3
- def fib(int n):
-
cdef int i
-
for i in range(n): # <<<<<<<<<<<<<<
-
print(n)
-
return n
*/
## インポート時に自動コンパイル
- 以下のような fib.pyxを作成しておく
(fibってなっているが、簡単化のためフィボナッチ数列じゃない適当なものにしている。)
```fib.pyx
def fib(int n):
cdef int i
for i in range(n):
print(i)
- import pyximportをすると、fib.pyxをimportできるようになる。
In [21]: import pyximport
In [22]: pyximport.install()
Out[22]: (None, <pyximport.pyximport.PyxImporter at 0x64f2cc0>)
In [23]: import fib
In [24]: fib.fib(10)
0
1
2
3
4
5
6
7
8
9
- タブとスペースが混在していたりすると、大量のエラーがでるので注意すること。