Prozessoroptimierte Funktionen



  • Theoretisch sind DLLs nie für Klassen ausgelegt worden.
    Praktisch gibt es ein paar Compiler, die auch C++ Klassen in DLLs quetschen können. Das ist aber nur eine Behelfslösung und verfehlt IMHO völlig den Sinn von DLLs. Solche DLLs laufen nämlich immer nur mit einem bestimmten Compiler in einer bestimmten Version.
    Außerdem gibt es noch weitere Einschränkungen, z.B. dürfen Exceptions niemals eine DLL verlassen.

    Fazit: DLLs und Klassen vertragen sich nicht.



  • Shade Of Mine schrieb:

    um Japros Vorschlag zu verbessern:

    int (*function)(int, int) = functionInit;
    
    int functionInit(int a, int b)
    {
      switch(CPUType)
      {
      case P3:
        function=functionP3;
        brea;
      case P4:
        function=functionP4;
      }
      return function(a, b);
    }
    

    Der Vorteil: wir müssen das switch nur einmal ausführen - und wir können es nicht vergessen - dh. wir müssen es nur dann ausführen, wenn wir es brauchen.

    versteh ich nicht. wo muss man denn bei mir das switch mehrmals ausführen? wieso kann ich nicht vergessen functionInit aufzurufen?



  • Wenn du auf einzelne Prozessor optimieren möchtest, dann kommst du um Assembler (ASM) nicht rum.



  • japro schrieb:

    versteh ich nicht. wo muss man denn bei mir das switch mehrmals ausführen? wieso kann ich nicht vergessen functionInit aufzurufen?

    ne, bei dir muss man das switch auch nur einmal ausführen - aber bei mir wird es nur dann ausgeführt, wenn man das erste mal function() aufruft...

    ich sagte ja, es ist nur eine kleine verbesserung von deiner version.

    wieso du nicht vergessen kannst die init Funktion aufzurufen beantwortet doch schon der code:

    int (*function)(int, int)=functionInit;

    wenn wir jetzt
    function(1,2)
    schreiben, wird functionInit aufgerufen, welches den function pointer auf die richtige Funktion setzt.

    der vorteil ist der: wenn wir function garnicht verwenden, zahlen wir keine kosten für das switch()



  • aahhh, jetzt hab ichs verstanden. danke 😃



  • Shade Of Mine schrieb:

    dh. die Funktion wird nicht direkt aufgerufen, sondern muss erst einen Zeiger dereferenzieren - das ist natürlich im vergleich zu einem direkten call ziemlich lahm. Weiters kann es kein inlining geben.

    Ich glaub du übertreibst hier 'n bissl. Function calls sind heutzutage bei weitem nicht mehr so prozessor-intensiv wie vor 15 Jahren. Und ob ein call Aufruf die Adresse direkt als Parameter hat oder diese zuvor in ein Register geladen wird und call das Register als Parameter bekommt ist fast schon egal. Bei Tests mit meinem alten Prozessor (AMD Thunderbird 900) konnte ich zumindest keine nennenswerte Unterschiede feststellen.
    Inlining kann hier wesentlich mehr rausholen, da nicht nur der Aufruf wegoptimiert werden kann.
    Wenn man für verschiedene Prozessoren optimieren will, ist es imo das beste, wenn man für jeden Prozessor eine eigene Executable hat (zB allgemeine .exe, AMD .exe, Intel .exe). So kann man unter anderem auch Inlining voll ausnutzen. Bei der Initialisierung der Anwendung sollte man dann noch sicherstellen, dass diese auch für den ausführenden Prozessor zulässig ist.



  • @groove: das overhead des Funktionsaufrufes ist es nicht mehr, aber verpaßte gelegenheiten für andere Optimierungen.

    Wenn man bedenkt, daß nur für wenige Anwendungen, und dort nur für kleine Stellen, die CPU das Bottleneck ist, lohnen sich verschiedene EXE'n nur selten. Erhöht einfach die "logistik" für Buiuld/Installer/Config. Ist schon hübscher wenn man eine EXE hat die alles kann.



  • @ötzi,

    ich weiß nicht ob es sowas auch gebrauchen kannst.
    Aber auf www.amd.com liegt irgendwo eine Dokumentation
    zum optimieren von C-Code für x86 Prozessoren.
    Fand ich ziemlich interessant.
    Leider kann ich dir den Link nicht posten...
    hab den irgendwo verlegt 😞

    Bye Peter.



  • @peterchen
    Was meinst du mit "verpaßte gelegenheiten" ?

    Wenn man bedenkt, daß nur für wenige Anwendungen, und dort nur für kleine Stellen, die CPU das Bottleneck ist, lohnen sich verschiedene EXE'n nur selten.

    Kann ich dir eigentlich nur zustimmen. Dort wo Geschwindigkeit gebraucht wird ist es immer besser einen guten Algo zu haben als jeden Assembler Befehl durchzukauen. Zumal ist der beste Optimierer wohl eh der Compiler.



  • Verpßte Gelegenheiten:
    Parameter sind schon in Registern, Registervergabe durch den Optimizer, Instruction Reordering durch den Optimizer (um die Pipelines richtig auszunutzen), Ergebnisse in Registern halten, Instruction Reordering und Register Renaming durch den Prozessor.

    Auswertung zur Compile-Zeit ist im gegebenen Beispiel nicht so relevant (bringt ja nur was merkliches, wenn beide Werte bekant sind), cann aber ganze Ablaufkonstrukte "wegwerfen", und eine Funktion so klein machen das sie tatsächlich geinlinet wird, was dann obige Optimierungen wieder ermöglicht.

    Zumal ist der beste Optimierer wohl eh der Compiler

    Da muß kann ich eigentlich nur zustimmen ( 😃 ). Uneigentlich muß man extrem viel wissen, damit man keinen Unsinn baut. War früher einfacher 😉 (Bis zum 486 fand ich es noch machbar, danach hat mich der Compiler immer geschlagen 😞 )


Anmelden zum Antworten