¿Cuándo deberíamos llamar multiprocessing.Pool.join?

96

Estoy usando 'multiprocess.Pool.imap_unordered' de la siguiente manera

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

¿Necesito llamar pool.closeo pool.joindespués del bucle for?

hch
fuente
Por lo general, llamo pool.join()entonces pool.close()una vez que he iniciado todos los subprocesos del grupo, pero no he intentado usarlos pool.imap_unordered()como iterable.
Bamcclur
8
¿Cuál es el punto de llamar a unirse o cerrar? No los llamé y mi código parece estar funcionando bien. Sin embargo, me preocupa que no llamarlos resulte en procesos zombies u otras cosas sutiles.
hch

Respuestas:

113

No, no lo hace, pero probablemente sea una buena idea si ya no va a usar la piscina.

Motivos para llamar pool.closeo pool.joinbien lo dijo Tim Peters en esta publicación SO :

En cuanto a Pool.close (), debe llamarlo cuando, y solo cuando, nunca enviará más trabajo a la instancia de Pool. Por lo tanto, normalmente se llama a Pool.close () cuando finaliza la parte paralelizable de su programa principal. Luego, los procesos de trabajo terminarán cuando todo el trabajo ya asignado se haya completado.

También es una práctica excelente llamar a Pool.join () para esperar a que finalicen los procesos de trabajo. Entre otras razones, a menudo no existe una buena manera de informar excepciones en código paralelizado (las excepciones ocurren en un contexto relacionado solo vagamente con lo que está haciendo su programa principal), y Pool.join () proporciona un punto de sincronización que puede informar algunas excepciones que ocurrieron en procesos de trabajo que de otro modo nunca verías.

Bamcclur
fuente
9
¿Es mejor llamar a uno antes que al otro?
RSHAP
9
Parece que a la gente le gusta llamar pool.close()primero y pool.join()segundo. Esto le permite agregar trabajo entre pool.close()y pool.join()que no necesita esperar a que el grupo termine de ejecutarse.
Bamcclur
34
Solo para agregar al comentario de @ Bamcclur: no solo es una buena idea llamar pool.close()primero, en realidad es obligatorio. De los documentos : uno debe llamar close()o terminate()antes de usar join().
Bogd
4
@Bogd ¿ Pero por qué es obligatorio? ¿Podría responder a esta pregunta, por favor?
agdhruv
¡Una respuesta a la pregunta de agdhruvs sería increíble!
Whip
44

Tuve el mismo problema de memoria ya que el uso de la memoria sigue creciendo con multiprocessing.pool de Python cuando no lo usaba pool.close()y pool.join()cuando lo usaba pool.map()con una función que calculaba la distancia de Levenshtein. La función funcionaba bien, pero la basura no se recogía correctamente en una máquina Win7 64, y el uso de la memoria seguía creciendo fuera de control cada vez que se llamaba a la función hasta que desactivaba todo el sistema operativo. Aquí está el código que solucionó la fuga:

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

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

Después de cerrar y unirse a la piscina, la pérdida de memoria desapareció.

Ulises Ítaca
fuente
1
Estaba obteniendo ERROR: Terminated with signal 15antes de agregar el código de limpieza, pool.close();pool.join();pero después de agregar ese código de limpieza no recibo los mensajes de la consola. así que sospecho que al menos en mi versión, python 2.7 de C7, que el grupo tal vez no se estaba limpiando exactamente de alguna manera.
Trevor Boyd Smith