93 votes

Pourquoi les programmes Python sont-ils souvent plus lents que le programme équivalent écrit en C ou en C++ ?

Pourquoi Python semble-t-il plus lent, en moyenne, que C/C++ ? J'ai appris Python comme premier langage de programmation, mais je viens juste de commencer avec C et j'ai déjà l'impression de voir une nette différence.

21 votes

Savez-vous que Python est interprété ?

11 votes

@kaizer.se - alors nous devons aussi dire les autres vérités évidentes, nous ne travaillons pas avec des langages de programmation mais avec des implémentations de langages de programmation ; etc etc

7 votes

@kaizer.se : oui, nous savons, nous savons. Mais imaginez à quel point il est gênant d'écrire en évitant des commentaires comme les vôtres. "Pourquoi le code Python (exécuté avec n'importe quel interpréteur courant) est-il si lent ?"

112voto

Mark Byers Points 318575

Python est un langage de plus haut niveau que le C, ce qui signifie qu'il fait abstraction des détails de l'ordinateur (gestion de la mémoire, pointeurs, etc.) et vous permet d'écrire des programmes d'une manière plus proche de la façon dont les humains pensent.

Il est vrai que le code C s'exécute généralement 10 à 100 fois plus vite que le code Python si l'on ne mesure que le temps d'exécution. Cependant, si vous incluez également le temps de développement, Python bat souvent C. Pour de nombreux projets, le temps de développement est bien plus critique que les performances d'exécution. Un temps de développement plus long se traduit directement par des coûts supplémentaires, moins de fonctionnalités et une mise sur le marché plus lente.

En interne, la raison pour laquelle le code Python s'exécute plus lentement est que le code est interprété au moment de l'exécution au lieu d'être compilé en code natif au moment de la compilation.

D'autres langages interprétés, tels que le bytecode Java et le bytecode .NET, s'exécutent plus rapidement que Python, car les distributions standard incluent un module de gestion de l'interface utilisateur. Compilateur JIT qui compile le bytecode en code natif au moment de l'exécution. La raison pour laquelle CPython ne dispose pas déjà d'un compilateur JIT est que la nature dynamique de Python rend difficile l'écriture d'un tel compilateur. Il existe travail en progrès pour écrire un runtime Python plus rapide, vous pouvez donc vous attendre à ce que l'écart de performance soit réduit à l'avenir, mais il faudra probablement attendre un certain temps avant que la distribution standard de Python n'inclue un compilateur JIT puissant.

46 votes

Pour être pédant : Python n'est pas typiquement compilé en natif au moment de la compilation. Le bytecode Python doit toujours être interprété.

22 votes

Vous n'avez pas vraiment expliqué pourquoi les implémentations de Python ont tendance à être si gourmandes en CPU. Vous pouvez faire abstraction de tout ce qui précède sans encourir trop de coûts à l'exécution ; c'est la nature extrêmement dynamique de Python qui consomme tout le CPU : toutes ces recherches d'attributs/dispatches de méthodes s'additionnent et donnent du fil à retordre même aux JIT - et Python est généralement utilisé sans JIT à l'heure actuelle.

0 votes

@SamB : J'ai ajouté une comparaison avec d'autres langues interprétées pour répondre à votre question. La partie que j'ai écrite sur les abstentions n'était pas pour expliquer pourquoi Python est plus lent à exécuter, mais pour expliquer pourquoi il peut être plus rapide à programmer.

56voto

CPython est particulièrement lent parce qu'il n'a pas d'optimiseur Just in Time (puisqu'il s'agit de l'implémentation de référence et qu'il choisit la simplicité au détriment de la performance dans certains cas). Hirondelle déchargée est un projet visant à ajouter un JIT soutenu par LLVM dans CPython, et permet d'obtenir des accélérations massives. Il est possible que Jython et IronPython soient beaucoup plus rapides que CPython car ils sont soutenus par des machines virtuelles fortement optimisées (JVM et .NET CLR).

Une chose qui rendra Python plus lent, c'est qu'il est typiquement dynamique, et qu'il y a des tonnes de recherches pour chaque accès à un attribut.

Par exemple, appeler f sur un objet A entraînera d'éventuelles recherches dans la base de données __dict__ appelle à __getattr__ etc, puis appeler enfin __call__ sur l'objet appelable f .

En ce qui concerne le typage dynamique, de nombreuses optimisations sont possibles si l'on sait à quel type de données on a affaire. Par exemple, en Java ou en C, si vous avez un tableau d'entiers que vous voulez additionner, le code d'assemblage final peut être aussi simple que d'aller chercher la valeur à l'index i en l'ajoutant à la liste des accumulator puis en incrémentant i .

En Python, il est très difficile d'obtenir un code aussi optimal. Supposons que vous ayez un objet de sous-classe de liste contenant int s. Avant même d'en ajouter, Python doit appeler list.__getitem__(i) puis l'ajouter à l'"accumulateur" en appelant accumulator.__add__(n) puis répéter. Des tonnes de recherches alternatives peuvent se produire ici parce qu'un autre fil de discussion peut avoir modifié, par exemple, le fichier __getitem__ le dict de l'instance de liste ou le dict de la classe, entre les appels à add ou getitem. Même le fait de trouver l'accumulateur et la liste (et toute variable utilisée) dans l'espace de noms local entraîne une recherche dans le dict. Ce même surcoût s'applique lors de l'utilisation de tout objet défini par l'utilisateur, bien que pour certains types intégrés, il soit quelque peu atténué.

Il convient également de noter que les types primitifs tels que bigint (int dans Python 3, long dans Python 2.x), list, set, dict, etc, etc, sont ceux que les gens utilisent le plus en Python. Il y a des tonnes d'opérations intégrées sur ces objets qui sont déjà suffisamment optimisées. Par exemple, pour l'exemple ci-dessus, il suffit d'appeler sum(list) au lieu d'utiliser un accumulateur et un index. En vous en tenant à cela, et en faisant un peu de calcul avec int/float/complex, vous n'aurez généralement pas de problèmes de vitesse, et si c'est le cas, il y a probablement une petite unité critique (une fonction SHA2 digest, par exemple) que vous pouvez simplement déplacer vers le C (ou le code Java, dans Jython). Le fait est que lorsque vous codez en C ou en C++, vous allez gaspiller de l'énergie et de l'argent. lots de temps pour faire des choses que vous pouvez faire en quelques secondes/lignes de code Python. Je dirais que le compromis en vaut toujours la peine, sauf dans les cas où vous faites quelque chose comme de la programmation embarquée ou en temps réel et que vous ne pouvez pas vous le permettre.

0 votes

L'hirondelle déchargée n'utilise-t-elle pas actuellement un peu plus de mémoire ? 2009 Q2 [ [code.google.com/p/unladen-swallow/wiki/Release2009Q2]](http://code.google.com/p/unladen-swallow/wiki/Release2009Q2]) Les résultats indiquent que la mémoire a été multipliée par 10, et les résultats du troisième trimestre 2009 [ [code.google.com/p/unladen-swallow/wiki/Release2009Q3]](http://code.google.com/p/unladen-swallow/wiki/Release2009Q3]) dit qu'ils l'ont réduit de 930 % (je ne sais pas comment interpréter ce chiffre). Il semble que la réduction de la mémoire soit un objectif, mais qu'il n'ait pas encore été atteint.

0 votes

Doh, la phrase que j'ai écrite n'avait même pas de sens de toute façon.

0 votes

"Une chose qui laissera sans doute Python plus lent est qu'il est dynamiquement typé, et qu'il y a des tonnes de recherches pour chaque accès à un attribut." En fait, c'est là que le JIT de PyPy gagne vraiment. Le JIT peut remarquer que votre code fait quelque chose de simple et de pas trop compliqué, et peut optimiser sur des instructions machine simples. Ainsi PyPy est maintenant beaucoup plus rapide que CPython chaque fois que vous faites quelque chose de simple dans une boucle.

30voto

La question de la compilation ou de l'interprétation n'est pas importante ici : Python est compilé, et il ne représente qu'une infime partie du coût d'exécution de tout programme non trivial.

Les principaux coûts sont les suivants : l'absence d'un type d'entier correspondant aux entiers natifs (ce qui rend toutes les opérations sur les entiers beaucoup plus coûteuses), l'absence de typage statique (ce qui rend la résolution des méthodes plus difficile et signifie que les types de valeurs doivent être vérifiés au moment de l'exécution), et l'absence de valeurs non encadrées (ce qui réduit l'utilisation de la mémoire et permet d'éviter un niveau d'indirection).

Non pas que ces choses ne soient pas possibles ou ne puissent pas être rendues plus efficaces en Python, mais le choix a été fait de privilégier la commodité et la flexibilité du programmeur, et la propreté du langage plutôt que la vitesse d'exécution. Certains de ces coûts peuvent être surmontés par une compilation JIT intelligente, mais les avantages offerts par Python auront toujours un coût.

8voto

Femaref Points 41959

La différence entre Python et C est la différence habituelle entre un langage interprété (bytecode) et compilé (en langage natif). Personnellement, je ne considère pas vraiment python comme lent, il se débrouille très bien. Si vous essayez de l'utiliser en dehors de son domaine, bien sûr, il sera plus lent. Mais pour cela, vous pouvez écrire des extensions C pour Python, qui placent les algorithmes critiques en code natif, ce qui les rend beaucoup plus rapides.

2 votes

S/it's/its. Interprétée ou compilée signifie rien en termes d'optimisabilité. La JVM et le C peuvent être interprétés ou compilés. Différentes optimisations peuvent être appliquées dans les deux cas (optimisation adaptative vs temps de compilation + LTO).

4 votes

Python se compile en bytecode, qui est ensuite interprété. il peut également être compilé en code machine, donc par essence, aucun de nous deux n'a raison.

2 votes

En plus d'être fausse, cette réponse ne parle pas du vrai problème, que @Longpoke explique assez bien dans sa réponse.

5voto

dawg Points 26051

Comparer C/C++ à Python n'est pas une comparaison équitable. C'est comme comparer une voiture de course de F1 à un camion utilitaire.

Ce qui est surprenant, c'est la rapidité de Python par rapport à ses pairs des autres langages dynamiques. Bien que la méthodologie soit souvent considérée comme défectueuse, regardez Le jeu des tests de performance des langages informatiques pour connaître la vitesse relative des langues sur des algorithmes similaires.

La comparaison avec Perl, Ruby et C# est plus "juste

5 votes

Je préfère utiliser la métaphore d'une Lamborghini se rendant à toute vitesse au travail à 5 pâtés de maisons (langues non sûres pour la mémoire) par rapport à une voiture respectant les limitations de vitesse (langues sûres pour la mémoire) :)

0 votes

Le langage C# est statiquement typé, bien qu'il ait des types dynamiques optionnels.

5 votes

Le C me semble plus proche d'une voiture-fusée - idéal si l'on veut aller en ligne droite et qu'il n'y a rien à percuter à proximité, mais pas vraiment dans le cas contraire !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X