Quando devemos chamar multiprocessing.Pool.join?

94

Estou usando 'multiprocess.Pool.imap_unordered' conforme a seguir

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

Eu preciso ligar pool.closeou pool.joinapós o loop for?

hch
fonte
Eu geralmente chamo pool.join()então pool.close()depois de iniciar todos os threads do pool, mas não tentei usar pool.imap_unordered()como iterável.
Bamcclur
8
qual é o ponto de chamar join ou close? Não liguei para eles e meu código parece estar funcionando bem. No entanto, estou preocupado que não chamá-los resultaria em processos zumbis ou outras coisas sutis.
HCH

Respostas:

111

Não, não precisa, mas provavelmente é uma boa ideia se você não vai mais usar a piscina.

Razões para ligar pool.closeou pool.joinsão bem ditas por Tim Peters neste post do SO :

Quanto a Pool.close (), você deve chamá-lo quando - e somente quando - você nunca enviar mais trabalho para a instância Pool. Portanto, Pool.close () é normalmente chamado quando a parte paralelizável do programa principal é concluída. Em seguida, os processos de trabalho serão encerrados quando todo o trabalho já atribuído for concluído.

Também é uma prática excelente chamar Pool.join () para aguardar o término dos processos de trabalho. Entre outras razões, geralmente não há uma boa maneira de relatar exceções em código paralelizado (as exceções ocorrem em um contexto vagamente relacionado ao que seu programa principal está fazendo), e Pool.join () fornece um ponto de sincronização que pode relatar algumas exceções que ocorreram em processos de trabalho que de outra forma nunca veria.

Bamcclur
fonte
9
é melhor chamar um antes do outro?
RSHAP de
9
Parece que as pessoas gostam de ligar pool.close()primeiro e pool.join()segundo. Isso permite que você adicione trabalho entre o pool.close()e o pool.join()que não precisa aguardar o término da execução do pool.
Bamcclur
33
Apenas para adicionar ao comentário de @Bamcclur - não é apenas uma boa ideia ligar pool.close()primeiro, é realmente obrigatório. Dos documentos : Deve-se ligar close()ou terminate()antes de usar join().
Bogd,
4
@Bogd Mas porque é obrigatório? Você poderia responder a esta pergunta, por favor?
agdhruv
Uma resposta à pergunta do agdhruvs seria incrível!
Whip
44

Eu tive o mesmo problema de memória, pois o uso de memória continua crescendo com o multiprocessing.pool do Python quando eu não usei pool.close()e pool.join()ao usar pool.map()com uma função que calculava a distância de Levenshtein. A função funcionava bem, mas não era coletada como lixo corretamente em uma máquina Win7 64, e o uso de memória continuava crescendo fora de controle toda vez que a função era chamada, até derrubar todo o sistema operacional. Aqui está o código que corrigiu o vazamento:

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

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

Após fechar e ingressar no pool, o vazamento de memória foi embora.

Odysseus Ithaca
fonte
1
Eu estava recebendo ERROR: Terminated with signal 15antes de adicionar o código de limpeza, pool.close();pool.join();mas depois de adicionar esse código de limpeza, não recebo as mensagens do console. então eu suspeito pelo menos na minha versão, python 2.7 de C7, que o pool talvez de alguma forma não estava limpando exatamente.
Trevor Boyd Smith