BlankTar

about | blog | works | photo

追記: この記事とは真逆の事をする記事も書きました。 pythonのモジュールをC言語から使う


pythonは楽だ。難しいこと考えずに書けて、難しいこと考えずともどこでも動く。
でもね、遅いんだ。速度が出ないんだ。
C言語は速い。馬鹿みたいに速い。とりあえず大体速いし、最適化もしやすい。
でもね、面倒なんだ。色々自分で考えなきゃいけないんだ。

なら組み合わせて使えば良いんじゃね? と言う訳で。
試しにベンチマークしてみましたよ。
使ったコードはこれね。

結果はこんな感じ。
-----階乗計算-----
20の階乗を一万回計算してみる
python: 0.144444775581 秒くらい
pythonAPI: 0.00294818878174 秒くらい
ctypes: 0.00294799804687 秒くらい

-----Adler32-----
アルファベットのAdler32を一万回計算してみる
python: 0.382977795601 秒くらい
pythonAPI: 0.00905439853668 秒くらい
ctypes: 0.00903975963593 秒くらい
速いねー、C速いねー。

今回使ってみたのは二通りの方法。
一つめがPython.hをインクルードしてCを書く方法。Python/C APIってやつ。
モジュールを作るならこれが標準っぽい。書くのが面倒だけど、その分例外処理とかpythonの形を考慮するとか、まあ色々できるんだろうね。
二つめがctypesモジュールを使ってpython側で何とかする方法。普通のCのライブラリを使えるっぽい。
Cのソースは普通のCなので、とっても楽ちん。ただ、例外処理とかがよく分からない。
引数間違えたらエラー出さずにフリーズしちゃったしね。結構怖いかも分からん。

あら手軽、素敵だわ。って事で、今回はctypesの方をご紹介。
手軽なのはいい事だね。コードなんて短くてなんぼです。
試した限りPython/C APIとの速度差もほとんどなさげだしね。

1.普通にC言語でコードを書きます。
単体のプログラムじゃないから、main関数は無し。
2.コンパイルします。
gccならgcc -shared -fPIC -o モジュール名.so ソースコードの名前で。
3.pythonのctypesでロードします。
import ctypes
test = ctypes.CDLL('./test.so')
みたいな感じ。モジュール名がtestの場合ね。
5.使います。
後は普通にtest.func()みたいに使える。楽ちん。

いやー、楽ちん楽ちん。
上手いことやればかなりの高速化を期待できるはず。
エラー処理がよく分からないので、その辺だけ注意で。

まあ、これだけ手軽でもさ、そこまで速度が欲しいものって作らないのよね・・・。
統計取りまくりとか、ゲーム作ってるとか、そういうんなら使えるんだろうけどさ。

参考:
PythonのC言語拡張モジュール作成ガイド - hexacosa.net
Python インタプリタの拡張と埋め込み - Pythonドキュメント
< CONFIG_DEVTMPFSがどうのでgentooが起動しない ACCESS VIOLATION SUMMARY とかいうエラー >