Schneller Code vs. Übersichtlichkeit/Wartbarkeit



  • slax schrieb:

    Wie kann ich den Compiler zwingen den gesamten code zu inlinen?

    Das kannst du auch so nicht.

    slax schrieb:

    Wie gesagt, die condition kann sich zur Laufzeit ändern (aber nicht während dem Funktionsaufruf).

    Dann helfen templates natürlich nix.



  • otze schrieb:

    Bei 20-30 instruktionen sollte der compiler jede als inline deklarierte Funktion auch inline machen.

    Ich hoff, du compileirst mit maximalen Optimierungen. In dem Setup sollte der Compiler schon ziemlich gut optimieren.

    Ok, ich sollte noch folgendes erwähnen:
    Die Compilereinstellungen sind auf optimale Geschwindigkeit eingestellt.
    Der Code muss von unterschiedlichen Compilern für verschiedene Plattformen kompiliert werden (x86 u. x64).

    Ja er sollte aber wie kann ich mir sicher sein, ohne jedesmal das Disassembly zu prüfen?



  • slax schrieb:

    Ja er sollte aber wie kann ich mir sicher sein, ohne jedesmal das Disassembly zu prüfen?

    gar nicht...



  • dot schrieb:

    Das kannst du auch so nicht.

    Doch, und zwar indem ich ihn über die hässliche Macromethodik ihn dazu zwinge den kompletten Code aufzublähen. Aber das will ich ja nicht.



  • Gut, Makros sind natürlich ein Weg. Aber ich würd einfach eine inline Funktion verwenden.



  • dot schrieb:

    slax schrieb:

    Wie gesagt, die condition kann sich zur Laufzeit ändern (aber nicht während dem Funktionsaufruf).

    Dann helfen templates natürlich nix.

    Hm.. warum nicht?

    template<bool condition>
    void calc()
    {
      for ()
      {
        for()
        {
          if (condition)
        }
      }
    }
    

    Klar, das ist immer noch nicht erzwungen, aber wenn der Compiler hier immer noch nicht optimiert fress ich nen Donut.



  • Weil condition zur Compiletime bekannt sein muss...

    EDIT: Achso, es geht wirklich nur um ein if. Dann sind Templates natürlich die Lösung...



  • dot schrieb:

    Weil condition zur Compiletime bekannt sein muss...

    Na ja..

    cout << "Wanna condition?";
    bool wanna;
    cin >> wanna;
    if (wanna)
      calc<true>();
    else
      calc<false>();
    


  • Ja, das ist die Lösung. Ich dachte bei Condition gings um irgendwelche Werte die erst irgendwo mitten drin zur Laufzeit bestimmt werden müssten und so...



  • Ahja danke, dass hilft mir ungemein.
    Hatte templates "sorum" bisher noch nicht benutzt.



  • slax schrieb:

    Ahja danke, dass hilft mir ungemein.
    Hatte templates "sorum" bisher noch nicht benutzt.

    ist doch auch humbug...



  • King George schrieb:

    humbug...

    Bitte bleib doch im NadRW Forum, da schätzen wir alle deine Meinung sehr.



  • Man schreibt fuer Datenforma A eine Funktion, fuer B, fuer C, ... da wuerde ich dann gemeinsame Teile nicht weiter in Funktionen auslagern. Wenns dann mehrmals ist, ist es halt so. Auf dem Top-Level bleibt es aber uebersichtlich. Dazu braucht man nicht zwingend Templates.



  • Grund: Die Verarbeitung an "einem Stück" ist schnell. Kapselt man nun jetzt gemeinsam genutzte Codeteile bricht die Performance teilweise massiv ein, weil der Compiler dann halt Funktionsaufrufe macht, o.g. Konstanten nicht mehr zur Compilezeit berechnet sondern zur Laufzeit.

    Und was ist mit inline?



  • Was soll damit sein?



  • knivil schrieb:

    Man schreibt fuer Datenforma A eine Funktion, fuer B, fuer C, ... da wuerde ich dann gemeinsame Teile nicht weiter in Funktionen auslagern. Wenns dann mehrmals ist, ist es halt so. Auf dem Top-Level bleibt es aber uebersichtlich. Dazu braucht man nicht zwingend Templates.

    Nö aber mit Templates ist das halt drei mal weniger Code..



  • Naja dann habe ich keine Aufrüfe mehr, sondern direkt "geinlineten" code, oder irre ich mich?
    Sodass zwar für den Compiler eine Codeduplizierung existiert, aber nicht für den Programmierer. Die Geschwindigkeit bleibt dennoch gleich.



  • cooky451 schrieb:

    Nö aber mit Templates ist das halt drei mal weniger Code..

    Haha! Es kommt immer drauf an: http://www.youtube.com/watch?v=zh8W4ZglOlw 49:35 . Ich kann dir auch leicht eine Aufgabe geben, an der du dich probieren kannst.



  • inline ist ein Hinweis, aber zwingt den Compiler zu nichts. Moderne Compiler wie MSVC entscheiden von selbst was geinlined wird und was nicht, unabhängig davon ob inline davor steht oder nicht...



  • slax schrieb:

    Die if Abfrage in der inneneren Schleife ist völlig ineffizient, weil die Schleifen entsprechend oft durchlaufen werden. Die Bedingung kann sich aber auch während dem Funktionsaufruf nicht ändern.

    Du schreibst die Bedingung ändert sich nicht.

    Angenommen du hilfst dem Compiler etwas indem du die Bedingung in ein eigenes bool speicherst ala

    // ...
        bool const someCondition = PossiblySomeComputationsOrComparisons;
        for (...)
        {
            // ...
            if (someCondition)
            {
                // ...
            }
            else
            {
                // ...
            }
            // ...
        }
    

    Dann ist schonmal sichergestellt dass es wirklich nur mehr um einen Conditional-Branch geht, und nicht diverse Berechnungen bei jedem Schleifendurchlauf neu angestellt werden. (Das könnte sonst nämlich passieren, z.B. weil der Compilier auf Grund von möglichem Aliasing nicht sicher weiss, dass die Variablen in der Bedingung in der Schleife garantiert nicht verändert werden können).

    Dann hast du also einen Conditional-Branch in der Schleife, der immer immer immer gleich ausgeht.

    Genau dafür wurde Branch-Prediction erfunden, und genau das macht sie sensationell gut. Zumindest auf den CPUs wo ich es ausprobiert habe (Pentium 4, Core 2).
    D.h. mach erstmal nen Versuch mit "if vs. kein-if", und wenn er so ausgeht wie ich es mir erwarte (=kein relevanter Unterschied messbar), dann schreib es einfach mit nem normalen "if".

    Falls der Unterschied doch gut spürbar ist (z.B. weil du CPUs unterstützen musst die keine (gute) Branch-Prediction haben), dann würde ich die Template-Variante empfehlen.

    Ansonsten gibt es immer noch den Präprozessor:

    // foo_variant_impl.hpp
    
    // Kein Include-Guard!
    
    namespace {
    
    void FOO_VARIANT_NAME()
    {
        // ...
    
        for (...)
        {
            // ...
            DoStuffWith(FOO_VARIANT_SOME_CONSTANT);
    #if FOO_VARIANT_SOME_CONDITION != 0
            {
                // ...
            }
    #else
            {
                // ...
            }
    #endif
            // ...
        }
    }
    
    } // namespace
    
    #undef FOO_VARIANT_NAME
    #undef FOO_VARIANT_SOME_CONDITION
    #undef FOO_VARIANT_SOME_CONSTANT
    
    // foo.cpp
    #define FOO_VARIANT_NAME FooA
    #define FOO_VARIANT_SOME_CONDITION 1
    #define FOO_VARIANT_SOME_CONSTANT 12
    #include "foo_variant_impl.hpp"
    
    #define FOO_VARIANT_NAME FooB
    #define FOO_VARIANT_SOME_CONDITION 0
    #define FOO_VARIANT_SOME_CONSTANT 42
    #include "foo_variant_impl.hpp"
    
    void Foo(bool someCondition)
    {
        if (someCondition)
            FooA();
        else
            FooB();
    }
    

    Bietet sich auf für C-Projekte an, wenn man sich nicht auf das Inlining des Compilers verlassen will.

    (Wenn schon, dann kann man ja genau das selbe machen wie mit Templates, nur nen normalen bool Parameter übergeben statt des Template-Arguments. Wenn der Compiler das inlinen tut, sieht er ja dass die Condition Konstant ist, und wird entsprechend den "if" oder den "else" Zweig wegwerfen)

    Ist mMn. auf jeden Fall alles besser als den Code mehrfach zu schreiben (Wartbarkeit!). Speziell wenn es mehr als ein paar Zeilen sind, doppelt speziell wenn es Code ist der nicht ganz einfach zu verstehen ist (was bei SSE-Code ja oft der Fall ist).


Anmelden zum Antworten