waynemystir
waynemystir

Reputation: 343

Is it possible to use a Cython Extension Type in a nogil section?

I have created a Cython Extension Type and I would like to use it in a nogil context. But the compiler always throws an error. Here is a simple example of what I'm trying to do:

  1 # cython: language_level=3
  2 
  3 from cython.parallel import prange
  4 
  5 cdef class C1:
  6 
  7     cdef public:
  8         int val
  9 
 10     def __cinit__(self, value):
 11         self.val = value
 12 
 13 def iterate_C1():
 14 
 15     cdef int i
 16     cdef int N = 4
 17     cdef C1 c1_i
 18 
 19     # This compiles fine
 20     c1 = C1(4)
 21     print(f'c1.val={c1.val}')
 22 
 23     # But this doesn't
 24     with nogil:
 25         for i in prange(N):
 26             c1_i = C1(i)

I get a number of exceptions but they all look like this:

Compiling c_one.pyx because it changed.
[1/1] Cythonizing c_one.pyx

Error compiling Cython file:
------------------------------------------------------------
...
    print(f'c1.val={c1.val}')

    # But this doesn't
    with nogil:
        for i in prange(N):
            c1_i = C1(i)
           ^
------------------------------------------------------------

c_one.pyx:26:12: Assignment of Python object not allowed without gil

Error compiling Cython file:
------------------------------------------------------------
...
    print(f'c1.val={c1.val}')

    # But this doesn't
    with nogil:
        for i in prange(N):
            c1_i = C1(i)
                    ^
------------------------------------------------------------

c_one.pyx:26:21: Calling gil-requiring function not allowed without gil

So is it not possible to use Cython Extension Types in a nogil context?

Upvotes: 0

Views: 627

Answers (1)

DavidW
DavidW

Reputation: 30889

You definitely cannot create instances of cdef extension types inside a nogil block. They are ultimately Python objects and that requires reference counting (including in some non-obvious places, such as the type object), allocation of Python-managed memory, and deallocation of the previous contents of ci, including calling its destructor.

You should be able to access their cdef members (e.g. val for this class) and call their cdef functions that are marked as nogil.

Upvotes: 2

Related Questions