Frage

Was ist ein globales Dolmetscherschloss und warum ist es ein Problem?

Es wurde viel Lärm gemacht, um die Gil aus Python zu entfernen, und ich würde gerne verstehen, warum das so wichtig ist. Ich habe noch nie einen Compiler oder selbst einen Dolmetscher geschrieben. Seien Sie also nicht sparsam mit Details, ich muss sie wahrscheinlich verstehen.

War es hilfreich?

Lösung

Pythons GIL soll den Zugriff auf Interpreter -Interna aus verschiedenen Fäden serialisieren. Auf Multi-Core-Systemen bedeutet dies, dass mehrere Threads nicht mehreren Kerne effektiv verwenden können. (Wenn der GIL nicht zu diesem Problem geführt hätte, würde sich die meisten Menschen nicht um den Gil kümmern - es wird nur aufgrund der zunehmenden Prävalenz von Multi -Core -Systemen als Problem angesprochen.) Wenn Sie es im Detail verstehen möchten, Sie können anzeigen Dieses Video oder schauen Sie sich an Dieser Satz von Folien. Es könnte zu viele Informationen sein, aber dann haben Sie nach Details gefragt :-)

Beachten Sie, dass Pythons GIL nur ein Problem für CPython ist, der Referenzimplementierung. Jython und Ironpython haben keinen Gil. Als Python -Entwickler stoßen Sie im Allgemeinen nicht auf den GIL, es sei denn, Sie schreiben eine C -Erweiterung. C -Erweiterungsautoren müssen die GIL freigeben, wenn ihre Erweiterungen I/O blockieren, so dass andere Fäden im Python -Prozess die Chance haben, zu laufen.

Andere Tipps

Angenommen, Sie haben mehrere Threads, die dies nicht tun Ja wirklich Berühren Sie die Daten des anderen. Diese sollten so unabhängig wie möglich ausgeführt werden. Wenn Sie ein "globales Schloss" haben, das Sie erwerben müssen, um eine Funktion aufzurufen, kann dies als Engpass enden. Sie können nicht viel davon von mehreren Fäden profitieren.

Um es in eine reale Analogie zu bringen: Stellen Sie sich 100 Entwickler vor, die in einem Unternehmen mit nur einer einzigen Kaffeetasse arbeiten. Die meisten Entwickler verbringen ihre Zeit damit, auf Kaffee zu warten, anstatt auf Kaffee zu kodieren.

Nichts davon ist pythonspezifisch - ich weiß nicht die Details dessen, wofür Python in erster Linie einen Gil brauchte. Hoffentlich hat es Ihnen jedoch eine bessere Vorstellung vom allgemeinen Konzept gegeben.

Lassen Sie uns zunächst verstehen, was der Python Gil bietet:

Jede Operation/Anweisung wird im Dolmetscher ausgeführt. Gil stellt sicher, dass der Dolmetscher von einem einzigen Faden bei gehalten wird ein bestimmter Zeitpunkt. Und Ihr Python -Programm mit mehreren Threads funktioniert in einem einzigen Dolmetscher. Zu einem bestimmten Zeitpunkt wird dieser Dolmetscher von einem einzigen Thread gehalten. Es bedeutet, dass nur der Faden, der den Dolmetscher hält laufend bei Zeitall sofort.

Warum ist das ein Problem:

Ihre Maschine hat möglicherweise mehrere Kerne/Prozessoren. Und mehrere Kerne ermöglichen es mehreren Threads auszuführen gleichzeitig dh mehrere Threads könnten ausgeführt werden zu einem bestimmten Zeitpunkt.. Da der Dolmetscher jedoch von einem einzigen Thread gehalten wird, tun andere Threads nichts, obwohl sie Zugriff auf einen Kern haben. Sie erhalten also keinen Vorteil von mehreren Kernen, da zu jedem Zeitpunkt nur ein einzelner Kern verwendet wird, der der Kern ist, der vom Thread verwendet wird, der derzeit den Dolmetscher hält, verwendet wird. Daher dauert Ihr Programm so lange, wie es ein einzelnes Thread -Programm wäre.

Potenziell blockierende oder langlebige Operationen wie E/A, Bildverarbeitung und Numpy-Nummer knirschen außerhalb des Gils. Genommen von hier. Für solche Operationen ist ein Multithread -Betrieb trotz der Anwesenheit von GIL immer noch schneller als ein einzelner Gewindeoperation. Gil ist also nicht immer ein Engpass.

Bearbeiten: Gil ist ein Implementierungsdetail von CPython. Ironpython und Jython haben Gil nicht, daher sollte ein wirklich multitHhread -Programm in ihnen möglich sein, dachte, ich hätte nie Pypy und Jython verwendet und sicher nicht sicher.

Python erlaubt Multi-Threading im wahrsten Sinne des Wortes nicht. Es verfügt über ein Multi-Threading-Paket, aber wenn Sie Multi-Thread dazu möchten, Ihren Code zu beschleunigen, ist es normalerweise keine gute Idee, ihn zu verwenden. Python hat ein Konstrukt namens Global Interpreter Lock (GIL).

https://www.youtube.com/watch?v=ph374fjqfpe

Der Gil stellt sicher, dass nur einer Ihrer "Threads" gleichzeitig ausgeführt wird. Ein Faden erwirbt den Gil, erledigt ein wenig Arbeit und übergibt dann den GIL auf den nächsten Faden. Dies geschieht sehr schnell, so dass es für das menschliche Auge so aussieht, als würden Ihre Fäden parallel ausgeführt, aber sie wechseln sich wirklich nur mit demselben CPU -Kern ab. All dieser Gil -Passing fügt der Ausführung einen Overhead hinzu. Dies bedeutet, dass es keine gute Idee ist, wenn Sie Ihren Code schneller ausführen möchten, dann ist es häufig keine gute Idee.

Es gibt Gründe, Pythons Threading -Paket zu verwenden. Wenn Sie einige Dinge gleichzeitig ausführen möchten und Effizienz kein Problem ist, ist dies völlig in Ordnung und bequem. Oder wenn Sie Code ausführen, der auf etwas warten muss (wie ein IO), könnte es viel Sinn machen. Mit der Threading -Bibliothek können Sie jedoch zusätzliche CPU -Kerne verwenden.

Multi-Threading kann an das Betriebssystem (durch Multi-Verarbeitung), eine externe Anwendung ausgelagert werden, die Ihren Python-Code (z. Code rufen Sie eine C-Funktion auf, die das teure Multi-Thread-Zeug ausübt).

Wenn zwei Themen Zugriff auf dieselbe Variable haben, haben Sie ein Problem. In C ++ besteht beispielsweise der Weg, um das Problem zu vermeiden, darin, eine Mutex -Sperre zu definieren, um zwei Threads gleichzeitig den Setter eines Objekts einzugeben.

Multithreading ist in Python möglich, aber zwei Threads können jedoch nicht gleichzeitig zu einer granularischen Körnung ausgeführt werden als eine Python -Anweisung. Der laufende Thread erhält ein globales Schloss namens GIL.

Wenn Sie mit dem Schreiben von Multithread -Code beginnen, um Ihren Multicore -Prozessor zu nutzen, verbessert sich Ihre Leistung nicht. Die übliche Problemumgehung besteht aus Multiprozess.

Beachten Sie, dass es möglich ist, die GIL zu veröffentlichen, wenn Sie sich in einer Methode in C in C geschrieben haben.

Die Verwendung eines GIL ist nicht Python innewohnt, sondern einem seiner Dolmetscher, einschließlich des häufigsten CPython. (#Edited, siehe Kommentar)

Die GIL -Ausgabe ist in Python 3000 immer noch gültig.

Python 3.7 Dokumentation

Ich möchte auch das folgende Zitat von der hervorheben Python threading Dokumentation:

CPython-Implementierungsdetail: In CPython kann aufgrund der globalen Interpreter-Sperre nur ein Thread gleichzeitig den Python-Code ausführen (obwohl bestimmte leistungsorientierte Bibliotheken diese Einschränkung überwinden könnten). Wenn Sie möchten, dass Ihre Anwendung die Rechenressourcen von Multi-Core-Maschinen besser nutzt, wird Ihnen empfohlen, die Verwendung zu verwenden multiprocessing oder concurrent.futures.ProcessPoolExecutor. Das Threading ist jedoch immer noch ein geeignetes Modell, wenn Sie mehrere E/O-gebundene Aufgaben gleichzeitig ausführen möchten.

Dies links zu dem Glossareintrag für global interpreter lock Das erklärt, dass der Gil impliziert, dass die Parallelität in Python mit Gewinde für die Gewinde für die Gewinde für die Gewinde ist für nicht geeignet CPU -gebundene Aufgaben:

Der vom CPython -Interpreter verwendete Mechanismus, um sicherzustellen, dass nur ein Thread Python -Bytecode gleichzeitig ausführt. Dies vereinfacht die CPython-Implementierung, indem das Objektmodell (einschließlich kritischer integrierter Typen wie DICT) implizit vor dem gleichzeitigen Zugriff sicher ist. Wenn Sie den gesamten Dolmetscher sperren, erleichtert es dem Dolmetscher, auf Kosten eines Großteils der Parallelität, die von Multi-Proprozessoren-Maschinen gewährt wird, multi-threades zu erleichtern.

Einige Erweiterungsmodule, entweder Standard oder Drittanbieter, sind jedoch so konzipiert, dass die GIL bei rechnerischintensiven Aufgaben wie Komprimierung oder Hashing freigegeben werden. Außerdem wird der Gil immer freigelassen, wenn er I/O macht.

Vergangene Bemühungen, einen „freien“ Dolmetscher zu schaffen (einer, der gemeinsame Daten mit viel feinerer Granularität sperrt), waren nicht erfolgreich, da die Leistung im Fall eines Einzelprozessors erlitten hat. Es wird angenommen, dass die Überwindung dieses Leistungsproblems die Implementierung viel komplizierter und kostspieliger machen würde.

Dieses Zitat impliziert auch, dass Diktate und somit variable Zuordnung auch als CPython -Implementierungsdetail sicher sind:

Als nächstes die Dokumente für die multiprocessing Paket Erklären Sie, wie es den GIL überwindet, indem er den Laichprozess lasiert und gleichzeitig eine Schnittstelle enthält, die der von ähnlich ist threading:

Multiprocessing ist ein Paket, das Laichprozesse unter Verwendung einer API ähnlich dem Threading -Modul unterstützt. Das Multiprocessing-Paket bietet sowohl eine lokale als auch die Fernzugesetzung und setzt das globale Interpreter-Sperre effektiv mit Subprozessen anstelle von Threads ein. Aus diesem Grund ermöglicht das Multiprocessing -Modul dem Programmierer, mehrere Prozessoren auf einer bestimmten Maschine vollständig zu nutzen. Es läuft sowohl auf Unix als auch auf Windows.

Und die Dokumente für concurrent.futures.ProcessPoolExecutor Erklären Sie, dass es verwendet wird multiprocessing als Backend:

Die ProcessPoolexecutor -Klasse ist eine Subklasse ausführender, die einen Prozesspool verwendet, um Anrufe asynchron auszuführen. ProcessPoolexecutor verwendet das Multiprocessing-Modul, mit dem es das globale Interpreter-Sperre aufsteigen kann, aber auch bedeutet, dass nur aussagbare Objekte ausgeführt und zurückgegeben werden können.

das sollte der anderen Basisklasse kontrastiert werden ThreadPoolExecutor das Verwendet Threads anstelle von Prozessen

ThreadPoolexecutor ist eine Subklasse ausführender, die einen Pool von Threads verwendet, um Anrufe asynchron auszuführen.

aus dem wir das schließen ThreadPoolExecutor ist nur für E/A -gebundene Aufgaben geeignet ProcessPoolExecutor Kann auch CPU -gebundene Aufgaben erledigen.

In der folgenden Frage wird in erster Linie gefragt, warum der GIL existiert: Warum das Global Interpreter Lock?

Prozess gegen Thread -Experimente

Bei Multiprozessing gegen Python Ich habe eine experimentelle Analyse von Prozess gegen Threads in Python durchgeführt.

Schnelle Vorschau der Ergebnisse:

enter image description here

Warum Python (CPython und andere) den Gil verwendet

Aus http://wiki.python.org/moin/globalinterpreterlock

In CPython ist das Global Interpreter Lock oder GIL ein Mutex, der verhindert, dass mehrere native Threads gleichzeitig Python -Bytecodes ausführen. Diese Sperre ist vor allem, weil die Speicherverwaltung von CPython nicht mit Thread-Sicherheit ist.

Wie entferne ich es von Python?

Wie Lua könnte Python vielleicht mehrere VM starten, aber Python tut das nicht, ich denke, es sollte einige andere Gründe geben.

In Numpy oder einer anderen Python -erweiterten Bibliothek kann es manchmal die Effizienz des gesamten Programms steigern, wenn die GIL an andere Threads freigegeben wird.

Ich möchte ein Beispiel aus dem Buch Multithreading für visuelle Effekte teilen. Hier ist also eine klassische Situation für tote Schloss

static void MyCallback(const Context &context){
Auto<Lock> lock(GetMyMutexFromContext(context));
...
EvalMyPythonString(str); //A function that takes the GIL
...    
}

Betrachten Sie nun die Ereignisse in der Sequenz, die zu einem toten Lock führen.

╔═══╦════════════════════════════════════════╦══════════════════════════════════════╗
║   ║ Main Thread                            ║ Other Thread                         ║
╠═══╬════════════════════════════════════════╬══════════════════════════════════════╣
║ 1 ║ Python Command acquires GIL            ║ Work started                         ║
║ 2 ║ Computation requested                  ║ MyCallback runs and acquires MyMutex ║
║ 3 ║                                        ║ MyCallback now waits for GIL         ║
║ 4 ║ MyCallback runs and waits for MyMutex  ║ waiting for GIL                      ║
╚═══╩════════════════════════════════════════╩══════════════════════════════════════╝
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top