2014-12-15 5 views
10

Я обрабатываю некоторые ascii-данные, делаю некоторые операции, а затем записываю все обратно в другой файл (работа выполняется post_processing_0.main, не возвращая ничего). Я хочу, чтобы распараллелить код с модулем многопроцессорной см следующего фрагмента кода:map_async vs apply_async: что я должен использовать в этом случае

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: when to use apply, apply_async or map?. В этом вопросе ответ сосредоточен на порядке результата, который может быть получен с использованием двух функций. Здесь я спрашиваю: в чем разница, когда ничего не возвращается?

+0

Возможный дубликат [Python multiprocessing.Pool: когда применять, применять \ _async или карту?] (Http://stackoverflow.com/questions/8533318/python-multiprocessing-pool-when-to-use-apply -apply-async-or-map) – user4815162342

+1

Я прочитал этот вопрос, но он не раскрывает мои сомнения. Я задаю более строгий вопрос: в чем разница в этом случае, когда результат от параллелизированной функции не возвращается? – Pierpaolo

ответ

12

Я бы рекомендовал map_async по трем причинам:

  1. Это уборщик ищет код. Это:

    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() 
    
  2. С apply_async, если исключение происходит внутри post_processing_0.main, вы не будете знать об этом, если вы явно не вызовете P['process_x'].get() на неисправном AsyncResult объекта , что потребует итерации по всем P. С map_async исключение будет поднято, если вы вызываете async_result.get() - не требуется итерации.

  3. map_async имеет встроенную функцию коммутации, которая заставит ваш код работать заметно лучше, если split_list очень большой.

Помимо этого, поведение в основном то же самое, если вы не заботитесь о результатах.

8

apply_async отправляет одно задание в бассейн. map_async представляет несколько заданий, вызывающих одну и ту же функцию с разными аргументами. Первая имеет функцию плюс список аргументов; последняя принимает функцию плюс итерабельную (т.е. последовательность), которая представляет аргументы. map_async может вызывать только унарные функции (т. Е. Функции, принимающие один аргумент).

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

+0

Итак, если мы рассмотрим 4 процесса и 16 файлов для постпроцесса, карта будет «создавать» 16 экземпляров, которые будут запускать все одновременно? – Pierpaolo

+0

Вы имеете в виду, что пул имеет размер 4, а список аргументов имеет размер 16? В этом случае будет выполняться только 4 за один раз; когда первый закончен, начнется пятый и т. д. –

+0

Хорошо! Тогда я понимаю, что нет различий (кроме изменения кода). Это правильно? – Pierpaolo