2017-01-05 6 views
2

cythonでは、配列ビューを使用できます。cython静的形状の配列ビュー

cdef void func(float[:, :] arr) 

私の使い方では、2番目のディメンションは常に2のシェイプを持つ必要があります。これをcythonに伝えることはできますか?私は次のようなものを考えていました:

cdef void func(float[:, 2] arr) 

しかし、これは無効な構文になります。あるいは、C++にもっと似たものを持つことが可能ですか?

cdef void func(tuple<float, float>[:] arr) 

ありがとうございます!

答えて

1

代わりに2D静的配列を使用できます。ポインタ表記を使用するだけです。ここでは、あなたが得るそれを呼び出す

def pyfunc(): 
    # static 1D array 
    cdef float *arr1d = [1,-1, 0, 2,-1, -1, 4] 
    # static 2D array 
    cdef float[2] *arr2d = [[1,.2.],[3.,4.]] 
    # pass to a "cdef"ed function 
    cfunc(arr2d) 

# your function signature would now look like this 
cdef void cfunc(float[2] *arr2d): 
    print("my 2D static array") 
    print(arr2d[0][0],arr2d[0][1],arr2d[1][0],arr2d[1][1]) 

にそれを達成する方法である:

>>> pyfunc() 
my 2D static array 
1.0, 2.0, 3.0, 4.0 
+0

質問:numpy配列のデータを 'float [2] *'に変換するにはどうすればよいですか? – user1447257

+0

@ user1447257これで何を達成したいですか?パフォーマンスのために静的な形状の配列が必要だったようです。しかし、これがコード内の文法的な砂糖であるならば、汎用メモリビュー構文 'float [:、:]'を使うこともできます。 'numpy'配列は動的なので、データを明示的にコピーしない限り、' float [2] * 'に束縛されません。 – romeric

+0

キャッシュミスを少なくするために、私のコードはエントリを何度も繰り返し処理するので、私は連続した配列にコピーします。ポインタを完全に線形にインクリメントできるので、 'float [2] *'データ型へのキャストはパフォーマンスを少し向上させるかもしれないと私は考えていました。 – user1447257

0

私はこれが本当にサポートされているとは思わないが、あなたはこれをしたいならば、最良の方法は、使用することをおそらくstructsのmemoryviews(numpysカスタムdtypesと互換性のある):

import numpy as np 

cdef packed struct Pair1: # packed ensures it matches custom numpy dtypes 
       # (but probably doesn't matter here!) 
    double x 
    double y 

# pair 1 matches arrays of this dtype  
pair_1_dtype = [('x',np.float64), ('y',np.float64)] 

cdef packed struct Pair2: 
    double data[2] 

pair_2_dtype = [('data',np.float64, (2,))] 

def pair_func1(Pair1[::1] x): 
    # do some very basic work 
    cdef Pair1 p 
    cdef Py_ssize_t i 
    p.x = 0; p.y = 0 
    for i in range(x.shape[0]): 
     p.x += x[i].x 
     p.y += x[i].y 

    return p # take advantage of auto-conversion to a dict 

def pair_func2(Pair2[::1] x): 
    # do some very basic work 
    cdef Pair2 p 
    cdef Py_ssize_t i 
    p.data[0] = 0; p.data[1] = 0 
    for i in range(x.shape[0]): 
     p.data[0] += x[i].data[0] 
     p.data[1] += x[i].data[1] 

    return p # take advantage of auto-conversion to a dict 

と、それを呼び出す方法をお見せするための機能:

def call_pair_funcs_example(): 
    # generate data of correct dtype 
    d = np.random.rand(100,2) 
    d1 = d.view(dtype=pair_1_dtype).reshape(-1) 
    print(pair_func1(d1)) 

    d2 = d.view(dtype=pair_2_dtype).reshape(-1) 
    print(pair_func2(d2)) 

私が行っているしたい事はある:

正常にコンパイルが、私はnumpyのからそれを変換する任意の方法を見つけることができませんでした
ctypedef double[2] Pair3 

def pair_func3(Pair3[::1] x): 
    # do some very basic work 
    cdef Pair3 p 
    cdef Py_ssize_t i 
    p[0] = 0; p[1] = 0 
    for i in range(x.shape[0]): 
     p[0] += x[i][0] 
     p[1] += x[i][1] 

    return p # ??? 

。あなたがこのバージョンを動作させる方法を考え出すことができれば、それは最も洗練されたソリューションだと思います。


これらのソリューションのパフォーマンス上の利点はわかりません。あなたの最善の動きはおそらく、後続の次元がメモリ内で連続していることをCythonに伝えることです(例えばdouble [:,::1])。