for-Optimierung



  • Wurstinator schrieb:

    Der Compiler ist also schlau genug, zu erkennen, ob sich während der Schleife etwas am Funktionswert ändert und optimiert gegebenenfalls.

    Nein, siehe Antwort von knivil. Ich bin sogar ziemlich skeptisch, ob er das bei so vielen Funktionen tatsächlich erkennen kann. Trotzdem würde ich den Endwert nur selten rausziehen, außer ich weiß von vornherein, dass der Compiler das nicht erkennen kann und es was ausmacht (z.B. COM Aufrufe).

    @Cooky: typische Einstellung von einem Schüler 😉 Ich habe damals auch so gedacht. Aber robuster, allgemein gut lesbarer Code ist sehr viel wichtiger als irgendwelche obskuren Tricks oder potentielle minimale Optimierungen. Ich habe so eine Schleife wie bei dir noch nie im Real Life Code gesehen, und überhaupt hab ich noch nie eine Schleife gesehen, die rückwärts iteriert, außer es ist explizit so gewollt, und ich will sowas auch nicht sehen 😉
    Auch mit irgendwelchem Templatecode würden sich zumindest bei uns in der Arbeit gleich mal paar nicht ganz unwichtige Leute beschweren. Wenn das interner Code ist, den niemand direkt benutzt und der gekapselt ist, ok. Aber wenn das zum "normalen" "Hauptcode" gehört, wo jeder dran arbeitet und das jeder irgendwo verstehen muss, oder auch mal schnell ändern/fixen, wenn der jenige im Urlaub ist, oder man das Projekt übernommen hat oder was auch immer, keine Chance. Niemand will da Template Code sehen und sich schon gar nicht in sowas reindenken. Ausnahmen sind interne Bibliotheken, wo das wirklich Sinn macht. Aber je "dümmer" und einfacher der normale Code ist, desto besser.



  • Wurstinator schrieb:

    Der Compiler ist also schlau genug, zu erkennen, ob sich während der Schleife etwas am Funktionswert ändert und optimiert gegebenenfalls.
    Ok, danke 🙂

    Bei Funktionen in einer anderen Übersetzungeinheit nicht. Der GCC könnte es wahrscheinlich, wenn du die aufzurufende Funktion als "pur" deklarierst, aber das ist dann nicht mehr portabel. Eine andere Möglichkeit wäre Link-Time-Optimization.



  • Die ~i Variante war bloss als Beispiel für eine komplett bescheuerte Schreibweise gedacht. Wenn es wichtig ist sagt es, vielleicht fällt mit ja noch was bekloppteres ein.

    Und ja, da muss dann natürlich foo() - 1 hin.



  • Mechanics schrieb:

    Nein, siehe Antwort von knivil. Ich bin sogar ziemlich skeptisch, ob er das bei so vielen Funktionen tatsächlich erkennen kann.

    Und ich bin mir ziemlich sicher, dass VS, GCC und der Intel Compiler das bei allen Funktionen packen die geinlined werden.

    Mechanics schrieb:

    obskuren Tricks

    Hättest du die letzten 4 Seiten gelesen, sollte dir klar sein, dass ich das eben nicht als obskuren Trick ansehe. std::tuple, std::function und std::make_shared sind obskure Tricks, aber doch nicht "i-- != 0". 😉



  • Liebes Keks,
    DU empfindest es vielleicht nicht als obskure Tricks.
    Andere schon.
    Ist eben alles Ansichtssache.

    Und bei Kritik im Sinne von "das versteht ja keiner" einfach immer sagen "pf, ich versteh das super" ist irgendwie nicht sinnvoll.



  • cooky451 schrieb:

    Mechanics schrieb:

    Nein, siehe Antwort von knivil. Ich bin sogar ziemlich skeptisch, ob er das bei so vielen Funktionen tatsächlich erkennen kann.

    Und ich bin mir ziemlich sicher, dass VS, GCC und der Intel Compiler das bei allen Funktionen packen die geinlined werden.

    Mhm, ja, täusch dich mal nicht.



  • knivil schrieb:

    krümelkacker schrieb:

    for (size_t i = foo(); ~i; i--)
        ...
    

    Sie läuft von einschließlich foo() bis ausschließlich 0.

    Bei mir lauft sie sogar bis einschliesslich 0.

    Jo, stimmt. Da habe ich mich echt vertan. Ich finde ~i irgendwie weniger lesbar als das i-->0 in anderen Schleifen.

    knivil schrieb:

    Wie würdest du denn eine Schleife bauen, die
    von ausschließlich foo() bis einschließlich 0
    läuft?

    for (size_t i = foo()-1; ~i; i--)
    

    So?

    Ist das dein Ernst? Tja, so kann's gehen. for(;;) ist wohl doch zu mächtig und wenig lesbar, wenn ich mir diese Tricks i-->0 bzw ~i zum Umgehen des Unterlaufproblems anschaue ...

    Kann mir vorstellen, dass for-range bald so oder so ähnlich genutzt wird:

    for (auto i : reversed(range(0,foo()))) {
    
    }
    

    oder in Boost.Range Pipe-Syntax:

    for (auto i : range(0,foo()) | reverse) {
    
    }
    

    🙂



  • Das schreit nach einer Spracherweiterung...

    for (auto i ~: dings)
    

    😃



  • cooky451 schrieb:

    Hättest du die letzten 4 Seiten gelesen, sollte dir klar sein, dass ich das eben nicht als obskuren Trick ansehe.

    Ich hab alles gelesen und ich weiß, dass du das nicht als obskuren Trick ansiehst. So obskur find ich das jetzt auch nicht mal, die Aussage war nicht ausschließlich darauf bezogen. Aber es ist eben obskur genug. Ich kann mich nur wiederholen, je einfacher und dümmer der Code ist, desto besser ist es meist. Alles was nicht absolut straight forward ist, ist nur eine zusätzliche Stör- und Fehlerquelle.



  • hustbaer schrieb:

    Das schreit nach einer Spracherweiterung...

    for (auto i ~: dings)
    

    😃

    Könnt' man nicht einfach ein neues "reversed_for" einführen? Das wäre doch schöner als das, wo man sich ohne Vorkenntnisse einfach fragt, was die Tilde da jetzt soll...



  • Ich wollte es wissen:

    noinline unsigned test_klassisch(unsigned n)
    {
      unsigned counter = 0;
      unsigned bla = foo();
      for( unsigned i = 0; i < bla; ++i )
           counter += i * n;
      return counter;
    }
    
    noinline unsigned test_dekrementierend(unsigned n)
    {
      unsigned counter = 0;
      for( unsigned i = foo(); i-- != 0; )
           counter += i * n;
      return counter;
    }
    
    noinline unsigned test_range(unsigned n)
    {
      unsigned counter = 0;
      for ( auto i : irange(0u,foo()) | reversed) 
            counter += i * n;
      return counter;
    }
    

    Ergebnis: http://81.169.152.91/etc/results.html



  • Athar schrieb:

    Ich wollte es wissen:

    Und hast dabei die Schleife falsch abgeschrieben..

    Athar schrieb:

    Ergebnis: http://81.169.152.91/etc/results.html

    Hatten wir genau den gleichen Benchmark nicht schon vor ein paar Seiten? Oo Ja genau, und hatten festgestellt dass GCC die Optimierung hier einfach nicht rafft, im Gegensatz zu VS. Interessant wäre höchstens noch ein Vergleich auf einem i386 mit VS.



  • jeder sagt es ist unleserlicher, aber cooky451 findet es leserlich, also hat cooky451 recht. 🙄

    cooky451 hast du schon mal einen profiler verwendet und hast dann festgestellt, dass die klassischen Schleifen dein Programm langsam machen und nicht der Schleifeninhalt?


Anmelden zum Antworten