Wiederverwendung von häufig aufgerufenem Code



  • Na ja, die Funktion besteht halt aus unterschiedlichen Abfragen. In einer zweiten, sehr redundanten Funktion, stimmen davon 3/5 der Abfragen überein, also würde es Sinn machen diesen Teil auszulagern. Zurzeit gibt es keine Auslagerung und daher auch keinen Funktionsaufruf. Mit Auslagerung gäbe es einen und wenn der Compiler diesen nicht komplett wegoptimiert, würde man das vermutlich schon merken.

    Einfachere Testfälle gibt es nicht wirklich. Es geht darum auf einer bestimmten Datenmenge von mehreren 100.000 Einträgen gewisse Laufzeitanalysen zu machen. Der Benutzer soll schnell ein paar Variablen ändern können und sofort soll sich das Ergebnis zeigen. Im Debugmodus dauert das sowieso gerade schon 7-8 Sekunden und es ist ziemlich leicht das weiter zu verlangsamen.

    Meine Funktionen haben auch nur 3-4 Parameter (wobei zwei 64 Bit betragen), aber durch Auslagerungen komme ich auf 2-3 Funktionsaufrüfe pro Funktion. Und die Funktion ansich wird ja schon >100.000 Mal pro Sekunde aufgerufen und ich würde es gerne noch schneller machen, was kaum geht. Es aber für hübscheren Code langsamer zu machen... das ist es mir dann wiederum nicht wert.

    Irgendwas mit Compilezeit-Codewiederverwendung gefiele mir daher sehr gut.



  • Wenn du für 64 Bit kompilierst hast du relativ grosse Chancen, dass es gar keine Funktionsaufrufe, respektive ein teures Stackframe gibt, sondern direkt alles mit den Registern gemacht wird. Wenn es trotz all dem doch langsamer ist (probier es am besten mal aus), dann wären Makros/Templates wahrscheinlich the way to go.



  • Die Sache ist nur, dass ich es nicht nur für 64 Bit kompilieren möchte, da es auch auf x86-Maschinen laufen soll. Ich habe noch nicht viel damit experimentiert, aber nach meinem Verständnis würde ich mir das damit doch verbauen, oder?

    Wie könnte ich denn Templates zur Wiederverwendung nutzen? Wenn ich nur Teile von Funktionen neuschreiben müsste, hätte ich doch trotzdem wieder Aufrüfe oder alternativ Redundanzen drin, oder?



  • 32-Bit Systeme sind Steinzeit.



  • 314159265358979 schrieb:

    32-Bit Systeme sind Steinzeit.

    unnötiger kommentar... 😞
    und falsch dazu

    @eisflamme: geht es dir darum, dass ein und derselbe code nicht mehrmals aufgeführt wird, oder dass du ihn nicht mehrmals schreiben musst?!

    mh gehen sowas wie lookup tables? oder ja per TMP vorberechnen?
    ich wes nicht, da wären ein paar genauere infos ganz gut



  • Da ist nix falsch dran. Jeder einigermaßen moderne Prozessor heutzutage kann 64 Bit. Ein gewisser Fensterhersteller stellt dennoch 32-Bit OS her. Damit hinkt dieser ungefähr so weit hinterher, wie mit seinem C++-Compiler bei C++11. Na, wer errät, von welchem Unternehmen ich spreche? 🤡



  • na und?
    abwärtskompatiblität ist auch nicht zu unterschätzen...

    es sei denn du unterstützt gewisse andere produzenten, die alles überteuert anbieten, keinerlei optionen anbieten, und die nur mit mühe und not programmierbar sind.

    na errätst du, welchen obstkonzern ich meine?!

    zu mal manche software schmieden noch ältere sachen benutzen als deine angeprangere firma produziert... (ich meine seppJ oder drakon meinte mal gesagt zu haben, dass er auf seiner firma noch ms vc 2005 nutzt/nutzen muss)

    aber das soll nicht in nem flamewar enden:
    fakt ist, 64bit ist nicht allgegenwärtig, und wie eisflamme gesagt hat, er will es nicht. also wäre die diskussion hinfällig -> 32 + 64 Bit soll supportet werden



  • 314159265358979 schrieb:

    Da ist nix falsch dran. Jeder einigermaßen moderne Prozessor heutzutage kann 64 Bit. Ein gewisser Fensterhersteller stellt dennoch 32-Bit OS her. Damit hinkt dieser ungefähr so weit hinterher, wie mit seinem C++-Compiler bei C++11. Na, wer errät, von welchem Unternehmen ich spreche? 🤡

    Die ganzen Pinguin-Hersteller machen das ebenso. Genauso wie die ganzen Teufelchen-Hersteller (Mal das Teufelchen für alle Unixe, sieht einfach toll aus) auch. Nur weil das ein gewisser fauler Apfel nicht mehr macht (?) hat das keine Aussage.

    Viele in meinem Bekanntenkreis haben noch 32bit Rechner, weil so ein Pentium mit 512 MB RAM und nem Linux/XP noch wunderbar für praktisch alles reicht.



  • Es kann durchaus Sinn machen 32 Bit noch zu unterstützen, aber es kann auch sehr viel Sinn machen solche Systeme zu vernachlässigen. Wenn man weiss, dass die Applikation hauptsächlich auf rechenstarken Maschinen, welche für Hochleistung gedacht sind optimal laufen soll, dann kann man es auch dafür auslegen. 32 Bit wird dann ja auch noch ohne Umwege unterstützt, aber halt nicht optimal für das System ausgelegt. Zusätzlich kann man Prozessor Erweiterungen benutzen, welche man bei 64Bit Systemen bestimmt hat um das ganze noch mehr zu optimieren.

    @Eisflamme
    Ohne die genauen Umstände zu wissen und die etwas genauere Struktur dieser Funktionen zu kennen ist eine allgemeine Aussage eher schwer. Ohnehin wirst du um Testläufe nicht herum kommen wenn du effektiv wissen willst was besser ist.



  • Eisflamme schrieb:

    Die Frage ist, ob ich das irgendwie lösen kann? Wie würdet ihr vorgehen?

    Mach Dir auf einem Zettel eine Rechnung: Deine CPU bekommt soundso viele Takte pro Sekunde, deine Funktion wird 100 Tausend mal pro Sekunde aufgerufen - dividiere die beiden Zahlen und Du bekommst sozusagen die Anzahl der CPU Takte, die Deine Funktion pro Sekunde zur Verfügung bekommt - "Best Case" sozusagen, natürlich Pi-mal-Daumen - das ist aber ein Wert, mit dem man abschätzen kann, wie schnell deine Funktion überhaupt sein sollte. Nun kannst Du messen, wie viele CPU Takte Deine Funktion rechnet und mit diesem Wert kannst Du abschätzen, wie viele Takte musst Du überhaupt rausholen, damit die 100 Tausend Aufrufe innerhalb einer Sekunde fertig sein sollten. Dann weisst Du auch ungefähr, ob es realistisch ist und ob es sich lohnt, die Funktion zu optimieren.



  • Ist der Algorithmus schon auf Cachefreundlichkeit optimiert?
    Und könnte man vielleicht mit Indizierung der Datensätze irgendwas rausholen?



  • Hi,

    danke für die Antworten erstmal. Die Kundengruppe darf auch recht alte Maschinen nutzen und tut es. 32 Bit schließe ich also in keinem Fall aus.

    Es handelt sich bei dem Programm um ein Analysetool für Pokerhände, ich hatte ja schon häufiger in der Vergangenheit damit rumgespielt. Alle möglichen Kombinationen von 7 Karten werden in 64-Bit-Integern bitweise kodiert. Oft werden aber mehrere solcher Kombinationen eingegeben und damit durchlaufen. Das Durchlaufen geschieht durch einfaches Iterieren, deswegen lässt sich wohl nichts Indizieren und auch für den Cache eher nichts optimieren.

    Also mir geht es nur darum Code nicht mehrfach zu schreiben, das ist alles. Wenn ich den Code anfasse und das bei 5 Stellen nachbessern muss, ist das einfach sehr unpraktisch.

    Makros gefallen mir bisher immer noch am besten, ich denke, die werde ich auch nehmen. 🙂



  • Eisflamme schrieb:

    Zurzeit gibt es keine Auslagerung und daher auch keinen Funktionsaufruf. Mit Auslagerung gäbe es einen und wenn der Compiler diesen nicht komplett wegoptimiert, würde man das vermutlich schon merken.

    Willst du statt Vermutungen nicht eher Messungen anstellen?

    Mit dem Makro-Ansatz wäre ich vorsichtig, da entstehen recht schnell Fehler, z.B. weil ein Ausdruck mehrfach ausgewertet wird. Davon abgesehen musst du bedenken, dass inline -Funktionen nicht automatisch schneller sind. Sie können die Ausführung sogar verlangsamen, wenn sie zu viel Code enthalten.



  • wenn es dir wirklich nur darum geht, nicht redundanten code zu schreiben, dann lager wie du es selbst gesagt und erkannt hast, soweit es geht in funktionen aus.
    vielleicht kannst du es so designen, dass du z.b. funktoren nutzen kannst, dann sparst nochmal einige funktionen...



  • Skym0sh0 schrieb:

    vielleicht kannst du es so designen, dass du z.b. funktoren nutzen kannst, dann sparst nochmal einige funktionen...

    Und was würde das bringen? Dann hat man zusätzlich zur Funktion auch noch Konstruktor und Destruktor, die aufgerufen werden...



  • wie machts denn die stl?
    auch ein paar zusätzliche con-/destruktoraufrufe aber sehr viel unabhängigkeit

    ich meine, das halt in etwa wie die STL
    sprich funktionszeiger gehen ja auch



  • Äh ja. Ob man Funktionen an andere Funktionen übergibt oder sie direkt aufruft, ist ein Unterschied. Im zweiten Fall sind weder Funktionszeiger noch Funktoren sinnvoll, da sie nur eine unnötige Indirektion mit sich bringen, die im besten Fall die gleiche Performance wie der direkte Aufruf hat.



  • Nexus schrieb:

    Willst du statt Vermutungen nicht eher Messungen anstellen?

    Die erste vernünftige Antwort.



  • wzeit schrieb:

    Nexus schrieb:

    Willst du statt Vermutungen nicht eher Messungen anstellen?

    Die erste vernünftige Antwort.

    Ich habe in meinen beiden Posts darauf hingewiesen, dass er es testen muss um zu wissen was schneller ist, aber es scheint den TO nicht zu interessieren und stützt sich lieber auf Vermutungen.



  • Wenn Du ähnliche Funktionen zusammen fasst, dann wird dein Code insgesamt kleiner und passt eher in den Cache. Daher ist ein zusätzlicher Funktionsaufruf eventuell sogar ein Performancegewinn. Ohne Messung erhälst Du darauf aber keine Antwort.


Anmelden zum Antworten