Schleifenzähler aufwärts oder abwärts schneller?

Algorithmen, Sprachunabhängige Diskussionen zu Konzepten, Programmiersprachen-Design
Antworten
Orioner
Beiträge: 102
Registriert: Mo Dez 10, 2012 10:52 am

Schleifenzähler aufwärts oder abwärts schneller?

Beitrag von Orioner » Sa Mai 18, 2013 3:28 pm

Ich weiß nicht mehr, wo ich es gelesen oder gehört habe, es könnte sogar in diesem Forum gewesen sein, doch wenn, wüsste ich nicht mehr, wo: Ein Rechner ist in der Lage, schneller "herunter" zu zählen, als "hinauf". So ist z. B. eine Schleife schneller durchlaufen, wenn der Schleifenzähler abwärts, statt aufwärts zählt. Kann das jemand bestätigen?

Des weiteren: Welche Art von Vergleich kann ein Rechner schneller ausführen, den auf Gleichheit, oder Ungleichheit? Wenn Ungleichheit: Spielt es eine Rolle, ob man "!=" schreibt, oder "<", bzw. ">", oder ist das (vom Prinzip her) das gleiche? Man könnte ja auf die Idee kommen, zu schreiben:

Code: Alles auswählen

int i = 2;
if( i < 2 || i >2 ) {
anweisung();
}
Kann sein, dass die Antwort recht einfach ist, aber ich weiß ja nicht, was Compiler und Computer "intern" so anstellen.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3123
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Schleifenzähler aufwärts oder abwärts schneller?

Beitrag von cloidnerux » Sa Mai 18, 2013 7:20 pm

Diese Fragen sind heutzutage mehr oder weniger Sinnbefreit, denn:
  • Moderne Rechner sind so schnell, dass da die Ersparnis von einigen wenigen Operationen keinen Unterschied macht
    Moderne Compiler sowieso deinen Code sehr gut optimieren
    und man keine Aussage über den entstandenen Maschinencode mehr treffen kann
Wenn du dich für Code-Optimierung interessierst, dann kannst du dir ja mal das zu Gemüte führen:
http://www.proggen.org/doku.php?id=project:wordcount

Zu den Vergleichen. Bei den Grunddatentypen sollte der Vergleich auf Gleichheit einfacher sein, da hier nur eine Bedingung geprüft werden muss(a=b), während Ungleichheit zwei Bedingungen voraussetzt(a<b || a>b). Wobei auch hier wieder die Prozessoren schon aufgeholt haben könnten und eben die Prüfung auf Ungleichheit als Operation anbieten, dann ist es egal da beides gleich schnell vom Prozessor abgearbeitet wird.
Das Prüfen mit Größer und Kleiner anstatt Ungleich sollte unter der Prämisse langsamer sein, da hier 2 Operationen ausgeführt werden müssen. Aber auch hier kann ein guter Compiler diese Zeile direkt Optimieren und es ist wieder egal.
Generell ist das aber kein guter Stil, da du hier mehr oder weniger Optimierungen durch Umständlichkeit erschwerst.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Schleifenzähler aufwärts oder abwärts schneller?

Beitrag von Xin » So Mai 19, 2013 8:49 am

Orioner hat geschrieben:Ich weiß nicht mehr, wo ich es gelesen oder gehört habe, es könnte sogar in diesem Forum gewesen sein, doch wenn, wüsste ich nicht mehr, wo: Ein Rechner ist in der Lage, schneller "herunter" zu zählen, als "hinauf". So ist z. B. eine Schleife schneller durchlaufen, wenn der Schleifenzähler abwärts, statt aufwärts zählt. Kann das jemand bestätigen?
Kann ich nicht bestätigen.

Was aber bei alten Computern zum Tragen kommen kann ist, dass die untere Grenze häufig 0 ist und es für den Vergleich gegen 0 einen Extra-Assemblerbefehl gibt, der schnell als der Vergleich gegen eine beliebige Zahl ist (ganz einfach, weil die Zahl nicht erst aus dem Programm geladen werden muss). Geht die Schleife aber von -7 nach 0 ist sie aufwärts genauso schnell wie eine Schleife von 7 nach 0 abwärts.
Orioner hat geschrieben:Des weiteren: Welche Art von Vergleich kann ein Rechner schneller ausführen, den auf Gleichheit, oder Ungleichheit? Wenn Ungleichheit: Spielt es eine Rolle, ob man "!=" schreibt, oder "<", bzw. ">", oder ist das (vom Prinzip her) das gleiche? Man könnte ja auf die Idee kommen, zu schreiben:

Code: Alles auswählen

int i = 2;
if( i < 2 || i >2 ) {
anweisung();
}
Kann sein, dass die Antwort recht einfach ist, aber ich weiß ja nicht, was Compiler und Computer "intern" so anstellen.
Auch hier ist weniger die Frage welcher Vergleich durchgeführt wird, sondern ob er gegen 0 oder gegen eine andere Zahl durchgeführt wird. So vergleichen manche CPUs die geladene Zahl bereits beim Laden mit 0, also ohne dass Du überhaupt einen Vergleich angefordert hast. Wenn Du also gegen 0 vergleichst kannst Du bei einigen CPUs den Vergleich weglassen und nach dem mov Befehl, der die Zahl in die CPU geladen hat mit dem then-Teil weitermachen.

Code: Alles auswählen

Mot 68k ASM

move.l a,d0        # Lade Variable a in Register d0
# cmp.l #0, d0    # Vergleiche d0 mit 0 überflüssig
jeq label            # Springe wenn gleich
Der Vergleich mit einer anderen Zahl als 0 ist immer eine Subtraktion:
a == 7 => a-7 == 0?

Eine CPU vergleicht auch nicht ob == oder !=, ob > oder <, sondern eine Zahl wird immer mit 0 verglichen und dann springen entsprechende Register in der CPU an: gleich 0, größer 0, kleiner 0. Wenn Du also mit != vergleichen möchtest ist, lautet die Frage "Ist das 'gleich 0'-Flag aus, dann springt dorthin'.
Das drückst Du über den entsprechenden Jump-Befehl aus: JEQ (Jump if Equal), JNE (Jumo if Not Equal), JL (Jump if Less), JG (Jump if Greater), JLE (Jump if Less Or Equal), JGE (Jump If Greater or Equal).
Jeder dieser Befehle braucht einen Takt. Sie sind also alle gleich schnell.
Von der Geschwindigkeit her also wieder nicht die Frage wie Du vergleichst, als wogegen Du vergleichst.

In C wirst Du Dir darum keine Gedanken machen müssen, bei unserem Wörterzählwettbewerb haben dani93 und ich Assemblerversionen geschrieben. Wir waren zwar schneller als die C-Versionen, aber wenn man den Compiler optimieren ließ, sah das Feld wieder ganz anders aus.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Orioner
Beiträge: 102
Registriert: Mo Dez 10, 2012 10:52 am

Re: Schleifenzähler aufwärts oder abwärts schneller?

Beitrag von Orioner » Mo Mai 20, 2013 9:03 pm

Vielen Dank für eure Antworten. Eure Beiträge waren sehr erhellen, wenn ich auch zugeben muss, dass ich mir das ein oder andere hätte denken können. Aber: Fang mir bloß nicht mit Assembler an, jedenfalls jetzt noch nicht! Davon habe ich keine Ahnung. Mich damit zu beschäftigen steht auf meiner Projektliste. ;)

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Schleifenzähler aufwärts oder abwärts schneller?

Beitrag von Xin » Mo Mai 20, 2013 10:05 pm

Orioner hat geschrieben:Vielen Dank für eure Antworten. Eure Beiträge waren sehr erhellen, wenn ich auch zugeben muss, dass ich mir das ein oder andere hätte denken können. Aber: Fang mir bloß nicht mit Assembler an, jedenfalls jetzt noch nicht! Davon habe ich keine Ahnung. Mich damit zu beschäftigen steht auf meiner Projektliste. ;)
Wenn Du (noch) keinen Bock hast bis zu dieser Ebene runter zu kommen, dann spielt es keine Rolle, ob Du aufwärts oder abwärts zählst und auch nicht, welche Vergleichsoperation Du ausführst.

Auch darf man vorsichtig davon ausgehen, dass moderne CPUs diese Aufgaben erledigt haben, bevor sie im eigentlichen Kern angekommen sind. Heutige CPUs sind häufig eine Reihe von spezialisierten Prozessoren. Das komplizierte landet im Kern, Kleinkram wie Vergleiche oder Additionen mit 1 sind bereits gelöst, so dass der Kernprozessor die Anweisung überhaupt nicht mehr zu sehen bekommt, sondern nur noch das Ergebnis durchreicht.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten