web-dev-qa-db-fra.com

Futures concurrentes vs multitraitements dans Python 3

Python 3.2 a introduit Concurrent Futures , qui semble être une combinaison avancée des modules plus anciens de threading et multitraitement .

Quels sont les avantages et les inconvénients de son utilisation pour les tâches liées à la CPU par rapport à l'ancien module de multitraitement?

Cet article suggère qu'il est beaucoup plus facile de travailler avec - est-ce le cas?

117
GIS-Jonathan

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 gimmick de parallélisation sous-jacent .

Donc, comme pratiquement toutes les instances "d'interface plus simple", les mêmes compromis sont en jeu: la courbe d'apprentissage est moins profonde, en grande partie simplement parce qu'il y a beaucoup moins de possibilités à être appris; mais, comme il offre moins d'options, il peut éventuellement vous frustrer, contrairement aux interfaces les plus riches.

En ce qui concerne les tâches liées à la CPU, c'est trop sous-spécifié pour en dire plus. 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'accélérer les choses. Toutefois, le degré d'accélération obtenu (le cas échéant) 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 gimmicks 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 primordial pour la vitesse de traitement.

Edit: example

Voici le code final indiqué dans l'article que vous avez référencé, mais j'ajoute une instruction d'importation nécessaire pour que cela fonctionne:

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 multiprocessing à la 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 multiprocessing.Pool objets en tant que gestionnaires de contexte a été ajouté dans Python 3.3.

Lequel est le plus facile de travailler avec? LOL ;-) Ils sont essentiellement identiques.

Une différence est que Pool supporte tellement de façons différentes de faire les choses que vous ne réaliserez peut-être pas à quel point il est facile de grimpé assez loin dans la courbe d'apprentissage.

Encore une fois, toutes ces manières différentes sont à la fois une force et une faiblesse. Ils sont une force, car la flexibilité peut être nécessaire dans certaines situations. Ils sont une faiblesse en raison de "de préférence seulement un moyen évident de le faire". Un projet collant exclusivement (si possible) à concurrent.futures sera probablement plus facile à maintenir sur le long terme, en raison de l’absence de nouveauté gratuite dans la manière dont son API minimaliste peut être utilisée.

107
Tim Peters

La réponse de @TimPeters a l'air géniale pour moi, mais je voulais simplement ajouter une expérience que j'ai eu qui pourrait être pertinente.

Une fois, j'ai souhaité que les processus enfants créent des processus enfants lors de la communication entre des clusters. Je ne pouvais pas utiliser le multitraitement pour le faire, même si les concurrents l’avaient fait facilement. Je pense que c'est parce que le multitraitement n'a pas cette fonctionnalité, mais je ne suis pas sûr à 100%. À tout le moins, c’était beaucoup plus facile dans les transactions simultanées et tout au plus une fonctionnalité disponible pour les communications simultanées, mais pas le multitraitement. Si quelqu'un peut confirmer ou infirmer cela, alors ce serait génial?

0
ojunk