2009年9月23日水曜日

PythonとC/C++のインターフェイス開発の手段

手元のマシンにも4GBのメモリを入れ、もっと大きなメモリのデスクトップマシンも用意したが、その一番の理由は大規模なテキストの処理や行列演算などを行ないたいからだ。
行列演算そのものは、特異値分解(SVD)などの一般的なものがほとんどになるため、そのためのライブラリが必要になる。
さらに、できればC/C++でゴリゴリやるよりもスクリプトでやりたい。

それで、やはり馴染みのPythonとその数値演算用モジュールnumpyを使おうと思っている。
SVDをはじめ大抵のことはそれでなんとかなると思う。
しかし、中には自分で細かいところから書かなければいけない事もある。
numpyの良い点は、実際の計算のほとんどはC(Fortran?)で書かれた拡張モジュール内で行なわれるので、Python<->C間でのデータの受け渡しなどのわずかなオーバーヘッドがあるだけで、とても効率良く計算できることだ。例えば行列のかけ算などは実際にはそのすべてがCモジュール内で行なわれる。
しかし行列の要素の一つ一つに個別にアクセスするようなコードをPythonで書くと、その一つ一つでオーバーヘッドが生じ、実計算と比率として無視できなくなってくる。

ということで、やはり自分がやりたい計算はC/C++で書いて、それをPythonからシームレスに呼び出せるようにしたい。
そういう目的のための基本はPythonのCライブラリを利用して正規の拡張モジュールを作成することだろうが、リファレンスカウントなどの面倒も自分でみなければいけないとか何かと面倒っちい。
また、既に存在するC/C++のリソースを取り込むのも面倒だ。
幸い正規のモジュール開発方法以外にも、Pythonには様々なC/C++インターフェイス開発方法が用意されている。

その中で最終的に選択肢として残したのは、ctypesとboost.pythonだ。

ctypesはなんと言っても2.6で正規モジュールになり、2.5.xにもバックポートされていること、またPython3.xでも正規モジュールになっており、先々を考えても安心感があることが大きい。
さらにctypesの良い点は、既存のライブラリ(shared object)があれば、Cコードを書く必要がなく、Pythonサイドだけで方が付くという点だ。
もっともその分Python内でライブラリ関数の引数の型情報の設定などが必要だが。

boost.pythonは、C++のSTLの拡張とも言えるboostライブラリに含まれている。
boostはとても活発に開発されており、標準化の進捗と共にその一部はC++の規格自体に取り込まれるらしい。
そういう活発な開発母体があるので、Python 3.xにも対応するのではないかと期待している。
また、C++用ということもあり、C++のSTLや、もちろんboostのその他のライブラリも利用できるため、何かと便利だ。
で、実際に試してみたのだが、思っていた以上に簡単に使うことができた。
二つの点を除いては、もうこれが本命と言って良いと思う。
一つは、あくまでもPythonの外部から提供されているものであり、ctypesのようにPython正統のものではないこと。
もう一つは、いずれこの点も書きたいが、並列処理との兼ね合い。

ということで、ctypesとboost.pythonがお勧め。
サンプルはいずれ。

0 件のコメント: