Когда следует вызывать multiprocessing.Pool.join?

96

Я использую multiprocess.Pool.imap_unordered следующим образом

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

Мне нужно позвонить pool.closeили pool.joinпосле цикла for?

чч
источник
Обычно я вызываю его pool.join()после того, pool.close()как запустил все потоки пула, но я не пробовал использовать его pool.imap_unordered()в качестве итеративного.
Bamcclur 08
8
какой смысл призывать присоединиться или закрыть? Я им не звонил, и мой код вроде работает нормально. Тем не менее, я обеспокоен тем, что отказ от их вызова приведет к зомби-процессам или другим тонким вещам.
hch

Ответы:

113

Нет, нет, но, вероятно, это хорошая идея, если вы больше не собираетесь использовать бассейн.

Причины звонка, pool.closeили pool.joinони хорошо сказаны Тимом Питерсом в этом сообщении SO :

Что касается Pool.close (), вы должны вызывать его тогда и только тогда, когда вы никогда не собираетесь отправлять больше работы экземпляру Pool. Поэтому Pool.close () обычно вызывается, когда распараллеливаемая часть вашей основной программы завершена. Затем рабочие процессы завершатся, когда вся уже назначенная работа будет завершена.

Также отличной практикой является вызов Pool.join () для ожидания завершения рабочих процессов. Среди других причин часто нет хорошего способа сообщить об исключениях в распараллеленном коде (исключения возникают в контексте, который лишь отдаленно связан с тем, что делает ваша основная программа), а Pool.join () предоставляет точку синхронизации, которая может сообщать о некоторых произошедших исключениях. в рабочих процессах, которые вы иначе никогда бы не увидели.

Bamcclur
источник
9
лучше позвонить одному перед другим?
РСГАП
9
Кажется, людям нравится звонить pool.close()первым и pool.join()вторым. Это позволяет вам добавлять работу между pool.close()и pool.join(), не дожидаясь завершения выполнения пула.
Bamcclur
34
Просто добавлю к комментарию @Bamcclur - это не просто хорошая идея, чтобы позвонить pool.close()первым, это действительно обязательно. Из документов : Необходимо позвонить close()или terminate()перед использованием join().
Богд
4
@Bogd Но почему это обязательно? Не могли бы вы ответить на этот вопрос?
agdhruv
Ответ на вопрос agdhruvs был бы потрясающим!
Whip
44

У меня была та же проблема с памятью, что и использование памяти с помощью Python multiprocessing.pool, когда я не использовал его, pool.close()и pool.join()при использовании pool.map()с функцией, которая вычисляет расстояние Левенштейна, продолжает расти . Функция работала нормально, но сборщик мусора на машине с Win7 64 происходил некорректно, а использование памяти продолжало выходить из-под контроля каждый раз при вызове функции, пока не прекращала работу всей операционной системы. Вот код, исправивший утечку:

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

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

После закрытия и присоединения к пулу утечка памяти ушла.

Одиссей Итака
источник
1
я получал ERROR: Terminated with signal 15до того, как добавил код очистки, pool.close();pool.join();но после добавления этого кода очистки я не получаю сообщения консоли. поэтому я подозреваю, что, по крайней мере, в моей версии, python 2.7 от C7, пул, возможно, каким-то образом не очищался точно.
Тревор Бойд Смит,