2010-05-13 8 views
3

L'interpréteur Python possède un verrou Global Interpreter, et je crois comprendre que les extensions doivent l'acquérir dans un environnement multithread. Mais Boost.Python HOWTO page dit que la fonction d'extension doit libérer le GIL et le réacquérir à la sortie.Explication des extensions Python multithreading

Je veux résister à la tentation de deviner ici, donc je voudrais savoir ce qui devrait être GIL modèles de verrouillage dans les scénarios suivants:

  1. Extension est appelé à partir de Python (en cours d'exécution vraisemblablement dans un thread python).
  2. Et le thread d'arrière-plan de l'extension rappelle les fonctions Py_*.

Et une dernière question est, pourquoi le document lié dit que le GIL devrait être libéré et ré-acquis?

Répondre

4

Chaque fois que Python interprète un bytecode, le GIL est maintenu par le thread en cours d'exécution. Aucun autre thread Python ne peut fonctionner avant d'avoir réussi à acquérir le GIL.

Lorsque l'interprète a appelé en code natif que le code a deux options concernant le GIL:

  1. Il ne pouvait rien faire du tout.
  2. Il pourrait libérer le GIL pendant qu'il fonctionne et réacquérir avant de retourner à Python

Si le code natif fait beaucoup d'appels vers l'exécution de Python, il devrait prendre l'option 1: vous ne pouvez jamais appeler l'exécution de Python en toute sécurité sauf si vous détenez le GIL (à quelques exceptions près, comme faire l'appel pour acquérir le GIL si vous ne l'avez pas). Si le code natif fait beaucoup de travail qui n'implique Python en aucune façon, alors vous pouvez utiliser l'option 2: dès que vous libérerez le GIL Python sera en mesure de planifier un autre thread Python afin d'obtenir un certain parallélisme . Si vous ne libérez pas le GIL, aucun des autres threads de Python ne peut s'exécuter tant que votre code Boost est en cours d'exécution: c'est pourquoi les docs vous demandent de libérer et réacquérir le GIL.

Si vous allez de cette façon, vous devez faire attention à avoir accès à toutes les fonctions Py_* avant de libérer le GIL ou après l'avoir réacquise. Cela peut signifier que vous devez effectuer des copies locales de données car vous ne pouvez pas accéder en toute sécurité aux types de données Python tels que les éléments de liste ou de dictionnaire pendant la publication du GIL.

Si votre code Boost doit rappeler en Python alors que le GIL est libéré, vous devez acquérir le GIL, passer l'appel, libérer le GIL. Essayez d'éviter de faire de tels appels à partir de threads qui n'ont pas été créés par Python car ils ont besoin d'un travail supplémentaire pour pouvoir acquérir le GIL.

+0

Merci, cela éclaircit les choses. Cependant, une dernière chose doit être clarifiée: lorsque le code Python appelle en code d'extension natif, il peut choisir de libérer le GIL. Mais la callstack, lors de l'appel en code natif, contient des appels aux fonctions Python comme 'PyObject_CallFunction',' PyObject_Call'. Pourquoi est-il sûr de libérer GIL dans le cadre de ces fonctions? –

+0

Ces fonctions ne "font" rien jusqu'à ce que la pile soit déroulée et qu'elles soient "renvoyées". À ce moment-là, vous devriez avoir acquis de nouveau le GIL pour pouvoir travailler. –