Cython不使用python为数组分配内存

Cython不使用python为数组分配内存,python,cython,Python,Cython,我正在尝试对一个简单函数进行Cythonize,我希望能够使用nogil语句编译它。我(在jupyter笔记本中)拥有的是: %%cython-a 将numpy作为np导入 cimport numpy作为np 西姆波特赛顿酒店 来自libc.math cimport exp,pi @cython.boundscheck(错误) @cython.wrapparound(假) @cython.cdivision(真) cdef double[:,::1]_gauss(Py_-ssize_-t-yw,

我正在尝试对一个简单函数进行Cythonize,我希望能够使用
nogil
语句编译它。我(在jupyter笔记本中)拥有的是:

%%cython-a
将numpy作为np导入
cimport numpy作为np
西姆波特赛顿酒店
来自libc.math cimport exp,pi
@cython.boundscheck(错误)
@cython.wrapparound(假)
@cython.cdivision(真)
cdef double[:,::1]_gauss(Py_-ssize_-t-yw,Py_-ssize_-t-xw,double-y0,double-x0,double-sy,double-sx):
“”“用于渲染的简单规格化二维高斯函数”“”
#对于这个模型,x和y是分开的,所以我们可以生成
#两个高斯数,取外积
cdef双放大器=1/(2*pi*sy*sx)
cdefdouble[:,::1]结果=np.empty((yw,xw),dtype=np.float64)
cdef Py_ssize_t x,y
对于范围内的y(yw):
对于范围内的x(xw):
结果[y,x]=exp(-(y-y0)/sy)**2/2-((x-x0)/sx)**2/2)*amp
返回结果
def高斯(yw,xw,y0,x0,sy,sx):
返回高斯(yw,xw,y0,x0,sy,sx)
这很好。如果我将第一行
cdef
更改为:

...
cdef double[:, ::1] _gauss(Py_ssize_t yw, Py_ssize_t xw, double y0, double x0, double sy, double sx) nogil:
...

然后编译失败,因为第一行和第三行与python解释器交互,我不知道为什么(特别是第一行)。

创建类型化memoryview对象会导致与GIL交互,因为它是python对象。因此,您将无法从
cdef nogil函数返回新类型的memoryview对象。
但是,有几种方法可以通过GIL绕过此限制

一种选择是只在函数中释放GIL。这可以通过在迭代代码周围放置一个带有nogil:的
块来完成。该函数如下所示:

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
cdef double[:, ::1] _gauss(Py_ssize_t yw, Py_ssize_t xw, double y0, double x0, double sy, double sx):
    #Do gil-interacting, python stuff here
    cdef double amp = 1 / (2 * pi * sy * sx)
    cdef double[:, ::1] result = np.empty((yw, xw), dtype=np.float64)
    cdef Py_ssize_t x, y

    with nogil:
        #And now basically write C code
        for y in range(yw):
            for x in range(xw):
                result[y, x] = exp(-((y - y0) / sy) ** 2 / 2 - ((x - x0) / sx) ** 2 / 2) * amp
    return result
另一个选项是让用户在类型为
double[:,::1]
的numpy数组中传递。这样,就不会在函数本身中分配内存。使用这种方法,
\u gauss
可以被声明为
cdef nogil

如果您确实担心为numpy数组分配内存的开销,可以尝试使用C风格的函数,如
malloc
calloc
realloc
、和
free
来管理内存。然后,可以将该指针转换为适当的类型化memoryview;然而,这样做将在创建上述memoryview时调用gil