gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 00:45:49 27 4
gpt4 key购买 nike

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

%%cython -a
import numpy as np
cimport numpy as np
cimport cython
from libc.math cimport exp, pi

@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):
"""Simple normalized 2D gaussian function for rendering"""
# for this model, x and y are seperable, so we can generate
# two gaussians and take the outer product
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

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

def gauss(yw, xw, y0, x0, sy, sx):
return _gauss(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:
...

然后编译失败,因为第一行和第三行 cdef 行与 python 解释器交互,我不确定为什么(尤其是第一行)。

最佳答案

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

一种选择是仅在函数内释放 GIL。这可以使用可放置在迭代代码周围的 with nogil: block 来完成。该函数如下所示:

@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 数组。这样,内存就不会在函数本身内分配。使用这种方法,_gauss 可以声明为 cdef nogil

如果您确实担心为 numpy 数组分配内存的开销,您可以尝试使用 C 风格的函数,例如 malloccalloc reallocfree 来管理内存。然后可以将该指针强制转换为适当的类型化内存 View ;但是,这样做将在创建所述内存 View 时调用 gil。

关于python - Cython 不使用 python 为数组分配内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56997610/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com