Je n'ai pas vu d'exemples clairs avec des cas d'utilisation pour Pool.apply , Pool.apply_async et Pool.map . J'utilise principalement Pool.map
; quels sont les avantages des autres?
Je n'ai pas vu d'exemples clairs avec des cas d'utilisation pour Pool.apply , Pool.apply_async et Pool.map . J'utilise principalement Pool.map
; quels sont les avantages des autres?
Réponses:
À l'époque de Python, pour appeler une fonction avec des arguments arbitraires, vous utilisiez apply
:
apply(f,args,kwargs)
apply
existe toujours en Python2.7 mais pas en Python3, et n'est généralement plus utilisé. Aujourd'hui,
f(*args,**kwargs)
est préféré. Les multiprocessing.Pool
modules essaient 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 similaire à Python apply
, sauf que l'appel retourne immédiatement au lieu d'attendre le résultat. Un AsyncResult
objet est retourné. Vous appelez sa get()
méthode pour récupérer le résultat de l'appel de fonction. La get()
méthode se 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 Pool.apply_async
méthode 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()
.
Par 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]
Remarquez, 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 distinct, mais que vous souhaitez que le processus actuel se bloque jusqu'à ce que cette fonction revienne, utilisez Pool.apply
. Comme Pool.apply
, Pool.map
bloque jusqu'à ce que le résultat complet soit retourné.
Si vous souhaitez que le pool de processus de travail effectue de nombreux appels de fonction de manière asynchrone, utilisez Pool.apply_async
. L' ordre 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 fonctions différentes 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
aux résultats, les résultats sont renvoyés dans un ordre correspondant à l'ordre des arguments.
Pool.map(func,iterable)
c'est équivalent à Pool.map_async(func,iterable).get()
. La relation entre Pool.map
et Pool.map_async
est donc similaire à celle de Pool.apply
et Pool.apply_async
. Les async
commandes reviennent immédiatement, tandis que le async
bloc non- commandes. Les async
commandes ont également un rappel.
Pool.map
et Pool.apply
est similaire à décider quand utiliser map
ou apply
en Python. Vous utilisez simplement l'outil qui convient au travail. Le choix entre l'utilisation de la async
et de la non- async
version dépend de si vous souhaitez que l'appel bloque le processus en cours et / ou si vous souhaitez utiliser le rappel.
apply_async
renvoie un ApplyResult
objet. L' appel que ApplyResult
de » get
la méthode retourne la valeur de retour de la fonction associée (ou augmentation mp.TimeoutError
si les temps-out appel.) Donc , si vous mettez le ApplyResult
s dans une liste ordonnée, puis en appelant leurs get
méthodes renverra les résultats dans le même ordre. Vous pouvez simplement utiliser pool.map
dans cette situation cependant.
Concernant apply
vs map
:
pool.apply(f, args)
: f
n'est exécuté que dans UN des travailleurs de la piscine. Donc, l'un des processus du pool s'exécutera f(args)
.
pool.map(f, iterable)
: Cette méthode coupe l'itérable en plusieurs morceaux qu'elle soumet au pool de processus en tant que tâches distinctes. Vous profitez donc de tous les processus du pool.
apply_async()
8 fois? Le traitera-t-il automatiquement avec une file d'attente?
Voici un aperçu dans un format de table afin de montrer les différences entre Pool.apply
, Pool.apply_async
, Pool.map
et Pool.map_async
. Lorsque vous en choisissez un, vous devez prendre en compte plusieurs arguments, la concurrence, le blocage et la commande:
| Multi-args Concurrence Blocking Ordered-results
---------------------------------------------------------------------
Pool.map | no yes yes yes
Pool.map_async | no yes no yes
Pool.apply | yes no yes no
Pool.apply_async | yes yes no no
Pool.starmap | yes yes yes yes
Pool.starmap_async| yes yes no no
Pool.imap
et Pool.imap_async
- version paresseuse de map et map_async.
Pool.starmap
, très similaire à la méthode map en plus de l'acceptation de plusieurs arguments.
Async
Les méthodes soumettent tous les processus à la fois et récupèrent les résultats une fois qu'ils sont terminés. Utilisez la méthode get pour obtenir les résultats.
Pool.map
(ou Pool.apply
) les méthodes sont très similaires à la carte intégrée Python (ou s'appliquent). Ils bloquent le processus principal jusqu'à ce que tous les processus soient terminés et renvoient le résultat.
Est appelé pour une liste d'emplois en une seule fois
results = pool.map(func, [1, 2, 3])
Ne peut être appelé que pour un seul emploi
for x, y in [[1, 1], [2, 2]]:
results.append(pool.apply(func, (x, y)))
def collect_result(result):
results.append(result)
Est appelé pour une liste d'emplois en une seule fois
pool.map_async(func, jobs, callback=collect_result)
Ne peut être appelé que pour un seul travail et exécute un travail en arrière-plan en parallèle
for x, y in [[1, 1], [2, 2]]:
pool.apply_async(worker, (x, y), callback=collect_result)
Est une variante pool.map
qui prend en charge plusieurs arguments
pool.starmap(func, [(1, 1), (2, 1), (3, 1)])
Une combinaison de starmap () et map_async () qui itère sur l'itérable des itérables et appelle func avec les itérables décompressés. Renvoie un objet résultat.
pool.starmap_async(calculate_worker, [(1, 1), (2, 1), (3, 1)], callback=collect_result)
Retrouvez la documentation complète ici: https://docs.python.org/3/library/multiprocessing.html
if __name__=="__main__"
avantapply_async_with_callback()
sur Windows?