Heim > Artikel > Backend-Entwicklung > Welchen Nutzen haben Coroutinen und Parallelität in Python?
In diesem Kapitel werden Sie in die Rolle von Coroutinen und Parallelität in Python eingeführt, damit Sie die Vor- und Nachteile der Verwendung von Coroutinen und die Rolle des Gevent-Parallelitätsframeworks verstehen können. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird Ihnen hilfreich sein.
Coroutine
Coroutine ist ein leichter Thread im Benutzermodus, auch bekannt als Mikro-Thread.
Die Coroutine verfügt über einen eigenen Registerkontext und Stapel. Wenn der Zeitplan geändert wird, werden der Registerkontext und der Stapel an anderer Stelle gespeichert. Beim Zurückschalten werden der zuvor gespeicherte Registerkontext und Stapel wiederhergestellt. Daher kann die Coroutine den Status des letzten Aufrufs beibehalten (dh eine bestimmte Kombination aller lokalen Zustände), was dem Eintritt in den Status des letzten Aufrufs entspricht der Zustand, in dem er das letzte Mal verlassen wurde. Der Ort des logischen Flusses.
Vorteile:
Kein Overhead durch Thread-Kontextwechsel
Kein Overhead durch atomare Operationssperre und -synchronisierung
Bequem den Kontrollfluss umschalten und das Programmiermodell vereinfachen
Hohe Parallelität + hohe Skalierbarkeit + niedrige Kosten: Für eine CPU ist es kein Problem, Zehner zu unterstützen von Tausenden von Coroutinen. Daher eignet es sich sehr gut für die Verarbeitung mit hoher Parallelität.
Der sogenannte atomare Vorgang bezieht sich auf einen Vorgang, der vom Thread-Planungsmechanismus nicht unterbrochen wird, sondern bis zum Ende ohne Kontextwechsel (Wechsel) ausgeführt wird zu einem anderen Thread).
Atomere Operationen können ein oder mehrere Schritte umfassen, aber die Reihenfolge kann nicht gestört werden oder nur der ausgeführte Teil kann abgeschnitten werden. Das Sehen als Ganzes ist der Kern der Atomizität.
Nachteile:
Multi-Core-Ressourcen können nicht genutzt werden: Das Wesentliche der Coroutine ist ein einzelner Thread. Sie kann nicht mehrere Kerne einer einzelnen CPU gleichzeitig nutzen Die Coroutine muss zusammenarbeiten, um auf mehreren CPUs ausgeführt zu werden. Natürlich ist diese Notwendigkeit für die meisten Anwendungen, die wir täglich schreiben, nicht erforderlich, es sei denn, es handelt sich um CPU-intensive Anwendungen.
Blockierungsvorgänge (z. B. IO) blockieren das gesamte Programm
Gevent verwenden
gevent ist ein Parallelitäts-Framework von Python mit Micro-Thread-Greenlet als Kern, das den Epoll-Event-Listening-Mechanismus und viele andere Optimierungen nutzt, um es effizient zu machen.:
Einfaches Beispiel
gevents Schlaf kann die Kontrolle übergeben. Wenn wir gevent in Funktionen verwenden, die durch Netzwerk oder E/A eingeschränkt sind, werden diese Funktionen kooperativ geplant entfesselt. Gevent kümmert sich um alle Details, um sicherzustellen, dass Ihre Netzwerkbibliothek nach Möglichkeit implizit Ausführungsrechte an den Greenlet-Kontext übergibt.
import gevent def foo(): print('running in foo') gevent.sleep(0) print('com back from bar in to foo') def bar(): print('running in bar') gevent.sleep(0) print('com back from foo in to bar') # 创建线程并行执行程序 gevent.joinall([ gevent.spawn(foo), gevent.spawn(bar), ])
Ausführungsergebnis:
Synchron asynchron
import random import gevent def task(pid): gevent.sleep(random.randint(0, 2) * 0.001) print('Task %s done' % pid) def synchronous(): for i in range(1, 10): task(i) def asynchronous(): threads = [gevent.spawn(task, i) for i in range(10)] gevent.joinall(threads) print('Synchronous:') synchronous() print('Asynchronous:') asynchronous()
Ausführungsausgabe:
Coroutine in einer Unterklassenmethode verwenden
Sie können die Greenlet-Klasse in Unterklassen umwandeln und sie überladen _run-Methode, ähnlich wie Multi-Thread- und Multi-Prozess-Module
import gevent from gevent import Greenlet class Test(Greenlet): def __init__(self, message, n): Greenlet.__init__(self) self.message = message self.n = n def _run(self): print(self.message, 'start') gevent.sleep(self.n) print(self.message, 'end') tests = [ Test("hello", 3), Test("world", 2), ] for test in tests: test.start() # 启动 for test in tests: test.join() # 等待执行结束
Verwenden Sie Monkey Patch, um die Systemstandardbibliothek zu ändern (Koroutinen automatisch wechseln)
Wenn ein Greenlet auf einen E/A-Vorgang stößt, beispielsweise auf den Zugriff auf das Netzwerk, wechselt es automatisch zu anderen Greenlets, wartet, bis der E/A-Vorgang abgeschlossen ist, und wechselt dann zurück, um die Ausführung zu einem geeigneten Zeitpunkt fortzusetzen.
Da IO-Operationen sehr zeitaufwändig sind, bleibt das Programm oft im Wartezustand. Da gevent die Coroutinen für uns automatisch wechselt, ist gewährleistet, dass Greenlets immer ausgeführt werden, anstatt auf IO zu warten.
Da die Umschaltung automatisch während E/A-Vorgängen erfolgt, muss gevent einige der mit Python gelieferten Standardbibliotheken ändern. Dieser Vorgang wird durch Monkey Patch beim Start abgeschlossen
import gevent import requests from gevent import monkey monkey.patch_socket() def task(url): r = requests.get(url) print('%s bytes received from %s' % (len(r.text), url)) gevent.joinall([ gevent.spawn(task, 'https://www.baidu.com/'), gevent.spawn(task, 'https://www.qq.com/'), gevent.spawn(task, 'https://www.jd.com/'), ])
Ausführungsausgabe:
Es ist ersichtlich, dass die drei Netzwerkoperationen gleichzeitig ausgeführt werden und die Endreihenfolge unterschiedlich ist
Das obige ist der detaillierte Inhalt vonWelchen Nutzen haben Coroutinen und Parallelität in Python?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!