Python-Unterstützung für freies Threading¶
Ab der Version 3.13 unterstützt CPython eine Build-Variante von Python namens freies Threading, bei der der globale Interpreter-Lock (GIL) deaktiviert ist. Freies Threading ermöglicht die volle Auslastung der verfügbaren Rechenleistung durch paralleles Ausführen von Threads auf verfügbaren CPU-Kernen. Obwohl nicht jede Software automatisch davon profitiert, laufen Programme, die für Threading konzipiert sind, auf Multi-Core-Hardware schneller.
Der Modus für freies Threading funktioniert und wird ständig verbessert, birgt jedoch einen zusätzlichen Overhead bei Single-Thread-Workloads im Vergleich zum regulären Build. Darüber hinaus sind möglicherweise Drittanbieter-Pakete, insbesondere solche mit einem Erweiterungsmodul, noch nicht für die Verwendung in einem freiem Threading-Build bereit und reaktivieren den GIL.
Dieses Dokument beschreibt die Auswirkungen von freiem Threading auf Python-Code. Informationen zum Schreiben von C-Erweiterungen, die den Build mit freiem Threading unterstützen, finden Sie in C API-Erweiterungsunterstützung für freies Threading.
Siehe auch
PEP 703 – Making the Global Interpreter Lock Optional in CPython für eine allgemeine Beschreibung von freiem Threading Python.
Installation¶
Ab Python 3.13 unterstützen die offiziellen Installer für macOS und Windows optional die Installation von Python-Binärdateien mit freiem Threading. Die Installer sind unter https://pythonlang.de/downloads/ verfügbar.
Informationen für andere Plattformen finden Sie unter Installing a Free-Threaded Python, einem gemeinschaftlich gepflegten Installationsleitfaden für die Installation von Python mit freiem Threading.
Beim Erstellen von CPython aus dem Quellcode sollte die Konfigurationsoption --disable-gil verwendet werden, um einen Python-Interpreter mit freiem Threading zu erstellen.
Identifizieren von freiem Threading Python¶
Um zu überprüfen, ob der aktuelle Interpreter freies Threading unterstützt, enthalten python -VV und sys.version den Zusatz „free-threading build“. Die neue Funktion sys._is_gil_enabled() kann verwendet werden, um zu überprüfen, ob der GIL im laufenden Prozess tatsächlich deaktiviert ist.
Die Konfigurationsvariable sysconfig.get_config_var("Py_GIL_DISABLED") kann verwendet werden, um festzustellen, ob der Build freies Threading unterstützt. Wenn die Variable auf 1 gesetzt ist, unterstützt der Build freies Threading. Dies ist der empfohlene Mechanismus für Entscheidungen im Zusammenhang mit der Build-Konfiguration.
Der globale Interpreter-Lock im freiem Threading Python¶
Freie Threading-Builds von CPython unterstützen optional die Ausführung mit aktiviertem GIL zur Laufzeit über die Umgebungsvariable PYTHON_GIL oder die Kommandozeilenoption -X gil.
Der GIL kann auch automatisch aktiviert werden, wenn ein C-API-Erweiterungsmodul importiert wird, das nicht explizit als unterstützend für freies Threading gekennzeichnet ist. In diesem Fall wird eine Warnung ausgegeben.
Neben der Dokumentation einzelner Pakete verfolgen die folgenden Websites den Status der beliebten Pakete für freies Threading
Thread-Sicherheit¶
Der freie Threading-Build von CPython zielt darauf ab, auf Python-Ebene ein ähnliches Verhalten hinsichtlich der Thread-Sicherheit wie der standardmäßige GIL-aktivierte Build zu bieten. Integrierte Datentypen wie dict, list und set verwenden interne Sperren, um gleichzeitige Modifikationen zu verhindern, und verhalten sich dabei ähnlich wie der GIL. Python hat jedoch historisch keine spezifischen Verhaltensgarantien für gleichzeitige Modifikationen dieser integrierten Datentypen gegeben, daher sollte dies als Beschreibung der aktuellen Implementierung und nicht als Garantie für aktuelles oder zukünftiges Verhalten behandelt werden.
Hinweis
Es wird empfohlen, nach Möglichkeit threading.Lock oder andere Synchronisationsprimitive zu verwenden, anstatt sich auf die internen Sperren integrierter Datentypen zu verlassen.
Bekannte Einschränkungen¶
Dieser Abschnitt beschreibt bekannte Einschränkungen des CPython-Builds mit freiem Threading.
Unsterblichkeit¶
Der freie Threading-Build der Version 3.13 macht einige Objekte unsterblich. Unsterbliche Objekte werden nicht freigegeben und ihre Referenzzähler werden nie geändert. Dies geschieht, um eine Überlastung der Referenzzähler zu vermeiden, die eine effiziente Skalierung für Multithreading verhindern würde.
Ein Objekt wird unsterblich, wenn ein neuer Thread zum ersten Mal gestartet wird, nachdem der Hauptthread bereits läuft. Die folgenden Objekte werden unsterblich gemacht:
Funktionsobjekte, die auf Modulebene deklariert sind
Methoden-Deskriptoren
Codeobjekte
Modulobjekte und ihre Wörterbücher
Klassen (Typpobjekte)
Da unsterbliche Objekte nie freigegeben werden, können Anwendungen, die viele Objekte dieser Typen erstellen, einen erhöhten Speicherverbrauch aufweisen. Es wird erwartet, dass dies in der Version 3.14 behoben wird.
Zusätzlich werden numerische und Zeichenkettenliterale im Code sowie Zeichenketten, die von sys.intern() zurückgegeben werden, ebenfalls unsterblich gemacht. Dieses Verhalten wird voraussichtlich auch in der freie Threading-Build-Version 3.14 beibehalten.
Frame-Objekte¶
Es ist nicht sicher, Frame-Objekte von anderen Threads aus zuzugreifen, da dies zu einem Absturz Ihres Programms führen kann. Das bedeutet, dass sys._current_frames() in einem freie Threading-Build im Allgemeinen nicht sicher verwendet werden kann. Funktionen wie inspect.currentframe() und sys._getframe() sind im Allgemeinen sicher, solange das resultierende Frame-Objekt nicht an einen anderen Thread übergeben wird.
Iteratoren¶
Das Teilen desselben Iterator-Objekts zwischen mehreren Threads ist im Allgemeinen nicht sicher, und Threads können beim Iterieren doppelte oder fehlende Elemente sehen oder den Interpreter zum Absturz bringen.
Single-Thread-Performance¶
Der freie Threading-Build hat zusätzlichen Overhead bei der Ausführung von Python-Code im Vergleich zum standardmäßigen GIL-aktivierten Build. In 3.13 beträgt dieser Overhead auf der pyperformance-Suite etwa 40 %. Programme, die die meiste Zeit in C-Erweiterungen oder I/O verbringen, werden weniger beeinträchtigt. Die größte Auswirkung liegt darin, dass der spezialisierende adaptive Interpreter (PEP 659) im freie Threading-Build deaktiviert ist. Wir erwarten, ihn in der Version 3.14 auf eine thread-sichere Weise wieder zu aktivieren. Dieser Overhead wird voraussichtlich in zukünftigen Python-Versionen reduziert. Wir streben einen Overhead von 10 % oder weniger auf der pyperformance-Suite im Vergleich zum standardmäßigen GIL-aktivierten Build an.
Verhaltensänderungen¶
Dieser Abschnitt beschreibt Verhaltensänderungen von CPython mit dem freie Threading-Build.
Kontextvariablen¶
Im freie Threading-Build ist das Flag thread_inherit_context standardmäßig auf true gesetzt, was dazu führt, dass Threads, die mit threading.Thread erstellt werden, mit einer Kopie des Context() des Aufrufers von start() beginnen. Im standardmäßigen GIL-aktivierten Build ist das Flag standardmäßig false, sodass Threads mit einem leeren Context() beginnen.
Warnungsfilter¶
Im freie Threading-Build ist das Flag context_aware_warnings standardmäßig auf true gesetzt. Im standardmäßigen GIL-aktivierten Build ist das Flag standardmäßig false. Wenn das Flag true ist, verwendet der Kontextmanager warnings.catch_warnings eine Kontextvariable für Warnungsfilter. Wenn das Flag false ist, modifiziert catch_warnings die globale Filterliste, was nicht thread-sicher ist. Weitere Informationen finden Sie im Modul warnings.