Map_async vs apply_async: что я должен использовать в этом случае?
Я обрабатываю некоторые ascii-данные, делаю некоторые операции, а затем записываю все обратно в другой файл (работа выполняется post_processing_0.main
, не возвращая ничего). Я хочу распараллелить код с помощью модуля многопроцессорности, см. Следующий фрагмент кода:
from multiprocessing import Pool
import post_processing_0
def chunks(lst,n):
return [ lst[i::n] for i in xrange(n) ]
def main():
pool = Pool(processes=proc_num)
P={}
for i in range(0,proc_num):
P['process_'+str(i)]=pool.apply_async(post_processing_0.main, [split_list[i]])
pool.close()
pool.join()
proc_num=8
timesteps=100
list_to_do=range(0,timesteps)
split_list=chunks(list_to_do,proc_num)
main()
Я прочитал разницу между картой и асинхронным, но я не очень хорошо ее понимаю. Правильно ли применено мое многопроцессорное устройство?
В этом случае следует использовать map_async или apply_async? И почему?
Edit:
Я не думаю, что это дубликат вопроса Python multiprocessing.Pool: когда использовать apply, apply_async или map?. В этом вопросе ответ сосредоточен на порядке результата, который может быть получен с использованием двух функций. Здесь я спрашиваю: в чем разница, когда ничего не возвращается?
Ответы
Ответ 1
Я бы порекомендовал map_async
по трем причинам:
-
Это более чистый код. Это:
pool = Pool(processes=proc_num)
async_result = pool.map_async(post_processing_0.main, split_list)
pool.close()
pool.join()
выглядит лучше, чем это:
pool = Pool(processes=proc_num)
P={}
for i in range(0,proc_num):
P['process_'+str(i)]=pool.apply_async(post_processing_0.main, [split_list[i]])
pool.close()
pool.join()
-
С apply_async
, если исключение происходит внутри post_processing_0.main
, вы не узнаете об этом, если вы явно не назовете P['process_x'].get()
для объекта AsyncResult
, который требует итерации по всем P
. При map_async
исключение будет поднято, если вы вызываете async_result.get()
- не требуется итерация.
-
map_async
имеет встроенную функцию chunking, которая сделает ваш код заметно лучше, если split_list
очень большой.
Кроме того, поведение в основном то же самое, если вы не заботитесь о результатах.
Ответ 2
apply_async
отправляет одно задание в пул. map_async
представляет несколько заданий, вызывающих одну и ту же функцию с разными аргументами. Первая имеет функцию плюс список аргументов; последняя принимает функцию плюс итерабельную (т.е. последовательность), которая представляет аргументы. map_async
может вызывать только унарные функции (т.е. функции, принимающие один аргумент).
В вашем случае было бы лучше немного перестроить код, чтобы поместить все ваши аргументы в один список и просто вызвать map_async
один раз с этим списком.