Funktionsparameter effizient anlegen



  • Die Frage ist doch, muss die Funktion überhaupt reentrant sein? Da die erste vom TE vorgeschlagene Variante das nicht ist, gehe ich davon aus, dass das nicht erforderlich ist.


  • Mod

    Belli schrieb:

    Die Frage ist doch, muss die Funktion überhaupt reentrant sein? Da die erste vom TE vorgeschlagene Variante das nicht ist, gehe ich davon aus, dass das nicht erforderlich ist.

    Selbst wenn nicht, ist die zweite Variante einfach nur schneller und zudem noch ohne weitere Kosten reentrant. static sollte man nur benutzen, wenn es für das Funktionieren wirklich absolut unerlässlich ist. Ganz besonders nicht für Mikrooptimierungen, denn es ist einfach ein Irrglaube, dass das Erzeugen von Variablen irgendwie Zeit bräuchte. Da gibt es nämlich gar nichts zu Erzeugen. Diese "Erzeugung" ist schlimmstenfalls ein Versetzen des Stackpointers am Funktionsbeginn um einen anderen Wert als er sonst sowieso schon versetzt worden wäre.

    Mit dem static lebt hingegen die Variable in einem ganz anderen Speicherbereich als die anderen lokalen Variablen und es muss eine weitere Speicherseite in den Cache geladen werden die dort schlimmstenfalls 1. noch nicht drin war und 2. irgendwas anderem den Platz wegnimmt. Und es ist vermutlich auch nicht mehr möglich, dass die Variablen ganz wegoptimiert werden und selbst einfache Optimierungen werden erheblich erschwert oder verhindert.

    Ich wette bei einem Performancevergleich würde die static-Version niemals schneller sein, vermutlich sogar einknicken.



  • Belli schrieb:

    Die Frage ist doch, muss die Funktion überhaupt reentrant sein? Da die erste vom TE vorgeschlagene Variante das nicht ist, gehe ich davon aus, dass das nicht erforderlich ist.

    Warum unnoetig Nachteile in Kauf nehmen, wenn Realisierungen mit allen Vorteilen soviel einfacher sind.



  • Richtig!
    Ich bin (wohl irrtümlich (danke Seppj für die Erläuterung)) davon ausgegangen, dass es schneller ist, die Variable nur einmal (static) zu erzeugen.



  • Belli schrieb:

    Richtig!
    Ich bin (wohl irrtümlich (danke Seppj für die Erläuterung)) davon ausgegangen, dass es schneller ist, die Variable nur einmal (static) zu erzeugen.

    Genau das hatte ich auch erst gedacht, daher die Frage...

    Danke für die Erläuterungen. 🙂



  • SeppJ schrieb:

    Nathan schrieb:

    Das ist die erste Variante vom TE auch nicht.

    Ja, die ist ja auch Mist (was soll eigentlich dieses if?). Er soll unbedingt die zweite nehmen! Und falls er das Array aus der Funktion zurück geben möchte (es ist unklar, was er überhaupt mit dem Array machen möchte), dann soll er es so machen wie von xyz-offgeloggert0r vorgeschlagen.

    Achja, und hierzu noch: Ich hatte wohl fälschlicherweise angenommen, dass der allozierte Speicher quasi auch static ist, da schließlich der Pointer static ist... Scheint nicht so zu sein...



  • Doch selbstverständlich. Via malloc/calloc angeforderter Speicher liegt auf dem Heap und steht zur Verfügung, bis er irgendwann mittels free wieder freigegeben wird - insofern schon mit static vergleichbar.



  • Dann wiederum verstehe ich nicht ganz, worauf die Frage

    SeppJ schrieb:

    (was soll eigentlich dieses if?)

    zielt, da die if-Abfrage (wie die NULL-Initialisierung) ja schlicht dafür sorgt, dass das Calloc nur beim ersten Durchlauf ausgeführt wird und sowohl Pointer, wie auch Speicher, danach halt "da" sind.

    Aber egal, solange gilt

    SeppJ schrieb:

    es ist einfach ein Irrglaube, dass das Erzeugen von Variablen irgendwie Zeit bräuchte

    ist ja klar, wie das Ganze zu machen ist...



  • Naja, Du hättest einfach:

    void foo (int Arg1, int Arg2, int Arg3)
    {
        static BAR * foobar = Calloc(10, sizeof(TEST));
    
        // ...
    
    }
    

    machen können ...



  • Ne, das hatte schon seinen Sinn; wenn ich es mache, wie Du sagst, kommt bei mir:

    compiler schrieb:

    error : static/external initializers must be constant expressions


  • Mod

    Schock schrieb:

    Ne, das hatte schon seinen Sinn; wenn ich es mache, wie Du sagst, kommt bei mir:

    compiler schrieb:

    error : static/external initializers must be constant expressions

    Oh, ach ja. 💡 Das geht ja nur in C++, nicht in C. Tut mir leid, dann war die if-Abfrage doch sinnvoll. Solche Detailsunterschiede bei wenig genutzten Sprachfeatures entfallen mir manchmal.

    Aber, wie schon geklärt, sollte man diese Variante ohnehin nicht benutzen.



  • Okay, wusste ich auch nicht, dass das in C nicht klappt ...



  • Belli schrieb:

    void foo (int Arg1, int Arg2, int Arg3)
    {
        static struct BAR foobar[10];
    

    }

    Lokalstatische Variablen verhindern ein sinnvolles Inlining durch den Compiler und sind somit auch aus diesem Grund Schrott.



  • Dieses 'Inlining' ist mir nur von C++ bekannt, ist demnach in diesem Kontext vermutlich was völlig anderes?



  • Inlining ist ein gängiges Optimierungsverfahren vieler Compiler vieler Programmiersprachen für performanteren Code, und, ja, auch C Compiler können C Code optimieren und sie taten das schon lange bevor irgendjemand an C++ dachte.


  • Mod

    Belli schrieb:

    Dieses 'Inlining' ist mir nur von C++ bekannt, ist demnach in diesem Kontext vermutlich was völlig anderes?

    Es geht um das "richtige" Inlining, nicht bloß das Schlüsselwort in seinem semantischen Sinn (Mehrfachdefinition verhindern). Also das tatsächliche Einsparen eines Funktionsaufrufs, indem der Code der Funktion an der Stelle des Aufrufs eingesetzt wird.

    Das ist es, was ich weiter oben mit

    SeppJ schrieb:

    selbst einfache Optimierungen werden erheblich erschwert oder verhindert.

    meinte. Verhinderung von Inlining ist (bei kleinen Funktionen) eine ganz gewaltige Performancebremse. Es ist eine der einfachsten und effizientesten Optimierungen überhaupt und wird von vielen Compilern (egal welche Sprache) automatisch durchgeführt.

    edit: Zu langsam...



  • Macht der Compiler das bei jeder Funktion? Auch die in *.cpp Dateien?


  • Mod

    Nathan schrieb:

    Macht der Compiler das bei jeder Funktion? Auch die in *.cpp Dateien?

    Kommt drauf an wie gut er ist. Erst einmal sind Dateien schon lange Schall und Rauch, wenn der Optimierer dran kommt (Dateien existieren sogar schon nach der allerersten Übersetzungsphase, dem Präprozessor, nicht mehr). Da gibt es keine Unterscheidung nach Headern oder Source.

    Falls du das Inlining über verschiedene Quelltextmodule hinweg meinst: Ein wichtiges Stichwort, das in den letzten Jahren zur Standardausrüstung bei der Optimierung geworden ist, lautet:
    http://en.wikipedia.org/wiki/Link-time_optimization


Anmelden zum Antworten