Marco Lombardi
Marco Lombardi

Reputation: 557

Using nogil with cpdef class method in cython

I want to design a cdef class whose methods can be run in parallel and therefore I need to set them as nogil. I see I can do this for cdef methods, but for some reason I cannot understand I am not allowed to do the same with cpdef methods. This in particular fails

cdef class Test:
    cdef int i
    def __init__(self):
        self.i = 0
    cpdef int incr(self) nogil:
        self.i += 1;
        return self.i

while the same with cdef int incr would work. This is somewhat surprising, because in normal cpdef functions the nogil attribute is allowed:

cpdef int testfunc(int x) nogil:
    return x + 1

Am I missing something or doing something wrong here?

Upvotes: 8

Views: 3946

Answers (1)

DavidW
DavidW

Reputation: 30917

If you look at the C code generated (omitting nogil) you'll see that the first thing the method does is check to see whether the it has been overridden by a Python subclass. This requires the GIL.

(Note that this can't happen for a cdef function since it is never known about by Python, so there is no issue there.)

Fortunately, it is easy to make it so that your Cython class cannot be subclassed and the problem goes away (it compiles fine with nogil):

cimport cython

@cython.final
cdef class Test:
    # the rest of your code is exactly the same so isn't reproduced...

Upvotes: 13

Related Questions