2017-03-13 1 views
2

J'ai une classe C++ avec des méthodes qui utilisent std :: thread que je rends accessible à Python via Cython. Savez-vous où dans mon code Cython je voudrais mettre la directive nogill? Voudrais-je le mettre quand je déclare les méthodes de classe ou quand je crée une classe de wrapper de Cython? Je l'ai utilisé la classe par exemple des cython docs ci-dessous:Comment libérer le GIL dans Cython pour une classe C++ multithread?

Déclarer la classe:

cdef extern from "Rectangle.h" namespace "shapes": 
    cdef cppclass Rectangle: 
     Rectangle() except + 
     Rectangle(int, int, int, int) except + 
     int x0, y0, x1, y1 
     int getArea() 
     void getSize(int* width, int* height) 
     void move(int, int) 

Cython classe wrapper:

cdef class PyRectangle: 
    cdef Rectangle c_rect  # hold a C++ instance which we're wrapping 
    def __cinit__(self, int x0, int y0, int x1, int y1): 
     self.c_rect = Rectangle(x0, y0, x1, y1) 
    def get_area(self): 
     return self.c_rect.getArea() 
    def get_size(self): 
     cdef int width, height 
     self.c_rect.getSize(&width, &height) 
     return width, height 
    def move(self, dx, dy): 
     self.c_rect.move(dx, dy) 

Répondre

3

Vous n'avez probablement pas vraiment besoin d'utiliser nogil. Le GIL n'arrête que plusieurs threads Python s'exécutant de manière simulante. Cependant, étant donné que vous utilisez des threads C++, ils peuvent très bien fonctionner en arrière-plan indépendamment du GIL, à condition qu'ils n'essaient pas d'utiliser PyObject ou d'exécuter du code Python. Donc, je soupçonne que vous avez mal compris le GIL et vous pouvez vous en sortir sans y penser.

Cependant, en supposant que vous ne voulez vraiment libérer, vous devez faire 2 choses:

  1. Mark les fonctions C++ comme nogil de dire Cython qu'ils ne ont pas besoin du GIL. Notez que cela ne libère pas réellement - il laisse juste Cython sais que ce n'est pas un problème si elle est libérée:

    cdef cppclass Rectange: 
        Rectangle(int, int, int, int) nogil except + 
        int getArea() nogil 
        # ... 
    
  2. Utilisez with nogil: blocs dans votre classe wrapper Cython pour marquer les zones où la GIL est réellement libéré.

    cdef class PyRectangle: 
        # ... 
        def __cinit__(self, int x0, int y0, int x1, int y1): 
         with nogil: 
          self.c_rect = Rectangle(x0, y0, x1, y1) 
        def get_area(self): 
         cdef int result 
         with nogil: 
          result = self.c_rect.getArea() 
         return result 
    

    get_area devient un peu plus compliquée, car la déclaration de retour ne peut exister à l'intérieur du bloc with nogil puisqu'il consiste à générer un objet Python.