Nachdem wir uns die vorherigen Fragen angeschaut haben 1 , 2 Ich habe mich gefragt, ob ich den Compiler zwingen kann, eine konstante Faltung für den folgenden Code durchzuführen, der Primzahlen ausgibt.
%Vor%Und ich baue es über:
%Vor%Als Ergebnis sind ein paar:
%Vor%Ich möchte Compiler zwingen, den Code ähnlich wie
zu betrachten %Vor%oder
%Vor%Aber das Lesen der Baugruppe zeigt, dass nichts passiert.
Ich habe sogar __builtin_expect
verwendet, aber es hat nicht funktioniert.
Gibt es eine Möglichkeit, den Compileroptimierer zu zwingen, die for-Schleife zu lesen und den Vorteil zu nutzen, dass die Ausgabedaten bekannt sind?
Ich würde es gerne tun, ohne Template-Metaprogrammierung zu verwenden.
PS. Mein Ziel ist es, nur den Compiler zu testen und nicht eine effiziente Methode, um Primzahlen zu berechnen. Ich möchte nur meinen Freunden zeigen, wie viel C ++ Compiler mächtig ist.
Wenn die Trennung von is_prime
wichtig ist, lege ich alles in den Hauptteil und es wurde kein Unterschied festgestellt:
Es gibt sogar ein weiteres Beispiel, das für den Compiler keine Entschuldigung bleibt:
%Vor%Assembly:
%Vor%Es gibt ein grundlegendes Missverständnis der Compiler hier. Untersuchen wir das Programm, das Sie sehr sorgfältig geschrieben haben, und denken Sie darüber nach, was Sie vom Compiler für Sie erwarten.
Das Hauptmerkmal des Programms ist, dass es keine Eingabe benötigt, aber es gibt eine Ausgabe aus, indem es in cout
schreibt. Beachten Sie, dass die Funktion is_prime
kein Compiler intrinsisch ist; der Compiler behandelt es nur als eine andere Funktion. Das ist wichtig und ich werde später darauf zurückkommen.
Nun, wie würde der Compiler das Programm so umwandeln, wie Sie es beschrieben haben? Wie kann es so etwas tun? Das heißt, wie kann der Compiler diese beiden verschachtelten Schleifen in eine einfache Sequenz von Anweisungen umwandeln, die ganze Zahlen in cout
schreiben? Die einzige Möglichkeit, dies zu tun, ist, das Programm auszuführen , um alle Werte herauszufinden, die in cout
geschrieben werden müssen.
Das macht keinen Sinn, oder? Schauen wir uns das große Bild hier an und betrachten Sie alle Programme (oder Anweisungsfolgen), die die gleiche Charakteristik haben; diejenigen, die keine Eingaben machen, sondern Ausgaben ausgeben. Die Frage würde lauten: Warum führt der Compiler den Quellcode nicht aus und gibt nur Code aus, der die Ausgabewerte schreibt? Aus folgenden Gründen:
cout
schreiben. Der Standard-Ausgabestream kann auf etwas Seltsames umgeleitet werden. Programme, die keine Eingaben machen, sind daher für den Compiler nicht unbedingt einfacher zu optimieren. Das heißt, einfache Codeabschnitte, die in sehr kurzer Zeit ausgewertet werden können, werden vom Compiler tatsächlich ausgewertet. Diese Optimierung wird als konstante Faltung bezeichnet. Codeabschnitte, die den Status des Programms nicht beeinflussen, können eliminiert werden, ohne sie auszuführen. Wenn Sie beispielsweise cout<<i<<endl;
entfernt haben, wird der Compiler nur den Rest des Codes optimieren. Dies wird Beseitigung von toten Codes genannt. Compiler machen diese Optimierungen, weil sie vom Compiler auf systematische Weise durchgeführt werden können und weil sie sehr effektiv auf echten Codebasen sind.
Aber was passiert, wenn die is_prime
-Funktion ein intrinsischer Compiler ist? In diesem Fall hätte der Compiler wahrscheinlich eine eingebaute Tabelle mit häufig verwendeten Primzahlen und eine sehr schnelle Implementierung des Primzahltests. Sie können dann vom Compiler erwarten, das loop
in der Hauptfunktion mehrmals, vielleicht sogar vollständig, zu entpacken, wobei nur Ausgabeanweisungen enthalten sind, die im Wesentlichen die von Ihnen gewünschte Transformation ausführen.
Tags und Links c++ compiler-optimization g++