2011-12-16 15 views

Respuesta

275

En los viejos días de Python, para llamar a una función con argumentos arbitrarios, se usaría apply:

apply(f,args,kwargs) 

apply todavía existe en Python2.7 aunque no en python3, y generalmente no se usa más . En la actualidad, se prefiere

f(*args,**kwargs) 

. Los módulos multiprocessing.Pool intentan proporcionar una interfaz similar.

Pool.apply es como Python apply, excepto que la llamada a la función se realiza en un proceso separado. Pool.apply bloques hasta que se complete la función.

Pool.apply_async es como Python's built-in apply, excepto que la llamada vuelve inmediatamente en lugar de esperar el resultado. Se devuelve un objeto ApplyResult. Llama al método get() para recuperar el resultado de la llamada a la función. El método get() bloquea hasta que se complete la función. Por lo tanto, pool.apply(func, args, kwargs) es equivalente a pool.apply_async(func, args, kwargs).get().

En contraste con Pool.apply, el método Pool.apply_async también tiene una devolución de llamada que, si se proporciona, se invoca cuando la función está completa. Esto se puede usar en lugar de llamar al 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 producir un resultado tal como

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

Aviso, a diferencia de pool.map, el orden de los resultados no puede corresponder al orden en el que se hicieron las pool.apply_async llamadas .


lo tanto, si usted necesita para ejecutar una función en un proceso separado, pero desea que el proceso actual para bloque hasta que devuelve la función, utilice Pool.apply. Como Pool.apply, Pool.map bloques hasta que se devuelva el resultado completo.

Si desea que el conjunto de procesos de trabajo realice muchas llamadas de función de forma asincrónica, utilice 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.

Observe también que puede llamar a un número de diferentes funciones de con Pool.apply_async (no todas las llamadas necesitan usar la misma función). Por el contrario, 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.

+6

¿Debería haber 'if __name __ ==" __ main __ "' antes de 'apply_async_with_callback()' en Windows? – jfs

+1

Sí, gracias por el recordatorio. – unutbu

+1

Muchas gracias. ¿Qué tal map_async? –

47

En cuanto a apply vs map:

pool.apply(f, args): f sólo se ejecuta en uno de los trabajadores de la piscina. Entonces, UNO de los procesos en el grupo se ejecutará f(args).

pool.map(f, iterable): Este método corta el iterable en una cantidad de fragmentos que envía al grupo de procesos como tareas separadas. Entonces, aprovecha todos los procesos del grupo.

+0

¿Qué pasa si el iterable es un generador –

+0

Hmm ... Buena pregunta. Para ser honesto, nunca he usado grupos con generadores, pero este hilo podría ser útil: https://stackoverflow.com/questions/5318936/python-multiprocessing-pool-lazy-iteration – kakhkAtion

+0

@kakhkAtion En cuanto a aplicar, si solo uno de los trabajadores ejecutan la función, ¿qué hacen los demás? ¿Debo realizar una solicitud varias veces para que el resto de los trabajadores realice una tarea? – Moondra

Cuestiones relacionadas