Как использовать multiprocessing.Pool в импортированном модуле?

1

Я не смог реализовать предложение здесь: Применение двух функций к двум спискам одновременно.

Я предполагаю, что это потому, что модуль импортируется другим модулем, и поэтому моя Windows порождает несколько процессов python?

Мой вопрос: как я могу использовать код ниже без if if __name__ == "__main__":

args_m = [(mortality_men, my_agents, graveyard, families, firms, year, agent) for agent in males]
args_f = [(mortality_women, fertility, year, families, my_agents, graveyard, firms, agent) for agent in females]

with mp.Pool(processes=(mp.cpu_count() - 1)) as p:
    p.map_async(process_males, args_m)
    p.map_async(process_females, args_f)

Оба process_males и process_females являются fuctions. args_m, args_f являются итераторами

Кроме того, мне не нужно ничего возвращать. Агенты - это экземпляры классов, которые нуждаются в обновлении.

  • 0
    Все будет в порядке, если вы переместите этот код в функцию, которая вызывается основным сценарием, который выполняется как __main__ , вместо использования кода модуля верхнего уровня.
Теги:
multiprocessing
python-multiprocessing

2 ответа

1
Лучший ответ

Идея if __name__ == '__main__': заключается в том, чтобы избежать бесконечного нереста процесса.

При травлении функции, определенной в вашем основном script, python должен выяснить, какая часть вашего основного script - это код функции. В основном это запустит ваш script. Если ваш код, создающий Pool, находится в том же script и не защищен "if main", то, попытавшись импортировать эту функцию, вы попытаетесь запустить еще один Pool, который попытается запустить еще один Pool....

Таким образом, вы должны отделить определения функций от фактического основного script:

from multiprocessing import Pool

# define test functions outside main
# so it can be imported withou launching
# new Pool
def test_func():
    pass

if __name__ == '__main__':
    with Pool(4) as p:
        r = p.apply_async(test_func)
        ... do stuff
        result = r.get()
  • 0
    Могу ли я импортировать test_func () из другого модуля и затем иметь p.apply_async(other_module.test_func) ? Дело в том, что я не могу вызвать test_func, пока не получу данные. Затем мне нужно звонить это неоднократно, каждый месяц. Я попробую дальше ... Спасибо.
  • 0
    Да, вы должны иметь возможность импортировать test_func в другой модуль без проблем. Проблемы возникают для функций, которые определены в модуле __main__ . Функции, переданные в apply_async должны быть просто присоединены к обычному модулю.
Показать ещё 1 комментарий
3

Причина, по которой вам нужно защитить код многопроцессорности в if __name__ == "__main__", заключается в том, что вы не хотите, чтобы он снова запускался в дочернем процессе. Это может произойти в Windows, где интерпретатору необходимо перезагрузить все его состояние, поскольку нет системного вызова fork, который скопирует адресное пространство родительского процесса. Но вам нужно использовать его только там, где код должен работать на верхнем уровне, так как вы находитесь в главном script. Это не единственный способ защитить ваш код.

В вашем конкретном случае, я думаю, вы должны поместить код multiprocessing в функцию. Это не будет выполняться в дочернем процессе, если никто не вызывает функцию, когда это не должно. Ваш основной модуль может импортировать модуль, а затем вызвать функцию (возможно, из блока if __name__ == "__main__").

Это должно быть примерно так:

some_module.py:

def process_males(x):
    ...

def process_females(x):
    ...

args_m = [...] # these could be defined inside the function below if that makes more sense
args_f = [...]

def do_stuff():
    with mp.Pool(processes=(mp.cpu_count() - 1)) as p:
        p.map_async(process_males, args_m)
        p.map_async(process_females, args_f)

main.py:

import some_module

if __name__ == "__main__":
    some_module.do_stuff()

В вашем реальном коде вам может понадобиться передать некоторые аргументы или получить возвращаемое значение из do_stuff (которому также должно быть дано более описательное имя, чем общее, которое я использовал в этом примере).

  • 0
    Но в этом-то и дело. Я не могу назвать это из main.py Моя полная программа выглядит следующим образом: main.py инициирует процесс. затем вызывается параметризация, затем загружаются или создаются агенты, затем выполняется модуль итерации времени. Время итерации вызывает running_month где мне нужно do_stuff() . Кроме того, при многократном моделировании я вызываю main.py 100 раз. В итоге, порядок событий не позволяет мне иметь do_stuff внутри, если имя ...
  • 1
    Вы можете сделать так, чтобы звонок поступил через другую функцию, если хотите. В конечном счете, это код скрипта, работающий в main.py, который начнет всю работу (или это должно быть, если ваш код будет работать с многопроцессорностью). Поместите все, что вы не хотите, чтобы запускать дополнительное время в дочерних процессах внутри функции, и вызывайте эти функции только из защиты if __name__ == "__main__" в main.py (или из других функций).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню