Je n'appellerais pas concurrent.futures
plus «avancé» - c'est une interface plus simple qui fonctionne à peu près de la même manière, que vous utilisiez plusieurs threads ou plusieurs processus comme gadget de parallélisation sous-jacent.
Ainsi, comme pratiquement toutes les instances d '«interface plus simple», les mêmes compromis sont à peu près impliqués: il a une courbe d'apprentissage moins profonde, en grande partie simplement parce qu'il y a tellement moins de choses à apprendre; mais, comme il offre moins d'options, il peut éventuellement vous frustrer d'une manière que les interfaces plus riches ne le feront pas.
En ce qui concerne les tâches liées au processeur, c'est beaucoup trop sous-spécifié pour dire beaucoup de sens. Pour les tâches liées au processeur sous CPython, vous avez besoin de plusieurs processus plutôt que de plusieurs threads pour avoir une chance d'obtenir une accélération. Mais l'ampleur (le cas échéant) de l'accélération que vous obtenez dépend des détails de votre matériel, de votre système d'exploitation et en particulier de la quantité de communication inter-processus requise par vos tâches spécifiques. Sous les couvertures, tous les gadgets de parallélisation inter-processus reposent sur les mêmes primitives de système d'exploitation - l'API de haut niveau que vous utilisez pour y parvenir n'est pas un facteur principal de la vitesse du résultat.
Edit: exemple
Voici le code final affiché dans l'article que vous avez référencé, mais j'ajoute une instruction d'importation nécessaire pour le faire fonctionner:
from concurrent.futures import ProcessPoolExecutor
def pool_factorizer_map(nums, nprocs):
# Let the executor divide the work among processes by using 'map'.
with ProcessPoolExecutor(max_workers=nprocs) as executor:
return {num:factors for num, factors in
zip(nums,
executor.map(factorize_naive, nums))}
Voici exactement la même chose en utilisant à la multiprocessing
place:
import multiprocessing as mp
def mp_factorizer_map(nums, nprocs):
with mp.Pool(nprocs) as pool:
return {num:factors for num, factors in
zip(nums,
pool.map(factorize_naive, nums))}
Notez que la possibilité d'utiliser des multiprocessing.Pool
objets comme gestionnaires de contexte a été ajoutée dans Python 3.3.
Lequel est le plus facile à utiliser? LOL ;-) Ils sont essentiellement identiques.
Une différence est qu'il Pool
prend en charge tellement de façons différentes de faire les choses que vous ne réaliserez peut- être pas à quel point cela peut être facile tant que vous n'avez pas gravi un chemin dans la courbe d'apprentissage.
Encore une fois, toutes ces différentes manières sont à la fois une force et une faiblesse. Ils sont une force car la flexibilité peut être requise dans certaines situations. Ils sont une faiblesse car "de préférence une seule façon évidente de le faire". Un projet collé exclusivement (si possible) à concurrent.futures
sera probablement plus facile à maintenir à long terme, en raison du manque de nouveauté gratuite dans la façon dont son API minimale peut être utilisée.
ProcessPoolExecutor
en fait plus d'options quePool
carProcessPoolExecutor.submit
renvoie desFuture
instances qui autorisent l'annulation (cancel
), vérifie quelle exception a été levée (exception
) et ajoute dynamiquement un rappel à appeler à la fin (add_done_callback
). Aucune de ces fonctionnalités n'est disponible avec lesAsyncResult
instances renvoyées parPool.apply_async
. Dans d' autres moyensPool
a plus d' options en raison deinitializer
/initargs
,maxtasksperchild
etcontext
dansPool.__init__
, et plus les méthodes exposées parPool
exemple.Pool
, mais les modules.Pool
est une petite partie de ce quimultiprocessing
est dedans, et est si loin dans la documentation qu'il faut un certain temps pour que les gens se rendent compte que cela existe mêmemultiprocessing
. Cette réponse particulière s'est concentrée surPool
parce que c'est tout l'article utilisé par l'OP et quicf
est «beaucoup plus facile à travailler» n'est tout simplement pas vrai sur ce que l'article a discuté. Au - delà,cf
estas_completed()
peut aussi être très utile.