我目前正在从Cython向C传递以下指针:
#convert the input Python 2D array to a memory view
cdef double[:,:] a_cython= np.asarray(a,order="C")
#define a pointer of a pointer with dimensions of a
cdef double** point_to_a = <double **>malloc(N * sizeof(double*))
#initialize the pointer
if not point_to_a: raise MemoryError
#try:
for i in range(N):
point_to_a[i] = &a_cython[i, 0]
#pass this double pointer to a C function
logistic_sigmoid(&point_to_a[0], N,M)
其中a
是一个numpy数组,其尺寸为N x M
,point_to_a
是指向Cython memoryview的指针的Cython指针a_cython
。由于a
来自Python的输入是二维数组,因此我认为这是将信息直接传递给C的最佳方法。通道运行顺利且计算正确。但是,我现在正尝试重新转换回point_to_a
一个numpy数组,但是我有点挣扎。
我正在考虑各种解决方案。我想研究在整个过程中是否可以保留N维数组,因此我在Cython中尝试了这种方法:
#define a integer array for dimensions
cdef np.npy_intp dims[2]
dims[0]= N
dims[1] = M
#create a new memory view and PyArray_SimpleNewFromData to deal with the pointer
cdef np.ndarray[double, ndim=2] new_a = np.PyArray_SimpleNewFromData(2, &dims[0], np.NPY_DOUBLE, point_to_a)
但是,当我转换new_a
为np.array时,因为array = np.asarray(new_a)
我只有一个0的数组。你有什么想法?
非常感谢
一旦使用int**
(或类似方法),数据就处于所谓的间接内存布局中。Cython的类型化内存视图支持间接内存布局(例如,请参见Cython:了解具有indirect_contignuous内存布局的类型化内存视图),但是实现此接口的类并不多。
Numpy的ndarray不实现间接内存布局-它们仅支持直接内存布局(例如,type的指针,int*
而不是int**
),因此将int**
num传递给numpy数组将无济于事。
好处是,因为您与共享内存a_cython
,所以这些值已就地更新。您可以通过返回base
键入的内存视图的-object来获取基础的numpy数组,即
return a_cython.base # returns 2d-numpy array.
根本不需要复制内存!
但是内存管理存在一些问题(例如,您需要free point_to_a
)。
在您的情况下,这可能是一个矫kill过正,但是我借此机会无耻地插入了我的一个库indirect_buffer
:因为间接内存布局缓冲区的替代品很少,而且不时需要一个,所以我创建了一个以避免编写始终相同的代码。
使用indirect_buffer
您的函数可能如下所示:
%%cython
#just an example for a c-function
cdef extern from *:
"""
void fillit(int** ptr, int N, int M){
int cnt=0;
for(int i=0;i<N;i++){
for(int j=0;j<M;j++){
ptr[i][j]=cnt++;
}
}
}
"""
void fillit(int** ptr, int N, int M)
from indirect_buffer.buffer_impl cimport IndirectMemory2D
def py_fillit(a):
#create collection, it is a view of a
indirect_view=IndirectMemory2D.cy_view_from_rows(a, readonly=False)
fillit(<int**>indirect_view.ptr, indirect_view.shape[0], indirect_view.shape[1])
# values are updated directly in a
现在可以使用,例如:
import numpy as np
a=np.zeros((3,4), dtype=np.int32)
py_fillit(a)
print(a)
# prints as expected:
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
上面的版本做了很多正确的事情:内存管理,缓冲区锁定等等。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句