Распараллеливание вложенных функций при сохранении четкой структуры модуля и единичных рабочих пулов - PullRequest
0 голосов
/ 01 ноября 2019

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

Эта цель может показаться тривиальной для тех, кто знаком спакет multiprocessing python;однако для того, кто использует его впервые, у меня возникли проблемы с согласованием рекомендуемой практики создания рабочих пулов в if __name__ == '__main__' и запуска только одного рабочего пула, при этом структурируя мой код в понятной форме.

Текущая структура модуля может быть абстрагирована следующим образом:

(для ясности я держал переменные минимальными)

define functions (e.g. define_x, filter_x, etc.):
|
|— ...

__name__ guard:

   x = define_x()
       | 
       |— return x     

   y = filter_x(x)
       | 
       |— iterate(x)  # runs evaluate() multiple times
       |  |
       |  |— evaluate(x)  # the function I would like to parallelize   
       |
       |— return y   

   z = filter_y(y)
       | 
       |— iterate(y)  # runs evaluate() multiple times
       |  |
       |  |— evaluate(y)  # the function I would like to parallelize  
       |
       |— return z          

   print(z)

Моя первая мысль быласоздать два пула рабочих, один до y = filter_x(x) в основной программе и второй до z = filter_y(y). Соответствующий рабочий пул будет затем проходить через вложенные функции до достижения iterate(), где рабочие назначаются различным процессам, выполняющим evaluate().

Однако я также читал, что лучшие практики предполагают, что только одинрабочий пул должен быть «запущен» (создан) в модуле. Следовательно, целесообразно / возможно ли снова выгружать задачи в тот же рабочий пул после выполнения pool.close() и pool.join()? На основании последней документации по питону представляется возможным:

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

Если в моих рассуждениях есть явные ошибки, укажите это. Кроме того, если вы можете придумать лучший способ структурирования этого модуля, который соответствует передовым методам, пожалуйста, дайте мне знать. Спасибо.

...