multitraitement.Pool: quand utiliser apply, apply async ou map?

Je n'ai pas vu d'exemples clairs avec des cas d'utilisation pour Pool.appliquer, Piscine.apply_async et Piscine.carte. J'utilise principalement Pool.map; quels sont les avantages des autres?

205
demandé sur martineau 2011-12-16 15:08:12

2 réponses

Dans L'ancien temps de Python, pour appeler une fonction avec des arguments arbitraires, vous utiliseriez apply:

apply(f,args,kwargs)

apply existe toujours en Python2.7 mais pas en Python3, et n'est généralement plus utilisé. De nos jours,

f(*args,**kwargs)

Est préféré. Les modules multiprocessing.Pool tentent de fournir une interface similaire.

Pool.apply est comme Python apply, sauf que l'appel de fonction est effectué dans un processus séparé. Pool.apply bloque jusqu'à ce que la fonction soit terminée.

Pool.apply_async est également comme le apply intégré de Python, sauf que l'appel retourne immédiatement au lieu d'attendre le résultat. Un objet ApplyResult est renvoyé. Vous appelez sa méthode get() pour récupérer le résultat de l'appel de fonction. La méthode get() bloque jusqu'à ce que la fonction soit terminée. Ainsi, pool.apply(func, args, kwargs) est équivalent à pool.apply_async(func, args, kwargs).get().

Contrairement à Pool.apply, la méthode Pool.apply_async a également un rappel qui, s'il est fourni, est appelé lorsque la fonction est terminée. Cela peut être utilisé au lieu d'appeler get().

Pour exemple:

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()

Peut donner un résultat tel que

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

Avis, contrairement à pool.map, l'ordre des résultats peut ne pas correspondre à l'ordre dans lequel les pool.apply_async appels ont été effectués.


Donc, si vous devez exécuter une fonction dans un processus séparé, mais que vous voulez que le processus actuel bloque jusqu'à ce que cette fonction retourne, utilisez Pool.apply. Comme Pool.apply, Pool.map bloque jusqu'à ce que le résultat complet soit retourné.

Si vous voulez que le Pool de processus de travail effectue plusieurs la fonction appelle de manière asynchrone, utilisez Pool.apply_async. Le commande des résultats n'est pas garanti d'être le même que l'ordre des appels à Pool.apply_async.

Notez également que vous pouvez appeler un certain nombre de différentes fonctions avec Pool.apply_async (tous les appels n'ont pas besoin d'utiliser la même fonction).

En revanche, Pool.map applique la même fonction à de nombreux arguments. Cependant, contrairement à Pool.apply_async, les résultats sont affichés dans un ordre correspondant à l'ordre des arguments.

306
répondu unutbu 2011-12-16 18:59:29

Concernant apply vs map:

pool.apply(f, args): f n'est exécuté dans l'UN des travailleurs de la piscine. Ainsi, l'un des processus du pool s'exécutera f(args).

pool.map(f, iterable): cette méthode découpe l'itérable en un certain nombre de morceaux qu'elle soumet au pool de processus en tant que tâches distinctes. Ainsi, vous profitez de tous les processus dans la piscine.

58
répondu kakhkAtion 2014-03-18 16:55:52