multiprocessing.Pool: В чем разница между map_async и imap?

Я пытаюсь узнать, как использовать multiprocessing пакет Python, но я не понимаю разницы между map_async и imap . Я заметил, что и map_async и imap выполняются асинхронно. Итак, когда я должен использовать один над другим? И как мне получить результат, возвращаемый map_async ?

Должен ли я использовать что-то вроде этого?

 def test(): result = pool.map_async() pool.close() pool.join() return result.get() result=test() for i in result: print i 

Существует два ключевых различия между imap / imap_unordered и map / map_async :

  1. То, как они потребляют итерируемый, вы передаете им.
  2. Как они возвращают результат к вам.

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

imap не превращает итерабельность, которую вы передаете в список, и не разбивает его на куски (по умолчанию). Он будет перебирать итерируемый один элемент за раз и отправлять их каждому рабочему процессу. Это означает, что вы не делаете захват памяти преобразованием целого итерабельного в список, но это также означает, что производительность для больших итераций медленнее, из-за отсутствия фрагментации. Это можно смягчить, передав аргумент chunksize больше, чем значение по умолчанию 1.

Другим важным отличием между imap / imap_unordered и map / map_async является то, что с imap / imap_unordered вы можете начать получать результаты от работников, как только они будут готовы, а не ждать, пока все они будут закончены. С map_async AsyncResult возвращается AsyncResult , но вы не можете получать результаты от этого объекта до тех пор, пока все они не будут обработаны, и в каких точках он вернет тот же список, что и map ( map фактически реализована внутри как map_async(...).get() ). Невозможно получить частичные результаты; вы либо имеете весь результат, либо ничего.

imap и imap_unordered возвращают итерации. С imap результаты будут получены из итерируемого, как только они будут готовы, сохраняя при этом порядок ввода итерабельным. С imap_unordered результаты будут получены, как только они будут готовы, независимо от порядка ввода итерации. Итак, скажите, что у вас есть это:

 import multiprocessing import time def func(x): time.sleep(x) return x + 2 if __name__ == "__main__": p = multiprocessing.Pool() start = time.time() for x in p.imap(func, [1,5,3]): print("{} (Time elapsed: {}s)".format(x, int(time.time() - start))) 

Это приведет к выводу:

 3 (Time elapsed: 1s) 7 (Time elapsed: 5s) 5 (Time elapsed: 5s) 

Если вы используете p.imap_unordered вместо p.imap , вы увидите:

 3 (Time elapsed: 1s) 5 (Time elapsed: 3s) 7 (Time elapsed: 5s) 

Если вы используете p.map или p.map_async().get() , вы увидите:

 3 (Time elapsed: 5s) 7 (Time elapsed: 5s) 5 (Time elapsed: 5s) 

Итак, основными причинами использования imap / imap_unordered над map_async являются:

  1. Ваш итерабельность достаточно велика, что преобразование его в список приведет к тому, что вам не хватит / использовать слишком много памяти.
  2. Вы хотите, чтобы начать обработку результатов, прежде чем все они будут завершены.