1

Я пытаюсь запустить некоторый пример кода модуля multiprocessing.pool python, найденного в Интернете. Код:Пул многопроцессорности Python застрял

def square(x): 
    return x * x 
if __name__ == '__main__': 
    pool = Pool(processes=4) 
    inputs = [0, 1, 2, 3, 4] 
    outputs = pool.map(square, inputs) 

Но когда я пытаюсь запустить его, он никогда не finsh выполнение и я должен перезапустить ядро ​​моего IpythonNotebook ноутбука. В чем проблема?

+0

Этот код работает в обычном (не-Notebook) Python. Можете ли вы подтвердить, что он работает в вашей системе за пределами ноутбука? Можете ли вы также заменить часть пула на регулярную 'map()', чтобы подтвердить, что работает внутри ноутбука? См. Также http://stackoverflow.com/a/23641560/4323 –

+0

работает для меня. Вы можете добавить более подробную информацию, например. версия 'ipython', ОС и т. д. – cel

ответ

3

Как вы можете прочитать от the answer, указанном Джоном в комментариях, multiprocessing.Pool, как правило, не должно нормально работать в интерактивном интерпретаторе. Чтобы понять, почему это так, рассмотрим, как Pool делает свою работу:

  • It рабочих вилки питона, передавая им имя текущего файла Python.
  • Рабочие тогда по существу делают import <this file> и прислушиваются к сообщениям от мастера.
  • Мастер отправляет имена функций вместе с аргументами функции рабочим через травление. Обратите внимание, что сами функции не могут быть отправлены, потому что протокол рассола не позволяет этого.

При попытке выполнить эту процедуру из интерактивного приглашения нет разумного «текущего файла Python» для передачи детям для импорта. Кроме того, функции, которые вы определили в своем интерактивном приглашении, не являются частью какого-либо модуля (они динамически определены) и, следовательно, не могут быть импортированы дочерними элементами из этого несуществующего модуля. Таким образом, ваша самая легкая ставка заключается в том, чтобы просто не использовать multiprocessing в IPython. IPython parallel намного лучше в любом случае :)


Для полноты ради я также проверил, что именно происходит в моем конкретном случае IPython 4 работает под Python 2.7 на Windows 8 (где я могу наблюдать за переводчика застрять в Что ж). Интересно, что причина, по которой IPython застревает в первую очередь, не является одной из упомянутых выше.

Оказывается, что многопроцессорность проверяет, определено ли значение __main__.__file__, а если нет, отправляет sys.argv[0] в качестве «текущего имени файла» для детей. В случае (моя версия) IPython sys.argv[0] равен C:\Dev\Anaconda\lib\site-packages\ipykernel\__main__.py.

К сожалению, рабочие процессы перед запуском происходят, чтобы проверить, находится ли файл, который они будут импортировать, уже в их sys.modules. Линия 488 multiprocessing/forking.py говорит:

assert main_name not in sys.modules, main_name 

Когда main_name является __main__ (как в случае с работниками IPython в) это утверждение не удается, и рабочие не запуститься. Тем не менее, один и тот же код является «умным», чтобы проверить, является ли переданное имя ipython, и в этом случае он не делает таких проверок и ничего не импортирует.

Следовательно, проблема рабочих, которые не могут начать, может быть решена с помощью уродливого взлома определения __main__.__file__ равным ipython. Следующий код работает отлично от клетки IPython:

import sys 
sys.modules['__main__'].__file__ = 'ipython' 
from multiprocessing import Pool 

pool = Pool(processes=4) 
inputs = [0, 1, 2, 3, 4] 
outputs = pool.map(abs, inputs) 

Обратите внимание, что этот пример просит рабочий вычислить abs, встроенную функцию.Он потерпит неудачу (изящно, с исключением), если вы попросите рабочих вычислить функцию, определенную вами в записной книжке.

Оказалось, что в принципе вы можете продолжить хакерство и передать свои функции рабочим, используя ручную травление их кода. Вы можете найти довольно классный пример такого взлома here.

Смежные вопросы