J'essaie d'apprendre à utiliser le paquetage multiprocessing
de Python, mais je ne comprends pas la différence entre map_async
et imap
. J'ai remarqué que map_async
et imap
sont exécutés de manière asynchrone. Alors, quand devrais-je utiliser l'un sur l'autre? Et comment dois-je récupérer le résultat renvoyé par map_async
?
Devrais-je utiliser quelque chose comme ça?
def test():
result = pool.map_async()
pool.close()
pool.join()
return result.get()
result=test()
for i in result:
print i
Il existe deux différences principales entre imap
/imap_unordered
et map
/map_async
:
map
utilise votre itérable en convertissant l'itérable en liste (en supposant qu'il ne soit pas déjà une liste), en la divisant en morceaux et en envoyant ces morceaux aux processus de travail dans le Pool
. Décomposer les éléments itérables en morceaux est plus efficace que de passer chaque élément de cet élément à un autre, en particulier si cet élément est volumineux. Cependant, transformer l'itérable en liste afin de le réduire en bloc peut avoir un coût en mémoire très élevé, car toute la liste devra être conservée en mémoire.
imap
ne transforme pas l'itéré que vous lui donnez en liste, ni ne le divise en morceaux (par défaut). Il itérera sur un élément itérable à la fois et les enverra chacun à un processus de travail. Cela signifie que vous ne prenez pas la mémoire de la conversion de l'ensemble itérable en une liste, mais cela signifie également que la performance est plus lente pour les grands itérables, en raison du manque de fragmentation. Cela peut toutefois être atténué en passant un argument chunksize
supérieur à 1 par défaut, égal à 1.
L’autre grande différence entre imap
/imap_unordered
et map
/map_async
, c’est que, avec imap
/imap_unordered
, vous pouvez commencer à recevoir les résultats des travailleurs dès qu’ils sont prêts. attendre que tout soit fini. Avec map_async
, un AsyncResult
est renvoyé immédiatement, mais vous ne pouvez pas extraire les résultats de cet objet tant que tous n'ont pas été traités. La liste est alors renvoyée à la même liste que map
(map
est effectivement appliqué à l'interne comme map_async(...).get()
). Il n'y a aucun moyen d'obtenir des résultats partiels; soit vous avez le résultat entier, soit rien.
imap
et imap_unordered
renvoient tous les deux des iterables. Avec imap
, les résultats seront générés à partir de l'itéré dès qu'ils seront prêts, tout en préservant l'ordre des entrées. Avec imap_unordered
, les résultats seront fournis dès qu’ils seront prêts, quel que soit l’ordre de l’entrée itérable. Alors, dites que vous avez ceci:
import multiprocessing
import time
def func(x):
time.sleep(x)
return x + 2
if __== "__main__":
p = multiprocessing.Pool()
start = time.time()
for x in p.imap(func, [1,5,3]):
print("{} (Time elapsed: {}s)".format(x, int(time.time() - start)))
Cela produira:
3 (Time elapsed: 1s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
Si vous utilisez p.imap_unordered
au lieu de p.imap
, vous verrez:
3 (Time elapsed: 1s)
5 (Time elapsed: 3s)
7 (Time elapsed: 5s)
Si vous utilisez p.map
ou p.map_async().get()
, vous verrez:
3 (Time elapsed: 5s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
Ainsi, les principales raisons d'utiliser imap
/imap_unordered
sur map_async
sont les suivantes: