Quando dovremmo chiamare multiprocessing.Pool.join?


96

Sto usando 'multiprocess.Pool.imap_unordered' come segue

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

Devo chiamare pool.closeo pool.joindopo il ciclo for?


Generalmente chiamo pool.join()quindi pool.close()una volta che ho avviato tutti i thread del pool, ma non ho provato a utilizzarli pool.imap_unordered()come iterabile.
Bamcclur

8
qual è il punto di chiamare join o close? Non li ho chiamati e il mio codice sembra funzionare bene. Tuttavia, sono preoccupato che non chiamarli si tradurrebbe in processi zombi o altre cose sottili.
hch

Risposte:


113

No, non lo fai, ma probabilmente è una buona idea se non usi più la piscina.

Motivi per chiamare pool.closeo pool.joinsono ben detti da Tim Peters in questo post SO :

Per quanto riguarda Pool.close (), dovresti chiamarlo quando - e solo quando - non invierai mai più lavoro all'istanza Pool. Quindi Pool.close () viene in genere chiamato quando la parte parallelizzabile del programma principale è terminata. Quindi i processi di lavoro termineranno quando tutto il lavoro già assegnato sarà completato.

È anche un'ottima pratica chiamare Pool.join () per attendere il termine dei processi di lavoro. Tra le altre ragioni, spesso non c'è un buon modo per segnalare eccezioni nel codice parallelizzato (le eccezioni si verificano in un contesto solo vagamente correlato a ciò che sta facendo il tuo programma principale) e Pool.join () fornisce un punto di sincronizzazione che può segnalare alcune eccezioni che si sono verificate in processi di lavoro che altrimenti non vedresti mai.


9
è meglio chiamare uno prima dell'altro?
RSHAP

9
Sembra che alle persone piaccia chiamare il pool.close()primo e il pool.join()secondo. Ciò consente di aggiungere del lavoro tra pool.close()e pool.join()non è necessario attendere che il pool termini l'esecuzione.
Bamcclur

34
Solo per aggiungere al commento di @ Bamcclur: non è solo una buona idea chiamare pool.close()prima, in realtà è obbligatorio. Dai documenti : uno deve chiamare close()o terminate()prima di utilizzare join().
Bogd

4
@Bogd Ma perché è obbligatorio? Puoi rispondere a questa domanda, per favore?
agdhruv

Una risposta alla domanda di agdhruvs sarebbe fantastica!
Whip

44

Ho avuto lo stesso problema di memoria poiché l' utilizzo della memoria continuava a crescere con il multiprocessing.pool di Python quando non lo utilizzavo pool.close()e pool.join()quando lo utilizzavo pool.map()con una funzione che calcolava la distanza di Levenshtein. La funzione funzionava bene, ma non veniva raccolta correttamente dai rifiuti su una macchina Win7 64 e l'utilizzo della memoria continuava a crescere senza controllo ogni volta che la funzione veniva chiamata fino a quando non veniva disattivato l'intero sistema operativo. Ecco il codice che ha risolto la perdita:

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

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

Dopo aver chiuso e unito al pool, la perdita di memoria è scomparsa.


1
stavo ottenendo ERROR: Terminated with signal 15prima di aggiungere il codice di pulizia pool.close();pool.join();ma dopo aver aggiunto quel codice di pulizia non ricevo i messaggi della console. quindi sospetto almeno sulla mia versione, python 2.7 da C7, che il pool forse in qualche modo non si stava ripulendo esattamente.
Trevor Boyd Smith
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.