In unserem vorherigen Tutorial haben wir über das Python-CSV-Beispiel gelernt. In diesem Tutorial werden wir Python-Multiprocessing mit Beispielen lernen.
Python-Multiprocessing
Paralleles Verarbeiten bekommt heutzutage mehr Aufmerksamkeit. Wenn Sie immer noch nicht über die parallele Verarbeitung Bescheid wissen, lernen Sie es von Wikipedia. Da CPU-Hersteller immer mehr Kerne zu ihren Prozessoren hinzufügen, ist das Erstellen von parallelem Code ein großartiger Weg, um die Leistung zu verbessern. Python hat das multiprocessing-Modul eingeführt, um uns das Schreiben von parallelem Code zu ermöglichen. Um das Hauptmotiv dieses Moduls zu verstehen, müssen wir einige Grundlagen der parallelen Programmierung kennen. Nach dem Lesen dieses Artikels hoffen wir, dass Sie etwas Wissen zu diesem Thema sammeln können.
Python Multiprocessing Prozess, Queue und Sperren
Es gibt viele Klassen im Python-Multiprocessing-Modul zum Aufbau eines parallelen Programms. Unter ihnen sind drei grundlegende Klassen Process
, Queue
und Lock
. Diese Klassen helfen Ihnen beim Aufbau eines parallelen Programms. Aber bevor wir darüber sprechen, lassen Sie uns dieses Thema mit einem einfachen Code initiieren. Um ein paralleles Programm nützlich zu machen, müssen Sie wissen, wie viele Kerne Ihr PC hat. Das Python-Multiprocessing-Modul ermöglicht es Ihnen, das herauszufinden. Der folgende einfache Code wird die Anzahl der Kerne in Ihrem PC ausgeben.
import multiprocessing
print("Number of cpu : ", multiprocessing.cpu_count())
Die folgende Ausgabe kann für Ihren PC variieren. Für mich beträgt die Anzahl der Kerne 8.
Python-Multiprocessing-Prozessklasse
Die Python-Multiprocessing-Klasse Process
ist eine Abstraktion, die einen weiteren Python-Prozess einrichtet, ihm Code zum Ausführen bereitstellt und der übergeordneten Anwendung eine Möglichkeit bietet, die Ausführung zu steuern. Es gibt zwei wichtige Funktionen, die zur Klasse Process gehören – die Funktionen start()
und join()
. Zuerst müssen wir eine Funktion schreiben, die vom Prozess ausgeführt werden soll. Dann müssen wir ein Prozessobjekt instantiieren. Wenn wir ein Prozessobjekt erstellen, passiert nichts, bis wir ihm mit der Funktion start()
mitteilen, dass er mit der Verarbeitung beginnen soll. Dann wird der Prozess ausgeführt und gibt sein Ergebnis zurück. Danach fordern wir den Prozess auf, mit der Funktion join()
abzuschließen. Ohne den Aufruf der Funktion join()
bleibt der Prozess untätig und wird nicht beendet. Wenn Sie also viele Prozesse erstellen und sie nicht beenden, können Sie auf Ressourcenknappheit stoßen. Dann müssen Sie sie möglicherweise manuell beenden. Eine wichtige Sache ist, dass Sie, wenn Sie ein Argument an den Prozess übergeben möchten, das Schlüsselwortargument args
verwenden müssen. Der folgende Code wird hilfreich sein, um die Verwendung der Klasse Process zu verstehen.
from multiprocessing import Process
def print_func(continent='Asia'):
print('The name of continent is : ', continent)
if __name__ == "__main__": # confirms that the code is under main function
names = ['America', 'Europe', 'Africa']
procs = []
proc = Process(target=print_func) # instantiating without any argument
procs.append(proc)
proc.start()
# Instanziierung des Prozesses mit Argumenten
for name in names:
# print(name)
proc = Process(target=print_func, args=(name,))
procs.append(proc)
proc.start()
# Beende die Prozesse
for proc in procs:
proc.join()
Der Output des folgenden Codes wird sein:
Python-Multiprocessing-Warteschlangenklasse
Sie haben grundlegende Kenntnisse über Datenstrukturen in der Informatik, Sie kennen wahrscheinlich die Warteschlange. Das Python-Multiprocessing-Modul bietet die Klasse Queue
, die genau eine First-In-First-Out-Datenstruktur ist. Sie können jedes Pickle-Objekt in den Warteschlangen speichern (obwohl einfache Objekte am besten geeignet sind) und sie sind äußerst nützlich zum Austausch von Daten zwischen Prozessen. Warteschlangen sind besonders nützlich, wenn sie als Parameter an die Ziel-Funktion eines Prozesses übergeben werden, um den Prozess das Verbrauchen von Daten zu ermöglichen. Durch Verwendung der put()
-Funktion können wir Daten in die Warteschlange einfügen, und durch Verwendung von get()
können wir Elemente aus den Warteschlangen abrufen. Sehen Sie sich den folgenden Code für ein schnelles Beispiel an.
from multiprocessing import Queue
colors = ['red', 'green', 'blue', 'black']
cnt = 1
# Instanziierung eines Warteschlangenobjekts
queue = Queue()
print('pushing items to queue:')
for color in colors:
print('item no: ', cnt, ' ', color)
queue.put(color)
cnt += 1
print('\npopping items from queue:')
cnt = 0
while not queue.empty():
print('item no: ', cnt, ' ', queue.get())
cnt += 1
Python multiprocessing Lock-Klasse
Die Aufgabe der Lock-Klasse ist ziemlich einfach. Sie ermöglicht es dem Code, ein Schloss zu beanspruchen, damit kein anderer Prozess den ähnlichen Code ausführen kann, bis das Schloss freigegeben wurde. Die Aufgabe der Lock-Klasse besteht hauptsächlich darin, ein Schloss zu beanspruchen, und das andere darin, das Schloss freizugeben. Um ein Schloss zu beanspruchen, wird die Funktion acquire()
verwendet, und um ein Schloss freizugeben, wird die Funktion release()
verwendet.
Python-Multiprocessing-Beispiel
In diesem Python-Mehrprozess-Beispiel werden wir all unser Wissen zusammenführen. Angenommen, wir haben einige Aufgaben zu erledigen. Um diese Aufgabe zu erledigen, verwenden wir mehrere Prozesse. Also werden wir zwei Queues pflegen. Eine wird die Aufgaben enthalten und die andere wird das Protokoll der abgeschlossenen Aufgabe enthalten. Dann instanziieren wir die Prozesse, um die Aufgabe abzuschließen. Beachten Sie, dass die Python Queue-Klasse bereits synchronisiert ist. Das bedeutet, dass wir die Lock-Klasse nicht verwenden müssen, um zu verhindern, dass mehrere Prozesse auf dasselbe Queue-Objekt zugreifen. Deshalb müssen wir in diesem Fall die Lock-Klasse nicht verwenden. Nachfolgend finden Sie die Implementierung, bei der wir Aufgaben zur Warteschlange hinzufügen, dann Prozesse erstellen und starten, dann join()
verwenden, um die Prozesse abzuschließen. Schließlich drucken wir das Protokoll aus der zweiten Queue.
from multiprocessing import Lock, Process, Queue, current_process
import time
import queue # imported for using queue.Empty exception
def do_job(tasks_to_accomplish, tasks_that_are_done):
while True:
try:
'''
try to get task from the queue. get_nowait() function will
raise queue.Empty exception if the queue is empty.
queue(False) function would do the same task also.
'''
task = tasks_to_accomplish.get_nowait()
except queue.Empty:
break
else:
'''
if no exception has been raised, add the task completion
message to task_that_are_done queue
'''
print(task)
tasks_that_are_done.put(task + ' is done by ' + current_process().name)
time.sleep(.5)
return True
def main():
number_of_task = 10
number_of_processes = 4
tasks_to_accomplish = Queue()
tasks_that_are_done = Queue()
processes = []
for i in range(number_of_task):
tasks_to_accomplish.put("Task no " + str(i))
# Erstellung der Prozesse
for w in range(number_of_processes):
p = Process(target=do_job, args=(tasks_to_accomplish, tasks_that_are_done))
processes.append(p)
p.start()
# Abschluss der Prozesse
for p in processes:
p.join()
# Ausgabe drucken
while not tasks_that_are_done.empty():
print(tasks_that_are_done.get())
return True
if __name__ == '__main__':
main()
Je nach Anzahl der Aufgaben wird der Code einige Zeit benötigen, um Ihnen die Ausgabe anzuzeigen. Die Ausgabe des folgenden Codes wird von Zeit zu Zeit variieren.
Python-Multiprozess-Pool
Der Python-Multiprozess-Pool kann für die parallele Ausführung einer Funktion über mehrere Eingabewerte verwendet werden, wobei die Eingabedaten auf Prozesse verteilt werden (Datenparallelismus). Nachfolgend finden Sie ein einfaches Beispiel für einen Python-Multiprozess-Pool.
from multiprocessing import Pool
import time
work = (["A", 5], ["B", 2], ["C", 1], ["D", 3])
def work_log(work_data):
print(" Process %s waiting %s seconds" % (work_data[0], work_data[1]))
time.sleep(int(work_data[1]))
print(" Process %s Finished." % work_data[0])
def pool_handler():
p = Pool(2)
p.map(work_log, work)
if __name__ == '__main__':
pool_handler()
Unten ist das Ergebnis des obigen Programms dargestellt. Beachten Sie, dass die Pool-Größe 2 beträgt, sodass zwei Ausführungen der Funktion work_log
parallel erfolgen. Wenn die Verarbeitung einer Funktion abgeschlossen ist, wird das nächste Argument ausgewählt und so weiter. Das ist alles zur Python-Multiprozessmodul. Referenz: Offizielle Dokumentation
Source:
https://www.digitalocean.com/community/tutorials/python-multiprocessing-example