Warum gibt es keine GIL in der Java Virtual Machine? Warum braucht Python einen so dringend?

177

Ich hoffe, jemand kann einen Einblick in die grundlegenden Unterschiede der Java Virtual Machine geben, die es ihr ermöglichen, Threads ohne die Notwendigkeit einer globalen Interpreter-Sperre (GIL) gut zu implementieren, während Python ein solches Übel erfordert.

AgentLiquid
quelle

Antworten:

223

Python (die Sprache) benötigt keine GIL (weshalb es perfekt auf JVM [Jython] und .NET [IronPython] implementiert werden kann und diese Implementierungen frei multithread-fähig sind). CPython (die beliebte Implementierung) hat immer eine GIL verwendet, um die Codierung (insbesondere die Codierung der Garbage Collection-Mechanismen) und die Integration nicht thread-sicherer C-codierter Bibliotheken zu vereinfachen (früher gab es eine Menge davon). -).

Das unb Projekt unter anderem ehrgeizigen Zielen, tut plant eine GIL-freie virtuelle Maschine für Python -. , Dass die Website zu zitieren : „Darüber hinaus wollen wir die GIL entfernen und den Zustand von Multithreading in Python beheben Wir glauben , dies ist möglich durch die Implementierung eines ausgefeilteren GC-Systems, ähnlich wie IBMs Recycler (Bacon et al., 2001). "

Alex Martelli
quelle
6
Alex, was ist mit den alten Versuchen, die GIL zu entfernen? War das nicht eine Menge Aufwand (ein Faktor von 2 ist das, woran ich mich erinnere)?
Bartosz Radaczyński
10
Ja, Bartosz, Greg Stein hat das 1999 gemessen. Die Müllabfuhr durch Referenzzählung war der Mörder, der einen riesigen Aufwand an feinkörnigen Verriegelungen erzwang. Deshalb ist dort eine fortgeschrittenere GC von entscheidender Bedeutung.
Alex Martelli
80
Das Team von Unladen Swallow hat das Entfernen der GIL aufgegeben
Seun Osewa
1
Alternativen zu Unladen und CPython sind PyPy, Jython und IronPython. Die beiden letzteren haben keine GIL, aber die Verwendung des Multiprocessing-Moduls umgeht die GIL und ist trotzdem sicherer.
Cees Timmerman
50

Die JVM (zumindest der Hotspot) hat ein ähnliches Konzept wie die "GIL", sie ist nur viel feiner in ihrer Lock-Granularität. Das meiste davon stammt von den GCs im Hotspot, die weiter fortgeschritten sind.

In CPython ist es eine große Sperre (wahrscheinlich nicht so wahr, aber gut genug für Argumente), in der JVM ist es mit unterschiedlichen Konzepten mehr verbreitet, je nachdem, wo es verwendet wird.

Schauen Sie sich zum Beispiel vm / runtime / safepoint.hpp im Hotspot-Code an, der praktisch eine Barriere darstellt. An einem sicheren Punkt hat die gesamte VM in Bezug auf Java-Code angehalten, ähnlich wie die Python-VM an der GIL angehalten hat.

In der Java-Welt werden solche VM-Pausenereignisse als "Stop-the-World" bezeichnet. An diesen Punkten läuft nur nativer Code, der an bestimmte Kriterien gebunden ist, frei, der Rest der VM wurde gestoppt.

Auch das Fehlen einer groben Sperre in Java erschwert das Schreiben von JNI erheblich, da die JVM weniger Garantien für ihre Umgebung für FFI-Aufrufe gibt. Dies ist eines der Dinge, die cpython ziemlich einfach macht (obwohl es nicht so einfach ist wie die Verwendung von ctypes).

Greg Bowyer
quelle
7

Unten in diesem Blog-Beitrag http://www.grouplens.org/node/244 gibt es einen Kommentar, der auf den Grund hinweist, warum es so einfach war, auf eine GIL für IronPython oder Jython zu verzichten. CPython verwendet die Referenzzählung Die anderen 2 VMs haben Garbage Collectors.

Die genaue Mechanik, warum das so ist, verstehe ich nicht, aber es klingt nach einem plausiblen Grund.

user235859
quelle
5
Wenn Sie Objekte promisku zwischen Threads austauschen, ist es mäßig umständlich, herauszufinden, wann niemand mehr auf ein bestimmtes Objekt verweist. Referenzzählung mit einer globalen Sperre ist eine (teure) Möglichkeit. Eine andere Möglichkeit, dies zu lösen, wäre gewesen, jeweils nur einen Thread Verweise auf das Objekt enthalten zu lassen, was dazu führen würde, dass die meisten Aktivitäten threadlokal sind, was die Kommunikation zwischen Threads umständlicher macht. Persönlich denke ich, dass es bezeichnend ist, dass HPC die Nachrichtenübermittlung zwischen Prozessoren und nicht gemeinsam genutztem Speicher verwendet, und dies aus Gründen der Skalierbarkeit ...
Donal Fellows
0

In diesem Link haben sie die folgende Erklärung:

... "Teile des Interpreters sind nicht threadsicher, allerdings hauptsächlich, weil sie alle Threadsicher durch massive Sperrenutzung extrem verlangsamen würden ( Quelle ). Dies scheint mit dem CPython-Garbage-Collector unter Verwendung der Referenzzählung (der JVM) in Zusammenhang zu stehen und CLR nicht und müssen daher nicht jedes Mal einen Referenzzähler sperren / freigeben. Aber selbst wenn jemand an eine akzeptable Lösung dachte und diese implementierte, hätten Bibliotheken von Drittanbietern immer noch die gleichen Probleme. "

Oliver Wilken
quelle
-1

Python fehlt jit / aot und der Zeitrahmen, in dem es auf Multithread-Prozessoren geschrieben wurde, existierte nicht. Alternativ können Sie alles in Julia lang neu kompilieren, dem GIL fehlt, und Ihren Python-Code etwas beschleunigen. Auch Jython saugt es ist langsamer als Cpython und Java. Wenn Sie sich an Python halten möchten, sollten Sie parallele Plugins verwenden. Sie erhalten keinen sofortigen Geschwindigkeitsschub, können jedoch mit dem richtigen Plugin parallel programmieren.

Jim
quelle
Was ist mit PyPy?
denis631