Я не видел четких примеров с примерами использования Pool.apply, Pool.apply_async и Pool.map. В основном я использую Pool.map
; в чем преимущества других?
Multiprocessing.Pool: Когда использовать apply, apply_async или карту?
Ответ 1
В старые времена 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
, за исключением того, что вызов немедленно возвращается, а не ждет результата. Возвращается объект ApplyResult
. Вы вызываете его метод 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
, результаты возвращаются в порядке, соответствующем порядку аргументов.
Ответ 2
Относительно apply
vs map
:
pool.apply(f, args)
: f
выполняется только в ОДИН из работников пула. Поэтому ОДИН из процессов в пуле будет работать f(args)
.
pool.map(f, iterable)
: этот метод прерывает итерацию в несколько фрагментов, которые он представляет в пул процессов как отдельные задачи. Таким образом, вы используете все процессы в пуле.