読者です 読者をやめる 読者になる 読者になる

Cython の落とし穴

Python

ポインタを使ってあれこれしたいときの落とし穴を会社で教えてもらった。

numpy の ndarray.data の挙動が型を指定するかによって変わる

tutorials NumpyPointerToC · cython/cython Wiki · GitHub

ここに書かれた方法2でポインタを取り出したい時、引数の型の指定を取り除くと、挙動が変わってしまう。コンパイルエラーも起きず、実行もできるが、ndarray の中が書き換わらないというかなり不思議な状態になる。

これは Cython (cimport) 側の numpy と Python (import) 側の numpy の両方で data が定義されており、Cython 側の定義が優先され上書きされるからである。

void* に Python の int を代入しようとすると意図しない挙動になる

a が Python object の int でありメモリアドレスを表現しているとする(例えば、cupy の ndarray.data.ptr)。から void* に直接キャストしようとすると、Python object のポインタをとってきてしまうようだ。正解は、size_t に一度キャストして、void* にキャストするということである。つまり、以下の2つのコードの挙動は異なる。

<void*>a
<void*><size_t>a