2017-01-05 35 views
2

在cython中,可以使用数组视图,例如,cython静态形状数组视图

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

在我的用法中,第二个维度的形状应该总是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)) 

我想所做的事情是:

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 # ??? 

即编译成功,但我无法找到numpy的转换它的任何方式。如果你能弄清楚如何让这个版本起作用,那么我认为这将是最优雅的解决方案。


请注意,我不相信任何这些解决方案的性能优势。您最好的举动可能是告诉Cython后面的维度在内存中是连续的(例如double [:,::1]),但让它成为任何大小。