Es gibt zwei wesentliche Unterschiede zwischen imap
/ imap_unordered
und map
/ map_async
:
- Die Art und Weise, wie sie das iterable konsumieren, das Sie an sie weitergeben.
- Die Art und Weise, wie sie das Ergebnis an Sie zurücksenden.
map
verbraucht Ihre Iterable, indem Sie die Iterable in eine Liste konvertieren (vorausgesetzt, es ist noch keine Liste), sie in Chunks aufteilen und diese Chunks an die Worker-Prozesse in der senden Pool
. Das Aufteilen des Iterables in Blöcke ist besser als das Übergeben jedes Elements im Iterable zwischen Prozessen einzeln - insbesondere, wenn das Iterable groß ist. Das Verwandeln des Iterables in eine Liste, um es zu zerlegen, kann jedoch sehr hohe Speicherkosten verursachen, da die gesamte Liste im Speicher gehalten werden muss.
imap
Verwandelt das Iterable, das Sie ihm geben, nicht in eine Liste und zerlegt es auch nicht in Blöcke (standardmäßig). Es wird jeweils ein iterierbares Element durchlaufen und jeweils an einen Arbeitsprozess gesendet. Dies bedeutet, dass Sie nicht den Speicher-Hit der Konvertierung des gesamten iterablen Objekts in eine Liste in Kauf nehmen müssen, aber es bedeutet auch, dass die Leistung bei großen iterierbaren Dateien aufgrund des Mangels an Chunking langsamer ist. Dies kann jedoch durch Übergeben eines chunksize
Arguments gemindert werden, das größer als der Standardwert 1 ist.
Der andere große Unterschied zwischen imap
/ imap_unordered
und map
/ besteht darin map_async
, dass Sie mit imap
/ imap_unordered
beginnen können, Ergebnisse von Mitarbeitern zu erhalten, sobald diese bereit sind, anstatt warten zu müssen, bis alle fertig sind. Mit map_async
wird ein AsyncResult
sofort zurückgegeben, aber Sie können die Ergebnisse von diesem Objekt erst dann abrufen, wenn alle verarbeitet wurden. An diesem Punkt wird dieselbe Liste zurückgegeben, die dies map
tut ( map
wird tatsächlich intern implementiert als map_async(...).get()
). Es gibt keine Möglichkeit, Teilergebnisse zu erzielen. Sie haben entweder das gesamte Ergebnis oder nichts.
imap
und imap_unordered
beide geben sofort iterables zurück. Mit imap
werden die Ergebnisse von der iterierbaren Datei ausgegeben, sobald sie fertig sind, wobei die Reihenfolge der iterierbaren Eingabe beibehalten wird. Mit imap_unordered
werden die Ergebnisse unabhängig von der Reihenfolge der iterierbaren Eingabe angezeigt, sobald sie fertig sind. Angenommen, Sie haben Folgendes:
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)))
Dies wird Folgendes ausgeben:
3 (Time elapsed: 1s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
Wenn Sie p.imap_unordered
anstelle von verwenden p.imap
, sehen Sie:
3 (Time elapsed: 1s)
5 (Time elapsed: 3s)
7 (Time elapsed: 5s)
Wenn Sie p.map
oder verwenden p.map_async().get()
, werden Sie sehen:
3 (Time elapsed: 5s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
Die Hauptgründe für die Verwendung imap
/ imap_unordered
Über map_async
sind also:
- Ihr Iterable ist groß genug, um bei der Konvertierung in eine Liste zu viel Speicherplatz zu verbrauchen.
- Sie möchten in der Lage sein, die Ergebnisse zu verarbeiten, bevor alle abgeschlossen sind.