Python cython中的c malloc数组指针返回
如何高效地将cython中的malloc数组指针(或numpy数组指针)返回到python3 只要我不返回数组指针,cython代码就可以完美地工作 我想:Python cython中的c malloc数组指针返回,python,c,arrays,numpy,cython,Python,C,Arrays,Numpy,Cython,如何高效地将cython中的malloc数组指针(或numpy数组指针)返回到python3 只要我不返回数组指针,cython代码就可以完美地工作 我想: def double complex* randn_zig(int n): ... r = malloc(n*n*sizeof(double complex)) ... return r c11(gcc 11)等效物为: double complex* randn_zig(int n){ r = malloc(n
def double complex* randn_zig(int n):
...
r = malloc(n*n*sizeof(double complex))
...
return r
c11(gcc 11)等效物为:
double complex* randn_zig(int n){
r = malloc(n*n*sizeof(double complex))
return r
}
我试过了
randn\u zig(int n):
和randn_zig(r,int n):
和其他迄今尚未成功的排列。如果我能找到一种方法返回指向大型10^6到10^10双复数数组的指针,那么c和cython代码版本的速度是Numby/pylab randn版本的5倍。我认为最好的方法是通过NumPy将Python中创建的现有数组的指针传递给cython,否则,您似乎必须将
malloc
创建的数组的内容复制到另一个数组,如本玩具示例所示:
import numpy as np
cimport numpy as np
from libc.stdlib cimport malloc, free
def main():
cdef int i, n=40
cdef double complex *r
cdef np.ndarray[np.complex128_t, ndim=1] a
a = np.zeros(n*n, dtype=np.complex128)
r = <double complex *>malloc(n*n*sizeof(double complex))
for i in range(n*n):
r[i] = 1.
for i in range(n*n):
a[i] = r[i]
free(r)
return a
将numpy导入为np
cimport numpy作为np
来自libc.stdlib cimport malloc,免费
def main():
cdef int i,n=40
cdef双复数*r
cdef np.ndarray[np.complex128_t,ndim=1]a
a=np.zero(n*n,dtype=np.complex128)
r=malloc(n*n*sizeof(双复数))
对于范围内的i(n*n):
r[i]=1。
对于范围内的i(n*n):
a[i]=r[i]
免费(r)
归还
Numpy C API
你的问题类似于
您可以使用下面的函数将C指针传递给Numpy数组。当Numpy阵列被回收时,内存将被自动释放。如果您希望完全释放指针,则不应设置NPY_OWNDATA标志
import numpy as np
cimport numpy as np
cdef pointer_to_numpy_array_complex128(void * ptr, np.npy_intp size):
'''Convert c pointer to numpy array.
The memory will be freed as soon as the ndarray is deallocated.
'''
cdef extern from "numpy/arrayobject.h":
void PyArray_ENABLEFLAGS(np.ndarray arr, int flags)
cdef np.ndarray[np.complex128, ndim=1] arr = \
np.PyArray_SimpleNewFromData(1, &size, np.NPY_COMPLEX128, ptr)
PyArray_ENABLEFLAGS(arr, np.NPY_OWNDATA)
return arr
供参考:
将numpy导入为np
cimport numpy作为np
cdef np.complex128_t[:,:]视图=c_指针
numpy_arr=np.asarray(视图)
上面的代码将C指针传输到numpy数组。
但是这不会自动释放内存,您必须自己释放内存,否则会导致内存泄漏 对于使用C-11标准(gcc-std=gnu11…)的gcc 5+,多维malloc和calloc数组的语法发生了显著变化 用于为n=1024创建二维双精度复杂calloc数组r[n][n]的main()过程现在是:
long n = 1024;
complex double (*r)[n] = calloc(n, sizeof *r);
高斯随机数生成器randn_box_muller()使用指向此calloc数组r[n][n]的指针的示例如下:
inline static void randn_box_muller(long n, complex double r[][n])
{
long i, j;
register double x, y;
for(i = 0; i < n; i++){
for(j = 0; j < n; j++){
x = 2.*M_PI*dsfmt_genrand_close_open(&dsfmt);
y = sqrt(-2.*log(dsfmt_genrand_close_open(&dsfmt)));
r[i][j] = (cos(x) + I*sin(x))*y;
}
}
return;
}
inline static void randn\u box\u muller(长n,复数双r[][n])
{
长i,j;
寄存器双x,y;
对于(i=0;i
这种相对较新的calloc分配语法有点奇怪。它适用于1维、2维甚至n维的calloc和malloc数组。希望这也能与Python3配合使用。我希望很快就可以进行测试 当您尝试调用此函数时,是否可以为部件提供更多代码?您会遇到哪些错误?没有与指针等效的python,因此它实际上不是您想要返回的指针,而是对已分配内存块的引用(即,某个python对象有一个指针)。您选择哪种python对象将取决于您打算对指针/内存块做什么。我一直忙于其他项目,现在又回来解决这个问题了。谢谢无论如何,Python3.4和numpy似乎包含Meresenne主生成器,我假设它是dsfmt(),这是Ubuntu 15.10中的默认值。我还没有看过ppython3.4的Python源代码,但是3.2没有。我不确定他们是否有randn()的Ziggurat或Leva算法。我需要看看。如果需要,我将实施一个。731Syrtis Thank将很快尝试。我现在真的需要为一个项目解决这个问题。请看下面的评论。
inline static void randn_box_muller(long n, complex double r[][n])
{
long i, j;
register double x, y;
for(i = 0; i < n; i++){
for(j = 0; j < n; j++){
x = 2.*M_PI*dsfmt_genrand_close_open(&dsfmt);
y = sqrt(-2.*log(dsfmt_genrand_close_open(&dsfmt)));
r[i][j] = (cos(x) + I*sin(x))*y;
}
}
return;
}