Могу ли я сопоставить подпроцесс с тем же мультипроцессором. Бассейн, где работает основной процесс? - PullRequest
0 голосов
/ 02 июля 2019

Я относительно новичок в мире multiprocessing в python3 , и поэтому мне жаль, если этот вопрос был задан ранее.У меня есть скрипт, который из списка из N элементов выполняет полный анализ каждого элемента, отображая каждый из них в отдельный процесс.

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

Вот как выглядит код:

max_processes = 7 
# it is passed by command line actually but not relevant here

def main_function( ... ):

    res_1 = sub_function_1( ... )
    res_2 = sub_function_2( ... )

if __name__ == '__main__':

    p = Pool(max_processes)
    Arguments = []

    for x in Paths.keys():
        # generation of the arguments
        ... 
        Arguments.append( Tup_of_arguments )

    p.map(main_function, Arguments)

    p.close()
    p.join()

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

1 Ответ

1 голос
/ 03 июля 2019

Нет, вы не можете.
Пул (в значительной степени) недоступен в рабочих процессах.Это немного зависит от метода запуска , используемого для пула.

spawn
Новый процесс интерпретатора Python запускается и импортирует модуль.Поскольку в этом процессе __name__ равно '__mp_main__', код в блоке __name__ == '__main__' не выполняется, и в рабочих не существует объекта пула.

fork
Памятьпространство родительского процесса копируется в пространство памяти дочернего процесса.Это эффективно приводит к существующему объекту Pool в области памяти каждого рабочего.
Однако этот пул непригоден для использования.Рабочие создаются во время выполнения пула __init__, поэтому инициализация пула является неполной, когда рабочие разветвляются.Копии пула в рабочих процессах не имеют ни одного из запущенных потоков, которые управляют рабочими, задачами и результатами.Потоки в любом случае не превращаются в дочерние процессы через fork.
Кроме того, поскольку рабочие объекты созданы во время инициализации, объект пула еще не был назначен ни одному имени в этой точке.Несмотря на то, что он скрывается в области памяти рабочего, он не имеет к нему никакого управления.Не отображается через globals();Я нашел его только через gc.get_objects(): <multiprocessing.pool.Pool object at 0x7f75d8e50048>
В любом случае, этот объект пула является копией объекта в основном процессе.

forkserver
Я не смог протестировать этот метод запуска

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

В качестве отступления: я не уверен, что хорошая идея - разрешить пользователям передавать число рабочих с помощью командной строки.Я рекомендую дать этому значению верхнюю границу как минимум через os.cpu_count().

...