Als ich an der Universität studierte, hörte ich oft die Idee, dass Fortran-Compiler für ein gleichwertiges Programm schnelleren Code erzeugten als C-Compiler.
Die wichtigste Überlegung lautete wie folgt : Ein Fortran-Compiler gibt durchschnittlich 1,1 Prozessoranweisungen pro Codezeile aus, während ein C-Compiler durchschnittlich 1,6 Prozessoranweisungen pro Codezeile ausgibt - ich erinnere mich nicht an die genauen Zahlen, aber an die Die Idee war, dass C-Compiler merklich mehr Maschinencode ausgaben und daher langsamere Programme produzierten.
Wie gültig ist ein solcher Vergleich? Können wir sagen, dass Fortran-Compiler schnellere Programme produzieren als C-Compiler oder umgekehrt und warum gibt es diesen Unterschied?
c
comparison
compiler
fortran
scharfer Zahn
quelle
quelle
Antworten:
IIRC Einer der Hauptgründe, warum Fortran als schneller gilt, ist das Fehlen von Pointer-Aliasing. Daher können sie Optimierungen verwenden, die C-Compiler nicht verwenden können:
Aber ich stimme anderen hier zu: Der Vergleich der durchschnittlichen Anzahl von Assembler-Anweisungen, die für eine Codezeile generiert wurden, ist völliger Unsinn. Beispielsweise kann ein moderner x86-Kern zwei Befehle parallel ausführen, wenn er nicht auf dieselben Register zugreift. Sie können also (theoretisch) eine Leistungssteigerung von 100% für denselben Befehlssatz erzielen, indem Sie ihn einfach neu anordnen . Gute Compiler generieren häufig auch mehr Assembler-Anweisungen, um schnelleren Code zu erhalten (think loop unrolling, inlining). Die Gesamtzahl der Assembler-Anweisungen sagt wenig über die Leistung eines Codeteils aus.
quelle
restrict
Schlüsselwort von C kann der Autor einer Funktion angeben, dass ein Zeiger keine Aliase enthält. Reicht dies aus, um den Unterschied zu beheben, oder steckt mehr dahinter?Völlig ungültiger Vergleich.
Zunächst müssen Sie, wie @ Péter Török betont, die Anzahl der Zeilen in entsprechenden Programmen von Fortran und C vergleichen um überhaupt einen gültigen Vergleich der Anzahl der produzierten Zeilen zu erhalten.
Zweitens entsprechen weniger Codezeilen nicht immer schnelleren Programmen . Nicht alle Maschinenbefehle erfordern die gleiche Anzahl von Zyklen , aber Sie haben auch andere Probleme wie Speicherzugriff , Zwischenspeicherung usw.
Darüber hinaus können lange Code-Läufe schneller sein, da dies zu einer geringeren Anzahl von Ausführungszeilen führt (dh Line Count! = Executed Line Count ).
quelle
Dan ist richtig, längere Programme bedeuten nicht langsamere Programme. Es hängt stark davon ab, was sie tun.
Ich bin kein Experte für Fortran, ich weiß ein bisschen. Wenn ich sie vergleiche, würde gut geschriebenes C mit komplexeren Datenstrukturen und Funktionen eine viel bessere Leistung bringen als Fortran. Jemand (bitte) korrigiert mich, wenn ich mich hier irre, aber ich denke, Fortran ist ein bisschen "niedriger" als C. Wenn ja, würde Fortran mit Sicherheit einige Probleme schneller lösen.
Eine andere Sache, auf den ersten Blick dachte ich, Sie fragten, ob die Compiler schneller sind. Ich denke tatsächlich, dass Fortran im Allgemeinen schneller für ähnliche Codemengen kompiliert wird, aber das resultierende Programm und die Art und Weise, wie es ausgeführt wird, wären eine andere Geschichte. Es ist nur einfacher zu analysieren.
quelle
Ich denke, ein Teil davon ist, dass FORTRAN-Compiler entworfen wurden, um einige Arten von Mathematik sehr schnell durchzuführen. Aus diesem Grund wird FORTRAN verwendet, um Berechnungen so schnell wie möglich durchzuführen
quelle
Die Aussage mag in früheren Zeiten (ca. Ende der 70er Jahre) zutreffen, als C noch in den Kinderschuhen steckte, und Fortran wurde von allen großen Herstellern unterstützt und stark optimiert. Frühe Fortrans basierten auf der IBM-Architektur, also einfache Sachen wie die Arithmetik, wenn sicherlich eine Aussage pro Montageanweisung gewesen wäre. Dies gilt für ältere Maschinen wie Data General und Prime, die 3-Wege-Sprünge hatten. Dies funktioniert bei modernen Befehlssätzen ohne 3-Wege-Sprung nicht.
Codezeilen sind nicht gleich Code-Anweisungen. In früheren Versionen von Fortran war nur eine Anweisung pro Zeile zulässig. In späteren Versionen von Fortran können mehrere Anweisungen pro Zeile verwendet werden. C kann mehrere Anweisungen pro Zeile enthalten. Auf den schnelleren Produktionscompilern wie Intels IVF (ehemals CVF, MS Powerstation) und Intels C gibt es keinen Unterschied zwischen den beiden. Diese Compiler sind stark optimiert.
quelle
Bei FORTRAN alter Art musste ein Programmierer, der einen Teil eines Arrays für eine Funktion verfügbar machen wollte, einen Verweis auf das gesamte Array zusammen mit einem oder mehreren ganzzahligen Werten übergeben, die den Startindex und entweder den Endindex oder die Anzahl der Elemente angeben . C macht es möglich, dies zu vereinfachen, indem ein Zeiger zusammen mit der Anzahl der Elemente an den Anfang des interessierenden Abschnitts übergeben wird . Direkt ausgedrückt würde dies die Dinge schneller machen (zwei Dinge anstatt drei). Indirekt kann es jedoch zu einer Verlangsamung kommen, indem die Optimierungsarten, die ein Compiler ausführen kann, eingeschränkt werden.
Betrachten Sie die Funktion:
Wenn ein Compiler wüsste, dass jeder der Zeiger den Anfang eines Arrays identifiziert, könnte er Code generieren, der auf Elemente des Arrays parallel oder in beliebiger Reihenfolge einwirkt, da für x! = y Operationen auf dest [x ] beeinflusst weder src1 [y] noch src2 [y]. Zum Beispiel kann ein Compiler auf einigen Systemen davon profitieren, Code zu generieren, der äquivalent ist zu:
Beachten Sie, dass jede Operation, die einen Wert lädt oder berechnet, mindestens eine weitere Operation zwischen sich und der nächsten Operation hat, die diesen Wert verwendet. Einige Prozessoren können die Verarbeitung verschiedener Vorgänge überlappen, wenn diese Bedingungen erfüllt sind, wodurch die Leistung verbessert wird. Beachten Sie jedoch, dass ein C-Compiler die obige Transformation nicht ausführen kann, da ein C-Compiler nicht weiß, dass der Code keine Zeiger auf teilweise überlappende Bereiche eines gemeinsamen Arrays übergeben wird. FORTRAN-Compiler, denen äquivalenter Code zugewiesen wurde, konnten und haben jedoch eine solche Transformation durchgeführt.
Während ein C-Programmierer versuchen könnte, eine vergleichbare Leistung zu erzielen, indem er explizit Code schreibt, der die Schleife abwickelt und die Operationen benachbarter Durchläufe überlappt, könnte ein solcher Code die Leistung leicht verschlechtern, wenn er so viele automatische Variablen verwendet, dass ein Compiler sie "verschütten" muss Erinnerung. Der Optimierer eines FORTRAN-Compilers weiß wahrscheinlich mehr als ein Programmierer darüber, welche Formen der Verschachtelung in einem bestimmten Szenario eine optimale Leistung erbringen würden, und solche Entscheidungen sollten häufig solchen Compilern überlassen werden. Während C99 versuchte, die Situation von C durch Hinzufügen eines
restrict
Qualifizierers zu verbessern , konnte dies hier nur verwendet werden, wenndest[]
es sich um ein von beidensrc1[]
und getrenntes Array handeltesrc2[]
, oder wenn der Programmierer separate Versionen der Schleife hinzufügte, um die Fälle zu behandeln, in denen alle nichtdest
zusammenhängend warensrc1
undsrc2
, wosrc1[]
unddest
waren gleich undsrc2
waren unzusammenhängend, wosrc2[]
unddest[]
waren gleich undsrc1
waren unzusammenhängend, und wo alle drei Reihen gleich waren. Im Gegensatz dazu konnte FORTRAN alle vier Fälle problemlos mit demselben Quellcode und demselben Maschinencode behandeln.quelle