Unterschied in Parallelitätsaspekten in Python
Man kann sich vorstellen, dass Python diese Begriffe oder Fähigkeiten gerade erst eingeführt hat, da wir mit der Veröffentlichung von Python 3 viele neue Trends in Bezug auf asynchrone Operationen und Parallelität hören.
Viele Neulinge glauben vielleicht, dass die Verwendung von asyncio
der einzige praktische Ansatz zur Durchführung gleichzeitiger und asynchroner Aktivitäten ist. In diesem Artikel wird erläutert, wie wir Nebenläufigkeit und ihre Vor- und Nachteile in Python erreichen können.
Threads und Multithreading
Threads gibt es schon sehr lange in Python. Infolgedessen können wir dank Threads mehrere Operationen gleichzeitig ausführen.
Leider verwendet CPython
, eine typische Mainline-Python-Version, immer noch die globale Interpreter-Sperre (GIL
), was Multi-Thread-Anwendungen – die heutzutage übliche Methode zur Implementierung von Parallelverarbeitung – alles andere als ideal macht.
Python hat GIL
eingeführt, um die Speicherverwaltung von CPython für Integrationen mit C (z. B. die Erweiterungen) besser handhabbar zu machen.
Die GIL
ist ein Verriegelungsmechanismus, bei dem der Python-Interpreter nur einen Thread gleichzeitig ausführt. Pythons byte
-Code kann immer nur von einem Thread gleichzeitig ausgeführt werden.
Beispielcode:
import threading
import time
import random
def worker(num):
sec = random.randrange(1, 5)
time.sleep(sec)
print("I am thread {}, who slept for {} seconds.".format(num, sec))
for i in range(3):
t = threading.Thread(target=worker, args=(i,))
t.start()
print("Completed!")
Ausgang:
Completed!
I am thread 1, who slept for 3 seconds.
I am thread 3, who slept for 2 seconds.
I am thread 4, who slept for 4 seconds.
Prozesse und Multiprocessing
Multiprocessing nutzt viele CPUs. Wir können effektiv mehrere Aufgaben gleichzeitig ausführen, da jede CPU parallel arbeitet. Für Jobs, die CPU-gebunden sind, ist Multiprocessing das, was Sie verwenden möchten.
Python führt das multiprocessing
-Modul ein, um Parallelität zu erreichen, was sich sehr ähnlich anfühlen wird, wenn Sie Threading verwendet haben.
Beispielcode:
import multiprocessing
import time
import random
def worker(num):
sec = random.randrange(1, 5)
time.sleep(sec)
print("I am process {}, who slept for {} seconds.".format(num, sec))
for i in range(3):
t = multiprocessing.Process(target=worker, args=(i,))
t.start()
print("Completed")
Ausgang:
Completed
I am process 1, who slept for 1 seconds.
I am process 2, who slept for 2 seconds.
I am process 0, who slept for 3 seconds.
Anstelle von Multithreading verwenden wir mehrere Prozesse, die auf verschiedenen Kernen Ihrer CPU ausgeführt werden, wodurch unser Python-Skript schneller wird.
Asynchron und asyncio
Beim synchronen Betrieb werden die Aufgaben synchron nacheinander ausgeführt. Jobs können jedoch völlig unabhängig voneinander in asynchronen Operationen beginnen.
Eine asynchrone
Aufgabe kann gestartet und weiter ausgeführt werden, während die Ausführung zu einer anderen Aktivität wechselt. Andererseits werden asynchrone Aufgaben oft im Hintergrund ausgeführt und blockieren nicht (lassen Sie die Implementierung auf den Abschluss warten).
Neben weiteren wertvollen Features bietet asyncio
eine Event-Schleife. Die Ereignisschleife überwacht verschiedene E/A-Ereignisse, schaltet auf bereite Aufgaben um und hält Aufgaben an, die auf E/A warten.
Daher verschwenden wir keine Zeit mit unvollendeten Projekten.
Beispielcode:
import asyncio
import datetime
import random
async def my_sleep_func():
await asyncio.sleep(random.randint(0, 5))
async def displayDate(num, loop):
endTime = loop.time() + 60.0
while True:
print("Loop: {} Time: {}".format(num, datetime.datetime.now()))
if (loop.time() + 1.0) >= endTime:
break
await my_sleep_func()
loop = asyncio.get_event_loop()
asyncio.ensure_future(displayDate(1, loop))
asyncio.ensure_future(displayDate(2, loop))
loop.run_forever()
Wenn wir das obige Code-Snippet durchgehen:
- Wir haben eine
async
-FunktiondisplayDate
, die eine Zahl und die Event-Schleife als Parameter nimmt. - Die genannte Funktion hat eine Endlosschleife, die nach 60 Sekunden stoppt. Aber während dieser 60 Sekunden druckt es immer wieder die Uhrzeit aus und macht ein Nickerchen.
- Die
await
-Funktion kann auf den Abschluss andererasync
-Funktionen warten. - Wir übergeben die Funktion an die Ereignisschleife (mit der Funktion
ensure_future
). - Wir starten die Ereignisschleife.
Immer wenn der await
-Aufruf gemacht wird, versteht asyncio
, dass die Funktion wahrscheinlich einige Zeit brauchen wird. Wenn asyncio
bemerkt, dass die E/A der angehaltenen Funktion bereit ist, setzt es den Prozess fort.
Nun, der Punkt ist, was müssen wir unter den drei Formen der Parallelität verwenden? Als Entscheidungshilfe können wir folgendes beachten:
- Verwenden Sie Multiprocessing für CPU-gebundene Operationen.
- Verwenden Sie Multithreading für I/O Bound, Fast I/O und Limited Number of Connections.
– Verwenden Sie asynchrone E/A für E/A-gebundene, langsame E/A und viele Verbindungen. asyncio/await
funktioniert auf Python 3.5 und höher.
Wir können auch auf den folgenden Pseudocode verweisen:
if io_bound:
if io_very_slow:
print("Use asyncio")
else:
print("Use multithreading")
else:
print("multiprocessing")
Marion specializes in anything Microsoft-related and always tries to work and apply code in an IT infrastructure.
LinkedInVerwandter Artikel - Python Threading
- Holen Sie sich einen Rückgabewert von einem Thread in Python
- Timer-Klasse im Threading-Modul in Python
- Unterschied zwischen Multiprocessing und Threading in Python
- Python-Threadpool