Es gibt zwei wesentliche Unterschiede zwischen imap
/imap_unordered
und map
/map_async
:
- Die Art, wie sie verbrauchen die iterable Sie an sie weitergeben.
- Die Art, wie sie das Ergebnis zurück zu Ihnen zurückgeben.
map
verbraucht Ihr iterable durch die iterable in eine Liste konvertieren (vorausgesetzt, es ist keine Liste bereits ist), sie in Stücke brechen und in der Pool
diese Brocken auf die Arbeitsprozesse zu senden. Das Iterable in Chunks zu zerlegen, ist besser, als jedes Element im Iterable zwischen den einzelnen Prozessen einzeln zu übergeben - insbesondere, wenn das Iterable groß ist. Das Iterable in eine Liste umzuwandeln, um es zu chunken, kann jedoch sehr hohe Speicherkosten haben, da die gesamte Liste im Speicher gehalten werden muss.
imap
nicht das iterable Sie es in eine Liste, noch bricht es in Stücke (standardmäßig). Es wird über das iterierbare Element einzeln iterieren und sie jeweils an einen Arbeitsprozess senden. Dies bedeutet, dass Sie nicht den Memory-Hit des Konvertierens des gesamten Iterablen in eine Liste verwenden, aber es bedeutet auch, dass die Leistung für große Iterables langsamer ist, weil Chunking fehlt. Dies kann gemildert werden, indem ein chunksize
-Argument, das größer als der Standardwert von 1 ist, übergeben wird.
Der andere große Unterschied zwischen imap
/imap_unordered
und map
/map_async
, ist, dass mit imap
/imap_unordered
, Sie Ergebnisse von Arbeitern empfangen, so bald beginnen können, wie sie bereit sind, anstatt für alle von ihnen zu warten zu sein fertig. Mit map_async
wird ein AsyncResult
sofort zurückgegeben, aber man kann nicht wirklich abrufen Ergebnisse von diesem Objekt, bis alle von ihnen verarbeitet worden sind, an welchen Stellen sie die gleiche Liste zurückgibt, dass map
tut (map
tatsächlich intern als map_async(...).get()
implementiert). Es gibt keine Möglichkeit, Teilergebnisse zu erhalten. Sie haben entweder das gesamte Ergebnis oder nichts.
imap
und imap_unordered
beide Iterables sofort zurückgeben. Mit imap
werden die Ergebnisse vom iterablen Wert zurückgegeben, sobald sie fertig sind, während die Reihenfolge der Eingabe iterierbar bleibt. Mit imap_unordered
werden Ergebnisse geliefert, sobald sie fertig sind, unabhängig von der Reihenfolge der Eingabe iterierbar.Also, sagen Sie dies haben:
import multiprocessing
import time
def func(x):
time.sleep(x)
return x + 2
if __name__ == "__main__":
p = multiprocessing.Pool()
start = time.time()
for x in p.imap(func, [1,5,3]):
print("{} (Time elapsed: {}s)".format(x, int(time.time() - start)))
erhalten Sie folgende Ausgabe:
3 (Time elapsed: 1s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
Wenn Sie p.imap_unordered
statt p.imap
verwenden, werden Sie sehen:
3 (Time elapsed: 1s)
5 (Time elapsed: 3s)
7 (Time elapsed: 5s)
Wenn Sie p.map
oder p.map_async().get()
, Sie werden sehen:
3 (Time elapsed: 5s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
die primären Gründe also, imap
/imap_unordered
über map_async
zu verwenden sind:
- Ihre iterable groß genug ist, dass es in eine Liste konvertieren würde dazu führen Sie aus/verwenden zu viel Speicher laufen.
- Sie möchten mit der Verarbeitung der Ergebnisse beginnen können, bevor von ihnen abgeschlossen sind.
was ist mit apply und apply_async? –
@HarshDaftary 'apply' sendet eine einzelne Aufgabe an einen Worker-Prozess und blockiert dann bis zum Abschluss. 'apply_async' sendet eine einzelne Aufgabe an einen Arbeitsprozess und gibt dann sofort ein' AsyncResult'-Objekt zurück, mit dem auf den Abschluss der Aufgabe gewartet und das Ergebnis abgerufen werden kann. 'apply' wird durch Aufruf von' apply_async (...). get() 'implementiert. – dano
@dano Ist es möglich, den Code so zu ändern, dass auch die in Kommentaren enthaltenen Sekunden gedruckt werden? Vielen Dank. –