cython静态形状的数组视图

时间:2017-01-05 10:35:53

标签: multidimensional-array cython

在cython中,可以使用数组视图,例如

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

在我的使用中,第二个维度应该总是具有2的形状。我可以告诉cython吗?我想的是:

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

但这会导致语法无效;或者是否可能有更类似于c ++的东西,例如

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

提前致谢!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

我不认为这是真的支持,但是如果你想这样做,那么最好的方法可能就是使用structs的内存视图(与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])但是它可以是任何大小。