Frage Wie funktionieren Threads in Python und was sind typische Python-Threading-spezifische Fallstricke?


Ich habe versucht, den Umgang mit Threads in Python zu verstehen, und es ist schwer, gute Informationen darüber zu finden, wie sie funktionieren. Es könnte sein, dass ich gerade einen Link oder etwas vermisse, aber es scheint, dass die offizielle Dokumentation zu diesem Thema nicht sehr gründlich ist, und ich konnte keine gute Beschreibung finden.

Von dem, was ich sagen kann, kann nur ein Thread gleichzeitig ausgeführt werden, und der aktive Thread wechselt alle 10 Anweisungen oder so?

Wo gibt es eine gute Erklärung, oder können Sie eine geben? Es wäre auch sehr schön, sich der allgemeinen Probleme bewusst zu sein, die bei der Verwendung von Threads mit Python auftreten.


75
2017-08-27 23:44


Ursprung


Antworten:


Ja, wegen der Global Interpreter Lock (GIL) kann nur ein Thread gleichzeitig ausgeführt werden. Hier sind einige Links mit einigen Einsichten dazu:

Vom letzten Link ein interessantes Zitat:

Lassen Sie mich erklären, was das alles bedeutet.   Threads laufen innerhalb derselben virtuellen Umgebung   Maschine und daher auf demselben laufen   physische Maschine. Prozesse können ausgeführt werden   auf der gleichen physischen Maschine oder in   eine andere physische Maschine. Wenn du   Architect Ihre Anwendung herum   Threads, du hast nichts getan, um darauf zuzugreifen   mehrere Maschinen. Sie können also skalieren   So viele Kerne sind auf der Single   Maschine (das werden einige sein   im Laufe der Zeit), aber wirklich das Web zu erreichen   Skalen, müssen Sie das lösen   Mehrmaschinenproblem sowieso.

Wenn Sie Multi-Core verwenden möchten, pyprocessing definiert eine prozessbasierte API, um eine echte Parallelisierung durchzuführen. Das PEP enthält auch einige interessante Benchmarks.


46
2017-08-28 00:19



Python ist eine ziemlich einfache Sprache, in die man sich einfügen kann, aber es gibt Vorbehalte. Das Wichtigste, was Sie wissen müssen, ist das Global Interpreter Lock. Dadurch kann nur ein Thread auf den Interpreter zugreifen. Das bedeutet zwei Dinge: 1) Sie finden selten eine Lock-Anweisung in Python und 2) wenn Sie Multi-Prozessor-Systeme nutzen möchten, müssen Sie separate Prozesse verwenden. EDIT: Ich sollte auch darauf hinweisen, dass Sie einen Teil des Codes in C / C ++ einfügen können, wenn Sie auch die GIL umgehen wollen.

Daher müssen Sie erneut überlegen, warum Sie Threads verwenden möchten. Wenn Sie Ihre App parallelisieren möchten, um die Vorteile der Dual-Core-Architektur zu nutzen, müssen Sie Ihre App in mehrere Prozesse aufteilen.

Wenn Sie die Reaktionszeit verbessern möchten, sollten Sie die Verwendung von Threads in Betracht ziehen. Es gibt jedoch andere Alternativen, nämlich Microthreading. Es gibt auch einige Frameworks, die Sie untersuchen sollten:


35
2017-08-28 00:00



Unten ist ein einfaches Threading-Beispiel. Es wird 20 Threads hervorbringen; Jeder Thread gibt seine Thread-Nummer aus. Führen Sie es aus und beobachten Sie die Reihenfolge, in der sie drucken.

import threading
class Foo (threading.Thread):
    def __init__(self,x):
        self.__x = x
        threading.Thread.__init__(self)
    def run (self):
          print str(self.__x)

for x in xrange(20):
    Foo(x).start()

Wie Sie bei Python angedeutet haben, werden Threads durch Time-Slicing implementiert. So erhalten sie den "parallelen" Effekt.

In meinem Beispiel erweitert meine Foo-Klasse Thread, ich implementiere dann die run Methode, wo der Code, den Sie in einem Thread ausführen möchten, geht. Um den Thread zu starten, den Sie anrufen start() auf dem Thread-Objekt, das automatisch die aufgerufen wird run Methode...

Natürlich sind das nur die Grundlagen. Sie werden schließlich Informationen über Semaphore, Mutexe und Sperren für die Thread-Synchronisierung und Nachrichtenübergabe erhalten.


19
2017-08-27 23:52



Verwenden Sie Threads in Python, wenn die einzelnen Worker E / A-gebundene Operationen ausführen. Wenn Sie versuchen, über mehrere Kerne auf einer Maschine zu skalieren, finden Sie eine gute Option IPC Framework für Python oder wählen Sie eine andere Sprache.


10
2017-08-28 02:34



Eine einfache Lösung für die GIL ist die Mehrfachverarbeitung Modul. Es kann als Ersatz für das Threading-Modul verwendet werden, verwendet jedoch mehrere Interpreter-Prozesse anstelle von Threads. Aus diesem Grund gibt es ein wenig mehr Overhead als einfaches Threading für einfache Dinge, aber es bietet Ihnen den Vorteil einer echten Parallelisierung, wenn Sie es brauchen. Es kann auch leicht auf mehrere physische Maschinen skaliert werden.

Wenn Sie eine wirklich große Parallelisierung benötigen, würde ich weiter schauen, aber wenn Sie nur auf alle Kerne eines Computers oder auf einige wenige andere skalieren möchten, ohne die gesamte Arbeit, die für die Implementierung eines umfassenderen Frameworks erforderlich wäre, dann ist dies für Sie .


3
2018-02-06 16:19



Hinweis:  wo auch immer ich erwähne thread ich meine speziell Threads in Python bis explizit angegeben.

Threads funktionieren in Python etwas anders, wenn du kommst C/C++ Hintergrund. In Python kann sich zu einem bestimmten Zeitpunkt nur ein Thread im Ausführungsstatus befinden. Dies bedeutet, dass Threads in Python die Leistung mehrerer Prozessorkerne nicht wirklich nutzen können, da Threads nicht parallel auf mehreren Kernen ausgeführt werden können.

Da die Speicherverwaltung in Python nicht threadsicher ist, benötigt jeder Thread einen exklusiven Zugriff auf Datenstrukturen im Python-Interpreter. Dieser exklusive Zugriff wird durch einen Mechanismus namens GIL  (globales Dolmetscherschloss).

Why does python use GIL?

Um zu verhindern, dass mehrere Threads gleichzeitig auf den Interpreter-Zustand zugreifen und den Interpreter-Zustand verfälschen.

Die Idee ist immer dann, wenn ein Thread ausgeführt wird (Auch wenn es der Hauptthread ist), wird eine GIL erworben und nach einem vordefinierten Zeitintervall GIL wird vom aktuellen Thread freigegeben und von einem anderen Thread (falls vorhanden) erneut erworben.

Why not simply remove GIL?

Es ist nicht so, dass es unmöglich ist, GIL zu entfernen, nur dass wir im Prozess dazu mehrere Sperren in den Interpreter setzen, um den Zugriff zu serialisieren, was sogar eine einzelne Thread-Anwendung weniger performant macht.

Die Kosten für die Entfernung von GIL werden also durch die geringere Leistung einer Anwendung mit einem einzigen Gewinde abgegolten, die niemals gewünscht wird.

So when does thread switching occurs in python?

Thread-Wechsel tritt auf, wenn GIL veröffentlicht wird. Wann wird GIL veröffentlicht? Es sind zwei Szenarien zu berücksichtigen.

Wenn ein Thread CPU-gebundene Operationen ausführt (z. B. Bildverarbeitung).

In älteren Versionen von Python wurde die Thread-Umschaltung nach einer festen Anzahl von Python-Anweisungen durchgeführt 100Es stellte sich heraus, dass es keine sehr gute Strategie ist, zu entscheiden, wann ein Wechsel stattfinden sollte, da die Zeit, die für die Ausführung eines einzelnen Befehls benötigt wird, abgelaufen sein kann sehr wild von Millisekunde bis zu einer Sekunde. Daher GIL nach jedem 100 Anweisungen unabhängig von der Zeit, die sie zur Ausführung benötigen, sind eine schlechte Richtlinie.

In neuen Versionen anstelle der Befehlszählung als Metrik zum Umschalten des Threads wird ein konfigurierbares Zeitintervall verwendet. Das Standard-Schaltintervall beträgt 5 Millisekunden. Sie können das aktuelle Schaltintervall mit verwenden sys.getswitchinterval(). Dies kann mit geändert werden sys.setswitchinterval()

Wenn ein Thread IO-gebundene Operationen ausführt (Ex-Dateisystemzugriff oder
    Netzwerk IO)

GIL wird freigegeben, wenn der Thread auf einige wartet, damit der IO-Vorgang abgeschlossen werden kann.

Which thread to switch to next?

Der Interpreter hat keinen eigenen Scheduler. Der Thread, der am Ende des Intervalls geplant wird, ist die Entscheidung des Betriebssystems. .


3
2018-03-30 11:47



Versuchen Sie sich daran zu erinnern, dass das GIL ab und zu abfragt, um das Auftreten mehrerer Aufgaben anzuzeigen. Diese Einstellung kann fein eingestellt werden, aber ich biete den Vorschlag an, dass es Arbeit geben sollte, die die Themen tun, oder viele Kontextschalter werden Probleme verursachen.

Ich würde so weit gehen, mehrere Eltern auf Prozessoren vorzuschlagen und zu versuchen, Jobs auf dem gleichen Kern zu halten.


2
2017-07-28 22:40