27

このサイトの cython で numpy を使用することについて多くの質問があります

ただし、cython/numpy インターフェース APIは少し変更されたようで、特にメモリ連続配列の受け渡しが確実になっています。

cython で次のようなラッパー関数を記述する最良の方法は何ですか?

  • 連続している可能性が高いが必ずしも連続していない numpy 配列を取ります
  • シグニチャを使用して C++ クラス メソッドを呼び出すdouble* data_in, double* data_out
  • double*メソッドが書き込んだnumpy 配列を返しますか?

私の試みは以下の通りです:

cimport numpy as np
import numpy as np # as suggested by jorgeca

cdef extern from "myclass.h":
    cdef cppclass MyClass:
        MyClass() except +
        void run(double* X, int N, int D, double* Y)

def run(np.ndarray[np.double_t, ndim=2] X):
    cdef int N, D
    N = X.shape[0]
    D = X.shape[1]

    cdef np.ndarray[np.double_t, ndim=1, mode="c"] X_c
    X_c = np.ascontiguousarray(X, dtype=np.double)

    cdef np.ndarray[np.double_t, ndim=1, mode="c"] Y_c
    Y_c = np.ascontiguousarray(np.zeros((N*D,)), dtype=np.double)

    cdef MyClass myclass
    myclass = MyClass()
    myclass.run(<double*> X_c.data, N, D, <double*> Y_c.data)

    return Y_c.reshape(N, 2)

このコードはコンパイルされますが、必ずしも最適ではありません。上記のスニペットを改善するための提案はありますか?

X_c = ...(2)実行時に呼び出すと、「np is not defined on line」)がスローされます。正確なテスト コードとエラー メッセージは次のとおりです。

import numpy as np
import mywrapper
mywrapper.run(np.array([[1,2],[3,4]], dtype=np.double))

# NameError: name 'np' is not defined [at mywrapper.pyx":X_c = ...]
# fixed!

4

1 に答える 1

20

あなたは基本的にそれを正しく理解しています。まず、最適化が大した問題にならないことを願っています。理想的には、ほとんどの時間が cythnon ラッパー コードではなく、C++ カーネル内で費やされます。

コードを簡素化するために行うことができるスタイル上の変更がいくつかあります。(1) 1D 配列と 2D 配列の間で形状を変更する必要はありません。データのメモリ レイアウト (C オーダーと Fortran オーダー、ストライディングなど) がわかっている場合、配列は、C++ で自分自身にインデックスを付ける予定の単なるメモリのチャンクと見なすことができるため、numpy の ndim はそうではありません。 C++ 側では問題ではありません。ポインタが表示されているだけです。(2) cython の address-of operator を使用&すると、 を使用して、少しクリーンな方法 (明示的なキャストは不要) で配列の先頭へのポインターを取得できます&X[0,0]

だから、これはあなたの元のスニペットの私の編集版です:

cimport numpy as np
import numpy as np

cdef extern from "myclass.h":
    cdef cppclass MyClass:
        MyClass() except +
        void run(double* X, int N, int D, double* Y)

def run(np.ndarray[np.double_t, ndim=2] X):
    X = np.ascontiguousarray(X)
    cdef np.ndarray[np.double_t, ndim=2, mode="c"] Y = np.zeros_like(X)

    cdef MyClass myclass
    myclass = MyClass()
    myclass.run(&X[0,0], X.shape[0], X.shape[1], &Y[0,0])

    return Y
于 2013-08-11T21:12:48.673 に答える