Wann sollten wir multiprocessing.Pool.join aufrufen?

94

Ich verwende 'multiprocess.Pool.imap_unordered' wie folgt

from multiprocessing import Pool
pool = Pool()
for mapped_result in pool.imap_unordered(mapping_func, args_iter):
    do some additional processing on mapped_result

Muss ich pool.closeoder pool.joinnach der for-Schleife aufrufen ?

hch
quelle
Normalerweise rufe ich pool.join()dann auf, pool.close()wenn ich alle Pool-Threads gestartet habe, aber ich habe nicht versucht, sie pool.imap_unordered()als iterable zu verwenden.
Bamcclur
8
Was bringt es, Join oder Close aufzurufen? Ich habe sie nicht angerufen und mein Code scheint gut zu funktionieren. Ich bin jedoch besorgt, dass ein Nichtaufruf dieser zu Zombie-Prozessen oder anderen subtilen Dingen führen würde.
hch

Antworten:

111

Nein, das tust du nicht, aber es ist wahrscheinlich eine gute Idee, wenn du den Pool nicht mehr benutzen willst.

Gründe für einen Anruf pool.closeoder pool.joinwerden von Tim Peters in diesem SO-Beitrag gut gesagt :

In Bezug auf Pool.close () sollten Sie dies aufrufen, wenn - und nur dann - Sie nie mehr Arbeit an die Pool-Instanz senden werden. Daher wird Pool.close () normalerweise aufgerufen, wenn der parallelisierbare Teil Ihres Hauptprogramms abgeschlossen ist. Dann werden die Arbeitsprozesse beendet, wenn alle bereits zugewiesenen Arbeiten abgeschlossen sind.

Es empfiehlt sich auch, Pool.join () aufzurufen, um auf das Beenden der Worker-Prozesse zu warten. Unter anderem gibt es oft keine gute Möglichkeit, Ausnahmen in parallelisiertem Code zu melden (Ausnahmen treten in einem Kontext auf, der nur vage mit der Arbeit Ihres Hauptprogramms zusammenhängt), und Pool.join () bietet einen Synchronisationspunkt, der einige aufgetretene Ausnahmen melden kann in Arbeitsprozessen, die Sie sonst nie sehen würden.

Bamcclur
quelle
9
ist es besser, einen vor dem anderen anzurufen?
RSHAP
9
Es scheint, dass die Leute gerne pool.close()zuerst und pool.join()zweitens anrufen . Auf diese Weise können Sie Arbeit zwischen pool.close()und hinzufügen pool.join(), ohne auf die Ausführung des Pools warten zu müssen.
Bamcclur
33
Nur um @ Bamcclurs Kommentar zu ergänzen - es ist nicht nur eine gute Idee, pool.close()zuerst anzurufen , es ist tatsächlich obligatorisch. Aus den Dokumenten : Man muss anrufen close()oder terminate()vor der Verwendung join().
Bogd
4
@ Bogd Aber warum ist es obligatorisch? Könnten Sie diese Frage bitte beantworten ?
Agdhruv
Eine Antwort auf die Frage von agdhruvs wäre großartig!
Peitsche
44

Ich hatte das gleiche Speicherproblem wie die Speichernutzung, die mit Pythons multiprocessing.pool weiter zunimmt, wenn ich sie nicht verwendet habe pool.close()und pool.join()wenn ich sie pool.map()mit einer Funktion verwende, die die Levenshtein-Entfernung berechnet. Die Funktion funktionierte einwandfrei, wurde jedoch auf einem Win7 64-Computer nicht ordnungsgemäß gesammelt, und die Speichernutzung geriet bei jedem Aufruf der Funktion außer Kontrolle, bis das gesamte Betriebssystem heruntergefahren wurde. Hier ist der Code, der das Leck behoben hat:

stringList = []
for possible_string in stringArray:
    stringList.append((searchString,possible_string))

pool = Pool(5)
results = pool.map(myLevenshteinFunction, stringList)
pool.close()
pool.join()

Nach dem Schließen und Beitreten zum Pool verschwand das Speicherleck.

Odysseus Ithaka
quelle
1
Ich habe bekommen, ERROR: Terminated with signal 15bevor ich den Bereinigungscode hinzugefügt habe, pool.close();pool.join();aber nachdem ich diesen Bereinigungscode hinzugefügt habe, bekomme ich keine Konsolenmeldungen. Ich vermute also zumindest bei meiner Version, Python 2.7 von C7, dass der Pool vielleicht irgendwie nicht genau aufgeräumt hat.
Trevor Boyd Smith