Pourquoi n'y a-t-il pas de compilateur Python pour le code machine natif?

25

Si je comprends bien, la cause de la différence de vitesse entre les langages compilés et python est que le premier compile du code jusqu'au code de la machine native, tandis que python compile en python bytecode, pour être interprété par le PVM. Je vois que de cette façon les codes python peuvent être utilisés sur plusieurs systèmes d'exploitation (au moins dans la plupart des cas), mais je ne comprends pas, pourquoi n'y a-t-il pas un compilateur supplémentaire (et facultatif) pour python, qui compile de la même manière que les compilateurs traditionnels . Cela laisserait au programmeur le choix, ce qui est plus important pour lui; exécutabilité multiplateforme ou performances sur machine native. En général; pourquoi n'y a-t-il pas de langues qui pourraient se comporter à la fois comme compilées et interprétées?

user2986898
la source
4
Il y en a . Haskell peut également se comporter comme compilé ou interprété via GHCI
toasted_flakes
C ++ a également des interprètes . Et probablement des tonnes d'autres langues ont les deux implémentations.
Claudio
2
En fait, en choisissant IronPythong ( ironpython.net ) et compiler le code IL produit en utilisant "ngen" ( msdn.microsoft.com/de-de/library/6t9t5wcf%28v=vs.110%29.aspx ), il existe un moyen pour compiler Python en code machine natif. Non pas que j'aie testé cette chaîne d'outils.
Doc Brown du
10
On peut écrire des compilateurs Python vers natif. Ils ne sont tout simplement pas très intéressants car ils n'améliorent pas réellement les performances de quelque manière que ce soit, à moins qu'ils n'implémentent en fait un langage qui ressemble à Python mais est beaucoup plus restreint. J'ai expliqué précédemment ailleurs pourquoi.

Réponses:

29

Non. La raison pour laquelle il existe des différences de vitesse entre des langages tels que Python et C ++ est que les langages de type statique fournissent au compilateur des tonnes d'informations sur la structure du programme et ses données, ce qui lui permet d'optimiser à la fois les calculs et l'accès à la mémoire. Parce que C ++ sait que la variable est de type int, il peut déterminer la manière optimale de manipuler cette variable avant même que le programme ne soit exécuté. En Python d'autre part, le runtime ne sait pas quelle est la valeur d'une variable jusqu'à ce que la ligne soit atteinte par l'interpréteur. Ceci est extrêmement important pour les structures, où en C ++, le compilateur peut facilement indiquer la taille de la structure et chaque emplacement de ses champs dans la mémoire pendant la compilation. Cela lui donne une énorme puissance pour prédire comment les données pourraient être utilisées et lui permet d'optimiser en fonction de ces prédictions.

Pour compiler efficacement des langages comme Python, vous devez:

  1. Assurez-vous que la structure des données est statique pendant l'exécution du programme. C'est problématique car Python a des eval et des métaclasses. Les deux qui permettent de changer la structure du programme en fonction de l'entrée du programme. C'est l'une des choses qui confèrent à Python un tel pouvoir expressif.
  2. Déduisez les types de toutes les variables, structures et classes à partir du code source lui-même. Bien que cela soit possible dans une certaine mesure, le système de type statique et l'algorithme seraient si complexes qu'il serait presque impossible de les mettre en œuvre de manière utilisable. Vous pouvez le faire pour un sous-ensemble de la langue, mais certainement pas pour l'ensemble des fonctionnalités linguistiques.
Euphorique
la source
6
Il convient de noter que cela rend le problème difficile , mais pas impossible. sbcl compile Common Lisp qui est également dynamique, a evalet beaucoup d'autres choses pour rendre les rédacteurs du compilateur tristes. Ce n'est pas au niveau de gcc, mais c'est certainement plus rapide que l'interpréteur de CPython.
Daniel Gratzer
3
@jozefg J'ai dit compiler efficacement. Pas seulement compiler. Python a aussi son compilateur Cython qui produit du code natif. Le fait est que ces compilateurs ne peuvent même pas fractionner les optimisations que les compilateurs pour les langages de type statique peuvent faire. Et lorsque vous comparez les performances, comparez-les au C ++ compilé et au Python non interprété.
Euphoric
2
Eh bien, en fait, vous seriez surpris de ce que sbcl peut faire. Le jeu de référence montre qu'il fonctionne aussi vite que Java, presque aussi vite que GHC, et dans une plage de 1 à 10x de C. Ce n'est pas lent par tous les standards. Oui, les types dynamiques inhibent la compilation dans une certaine mesure, mais pas autant que vous semblez le penser.
Daniel Gratzer
3
Comparer la vitesse du python interprété au python compilé est intéressant en soi. Arrêtez de dire "utilisez C ++". Peut-être que vous avez déjà le code écrit en Python. Peut-être que le code est plus facile à écrire en python. On s'en fout. Ce qui m'importe, c'est une accélération de 1,5x (quelle qu'elle soit). Cela peut faire une énorme différence.
Thomas Eding du
3
En d'autres termes, si vous souhaitez compiler, choisissez un autre langage qui est optimisé pour cela, comme C ++ ou Pascal.
Please_Dont_Bully_Me_SO_Lords
0

Deux concepts pourraient nous aider à mieux comprendre pourquoi Python compilé en code machine natif "peut" ne pas fonctionner aussi vite que C compilé ou d'autres langages compilés couramment. Ils sont appelés liaison anticipée et liaison tardive.

Je devrais commencer par dire que je ne suis pas un expert Python, et je suis venu sur ce site par accident. Mais j'aime ce site.

Comme mentionné dans une autre réponse ici, le compilateur C ++ peut en savoir beaucoup sur le programme et prendre des décisions sur les opérations à utiliser pour des structures de données spécifiques. Par exemple, si deux variables entières doivent être ajoutées ensemble, le compilateur sait qu'il s'agit d'entiers natifs, de 32 bits de large par exemple et il peut les ajouter avec une instruction "ADD". Il compile donc l'instruction ADD dans le code. Il est verrouillé et ne peut pas être modifié pendant l'exécution du programme. C'est une liaison anticipée.

D'un autre côté, dans un langage comme Python, nous pourrions nous attendre à ce que le programme jette différents types de données ensemble de manière complexe. Maintenant, le compilateur ne sait pas si nos 2 variables sont des entiers, des flottants, des chaînes ou des listes. Il doit donc compiler du code qui détermine ces informations au moment de l'exécution et sélectionner l'opération correcte pendant l'exécution du programme. Il s'agit d'une liaison tardive et nous pouvons comprendre qu'il y aura un impact sur les performances pour effectuer ce travail supplémentaire pendant l'exécution du programme. C'est le prix à payer pour garder ces options ouvertes dans un langage comme Python, mais il offre une flexibilité d'exécution maximale.

user214354
la source
-4

Je pense que cela a plus à voir avec les spécificités de Python lui-même, la même raison pour laquelle vous ne pouvez pas compiler C # en code machine. Les spécificités de la langue rendraient vos programmes bogués même si cela était possible en raison de la nature de la langue. Pourquoi ne pas simplement apprendre le langage C? C'est beaucoup plus facile que C ++ et légèrement avancé que Python mais toujours accessible.

Snappy
la source
5
C # peut aller directement au code machine: Common Intermediate Language: Ahead of Time compilation - "Les environnements d'exécution compatibles CLI ont également la possibilité de faire une compilation Ahead-of-time (AOT) d'un assemblage pour le rendre plus rapide en supprimant le processus JIT lors de l'exécution. Dans le .NET Framework, il existe un outil spécial appelé NGEN (Native Image Generator) qui exécute l'AOT. Dans Mono, il existe également une option pour effectuer un AOT. "