Warum gibt es keinen Python-Compiler für nativen Maschinencode?

25

Nach meinem Verständnis liegt der Grund für den Geschwindigkeitsunterschied zwischen kompilierten Sprachen und Python darin, dass der erste Code vollständig zum Code des nativen Computers kompiliert wird, während Python zu Python-Bytecode kompiliert wird, der vom PVM interpretiert wird. Ich sehe, dass auf diese Weise Python-Codes auf mehreren Betriebssystemen verwendet werden können (zumindest in den meisten Fällen), aber ich verstehe nicht, warum es keinen zusätzlichen (und optionalen) Compiler für Python gibt, der genauso kompiliert wie herkömmliche Compiler . Dies würde es dem Programmierer überlassen, auszuwählen, was für ihn wichtiger ist. Multiplattform-Ausführbarkeit oder -Leistung auf nativen Computern. Im Allgemeinen; warum gibt es keine sprachen, die sich sowohl kompiliert als auch interpretiert verhalten könnten?

user2986898
quelle
4
Gibt es . Haskell kann sich auch so verhalten, wie es von GHCI kompiliert oder interpretiert wird
toasted_flakes
C ++ hat auch Dolmetscher . Und wahrscheinlich haben Tonnen von anderen Sprachen beide Implementierungen.
Claudio
2
Wenn Sie IronPythong ( ironpython.net ) auswählen und den erstellten IL-Code mithilfe von "ngen" ( msdn.microsoft.com/de-de/library/6t9t5wcf%28v=vs.110%29.aspx ) kompilieren, gibt es eine Möglichkeit Kompilieren von Python in nativen Maschinencode. Nicht, dass ich diese Toolkette getestet hätte.
Doc Brown
10
Man kann Python-to-native-Compiler schreiben. Sie sind einfach nicht sehr interessant, da sie die Leistung nicht wesentlich verbessern, es sei denn, sie implementieren eine Sprache, die Python ähnelt, jedoch wesentlich eingeschränkter ist. Ich habe vorher woanders erklärt warum.

Antworten:

29

Nein. Der Grund für die Geschwindigkeitsunterschiede zwischen Sprachen wie Python und C ++ liegt darin, dass statisch typisierte Sprachen dem Compiler unzählige Informationen über die Struktur des Programms und seine Daten liefern, die es ihm ermöglichen, sowohl Berechnungen als auch den Speicherzugriff zu optimieren. Da C ++ weiß, dass eine Variable vom Typ int ist, kann es bereits vor dem Ausführen des Programms bestimmen, wie diese Variable optimal manipuliert werden kann. In Python hingegen weiß die Laufzeit erst, welcher Wert in einer Variablen enthalten ist, wenn der Interpreter die Zeile erreicht hat. Dies ist äußerst wichtig für Strukturen, bei denen der Compiler in C ++ die Größe der Struktur und jede Position ihrer Felder im Speicher während der Kompilierung leicht erkennen kann. Dies gibt ihm eine enorme Aussagekraft bei der Vorhersage, wie die Daten verwendet werden könnten, und ermöglicht eine Optimierung gemäß diesen Vorhersagen.

Um Sprachen wie Python effektiv zu kompilieren, müssten Sie:

  1. Stellen Sie sicher, dass die Datenstruktur während der Ausführung des Programms statisch ist. Dies ist problematisch, da Python über Evaluierungs- und Metaklassen verfügt. Beides ermöglicht es, die Struktur des Programms basierend auf der Eingabe des Programms zu ändern. Dies ist eines der Dinge, die Python eine solche Ausdruckskraft verleihen.
  2. Leiten Sie die Typen aller Variablen, Strukturen und Klassen aus dem Quellcode selbst ab. Obwohl es bis zu einem gewissen Grad möglich ist, dass das System und der Algorithmus vom statischen Typ so komplex sind, dass es nahezu unmöglich ist, sie auf brauchbare Weise zu implementieren. Sie könnten es für eine Teilmenge der Sprache tun, aber definitiv nicht für die gesamte Menge der Sprachfunktionen.
Euphorisch
quelle
6
Es ist erwähnenswert, dass dies das Problem schwierig , aber nicht unmöglich macht. sbcl kompiliert Common Lisp, das ebenfalls dynamisch ist eval, und eine Reihe anderer Dinge, die Compiler-Autoren traurig machen. Es ist nicht auf dem Niveau von gcc, aber es ist sicherlich schneller als CPythons Interpreter.
Daniel Gratzer
3
@jozefg Ich sagte effektiv kompilieren. Nicht nur kompilieren. Python hat auch einen Cython-Compiler, der nativen Code erzeugt. Der Punkt ist, dass diese Compiler nicht einmal einen Bruchteil der Optimierungen durchführen können, die Compiler für statisch typisierte Sprachen können. Und wenn Sie die Leistung vergleichen, vergleichen Sie sie mit kompiliertem C ++ und nicht mit interpretiertem Python.
Euphoric
2
Nun, Sie wären überrascht, was sbcl kann. Das Benchmarks-Spiel zeigt, dass es so schnell wie Java läuft, fast so schnell wie GHC und innerhalb von 1x bis 10x von C. Es ist in keiner Weise langsam. Ja, dynamische Typen hemmen die Kompilierung in gewissem Maße, aber nicht so sehr, wie Sie zu glauben scheinen.
Daniel Gratzer
3
Der Vergleich der Geschwindigkeit von interpretiertem Python mit kompiliertem Python ist an sich interessant. Hör auf zu sagen "benutze C ++". Vielleicht haben Sie den Code bereits in Python geschrieben. Vielleicht ist der Code einfacher in Python zu schreiben. Wen interessiert das. Was mir wichtig ist, ist eine 1,5-fache Geschwindigkeit (was auch immer es ist). Das kann einen großen Unterschied machen.
Thomas Eding
3
Mit anderen Worten, wenn Sie kompilieren möchten, wählen Sie eine andere Sprache, die dafür geeignet ist, wie C ++ oder Pascal.
Please_Dont_Bully_Me_SO_Lords
0

Zwei Konzepte helfen uns möglicherweise dabei, besser zu verstehen, warum Python, das mit nativem Maschinencode kompiliert wurde, möglicherweise nicht so schnell ausgeführt wird wie kompiliertes C oder andere häufig kompilierte Sprachen. Sie werden als Frühbindung und Spätbindung bezeichnet.

Zunächst sollte ich sagen, dass ich kein Python-Experte bin und zufällig auf diese Site gekommen bin. Aber ich mag diese Seite.

Wie in einer anderen Antwort erwähnt, kann der C ++ - Compiler viel über das Programm wissen und Entscheidungen darüber treffen, welche Operationen für bestimmte Datenstrukturen verwendet werden sollen. Wenn beispielsweise zwei Ganzzahlvariablen zusammenaddiert werden müssen, weiß der Compiler, dass es sich um native Ganzzahlen handelt, die beispielsweise 32 Bit breit sind, und kann sie mit einem "ADD" -Befehl zusammenaddieren. So kompiliert es den ADD-Befehl in den Code. Es ist gesperrt und kann nicht geändert werden, während das Programm ausgeführt wird. Das ist frühzeitig verbindlich.

Andererseits können wir in einer Sprache wie Python erwarten, dass das Programm verschiedene Datentypen auf komplexe Weise zusammenführt. Der Compiler weiß jetzt nicht, ob es sich bei unseren 2 Variablen um Ganzzahlen, Gleitkommazahlen, Zeichenfolgen oder Listen handelt. Daher muss Code kompiliert werden, der diese Informationen zur Laufzeit ermittelt, und der richtige Vorgang muss ausgewählt werden, während das Programm ausgeführt wird. Dies ist eine späte Bindung und wir können verstehen, dass es einen Leistungseinbruch geben wird, wenn Sie diese zusätzliche Arbeit ausführen, während das Programm ausgeführt wird. Es ist der Preis, den Sie zahlen, wenn Sie diese Optionen in einer Sprache wie Python offen halten, aber es bietet maximale Laufzeitflexibilität.

user214354
quelle
-4

Ich denke, es hat mehr mit den Python-Besonderheiten selbst zu tun, der gleiche Grund, warum Sie C # nicht in Maschinencode kompilieren können. Sprachspezifische Besonderheiten würden Ihre Programme sogar dann fehlerhaft machen, wenn dies aufgrund der Art der Sprache möglich wäre. Warum nicht einfach die C-Sprache lernen? Es ist viel einfacher als C ++ und etwas fortgeschrittener als Python, aber dennoch zugänglich.

Bissig
quelle
5
C # kann direkt zum Maschinencode wechseln: Common Intermediate Language: Ahead-of-Time-Kompilierung - "CLI-kompatible Ausführungsumgebungen bieten auch die Möglichkeit, eine Ahead-of-Time-Kompilierung (AOT) einer Assembly durchzuführen, damit diese durch Entfernen schneller ausgeführt werden kann den JIT-Prozess zur Laufzeit. In .NET Framework gibt es ein spezielles Tool namens Native Image Generator (NGEN), das das AOT ausführt. In Mono gibt es auch die Option, ein AOT durchzuführen. "