web-dev-qa-db-fra.com

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

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

58
Riemannliness

Python est un langage de niveau supérieur à C, ce qui signifie qu'il extrait de vous les 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 rapidement que le code Python si vous ne mesurez 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 beaucoup plus critique que les performances d'exécution. Un temps de développement plus long se transforme directement en coûts supplémentaires, moins de fonctionnalités et un temps de mise sur le marché plus lent.

En interne, la raison pour laquelle 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 Java bytecode et .NET bytecode s'exécutent plus rapidement que Python car les distributions standard incluent un compilateur JIT qui compile bytecode au code natif à l'exécution. La raison pour laquelle CPython n'a pas encore de compilateur JIT est parce que la nature dynamique de Python rend difficile l'écriture de celui-ci. Il y a travail in progress pour écrire un runtime plus rapide Python donc vous devriez vous attendre à ce que l'écart de performance soit réduit à l'avenir, mais il faudra probablement un certain temps avant la norme) Python inclut un puissant compilateur JIT.

69
Mark Byers

CPython est particulièrement lent car il n'a pas d'optimiseur Just in Time (car c'est l'implémentation de référence et choisit la simplicité plutôt que les performances dans certains cas). nladen Swallow est un projet visant à ajouter un JIT soutenu par LLVM dans CPython, et réalise des accélérations massives. Il est possible que Jython et IronPython soient beaucoup plus rapides que CPython et qu'ils soient soutenus par des machines virtuelles fortement optimisées (JVM et .NET CLR).

Une chose qui laissera sans doute Python plus lent cependant, c'est qu'il est typé dynamiquement, et il y a des tonnes de recherche pour chaque accès d'attribut.

Par exemple, appeler f sur un objet A provoquera des recherches possibles dans __dict__, Des appels à __getattr__, Etc., puis finalement appelera __call__ sur l'objet appelable f.

En ce qui concerne le typage dynamique, de nombreuses optimisations peuvent être effectuées si vous savez à quel type de données vous avez affaire. Par exemple, dans Java ou C, si vous avez un tableau droit d'entiers que vous voulez additionner, le code d'assemblage final peut être aussi simple que de récupérer la valeur à l'index i , en l'ajoutant à accumulator, puis en incrémentant i.

En Python, il est très difficile de rendre le code aussi optimal. Supposons que vous ayez un objet de sous-classe de liste contenant ints. Avant même d'en ajouter, Python doit appeler list.__getitem__(i), puis ajoutez cela à "l'accumulateur" en appelant accumulator.__add__(n), puis répétez. Des tonnes de recherches alternatives peut se produire ici, car un autre thread peut avoir modifié par exemple la méthode __getitem__, le dict de l'instance de liste ou le dict de la classe, entre les appels à ajouter ou getitem. Même la recherche de l'accumulateur et de la liste (et tout variable que vous utilisez) dans l'espace de noms local provoque une recherche dict. Cette même surcharge s'applique lorsque vous utilisez un 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 in Python 3, long in Python 2.x), list, set, dict, etc, etc, sont ce que les gens utilisent beaucoup 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, vous appelleriez simplement sum(list) à la place d'utiliser un accumulateur et un index. S'en tenir à ceux-ci, et un peu de calcul avec int/float/complex, vous n'aurez généralement pas de problèmes de vitesse, et si vous le faites, il y a probablement une petite unité critique de temps (une fonction de résumé SHA2 , par exemple) que vous pouvez simplement déplacer vers C (ou Java, en Jython). Le fait est que lorsque vous codez C ou C++, vous allez gaspiller beaucoup de temps à faire des choses que vous pouvez faire en quelques secondes/lignes de code Python. Je dirais que le compromis est vaut toujours la peine, sauf dans les cas où vous faites quelque chose comme une programmation intégrée ou en temps réel et que vous ne pouvez pas vous le permettre.

La compilation et l'interprétation ne sont pas importantes ici: Python is compilé, et c'est une infime partie du coût d'exécution pour tout programme non trivial.

Les principaux coûts sont: l'absence d'un type entier qui correspond aux entiers natifs (rendant toutes les opérations entières beaucoup plus chères), le manque 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 lors de l'exécution), et le manque de valeurs sans boîte (qui réduisent l'utilisation de la mémoire et peuvent éviter un niveau d'indirection).

Non pas qu'aucune de ces choses ne soit possible ou ne puisse être rendue plus efficace en Python, mais le choix a été fait pour favoriser la commodité et la flexibilité du programmeur, et la propreté du langage par rapport à la vitesse d'exécution. Certains de ces coûts peuvent être surmontés par une compilation JIT intelligente, mais les avantages Python fournit auront toujours un certain coût.

12
user97370

La différence entre python et C est la différence habituelle entre un langage interprété (bytecode) et compilé (vers natif). Personnellement, je ne vois pas vraiment python = aussi 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 met des algorithmes critiques en temps dans le code natif, ce qui le rend beaucoup plus rapide.

9
Femaref

Python est généralement implémenté en tant que langage de script. Cela signifie qu'il passe par un interpréteur, ce qui signifie qu'il traduit le code à la volée dans le langage machine plutôt que d'avoir l'exécutable tout en langage machine depuis le début. En conséquence, il doit payer le coût de la traduction du code en plus de son exécution. Cela est vrai même pour CPython même s'il compile en bytecode qui est plus proche du langage machine et peut donc être traduit plus rapidement. Avec Python vient également des fonctionnalités d'exécution très utiles comme le typage dynamique, mais de telles choses ne peuvent généralement pas être implémentées même sur les implémentations les plus efficaces sans coûts d'exécution élevés.

Si vous effectuez un travail très gourmand en processeur comme l'écriture de shaders, il n'est pas rare que Python soit quelque part environ 200 fois plus lent que C++. Si vous utilisez CPython, ce temps peut être réduit de moitié mais il est encore loin d'être aussi rapide. Avec tous ces goodies runtmie a un prix. Il y a beaucoup de repères pour le montrer et voici un particulièrement bon. Comme admis sur la première page, les repères sont défectueux. Ils sont tous soumis par des utilisateurs qui font de leur mieux pour écrire du code efficace dans la langue de leur choix, mais cela vous donne une bonne idée générale.

Je vous recommande d'essayer de mélanger les deux ensemble si vous êtes préoccupé par l'efficacité: vous pourrez alors tirer le meilleur parti des deux mondes. Je suis principalement un programmeur C++ mais je pense que beaucoup de gens ont tendance à coder trop de code mondain de haut niveau en C++ quand c'est juste une nuisance de le faire (compiler les temps comme un seul exemple). Mélanger un langage de script avec un langage efficace comme C/C++ qui est plus proche du métal est vraiment le chemin à parcourir pour équilibrer l'efficacité du programmeur (productivité) avec l'efficacité du traitement.

4
stinky472

Outre les réponses déjà publiées, une chose est la capacité des pythons à changer des choses en cours d'exécution que vous ne pouvez pas changer par exemple C. Vous pouvez ajouter des fonctions membres aux classes au fur et à mesure. De plus, la nature dynamique des pythons ne permet pas de dire quel type de paramètres sera transmis à une fonction, ce qui à son tour rend l'optimisation beaucoup plus difficile.

RPython semble être un moyen de contourner le problème d'optimisation.

Pourtant, il ne sera probablement pas proche des performances de C pour le nombrecrunching et similaires.

3
Mattias Nilsson

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

Ce qui est surprenant, c'est à quelle vitesse Python est en comparaison avec ses pairs d'autres langages dynamiques. Bien que la méthodologie soit souvent considérée comme défectueuse, regardez The Computer Language Benchmark Game to voir la vitesse relative du langage sur des algorithmes similaires.

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

3
dawg

C et C++ se compilent en code natif, c'est-à-dire qu'ils s'exécutent directement sur le CPU. Python est un langage interprété, ce qui signifie que le code Python que vous écrivez doit passer par de très nombreuses étapes d'abstraction avant de devenir un code machine exécutable).

1
Puppy