Python cython:将2D numpy数组传递给cdef函数
我想将一个2D numpy数组传递给一个cdef函数,在这个函数中,数组的尺寸可以变化。以下是我尝试过的:Python cython:将2D numpy数组传递给cdef函数,python,arrays,numpy,multidimensional-array,cython,Python,Arrays,Numpy,Multidimensional Array,Cython,我想将一个2D numpy数组传递给一个cdef函数,在这个函数中,数组的尺寸可以变化。以下是我尝试过的: cimport numpy as cnp input = numpy.array([[3.34, 2.2],[1.1, -0.6]]) input = input[:,:].astype(np.double) cdef int nrows = 2 cdef int ncols = 2 # output of function cdef cnp.ndarray[cnp.uint8_t,
cimport numpy as cnp
input = numpy.array([[3.34, 2.2],[1.1, -0.6]])
input = input[:,:].astype(np.double)
cdef int nrows = 2
cdef int ncols = 2
# output of function
cdef cnp.ndarray[cnp.uint8_t, ndim=2] output = np.zeros((2,2), dtype=np.uint8)
test_array(nrows, ncols, &input[0], <unsigned char**>output.data)
我的功能原型是:
cdef void test_array(Py_ssize_t nrows, Py_ssize_t ncols, double **x, unsigned char **output) nogil
当我编译时,我得到一个错误,说“不能获取Python对象的地址”,并指向
&input[0]
。这种语法适用于一维数组,但我不确定二维数组的语法是什么。我也尝试了&输入[0][0]
,但那也是错误的 不清楚您希望实现什么:
A:如果它应该是一个纯cython函数,那么您应该使用,这意味着您的函数签名应该是
cdef void test_array(double[:,:] x, unsigned char[:,:] output) nogil:
没有nrow
,ncol
,因为类型化内存视图包含此信息(类似于std::vector
)
B:array\u test
实际上是c函数的包装器,它需要double**
和unsigned char**
,那么您应该看看这个
事实上,我想解释一下,为什么你的尝试没有成功 首先,为什么
&input[0]
不起作用?真正的问题是什么是输入[0]
:
import numpy as np
input=np.zeros((3,3))
type(input[0])
<type 'numpy.ndarray'>
type(input[:,0])
<type 'numpy.ndarray'>
type(input[0,0])
<type 'numpy.float64'>
重要的部分:input
不再被视为python对象,而是被视为cython类型的np.ndarray[double,ndim=2]
,这就是语法&input[0,0]
首先成为可能的原因
也许更确切地说:cimport numpy
为我们提供了处理numpy数组的额外工具,因此我们可以访问纯python中无法访问的内部构件
然而,&input[0,0]
不是类型double**
,而是类型double*
,因为numpy.ndarray
只是一个连续的内存块,只有操作符[i,j]
模仿2d:
How it feels:
A[0] -> A00 A01 A02
A[1] -> A10 A11 A12
The real layout in the memory:
A00 A01 A02 A10 A11 A12
没有指向行的指针,但您可以通过cdef double*ptr2=&input[row_id,0]
创建它们,如何处理它将在中讨论
要说
numpy.ndarray
只是一段连续的内存,这是一种简化-numpy.ndarray
是一个相当复杂的野兽!请考虑以下例子:
import numpy as np
cimport numpy as np
def try_me2():
cdef np.ndarray[double, ndim=2] input = np.array([[1.0, 2.0],
[3.0, 4.0]])
cdef np.ndarray[double, ndim=1] column = input[:,1]
cdef double *ptr = &column[0]
print column #prints column "2 4"
print ptr[0],ptr[1] #prints "2 3" and not "2 4"!
现在,这里的
input
和column
共享相同的内存,并且input[1][0]
保存在input[0][1]=column[0]
之后,然后才input[1][1]=column[1]
ptr[1]
获取input[0][1]
旁边的存储单元,这是input[1][0]=3
而不是input[1][1]=4
你有没有可能对你试图编译的文件的确切内容做一个要点或小报告?二维数组的第一个元素是[0,0]
。我看到您想要传递一个指向输入的指针。这对于Cython的C部分来说是未知的,您必须将数据作为a来传递。如果给需要类型化memoryview的函数指定一个NumPy数组,它的行为将与预期的一样:-)
How it feels:
A[0] -> A00 A01 A02
A[1] -> A10 A11 A12
The real layout in the memory:
A00 A01 A02 A10 A11 A12
import numpy as np
cimport numpy as np
def try_me2():
cdef np.ndarray[double, ndim=2] input = np.array([[1.0, 2.0],
[3.0, 4.0]])
cdef np.ndarray[double, ndim=1] column = input[:,1]
cdef double *ptr = &column[0]
print column #prints column "2 4"
print ptr[0],ptr[1] #prints "2 3" and not "2 4"!