es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo compartir un diccionario en la función map_async de multiprocessing en Python?

Tengo una lista lst en Python. Quiero llamar a una función f en cada elemento de esta lista. Esta función f llama a una función de terceros g. También quiero medir el tiempo que tarda cada llamada a la función g en cada elemento de la lista lst. Quiero acelerar el proceso, por lo que uso un grupo de procesos para paralelizar la ejecución. Actualmente, tengo el siguiente código, pero no funciona. Aprendí de esta publicación aquí que map_async solo puede llamar a funciones unarias. También quiero aprovechar la creación de múltiples procesos en map_async y por eso no quiero cambiar a apply_async. ¿Alguien puede sugerirme cuál es la mejor alternativa aquí para lograr mi objetivo?

Mi solución actual que no funciona:

import multiprocessing as mp

time_metrics = {}

def f(idx):
    global time_metrics

    a = time.now()
    g(idx)
    b = time.now()
    time_metrics[idx] = b-a

lst = [1, 2, 3, 4, 5, 6]
pool = mp.Pool(7)
pool.map_async(f, lst)
pool.close()
pool.join()

print(time_metrics)
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Una solución alternativa podría ser utilizar la función starmap_async del módulo multiprocessing en lugar de map_async. Esto permite pasar múltiples argumentos a f en lugar de sólo uno. Por lo tanto, podemos pasar tanto idx como time_metrics como argumentos a f. Así es como se vería el código modificado:

    import multiprocessing as mp
    import time
    
    def f(idx, time_metrics):
        a = time.time() # utilizar time.time() en lugar de time.now()
        g(idx)
        b = time.time()
        time_metrics[idx] = b-a
    
    lst = [1, 2, 3, 4, 5, 6]
    time_metrics = {}
    pool = mp.Pool(7)
    results = pool.starmap_async(f, [(i, time_metrics) for i in lst])
    pool.close()
    pool.join()
    
    # obtener los resultados del objeto async y fusionarlos con time_metrics
    for d in results.get():
        time_metrics.update(d)
    
    print(time_metrics)
    

    Ten en cuenta que, como estamos pasando el diccionario time_metrics como argumento a f, ya no necesitamos utilizar la palabra clave global. Además, he utilizado time.time() en lugar de time.now() para obtener el tiempo desde la época en segundos. Por último, después de que el pool haya terminado de ejecutar las tareas, necesitamos recuperar los resultados del objeto AsyncResult devuelto por starmap_async y fusionarlos con time_metrics. Esto se hace con el método get, que espera a que todas las tareas se completen y devuelve una lista de diccionarios con los resultados. Luego podemos actualizar el diccionario time_metrics con cada uno de esos diccionarios utilizando el método update.

Comments are closed.