Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 238
Marco Lombardi Avatar asked Jun 16 '16 08:06

Marco Lombardi


1 Answers

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...
like image 58
DavidW Avatar answered Oct 13 '22 19:10

DavidW