Cython+Numpyメモ

いろいろと必要があってCythonとNumpyを使うことになりましたが、少し嵌ったのでメモ


数値計算にはPython+Numpyを利用していましたが、(禁忌とされる)データに対して直接forループを回さなければならないような状況に陥ったので、仕方なくCythonを導入。
CythonからNumpy.arrayにアクセスしたい時は、ナイーブな方法で行うとオーバーヘッドが大きい。
そのため、配列へのアクセスを高速に行うための仕組みがCythonにあります。

Working with Numpy
http://docs.cython.org/src/tutorial/numpy.html#efficient-indexing

このあたりの公式文書を参照のこと。Pythonのオブジェクトとして扱うのではなく、きちんと型と次元を指定してやって、もっとC寄りの配列を直接いじる感じ。
さて、この機能を利用するために冒頭で

import numpy as np
cimport numpy as np

としてnumpyのCのヘッダを読みこんでやらないといけません。
これをコンパイルするために、ドキュメントを参照しながら適当にsetup.pyを作り、

$ python setup.py build_ext --inplace

としてコンパイルを実行すると、ありとあらゆるコンパイルエラーが出たあとに、

error: command 'gcc' failed with exit status 1

とのたもうて落ちる。cythonでCのコードを生成するのは問題なくできるので、Cをコンパイルする段での問題なのは明らかだったのですが、なかなか問題が解決できず詰まるなどしていました。。


結論から言うと簡単なことで、gccにnumpyにまつわるヘッダファイルの所在を教えてあげなければいけない、ということだったようです。
numpy用のインクルードパスはnumpy.get_numpy_include()で取得できるので、setup.pyを上手く書き換えてやって

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

import numpy
setup(
    name="CPWOPTcritical",
    cmdclass={"build_ext":build_ext},
    ext_modules=[Extension("hoge",["hoge.pyx"],
                 include_dirs=[numpy.get_numpy_include()]#ここでインクルードパスを指定
)]
)

としてやれば、うまくコンパイルが通りました。


もっと早く気づいていれば…