Ich bin etwas verwirrt darüber, ob Multithreading in Python funktioniert oder nicht.
Ich weiß, dass es viele Fragen dazu gab und ich habe viele davon gelesen, aber ich bin immer noch verwirrt. Ich weiß aus eigener Erfahrung und habe gesehen, dass andere hier auf StackOverflow ihre eigenen Antworten und Beispiele veröffentlicht haben, dass Multithreading in Python tatsächlich möglich ist. Warum sagen alle immer wieder, dass Python von der GIL gesperrt ist und immer nur ein Thread gleichzeitig ausgeführt werden kann? Es funktioniert eindeutig. Oder gibt es einen Unterschied, den ich hier nicht bekomme?
Viele Poster / Befragte erwähnen auch immer wieder, dass das Threading begrenzt ist, da nicht mehrere Kerne verwendet werden. Aber ich würde sagen, dass sie immer noch nützlich sind, weil sie gleichzeitig arbeiten und somit die kombinierte Arbeitslast schneller erledigen. Ich meine, warum sollte es sonst überhaupt ein Python-Thread-Modul geben?
Aktualisieren:
Vielen Dank für alle bisherigen Antworten. Ich verstehe, dass Multithreading für einige E / A-Aufgaben nur parallel ausgeführt wird, für CPU-gebundene Mehrkernaufgaben jedoch jeweils nur eine.
Ich bin mir nicht ganz sicher, was dies für mich in der Praxis bedeutet, daher gebe ich nur ein Beispiel für die Art von Aufgabe, die ich gerne multithreading möchte. Nehmen wir zum Beispiel an, ich möchte eine sehr lange Liste von Zeichenfolgen durchlaufen und einige grundlegende Zeichenfolgenoperationen für jedes Listenelement ausführen. Wenn ich die Liste aufteile, jede Unterliste, die von meinem Schleifen- / Zeichenfolgencode verarbeitet werden soll, in einem neuen Thread sende und die Ergebnisse in einer Warteschlange zurücksende, werden diese Workloads ungefähr gleichzeitig ausgeführt? Wird dies theoretisch die Zeit beschleunigen, die zum Ausführen des Skripts benötigt wird?
Ein anderes Beispiel könnte sein, wenn ich vier verschiedene Bilder mit PIL in vier verschiedenen Threads rendern und speichern kann und dies schneller ist als die Verarbeitung der Bilder nacheinander? Ich denke, diese Geschwindigkeitskomponente ist das, worüber ich mich wirklich wundere, und nicht die richtige Terminologie.
Ich kenne mich auch mit dem Multiprozessor-Modul aus, aber mein Hauptinteresse gilt derzeit dem Laden kleiner bis mittlerer Aufgaben (10 bis 30 Sekunden). Daher denke ich, dass Multithreading besser geeignet ist, da die Initiierung von Unterprozessen langsam sein kann.
quelle
Antworten:
Die GIL verhindert das Einfädeln nicht. Die GIL stellt lediglich sicher, dass jeweils nur ein Thread Python-Code ausführt. Die Steuerung wechselt immer noch zwischen den Threads.
Was die GIL dann verhindert, ist die Verwendung von mehr als einem CPU-Kern oder separaten CPUs, um Threads parallel auszuführen.
Dies gilt nur für Python-Code. C-Erweiterungen können und müssen die GIL freigeben, damit mehrere Threads mit C-Code und ein Python-Thread über mehrere Kerne ausgeführt werden können. Dies erstreckt sich auf vom Kernel gesteuerte E / A, z. B.
select()
Aufrufe zum Lesen und Schreiben von Sockets, sodass Python Netzwerkereignisse in einem Multithread-Setup mit mehreren Threads relativ effizient verarbeitet.Viele Serverbereitstellungen führen dann mehr als einen Python-Prozess aus, damit das Betriebssystem die Planung zwischen den Prozessen übernimmt, um Ihre CPU-Kerne maximal zu nutzen. Sie können die
multiprocessing
Bibliothek auch verwenden , um die parallele Verarbeitung über mehrere Prozesse von einer Codebasis und einem übergeordneten Prozess hinweg zu handhaben, wenn dies Ihren Anwendungsfällen entspricht.Beachten Sie, dass die GIL nur für die CPython-Implementierung gilt. Jython und IronPython verwenden eine andere Threading-Implementierung (die nativen gemeinsamen Java VM- und .NET-Laufzeit-Threads).
So adressieren Sie Ihr Update direkt: Bei jeder Aufgabe, die versucht, durch parallele Ausführung mit reinem Python-Code einen Geschwindigkeitsschub zu erzielen, wird keine Beschleunigung angezeigt, da der Python-Thread-Code an jeweils einen Thread gebunden ist, der ausgeführt wird. Wenn Sie jedoch C-Erweiterungen und E / A einmischen (z. B. PIL- oder Numpy-Operationen), kann jeder C-Code parallel zu einem aktiven Python-Thread ausgeführt werden.
Python-Threading eignet sich hervorragend zum Erstellen einer reaktionsschnellen Benutzeroberfläche oder zum Behandeln mehrerer kurzer Webanforderungen, bei denen E / A der Engpass mehr ist als der Python-Code. Es eignet sich nicht zum Parallelisieren von rechenintensivem Python-Code, zum Festhalten am
multiprocessing
Modul für solche Aufgaben oder zum Delegieren an eine dedizierte externe Bibliothek.quelle
urllib.urlopen()
. B. ?),Image.transform()
Um ein Python-Skript aus einer Python-GUI heraus aufzurufen und mehrere PIL- (z. B. ) und numpy- (z. B.numpy.array()
) Operationen mit Threads aufzurufen . Und Sie haben in Ihrem Kommentar einige weitere Beispiele angegeben, z. B. die Verwendung mehrerer Threads zum Lesen von Dateien (zf.read()
. B. ?). Ich weiß, dass eine vollständige Liste nicht möglich ist. Ich wollte nur die Arten von Beispielen, die Sie in Ihrem Update angegeben haben.urllib.urlopen()
würde Netzwerk-Sockets aufrufen. Das Warten auf Socket-E / A ist eine hervorragende Gelegenheit, Threads zu wechseln und etwas anderes zu tun.Ja. :) :)
Sie haben das Low-Level- Thread- Modul und das High-Level- Threading- Modul. Wenn Sie jedoch einfach Multicore-Maschinen verwenden möchten, ist das Multiprocessing- Modul der richtige Weg.
Zitat aus den Dokumenten :
quelle
Threading ist in Python zulässig. Das einzige Problem besteht darin, dass die GIL sicherstellt, dass jeweils nur ein Thread ausgeführt wird (keine Parallelität).
Wenn Sie also den Code mit mehreren Threads versehen möchten, um die Berechnung zu beschleunigen, wird er nicht beschleunigt, da jeweils nur ein Thread ausgeführt wird. Wenn Sie ihn jedoch beispielsweise für die Interaktion mit einer Datenbank verwenden, wird dies der Fall sein.
quelle