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 один раз с этим списком.