Python 3.7-Dokumentation
Ich möchte auch das folgende Zitat aus der Python- threadingDokumentation hervorheben :
Details zur CPython-Implementierung: In CPython kann aufgrund der globalen Interpreter-Sperre nur ein Thread Python-Code gleichzeitig ausführen (obwohl bestimmte leistungsorientierte Bibliotheken diese Einschränkung möglicherweise überwinden). Wenn Sie möchten, dass Ihre Anwendung die Rechenressourcen von Mehrkernmaschinen besser nutzt, wird empfohlen, multiprocessingoder zu verwenden concurrent.futures.ProcessPoolExecutor. Threading ist jedoch immer noch ein geeignetes Modell, wenn Sie mehrere E / A-gebundene Aufgaben gleichzeitig ausführen möchten.
Dieser Link verweist auf den Glossareintrag, inglobal interpreter lock dem erklärt wird, dass die GIL impliziert, dass Thread-Parallelität in Python für CPU-gebundene Aufgaben ungeeignet ist :
Der Mechanismus, der vom CPython-Interpreter verwendet wird, um sicherzustellen, dass jeweils nur ein Thread Python-Bytecode ausführt. Dies vereinfacht die CPython-Implementierung, indem das Objektmodell (einschließlich kritischer integrierter Typen wie dict) implizit vor gleichzeitigem Zugriff geschützt wird. Das Sperren des gesamten Interpreters erleichtert das Multithreading des Interpreters auf Kosten eines Großteils der Parallelität, die Multiprozessor-Maschinen bieten.
Einige Erweiterungsmodule, entweder Standardmodule oder Module von Drittanbietern, sind jedoch so konzipiert, dass sie die GIL freigeben, wenn rechenintensive Aufgaben wie Komprimierung oder Hashing ausgeführt werden. Außerdem wird die GIL immer freigegeben, wenn E / A ausgeführt wird.
Frühere Bemühungen, einen "Free-Threaded" -Interpreter zu erstellen (der gemeinsam genutzte Daten mit einer viel feineren Granularität sperrt), waren nicht erfolgreich, da die Leistung im Fall eines herkömmlichen Einzelprozessors darunter litt. Es wird angenommen, dass die Überwindung dieses Leistungsproblems die Implementierung viel komplizierter und daher kostspieliger in der Wartung machen würde.
Dieses Zitat impliziert auch, dass Dikte und damit die Variablenzuweisung als CPython-Implementierungsdetail auch threadsicher sind:
Als Nächstes wird in den Dokumenten für das multiprocessingPaket erläutert, wie die GIL durch den Spawning-Prozess überwunden wird, während eine Schnittstelle verfügbar gemacht wird, die der threadingfolgenden ähnelt :
Multiprocessing ist ein Paket, das Spawning-Prozesse mithilfe einer API unterstützt, die dem Threading-Modul ähnelt. Das Multiprocessing-Paket bietet sowohl lokale als auch Remote-Parallelität und umgeht die globale Interpreter-Sperre effektiv, indem Subprozesse anstelle von Threads verwendet werden. Aus diesem Grund ermöglicht das Multiprozessor-Modul dem Programmierer, mehrere Prozessoren auf einer bestimmten Maschine vollständig zu nutzen. Es läuft sowohl unter Unix als auch unter Windows.
Und die Dokumente fürconcurrent.futures.ProcessPoolExecutor erklären, dass es multiprocessingals Backend verwendet:
Die ProcessPoolExecutor-Klasse ist eine Executor-Unterklasse, die einen Pool von Prozessen verwendet, um Aufrufe asynchron auszuführen. ProcessPoolExecutor verwendet das Multiprocessing-Modul, mit dem die globale Interpreter-Sperre umgangen werden kann, aber auch, dass nur auswählbare Objekte ausgeführt und zurückgegeben werden können.
Dies sollte im Gegensatz zu der anderen Basisklasse stehen ThreadPoolExecutor, die Threads anstelle von Prozessen verwendet
ThreadPoolExecutor ist eine Executor-Unterklasse, die einen Pool von Threads verwendet, um Aufrufe asynchron auszuführen.
Daraus schließen wir, dass dies ThreadPoolExecutornur für E / A-gebundene Aufgaben geeignet ist, während ProcessPoolExecutores auch CPU-gebundene Aufgaben verarbeiten kann.
Die folgende Frage fragt, warum die GIL überhaupt existiert: Warum die globale Interpretersperre?
Prozess gegen Thread-Experimente
Bei Multiprocessing vs Threading Python habe ich eine experimentelle Analyse von Process vs Threads in Python durchgeführt.
Schnelle Vorschau der Ergebnisse:
