multiprocessing.Pool: Когда использовать apply, apply_async или map? - PullRequest
239 голосов
/ 16 декабря 2011

Я не видел четких примеров использования вариантов для Pool.apply , Pool.apply_async и Pool.map . Я в основном использую Pool.map; в чем преимущества других?

Ответы [ 2 ]

358 голосов
/ 16 декабря 2011

В прежние времена Python для вызова функции с произвольными аргументами вы бы использовали apply:

apply(f,args,kwargs)

apply все еще существует в Python2.7, но не в Python3, икак правило, больше не используется.В настоящее время предпочтение отдается

f(*args,**kwargs)

.Модули multiprocessing.Pool пытаются предоставить аналогичный интерфейс.

Pool.apply похож на Python apply, за исключением того, что вызов функции выполняется в отдельном процессе.Pool.apply блокируется до тех пор, пока функция не будет завершена.

Pool.apply_async также похож на встроенный в Python apply, за исключением того, что вызов возвращается немедленно вместо ожидания результата.AsyncResult объект возвращается.Вы вызываете его метод get(), чтобы получить результат вызова функции.Метод get() блокируется до завершения функции.Таким образом, pool.apply(func, args, kwargs) эквивалентно pool.apply_async(func, args, kwargs).get().

В отличие от Pool.apply, метод Pool.apply_async также имеет обратный вызов, который, если он предоставляется, вызывается по завершении функции.Это можно использовать вместо вызова get().

Например:

import multiprocessing as mp
import time

def foo_pool(x):
    time.sleep(2)
    return x*x

result_list = []
def log_result(result):
    # This is called whenever foo_pool(i) returns a result.
    # result_list is modified only by the main process, not the pool workers.
    result_list.append(result)

def apply_async_with_callback():
    pool = mp.Pool()
    for i in range(10):
        pool.apply_async(foo_pool, args = (i, ), callback = log_result)
    pool.close()
    pool.join()
    print(result_list)

if __name__ == '__main__':
    apply_async_with_callback()

может дать такой результат, как

[1, 0, 4, 9, 25, 16, 49, 36, 81, 64]

Уведомление, в отличие от pool.mapпорядок результатов может не соответствовать порядку, в котором были сделаны вызовы pool.apply_async.


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

Если вы хотите, чтобы пул рабочих процессов выполнял много вызовов функций асинхронно, используйте Pool.apply_async.Не гарантируется, что порядок результатов будет таким же, как порядок вызовов на Pool.apply_async.

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

Напротив, Pool.map применяет одну и ту же функцию ко многим аргументам.Однако, в отличие от Pool.apply_async, результаты возвращаются в порядке, соответствующем порядку аргументов.

69 голосов
/ 18 марта 2014

Относительно apply против map:

pool.apply(f, args): f выполняется только в ОДНОМ из работников пула.Таким образом, ОДИН из процессов в пуле будет запускаться f(args).

pool.map(f, iterable): этот метод разбивает итерируемое на несколько кусков, которые он передает в пул процессов как отдельные задачи.Таким образом, вы используете все процессы в пуле.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...