Was ist rechnerisch schneller? simple formel



  • Alithecoaster schrieb:

    ach und ++y ist auch schneller als y++ oder ?

    Ja, aber das gilt nur für nicht-builtins. Bei builtins optimiert der Compiler ein unnötiges i++. Man sollte sich imho aber angewöhnen i++ wirklich nur zu schreiben wenn man i++ meint und nicht ++i.

    Alithecoaster schrieb:

    und gibt es ne besondere art der schleife die bei sehr häufigen laufen besonders geeignet ist? * bis zu 1 mio mal am stück und das sehr häufig hintereinander? *

    Setze dich doch einfach mal ein wenig damit auseinander wie Compiler Code übersetzen und optimieren. Dann klären sich die meisten deiner Fragen von alleine. Nein, ein for ist nicht langsamer als while oder do-while. Es kommt immer darauf an was in der Schleife passiert.



  • Alithecoaster schrieb:

    ach und ++y ist auch schneller als y++ oder ?

    Bei built ins (int, long, char etc) ist es egal. Bei benutzerdefinierten Typen ist Präinkrement (++i) eigentlich immer schneller, da keine Kopie erzeugt werden muss.

    und gibt es ne besondere art der schleife die bei sehr häufigen laufen besonders geeignet ist? * bis zu 1 mio mal am stück und das sehr häufig hintereinander? *

    Letztlich ist nur das Design der Schleife wichtig. Die verschiedenen Schleifentypen werden eh alle in compares und jumps umgewandelt.



  • ach und ++y ist auch schneller als y++ oder ?

    Du musst beachten, dass diese beiden Schreibweisen ganz unterschiedliche Effekte haben.



  • 5(0rP schrieb:

    Du musst beachten, dass diese beiden Schreibweisen ganz unterschiedliche Effekte haben.

    Der Vollständigkeit halber sollte man noch erwähnen, dass sie nur unterschiedliche Effekte haben, sofern es nicht "isoliert" geschieht.

    int i = 42;
    ++i; // Effekt: i wird inkrementiert
    i++; // Effekt: i wird inkrementiert (hier optimiert der Compiler zu ++i)
    int a = ++i; // Effekt: i wird inkrementiert und dann a zugewiesen
    int b = i++; // Effekt: i wird b zugewiesen und dann inkrementiert
    


  • Hast ja recht 🙄



  • Code-Hacker schrieb:

    2. Da fiele mir pow ein, also: pow(y, 3) oder pow(y, 3.0)
    Erstes ist die Funktion "double pow(double, int)" und letzteres "double pow(double, double)".

    Für Ganzzahlen ist pow sicher nie schneller als normales (geschicktes) Multiplizieren.



  • Bei bestimmten Zahlen bzw. Potenzen kannst du auch mit Shifts ein bisschen tricksen. Das ist dann nochmal schneller.
    Brauch man oft in der Graphikprogrammierung.
    Da zerlegst du dann z.B. 640 in 512 + 128 und kannst dann wunderbar
    2<<9+2<<7 rechnen. Also, wenn du deine Potenzierungsalgorithmen irgendwie auf 2er-Potenzen zurückführen kannst, könnte diese Methode die schnellste sein...



  • Hi!

    Ringding schrieb:

    Code-Hacker schrieb:

    2. Da fiele mir pow ein, also: pow(y, 3) oder pow(y, 3.0)
    Erstes ist die Funktion "double pow(double, int)" und letzteres "double pow(double, double)".

    Für Ganzzahlen ist pow sicher nie schneller als normales (geschicktes) Multiplizieren.

    Wieso sollte es für Ganzzahlen nie schneller sein? Wegen dem Cast?

    Code-Hacker



  • @etheral: Ich weiß nicht wie du Grafik Programmierst, aber wenn du auch nur einen müden Frame mit der Benutzung von Bitshifts in einem Programm gewinnst, dann würde mich das echt wundern.



  • Maschi schrieb:

    i++; // Effekt: i wird inkrementiert (hier optimiert der Compiler zu ++i)
    

    Könntest du mir bitte erklären, WIE der Compiler hier optimiert?



  • interpreter schrieb:

    Maschi schrieb:

    i++; // Effekt: i wird inkrementiert (hier optimiert der Compiler zu ++i)
    

    Könntest du mir bitte erklären, WIE der Compiler hier optimiert?

    Er stellt während der Abhängigkeitsanalyse fest, dass das Ergebnis des Ausdruckes verworfen wird, also läßt er den Teil des Codes, der dafür zuständig ist, weg. Würd ich mal sagen.



  • randa schrieb:

    @etheral: Ich weiß nicht wie du Grafik Programmierst, aber wenn du auch nur einen müden Frame mit der Benutzung von Bitshifts in einem Programm gewinnst, dann würde mich das echt wundern.

    Jeder Compiler macht das automatisch (bei Multiplikation mit Konstanten).



  • randa schrieb:

    @etheral: Ich weiß nicht wie du Grafik Programmierst, aber wenn du auch nur einen müden Frame mit der Benutzung von Bitshifts in einem Programm gewinnst, dann würde mich das echt wundern.

    Unterschätze die Bedeutung nicht. Für dich als Anwendungsprogrammierer ist das wahrscheinlich nur selten interessant.
    Aber Zahlen wie 16, 256 sind keine Hirngespinnste von irgendwelchen Freaks. Texturen werden z.B. meistens in einer 2er-Potenz Größe im Grafikspeicher abgelegt.

    Es lassen sich unendlich viele weitere Beispiele finden. Mehrdimensionale Arrays, die intern als eindimensionales Array abgebildet werden, multiplizieren sich nicht die Indizes zusammen sondern shiften sie sich zusammen...



  • @Optimizer
    Und das muss ich wirklich alles selbermachen und nicht den Compiler übernehmen lassen? Ich versteh nicht so ganz wo man da optimieren kann, weil bei Konstanten berechnungen optimiert sowas doch wirklich der Compiler oder etwa nicht?



  • Jo, ich rede auch nicht Ausdrücken mit Konstanten. Aber wenn man irgendwas entwickelt (ein mehrdimensionales Array), dann muss man sich da schon Gedanken machen.
    Ging mir nur darum, zu sagen, dass das shiften nicht generell uninteressant ist. 🙂



  • randa schrieb:

    @etheral: Ich weiß nicht wie du Grafik Programmierst, aber wenn du auch nur einen müden Frame mit der Benutzung von Bitshifts in einem Programm gewinnst, dann würde mich das echt wundern.

    Oft genug kommst du in Situationen, in denen du deine x/y-Koordinate als lineares Array betrachten musst. Dann gibt's kein x/y mehr, sondern nur noch einen Wert im Array, der die entsprechende Position repräsentiert. Ergo berechnest du den Wert mit

    pos=y*Zeilenbreite+x
    

    Deine Auflösung am PC ist aber leider sehr selten 512 oder 256. Sondern eben 640,800,1600. Da musst du dann selbst ran.
    Hier mal ein paar Daten zum einfachen Assembler-Mul:

    Clocks Size
    Operands 808x 286 386 486 Bytes
    reg32 - - 9-38 13-42 2-4

    Brauch auf nem 486 bei 32bit-Registern bis zu 42 Takte.
    Dagegen ein SHL:

    Clocks Size
    Operands 808x 286 386 486 Bytes
    reg,CL 8+4n 5+n 3 3 2

    Brauch 3 Takte...Nehmen wir an, du splittest die Bildschirmbreite in zwei Summanden, die Zweierpotenzen sind.
    Hast du also 2*3 Takte + 1*1Takt, um beide zu addieren = ~7 Takte at all.
    Im Vergleich zu den 13-42 Takte ist das doch schon mal ein kleiner Fortschritt, oder? Und auch, wenn deine GUI noch so ausgefeilt ist, wird's im Endeffekt wohl immer auf ähnliche Art gelöst werden.

    LaMothe schreibt dazu im "Tricks of the..." auch interessante Kommentare. Shifts sind mächtiger, als man denkt 😉

    edit:Sry für die Formatierungsfehler in den Tabellen...



  • KPC schrieb:

    @Optimizer
    Und das muss ich wirklich alles selbermachen und nicht den Compiler übernehmen lassen? Ich versteh nicht so ganz wo man da optimieren kann, weil bei Konstanten berechnungen optimiert sowas doch wirklich der Compiler oder etwa nicht?

    man muss wissen, daß der compiler so sachen optimiert.
    das führt zu schnellerem code.

    bool operator<(Zeit const& a,Zeit const& b){
       return a.stunde*60+a.minute < b.stunde*60+b.minute;
    }
    

    ist in diesem sinne kacke, denn mit dem wissen um den trick mit dem shiften muß es heißen:

    bool operator<(Zeit const& a,Zeit const& b){
       return a.stunde*64+a.minute < b.stunde*64+b.minute;
    }
    

    es ist gut, wenn man weiß, was in den unteren stockwerken des computers passiert. natürlich soll keiner mehr mit der hand shiften, es reicht, dem compiler auf die sprünge zu helfen.



  • Bashar schrieb:

    interpreter schrieb:

    Maschi schrieb:

    i++; // Effekt: i wird inkrementiert (hier optimiert der Compiler zu ++i)
    

    Könntest du mir bitte erklären, WIE der Compiler hier optimiert?

    Er stellt während der Abhängigkeitsanalyse fest, dass das Ergebnis des Ausdruckes verworfen wird, also läßt er den Teil des Codes, der dafür zuständig ist, weg. Würd ich mal sagen.

    Richtig, das wird er auch machen. Aber er wird nicht das machen, was im Kommentar steht, denn bei einem int ist ++i nicht effizienter als i++. (Wenn der Compiler die Zeile nicht einfach streichen würde, WÜRDE es zu einem add eax, 1 oder inc werden)



  • Schlaumeier, aber dann ist es auch kein "mov + inc" mehr, sondern nur ein "inc" und ein einzelnes "inc" erzeugt auf den mir bekannten Plattformen keine Kopie! Hat da der Compiler etwa nicht optimiert wenn er eine redundante Kopie einspart?



  • hi,
    schaut mal hier das koennte euch vielleicht auch helfen:
    http://library.simugraph.com/articles/opti/optimizing.html


Anmelden zum Antworten