processes - python parallel threads
multiprocessing.Pool: ¿Cuándo usar apply, apply_async o map? (2)
En los viejos tiempos de Python, para llamar a una función con argumentos arbitrarios, usaría apply
:
apply(f,args,kwargs)
todavía existe la aplicación en Python2.7 aunque no en Python3, y generalmente ya no se usa. Hoy en día,
f(*args,**kwargs)
se prefiere. Los módulos multiprocessing.Pool
intenta proporcionar una interfaz similar.
Pool.apply
es como Python, excepto que la llamada a la función se realiza en un proceso separado. Pool.apply
bloquea hasta que se complete la función.
Pool.apply_async
también es como la aplicación incorporada de Python, excepto que la llamada se devuelve inmediatamente en lugar de esperar el resultado. Se ApplyResult
objeto ApplyResult
. Llama a su método get()
para recuperar el resultado de la llamada a la función. El método get()
bloquea hasta que se completa la función. Por lo tanto, pool.apply(func, args, kwargs)
es equivalente a pool.apply_async(func, args, kwargs).get()
.
A diferencia de Pool.apply
, el método Pool.apply_async
también tiene una devolución de llamada que, si se proporciona, se llama cuando la función está completa. Esto se puede utilizar en lugar de llamar a get()
.
Por ejemplo:
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()
puede dar un resultado tal como
[1, 0, 4, 9, 25, 16, 49, 36, 81, 64]
Tenga en cuenta que, a diferencia de pool.map
, el orden de los resultados puede no corresponderse con el orden en que se realizaron las llamadas pool.apply_async
.
Por lo tanto, si necesita ejecutar una función en un proceso separado, pero desea que el proceso actual se bloquee hasta que esa función regrese, use Pool.apply
. Al igual que Pool.apply
, Pool.map
bloquea hasta que se devuelve el resultado completo.
Si desea que el Grupo de procesos de trabajo realice muchas llamadas de función de forma asíncrona, use Pool.apply_async
. No se garantiza que el orden de los resultados sea el mismo que el orden de las llamadas a Pool.apply_async
.
Tenga en cuenta también que puede llamar a varias funciones diferentes con Pool.apply_async
(no todas las llamadas necesitan usar la misma función).
En contraste, Pool.map
aplica la misma función a muchos argumentos. Sin embargo, a diferencia de Pool.apply_async
, los resultados se devuelven en un orden correspondiente al orden de los argumentos.
No he visto ejemplos claros con casos de uso para Pool.apply , Pool.apply_async y Pool.map . Estoy utilizando principalmente Pool.map
; ¿Cuáles son las ventajas de los demás?
Respecto a apply
vs map
:
pool.apply(f, args)
: f
solo se ejecuta en UNO de los trabajadores del pool. Entonces, UNO de los procesos en el grupo ejecutará f(args)
.
pool.map(f, iterable)
: este método divide el iterable en varios fragmentos que envía al grupo de procesos como tareas separadas. Así que aprovechas todos los procesos en la piscina.