Frage von Pretan4, 37

Haben Programmiersprachen interne Algohrithmen zur Verbesserrung der Laufzeit (Beispiel im Text)?

BEISPIEL: angenommen ich habe eine variable "A" und die hat den Wert "1"

Nun wird A immer um den wert '1' größer . wenn A gleich 1.000.000 ist ,soll er den wert von A ausgeben (oder sowas)

Nun die Frage : geht der rechner jetzt alle werte von A durch , bis der Wert 1.000.000 erreicht ist , (also >1.000.000 'Rechnungen')

oder sind (manche/alle) Programmiersprechen so aufgebaut,dass er das Wachstum analysiert , und sofort "1.000.000" ausspuckt ? (vielleicht 30 'rechnungen')

wie sieht das bei kommplexeren vorgängen aus, unterscheiden sich die sprachen ?

Hilfreichste Antwort - ausgezeichnet vom Fragesteller
von PWolff, 26

Das sind weniger die Sprachen, die sich hier unterscheiden, als vielmehr die verwendeten Compiler, bzw. ob die Sprache überhaupt nur auf einem Interpreter läuft.

Je aufwendiger ein Compiler gebaut ist und je mehr er per Einstellungen auf Optimierung getrimmt ist, desto mehr derartige Vereinfachungen wird er vornehmen.

Im von dir genannten Beispiel kann es durchaus sein, dass ein Compiler erkennt, dass in der Schleife nichts passiert. Jetzt kommt es darauf an, ob er auf Geschwindigkeit optimieren darf oder annehmen soll, dass der Thread hier ein paar Mikrosekunden auf der Stelle rotieren soll.

Auch bei wesentlich komplexeren Beispielen schaffen viele Compiler noch Erstaunliches.

Etwas anderes ist mit interpretierten Sprachen - hier wird Befehl für Befehl analysiert und gleich nach der Analyse ausgeführt, und derartige Optimierungen sind prinzipbedingt fast nicht möglich.

Expertenantwort
von TeeTier, Community-Experte für programmieren, 14

Ich bin mir nicht sicher, ob ich die andere Antwort von maximilianus7 richtig verstanden habe, und habe selbst ein Experiment gemacht ...

Ergebnis: GCC optimiert den ganzen Murks ab -O2 weg und Clang sogar schon ab -O1.

Das heißt, aus diesem Code:

long A = 0;

while (1) {
A = A + 1;

if (A == 10000000000L) {
printf("%lu\n", A);
break;
}
}

... machen beide Compiler diese Kurzform:

printf("%lu", A);

Da sich die Frage aber auf Java bezieht, habe ich das ganze auch mit Java probiert und folgendermaßen realisiert:

long A = 0;

while (true) {
A = A + 1;

if (A == 10000000000L) {
System.out.println(A);
break;
}
}

Ich habe auf meinem System jetzt hier kein Oracle/Sun Java, aber zumindest der javac vom OpenJDK optimiert diesen Teil!

Aaaaaber, die Ausführung dauert deutlich länger, als die C-Version, also scheint da etwas nicht zu 100% wegoptimiert zu werden. Allerdings ist die Ausführung viel viel viel zu kurz, um einmal komplett durchzulaufen. Ich tippe mal auf JIT-Magie: Es wird zwar optimiert, aber nicht ansatzweise so gut wie bei C. :)

Ich habe wie gesagt auf diesem Rechner hier nur das OpenJDK, aber ich wette, die Oracle-Version optimiert noch mal eine Nummer besser, und am Endeffekt wird aus dem riesen Block diese einzige Zeile:

System.out.println(10000000000L);

Ich kann mir wirklich nicht vorstellen, dass es einen guten Compiler geben soll, der das nicht entsprechend verkürzt.

Ob für die Optimierungen letzendlich der Compiler oder cleveres Pipelining der CPU zuständig sind, müsste man mal durch einen Disassemblat klären, aber ich bin dazu jetzt zu faul. Ich tippe aber auf ersteres!

...

Edit: War ja doch nur ein Einzeiler, also hab ich mal nachgeschaut. Wie erwartet ist es doch der Compiler, der die ganze Schleife wegoptimiert.

Der Beweis (kurz vor dem printf-Call):

movabs $0x2540be400,%rdx

Ich hoffe, damit ist deine Frage beantwortet. :)

Kommentar von TeeTier ,

PS: Ich sehe jetzt erst, dass du in deinem Beispiel kein "break" drin hast. In diesem Falle ist die Antwort von maximilianus7 natürlich korrekt!

Und nebenbei kann man bei gcc mit -O2 einen Compilerbug beobachten. Der produzierte Maschinencode ist fehlerhaft. :)

Antwort
von klimer2012, 25

Dieses Beispiel Rechnet dir jedes System einzeln aus also 1000000 Rechnungen aber die mit mehreren Variablen werden oft durch einen internen Algorythmus umgeformt bzw verschnellert.

Antwort
von maximilianus7, 14

ich glaub du machst dir da falsche vorstellungen:
bei dieser - wenn auch sinnfreien - programmschleife:

A = 0;
while ( ... )
{
A = A + 1;
if ( A == 1000000 ) printf ("1 Mio erreicht");
}

wird nichts optimiert.
würde jedoch zusätzlich noch - unsinnigerweise - in der schleife noch
B = 7;
stehen, so wird ein guter kompiler dies aus der schleife herausnehmen.

Kommentar von wotan38 ,

Ich möchte keinen Compiler benutzen, der mir meine angegebenen Anweisungen herausnimmt, weil sie ihm sinnlos erscheinen. Der Compiler hat die Aufgabe, meinen Source-Code zu übersetzen und nicht darüber nachzudenken, ob das Sinn macht oder nicht. Was anderes ist es, wenn der Code im Widerspruch zu den Regeln steht, nach denen der Compiler sich richten muss. Da muss er Meldungen ausgeben, aber nicht meinen Code verändern. Für die Programmlogik ist der Programmierer zuständig, für die formale Richtigkeit der Compiler.

Keine passende Antwort gefunden?

Fragen Sie die Community