在 cython 中使用 nogil 和 cpdef class 方法
Using nogil with cpdef class method in cython
我想设计一个cdef class,其方法可以运行并行,因此我需要将它们设置为nogil
。我看到我可以对 cdef
方法执行此操作,但出于某种原因我无法理解我不允许对 cpdef
方法执行相同的操作。这尤其失败
cdef class Test:
cdef int i
def __init__(self):
self.i = 0
cpdef int incr(self) nogil:
self.i += 1;
return self.i
虽然与 cdef int incr
相同也可以。这有点令人惊讶,因为在正常的 cpdef
函数中 nogil
属性是允许的:
cpdef int testfunc(int x) nogil:
return x + 1
我是不是遗漏了什么或者做错了什么?
如果您查看生成的 C 代码(省略 nogil
),您会发现该方法所做的第一件事是检查它是否已被 Python 子程序覆盖class。这需要 GIL。
(请注意,cdef
函数不会发生这种情况,因为 Python 永远不知道它,所以这里没有问题。)
幸运的是,很容易让你的 Cython class 无法被子classed 并且问题消失了(它可以用 nogil
编译):
cimport cython
@cython.final
cdef class Test:
# the rest of your code is exactly the same so isn't reproduced...
我想设计一个cdef class,其方法可以运行并行,因此我需要将它们设置为nogil
。我看到我可以对 cdef
方法执行此操作,但出于某种原因我无法理解我不允许对 cpdef
方法执行相同的操作。这尤其失败
cdef class Test:
cdef int i
def __init__(self):
self.i = 0
cpdef int incr(self) nogil:
self.i += 1;
return self.i
虽然与 cdef int incr
相同也可以。这有点令人惊讶,因为在正常的 cpdef
函数中 nogil
属性是允许的:
cpdef int testfunc(int x) nogil:
return x + 1
我是不是遗漏了什么或者做错了什么?
如果您查看生成的 C 代码(省略 nogil
),您会发现该方法所做的第一件事是检查它是否已被 Python 子程序覆盖class。这需要 GIL。
(请注意,cdef
函数不会发生这种情况,因为 Python 永远不知道它,所以这里没有问题。)
幸运的是,很容易让你的 Cython class 无法被子classed 并且问题消失了(它可以用 nogil
编译):
cimport cython
@cython.final
cdef class Test:
# the rest of your code is exactly the same so isn't reproduced...