
Teilen Sie:
Max ist ein Python-Entwickler und Software-Ingenieur, der sich für Kommunikations-APIs, maschinelles Lernen, Entwicklererfahrung und Tanz interessiert! Er hat Physik studiert, aber jetzt arbeitet er an Open-Source-Projekten und stellt Dinge her, die das Leben von Entwicklern verbessern.
Entfernen von Pythons GIL: Es passiert!
Lesedauer: 8 Minuten
Einführung
Das Global Interpreter Lock (GIL) in Python ist ein Sperrmechanismus, der sicherstellt, dass immer nur ein Thread Python-Code ausführen kann, selbst auf Prozessoren mit mehreren Kernen. Dies bringt zwar einige Vorteile mit sich, bedeutet aber auch, dass es nicht einfach ist, die Vorteile mehrerer CPU-Kerne für die parallele Verarbeitung in Python zu nutzen.
Kürzlich hat der Python-Lenkungsrat angedeutet, dass er die Absicht hat, das PEP 703zu genehmigen, einen Vorschlag zur Erstellung einer Version von CPython, dem beliebtesten Python-Interpreter, ohne die GIL. Dies hat weitreichende Auswirkungen auf die zukünftige Entwicklung von Python, daher lohnt es sich zu verstehen, was hier vor sich geht.
In diesem Beitrag werden wir erörtern, warum wir die GIL in Python haben, warum wir sie vielleicht entfernen wollen, und die Arbeit, die derzeit getan wird, um uns dorthin zu bringen.
Warum haben wir die GIL?
Die GIL vereinfacht die Thread-Verwaltung und schützt vor Wettlaufbedingungen und Speicherkorruption in Python, so dass es für Entwickler einfacher wird, nebenläufigen Code sicher zu schreiben. Sie wurde eingeführt, als die Unterstützung für Threading zu Python in den frühen Tagen der Sprache hinzugefügt wurde.
Kompatibilität
Viele Python-Pakete (und der Haupt-Python-Interpreter CPython) verwenden C-Erweiterungen, die nicht von Natur aus thread-sicher sind. Es ist möglich, dass mehrere Threads versuchen, auf dieselben Ressourcen zuzugreifen, was zu extrem negativen Auswirkungen führen kann. Die GIL machte es sicherer, C-Erweiterungen zu erstellen und zu verwenden, was es wiederum den Entwicklern in den 90er Jahren erleichterte, Python für die Erstellung von Software zu verwenden, was die Akzeptanz förderte.
Garbage Collection und Referenzzählung
Der andere wichtige Grund hat damit zu tun, wie Python die Garbage Collection handhabt. Die Garbage Collection ist ein automatischer Speicherverwaltungsprozess, bei dem der Interpreter den von Objekten belegten Speicher verfolgt und zurückfordert, die im Programm nicht mehr referenziert oder erreichbar sind. In Python gibt es zwei Hauptmethoden der Garbage Collection, aber die bekannteste ist ein Prozess, der Referenzzählung genannt wird.
Die Referenzzählung in Python ist ein effizienter Weg, um Speicher zu verwalten und sicherzustellen, dass Ressourcen freigegeben werden, wenn sie nicht mehr verwendet werden, um Speicherlecks in Python-Programmen zu verhindern. Die Referenzzählung funktioniert wie folgt:
Jedes Objekt verfolgt die Anzahl der Verweise, die auf es zeigen.
Wenn die Anzahl der Verweise auf ein Objekt auf Null sinkt, bedeutet dies, dass es keine weiteren Verweise auf dieses Objekt im Programm gibt.
Dies bedeutet, dass das Objekt nicht mehr benötigt wird.
Das Speicherverwaltungssystem von Python fordert automatisch den vom Objekt belegten Speicher zurück und löscht es somit.
Ohne die GIL könnten mehrere Threads, die gleichzeitig laufen, die Referenzzahlen von Objekten gleichzeitig manipulieren, was zu Wettlaufbedingungen und Speicherbeschädigung führen könnte. Die GIL fungiert als Schutzmechanismus, der es nur einem Thread erlaubt, Python-Bytecode zur gleichen Zeit auszuführen, um diese potenziellen Probleme zu vermeiden.
Warum wollen wir die GIL abschaffen?
Die GIL kann es zwar einfacher machen, Code zu schreiben, ohne sich zu viele Gedanken über die Thread-Sicherheit zu machen, aber sie kann auch die Leistungsgewinne begrenzen, die Sie von der Verwendung mehrerer Threads bei CPU-gebundenen Aufgaben erwarten können. Bei E/A-gebundenen Aufgaben wie HTTP-Anfragen oder Dateioperationen hat die GIL keine so großen Auswirkungen, so dass Sie in diesen Fällen immer noch von Multithreading profitieren können. Wenn Sie also Threads in Python verwenden, um viele HTTP-Anfragen zu senden, könnte dies die Leistung verbessern, aber wenn Sie Threads verwenden, um viele CPU-intensive Aufgaben auszuführen, ist dies wahrscheinlich nicht der Fall.
Wenn die GIL entfernt würde, könnten wir die Leistungsvorteile des Threading bei CPU-intensiven Aufgaben nutzen, die wir derzeit in CPython nicht haben.
Was ist falsch an anderen Ansätzen zur Verbesserung der Gleichzeitigkeit?
Threading und asynchrone Verarbeitung mit asyncio sind beides Methoden zur Verbesserung der Leistung, funktionieren aber nur bei IO-gebundenen Operationen. Es gibt jedoch eine Reihe von Methoden, die für CPU-gebundene Operationen funktionieren.
Python unterstützt Multiprocessing durch das multiprocessing Modulund es ist auch möglich, Python-ähnlichen Code zu schreiben mit Cython zu schreiben, um die Leistung zu verbessern. Beides kann die Leistung von CPU-gebundenen Operationen verbessern, hat aber auch seine Schattenseiten.
Multiprocessing
Das Python multiprocessing Modul können Sie mehrere CPU-Kerne nutzen, indem Sie separate Prozesse mit jeweils eigenem Python-Interpreter und Speicherbereich erstellen. Dies ist effektiv für CPU-gebundene Aufgaben, da es die GIL umgeht, die mit Threads arbeitet, und Sie die mehreren Kerne Ihres Rechners für eine echte parallele Ausführung nutzen können.
Leider ist die Erstellung mehrerer Prozesse im Vergleich zu Threads mit einem höheren Ressourcen-Overhead verbunden, was zu einer erhöhten Speichernutzung und Startzeit führt. Auch die Kommunikation zwischen Prozessen ist langsamer und komplizierter als zwischen Threads. Schließlich teilen sich Prozesse nicht standardmäßig den Speicher, was die gemeinsame Nutzung von Daten zwischen Prozessen und deren Synchronisierung erschwert.
Cython
Cython ist ein Python-Superset, mit dem Sie Python-ähnlichen Code mit einigen zusätzlichen Anmerkungen schreiben können, um die Leistung zu verbessern. Es ist eine Möglichkeit, Ihren Python-Code schneller laufen zu lassen, ohne die Sprache Python komplett verlassen zu müssen. Mit Cython kann Ihr Code schneller ausgeführt werden, indem kritische Teile optimiert werden, während die Leichtigkeit und Lesbarkeit der Sprache Python erhalten bleibt.
Cython hat jedoch eine höhere Lernkurve als Python und erfordert Kenntnisse der C-Sprachkonstrukte, was es weniger zugänglich macht. Das Schreiben und Warten von Cython-Code kann auch komplexer und fehleranfälliger sein als das Schreiben von reinem Python-Code, insbesondere wenn Sie ursprünglich in Python geschriebenen Code neu schreiben.
Es gibt also einige Methoden, um die Leistung zu verbessern, aber beide haben beträchtliche Nachteile. Dies zeigt, warum es ein großes Interesse an der Entfernung der GIL aus Python gibt.
Frühere Versuche - und warum sie nicht erfolgreich waren
Mehrere Projekte haben in der Vergangenheit versucht, die GIL aus CPython zu entfernen, mit einigem Erfolg, z.B. das Gilektomie Projekt. Die Bemühungen, die GIL zu entfernen, haben jedoch in der Regel einige Nachteile:
Dies ist eine komplexe Aufgabe, die das Potenzial hat, Fehler und Instabilität in den CPython-Interpreter einzubringen.
Sie können bestehenden Python-Code und Bibliotheken, die auf die GIL angewiesen sind, zerstören.
Sie können den Speicherverbrauch erhöhen.
Bestehende C-basierte Python-Erweiterungen würden erhebliche Änderungen erfordern.
Der größte Nachteil ist jedoch, dass ältere No-GIL-Projekte tatsächlich Single-Thread-Code langsamer machten als mit der GIL, was bedeutet, dass Ihr Code, wenn Sie nicht Multithreading verwenden, um CPU-gebundene Operationen zu beschleunigen, schlechter abschneiden würde als mit regulärem CPython, was nicht akzeptabel ist.
PEP 703den der Python-Lenkungsrat zu verabschieden beabsichtigtzu verabschieden beabsichtigt, wird all dies ändern und hat breite Unterstützung gefunden. Also lasst uns darüber reden!
Was hat es mit PEP 703 auf sich? No-GIL Python, der richtige Weg
PEP 703 schlägt einen Weg vor, die GIL aus Python zu entfernen, vermeidet aber die Auswirkungen auf die Leistung von nicht-multithreading-fähigem Code, die andere No-GIL-Python-Projekte betroffen haben. Das Python Steering Council gab am 28. Juli bekannt an, dass er beabsichtigt, den PEP zu genehmigen und damit den Weg dafür zu ebnen, dass No-GIL-Python in den Mainstream gelangt und schließlich zum Standard in Python wird.
Wie funktioniert es?
Die wichtigste Technik, die es ermöglicht, die GIL zu entfernen, ohne die Leistung von Single-Thread-Code zu beeinträchtigen, ist das Biased Reference Counting.
Beim Biased Reference Counting wird die Anzahl der Referenzen von Objekten, auf die ein einzelner Thread zugreift, effizienter verwaltet als bei Objekten, auf die mehrere Threads zugreifen, was zu einer Leistungssteigerung bei Single-Thread-Programmen führt, bei denen die meisten Objekte nur von einem Thread verwendet werden. Das bedeutet, dass die Leistung von No-GIL-Python mit dieser Technik bei Single-Thread-Operationen mit der von regulärem Python vergleichbar ist, während Multi-Thread-Python-Programme mit CPU-Bindung viel schneller sind!
Das Projekt macht No-GIL-Python auch effizienter, indem es den Prozess der Referenzzählung für Top-Level-Modul-Objekte, die sich in einem Python-Programm wahrscheinlich nicht ändern, aufschiebt und einige Objekte als "unsterblich" bezeichnet - Objekte wie None werden nie zerstört und müssen daher nicht gezählt werden. Es gibt auch Änderungen in der Art und Weise, wie Speicher für Python-Objekte zugewiesen wird, was es einfacher macht, Speicher auf eine thread-sichere Weise zuzuweisen.
Klingt großartig! Die eigentliche Frage lautet also: Wann werden wir Zugang zu Python ohne GIL haben?
Wie No-GIL Python implementiert werden wird
Der Python Steering Council hat die drei Stufen beschrieben, die no-GIL Python durchlaufen soll, um die Standardversion von CPython zu werden:
Kurzfristig: In Python Version 3.13 (oder möglicherweise 3.14) ist geplant, den no-GIL-Build als experimentellen Modus einzuführen. Dieser Modus soll dazu dienen, Erkenntnisse über die Nutzung, das API-Design, die Paketierung und die Verteilung zu gewinnen.
Mid-Term: Sobald sie sich sicher sind, dass die Community den No-GIL-Build ausreichend unterstützt, wird er eine unterstützte Option, aber nicht der Standard werden. Es wird ein Zieldatum/eine Zielversion festgelegt, um es zum Standard zu machen, wobei der Zeitplan von Faktoren wie API-Kompatibilität und Bereitschaft der Gemeinschaft abhängt. Sie schätzen, dass diese Phase ein oder zwei Jahre dauern könnte, aber es könnte auch länger dauern.
Langfristig: Ziel ist es, dass der No-GIL-Build zum Standard wird und die GIL ohne Unterbrechung der Abwärtskompatibilität abgeschafft wird. Sie schätzen, dass es bis zu 5 Jahre dauern könnte, bis dieses Stadium erreicht ist. Während dieses Prozesses werden regelmäßige Evaluierungen stattfinden, um sicherzustellen, dass der Fortschritt voranschreitet und gleichzeitig Probleme mit der Abwärtskompatibilität vermieden werden - niemand möchte eine weitere Änderung wie die 10-jährige Tortur der Einführung von Python 3 erleben...
Schlussfolgerung
Python steht kurz vor einer bedeutenden Änderung: (möglicherweise) der Abschaffung des Global Interpreter Lock (GIL), was die Fähigkeit von Python, mehrere Prozessorkerne für eine bessere Leistung zu nutzen, erheblich verbessern könnte. Die GIL, die bisher die Rolle eines Sicherheitsnetzes spielte, hat Pythons Potenzial, moderne Prozessoren für CPU-gebundene Aufgaben voll auszunutzen, behindert.
Im Gegensatz zu früheren Versuchen, PEP 703 eine intelligente Lösung, die neben anderen Techniken auch die einseitige Referenzzählung, die aufgeschobene Referenzzählung und unsterbliche Objekte umfasst. Damit wird sichergestellt, dass Python-Programme mit nur einem Thread nicht langsamer werden, während diejenigen, die mehrere Threads für CPU-lastige Aufgaben verwenden, einen Schub erhalten.
Diese Änderung wird in drei Schritten erfolgen: zunächst mit einem experimentellen Build-Modus, dann als unterstützte Option und schließlich als Standardeinstellung, möglicherweise innerhalb der nächsten fünf Jahre! Ziel ist es, diesen Übergang reibungslos zu gestalten, Kompatibilitätsprobleme zu vermeiden und Python zu mehr Leistung und Effizienz zu verhelfen.
Wenn Sie Fragen zu diesem Artikel haben, können Sie sich gerne an uns wenden auf unserem Vonage Community Slack und fragen Sie uns dort oder indem Sie uns eine Nachricht auf X, früher bekannt als Twitter.
Wenn Sie daran interessiert sind, APIs für alles zu nutzen, was mit Kommunikation zu tun hat, wie das Versenden von SMS, Sprachanrufen, Videokonferenzen, 2-Faktor-Authentifizierung, Betrugsprävention und mehr, können Sie sich sich für einen kostenlosen Vonage Developer Account anmelden (mit kostenlosem Guthaben!).
Teilen Sie:
Max ist ein Python-Entwickler und Software-Ingenieur, der sich für Kommunikations-APIs, maschinelles Lernen, Entwicklererfahrung und Tanz interessiert! Er hat Physik studiert, aber jetzt arbeitet er an Open-Source-Projekten und stellt Dinge her, die das Leben von Entwicklern verbessern.