multitraitement vs multithreading vs asyncio dans Python 3

107

J'ai trouvé que dans Python 3.4, il existe peu de bibliothèques différentes pour le multitraitement / threading: multiprocessing vs threading vs asyncio .

Mais je ne sais pas lequel utiliser ou est le "recommandé". Font-ils la même chose ou sont-ils différents? Si oui, lequel est utilisé pour quoi? Je veux écrire un programme qui utilise des multicores sur mon ordinateur. Mais je ne sais pas quelle bibliothèque je devrais apprendre.

user3654650
la source
1
Peut-être que je suis trop stupide pour qu'AsyncIO aide
Martin Thoma

Réponses:

80

Ils sont destinés à des fins et / ou exigences (légèrement) différentes. CPython (une implémentation Python principale typique) a toujours le verrou d'interpréteur global, donc une application multi-thread (un moyen standard d'implémenter le traitement parallèle de nos jours) est sous-optimale. C'est pourquoi multiprocessing on peut préférer threading. Mais tous les problèmes ne peuvent pas être efficacement divisés en parties [presque indépendantes], il peut donc être nécessaire de recourir à de lourdes communications interprocessus. C'est pourquoi multiprocessingne peut pas être préféré threadingen général.

asyncio(cette technique est disponible non seulement en Python, d'autres langages et / ou frameworks l'ont également, par exemple Boost.ASIO ) est une méthode pour gérer efficacement un grand nombre d'opérations d'E / S à partir de nombreuses sources simultanées sans besoin d'exécution de code parallèle . C'est donc juste une solution (une bonne en effet!) Pour une tâche particulière, pas pour le traitement parallèle en général.

user3159253
la source
7
Notant que même si les trois peuvent ne pas atteindre le parallélisme, ils sont tous capables d'effectuer des tâches simultanées (non bloquantes).
sargas du
68

[Réponse rapide]

TL; DR

Faire le bon choix:

Nous avons parcouru les formes les plus populaires de concurrence. Mais la question demeure: quand choisir lequel? Cela dépend vraiment des cas d'utilisation. D'après mon expérience (et lecture), j'ai tendance à suivre ce pseudo code:

if io_bound:
    if io_very_slow:
        print("Use Asyncio")
    else:
        print("Use Threads")
else:
    print("Multi Processing")
  • CPU lié => Traitement multiple
  • I / O Bound, Fast I / O, Limited Number of Connections => Multi Threading
  • I / O Bound, E / S lentes, nombreuses connexions => Asyncio

Référence


[ REMARQUE ]:

  • Si vous avez une méthode d'appel longue (c'est-à-dire une méthode contenant un temps de veille ou des E / S paresseuses), le meilleur choix est l' approche asyncio , Twisted ou Tornado (méthodes coroutine), qui fonctionne avec un seul thread comme concurrence.
  • asyncio fonctionne sur Python3.4 et versions ultérieures.
  • Tornado et Twisted sont prêts depuis Python2.7
  • uvloop est une asyncioboucle d'événement ultra rapide ( uvloop rend asyncio2-4x plus rapide).

[MISE À JOUR (2019)]:

  • Japranto ( GitHub ) est un serveur HTTP de pipelining très rapide basé sur uvloop .
Benyamin Jafari
la source
Donc, si j'ai une liste d'urls à demander, il vaut mieux utiliser Asyncio ?
mingchau
1
@mingchau, Oui, mais gardez à l'esprit que vous pouvez utiliser à partir de asyncioquand vous utilisez des fonctions attendues, la requestbibliothèque n'est pas une méthode attendue, au lieu de cela, vous pouvez utiliser comme la aiohttpbibliothèque ou la requête asynchrone , etc.
Benyamin Jafari
veuillez étendre sur slowIO et fastIO pour passer au multithread ou asyncio>?
qrtLs
@qrtLs Lorsque vous avez un SlowIO, AsyncIO est très utile et plus efficace.
Benyamin Jafari
1
@variable I / O bound signifie que votre programme passe la plupart de son temps à parler à un périphérique lent, comme une connexion réseau, un disque dur, une imprimante ou une boucle d'événements avec un temps de veille. Donc, en mode blocage, vous pouvez choisir entre threading ou asyncio, et si votre section de délimitation est très lente, le multitâche coopératif (asyncio) est un meilleur choix (c'est-à-dire éviter la famine de ressources, les impasses et les conditions de course)
Benyamin Jafari
8

Voici l'idée de base:

Est-ce IO- BOUND? ---------> UTILISATIONasyncio

EST- CE QUE LE CPU EST LOURD? -----> UTILISATIONmultiprocessing

AUTRE ? ----------------------> UTILISATIONthreading

Donc, tenez-vous-en au thread, sauf si vous avez des problèmes d'E / S / CPU.

Farsheed
la source
0

Dans le multitraitement, vous tirez parti de plusieurs processeurs pour distribuer vos calculs. Étant donné que chacun des processeurs fonctionne en parallèle, vous êtes effectivement en mesure d'exécuter plusieurs tâches simultanément. Vous souhaiterez utiliser le multitraitement pour les tâches liées au processeur . Un exemple serait d'essayer de calculer une somme de tous les éléments d'une énorme liste. Si votre machine a 8 cœurs, vous pouvez "couper" la liste en 8 listes plus petites et calculer la somme de chacune de ces listes séparément sur un noyau séparé, puis additionner simplement ces nombres. Vous obtiendrez une accélération d'environ 8x en faisant cela.

En filetagevous n'avez pas besoin de plusieurs processeurs. Imaginez un programme qui envoie de nombreuses requêtes HTTP sur le Web. Si vous utilisiez un programme à un seul thread, il arrêterait l'exécution (bloquer) à chaque demande, attendrait une réponse, puis continuerait une fois reçu une réponse. Le problème ici est que votre CPU ne fonctionne pas vraiment en attendant qu'un serveur externe fasse le travail; il aurait pu faire un travail utile entre-temps! Le correctif consiste à utiliser des threads - vous pouvez en créer beaucoup, chacun étant responsable de la demande de contenu sur le Web. La bonne chose à propos des threads est que, même s'ils fonctionnent sur un processeur, le processeur "gèle" de temps en temps l'exécution d'un thread et saute à l'exécution de l'autre (cela s'appelle la commutation de contexte et cela se produit constamment à non-déterministe. intervalles). - utilisez le filetage.

asyncio est essentiellement un threading où pas le CPU mais vous, en tant que programmeur (ou en fait votre application), décidez où et quand le changement de contexte se produit . En Python, vous utilisez un awaitmot-clé pour suspendre l'exécution de votre coroutine (défini à l'aide du asyncmot-clé).

Tomasz Bartkowiak
la source