Le verrou d'interprète global (GIL) semble être souvent cité comme l'une des principales raisons pour lesquelles enfiler des objets, entre autres, est un problème délicat en Python - ce qui soulève la question "Pourquoi cela a-t-il été fait?"
Étant pas un programmeur, je ne sais pas pourquoi cela pourrait être - quelle était la logique derrière la mise en place du GIL?
python
multithreading
Fomite
la source
la source
Réponses:
Il existe plusieurs implémentations de Python, par exemple, CPython, IronPython, RPython, etc.
Certains d'entre eux ont un GIL, d'autres non. Par exemple, CPython a le GIL:
De http://en.wikipedia.org/wiki/Global_Interpreter_Lock
Les applications écrites dans des langages de programmation avec GIL peuvent être conçues pour utiliser des processus distincts pour obtenir un parallélisme complet, chaque processus ayant son propre interpréteur et à son tour son propre GIL.
Avantages du GIL
Pourquoi Python (CPython et autres) utilise le GIL
Dans CPython, le verrou d'interpréteur global, ou GIL, est un mutex qui empêche plusieurs threads natifs d'exécuter en même temps des bytecodes Python. Ce verrou est nécessaire principalement parce que la gestion de la mémoire de CPython n'est pas thread-safe.
La GIL est controversée car elle empêche les programmes CPython multithreads de tirer pleinement parti des systèmes multiprocesseurs dans certaines situations. Notez que les opérations potentiellement bloquantes ou de longue durée, telles que les E / S, le traitement des images et la réduction du nombre de numéros NumPy, se produisent en dehors de la liste GIL. Par conséquent, ce n'est que dans les programmes multithreads qui passent beaucoup de temps dans GIL, interprétant le bytecode CPython, que GIL devient un goulot d'étranglement.
Python a un code GIL par opposition à un verrouillage à grain fin pour plusieurs raisons:
C'est plus rapide dans le cas des threads simples.
C'est plus rapide dans le cas multithread pour les programmes liés d'E / S.
Il est plus rapide dans le cas multithread des programmes liés à l'unité centrale qui effectuent leur travail de calcul intensif dans les bibliothèques C.
Cela facilite l’écriture des extensions C: il n’y aura pas de changement de threads Python, sauf si vous le permettez (c’est-à-dire entre les macros Py_BEGIN_ALLOW_THREADS et Py_END_ALLOW_THREADS).
Cela facilite l’emballage des bibliothèques C. Vous n'avez pas à vous soucier de la sécurité du fil. Si la bibliothèque n’est pas thread-safe, vous devez simplement verrouiller la GIL pendant que vous l’appelez.
Le GIL peut être publié par les extensions C. La bibliothèque standard de Python libère le GIL autour de chaque appel d'E / S bloquant. Ainsi, le GIL n'a aucune conséquence sur les performances des serveurs liés d'E / S. Vous pouvez ainsi créer des serveurs de réseau en Python à l'aide de processus (fork), de threads ou d'entrées / sorties asynchrones. GIL ne vous gênera pas.
Les bibliothèques numériques en C ou en Fortran peuvent également être appelées avec la version GIL publiée. Pendant que votre extension C attend la fin d'une FFT, l'interpréteur exécutera d'autres threads Python. Un GIL est donc plus facile et plus rapide qu'un verrouillage fin dans ce cas également. Ceci constitue l'essentiel du travail numérique. L'extension NumPy libère le GIL chaque fois que possible.
Les threads sont généralement un mauvais moyen d'écrire la plupart des programmes serveur. Si la charge est faible, le forgeage est plus facile. Si la charge est élevée, la programmation asynchrone des entrées / sorties et des événements (par exemple, à l'aide de la structure Twisted de Python) est préférable. La seule excuse pour utiliser des threads est le manque de os.fork sous Windows.
La GIL pose un problème si, et seulement si, vous effectuez un travail gourmand en ressources processeur en Python pur. Ici, vous pouvez obtenir une conception plus propre en utilisant des processus et la transmission de messages (par exemple, mpi4py). Il existe également un module de «traitement» dans la fromagerie Python, qui donne aux processus la même interface que les threads (c'est-à-dire, remplacez threading.Thread par processing.Process).
Les threads peuvent être utilisés pour maintenir la réactivité d'une interface graphique indépendamment de la GIL. Si le GIL altère votre performance (voir la discussion ci-dessus), vous pouvez laisser votre thread générer un processus et attendre qu'il se termine.
la source
s/RPython/PyPy/g
. @MichaelBorgwardt Donner des raisons pour GIL est un peu le but de la question, n'est-ce pas? Bien que je sois d’accord, une partie du contenu de cette réponse (à savoir une discussion sur les alternatives) n’est pas pertinente. Et pour le meilleur ou pour le pire, il est maintenant presque impossible de se débarrasser du recomptage - il est profondément enraciné dans l'ensemble de l'API et de la base de code; il est presque impossible de s'en débarrasser sans réécrire la moitié du code et casser tout le code externe.multiprocessing
bibliothèque - standard depuis 2.6. Ses pools de travailleurs sont une abstraction ultra-lisse pour certains types simples de parallélisme.Tout d'abord: Python n'a pas de GIL. Python est un langage de programmation. Un langage de programmation est un ensemble de règles et de restrictions mathématiques abstraites. Il n'y a rien dans la spécification du langage Python qui indique qu'il doit y avoir un GIL.
Il existe de nombreuses implémentations différentes de Python. Certains ont un GIL, d'autres non.
Une explication simple pour avoir un GIL est qu'il est difficile d'écrire du code simultané. En plaçant un verrou géant autour de votre code, vous le forcez à toujours fonctionner en série. Problème résolu!
Dans CPython, en particulier, un objectif important est de faciliter l’extension de l’interprète avec des plugins écrits en C. Une fois encore, l’écriture de code simultané est difficile; ainsi, en garantissant qu’il n’y aura pas d’accès simultané, il sera plus facile l'interprète. De plus, beaucoup de ces extensions ne sont que des maigres enveloppants autour de bibliothèques existantes qui n’ont peut-être pas été écrites avec l’accès simultané à l’esprit.
la source
Quel est le but d'un GIL?
La documentation CAPI dit ceci à ce sujet:
En d'autres termes, le GIL prévient la corruption d'État. Les programmes Python ne doivent jamais générer d'erreur de segmentation, car seules les opérations sécurisées pour la mémoire sont autorisées. Le GIL étend cette assurance aux programmes multithreads.
Quelles sont les alternatives?
Si le but du GIL est de protéger l’État de la corruption, une alternative évidente consiste à verrouiller le grain beaucoup plus fin; peut-être au niveau de chaque objet. Le problème, c’est que, même s’il a été prouvé que les programmes multithreads permettaient d’accroître les performances, il en résultait plus de frais généraux et que les programmes mono-thread en souffraient.
la source