inline funktionen?!



  • inline int SQUARE (int x) {return x * x;}

    vielleicht kennt ihr das beispiel schon. In dem buch aus dem ich das thema inline funktionen beziehe , steht dass das aufrufen einer inline funktion aus performancegründen besser ist.

    jetzt zu meiner frage: ich verstehe nicht warum das schneller sein soll.(also ich möchte auch gerne die hintergründe verstehen die wurden im buch leider nicht näher erklärt).
    und warum macht man dann nicht jede funktion zur inline funktion? also sprich was ist der nachteil daran?





  • danke



  • Das sind 2 unterschiedliche Sachen:

    inlining von Funktionen
    und
    das inline Keyword

    Die haben beide Miteinander eigentlich nichts zu tun.

    Ein Funktionsaufruf foo(x) sieht auf unterester Ebene (Assembler) ja so aus:

    push x
    call foo

    mittels push wird x auf den Stack gelegt und dann die Funktion foo aufgerufen, die Funktion foo holt sich x vom Stack wieder mit einem pop und berechnet dann das Ergebnis und schreibt das Ergebnis an eine bestimmte Stelle.

    Das ist kompliziert und aufwändig. Wenn du aber statt einer Funktion den Code direkt schreiben würdest, würdest du ja das call und das push und pop sparen - ergo der Code wird kleiner und somit ja auch schneller (er tut ja weniger).

    Der Compiler kann bestimmte Funktionen "inlinen" um eben diese Prologe und Epiloge eines Funktionsaufrufs zu sparen. Der Nachteil davon ist natürlich, dass der Code mehr wird und die ausführbare Datei größer wird (und größer heißt auch immer langsamer). Ein anderes "Problem" vom inlining ist dass man nur limitierte Speicherbereiche hat in die man reinschreiben kann (Register). Ein Funktionsaufruf (call) sichert alle register und der Prozessor macht hier viel automagische Sachen für uns. Wenn wir alles inlinen müssen wir selber immer wieder diese Register richtig speichern und wiederherstellen. Deshalb ist ein inlining nicht immer sinnvoll - deshalb überlässt man das auch idR dem Compiler. Er weiß das besser und kann besser abschätzen wo sich ein inlining lohnt und wo nicht.

    Der 2. Punkt ist das Keyword inline. Das macht nichts anderes als dir zu erlauben die Funktion in einer header Datei zu definieren. Technische Erklärung: http://stackoverflow.com/questions/6208990/my-c-class-is-having-trouble-linking-to-a-function-in-another-cpp-file/6209053#6209053



  • wow danke das hat mir weitergeholfen!
    sehr gut erklärt und verständlich gewesen ich danke dir.


  • Mod

    Die haben beide Miteinander eigentlich nichts zu tun.

    Ohne LTO kann eine Funktion, die nicht in meiner TU definiert wurde, schwer geinlined werden - in meiner TU kann sie aber nur garantiert definiert sein, wenn sie als inline deklariert wurde. Eine gewisse Verbindung besteht da schon.

    mittels push wird x auf den Stack gelegt und dann die Funktion foo aufgerufen, die Funktion foo holt sich x vom Stack wieder mit einem pop und berechnet dann das Ergebnis und schreibt das Ergebnis an eine bestimmte Stelle.

    "holen" tut sich die Funktion einen Wert mittels Adressierung über den frame oder stack pointer. Das Frame wird erst nach Beendigung der Funktion gepoppt, und auch i.d.R. vom Aufrufer.

    ergo der Code wird kleiner und somit ja auch schneller (er tut ja weniger)

    Der Code wird i.d.R. länger (was du auch im übernächsten Satz sagst 😕 ) und kann deshalb instruction caching negativ beeinflussen, was sich auf Performance auswirkt.



  • Arcoth schrieb:

    Die haben beide Miteinander eigentlich nichts zu tun.

    Ohne LTO kann eine Funktion, die nicht in meiner TU definiert wurde, schwer geinlined werden - in meiner TU kann sie aber nur garantiert definiert sein, wenn sie als inline deklariert wurde. Eine gewisse Verbindung besteht da schon.

    Und was hat das mit inline zu tun? Kann ich ja einfach static oder LTO oder sonstwas nehmen. inline ist ein Konstrukt das sich mit dem Linken befasst und nichts mit inlining von Funktionen zu tun hat.

    Schleifen verhindern zeitweise ja auch inlining, dennoch würde ich nicht sagen das for etwas mit inlining zu tun hat.

    mittels push wird x auf den Stack gelegt und dann die Funktion foo aufgerufen, die Funktion foo holt sich x vom Stack wieder mit einem pop und berechnet dann das Ergebnis und schreibt das Ergebnis an eine bestimmte Stelle.

    "holen" tut sich die Funktion einen Wert mittels Adressierung über den frame oder stack pointer. Das Frame wird erst nach Beendigung der Funktion gepoppt, und auch i.d.R. vom Aufrufer.

    Klar, führen wir noch extra komplexität in die Beschreibung ein. Wieso pushen wir überhaupt auf einen Stack? Einfach die Variablen per Register übergeben.

    Die Funktion darf übrigens sehr wohl popen. Da gibt es nichts das dagegen spricht. Klar ist ein ret am Ende idR besser aber zu was hängen wir uns jetzt hier bei Implementierungsdetails die für das Verständnis des Problems nichts bringen?

    ergo der Code wird kleiner und somit ja auch schneller (er tut ja weniger)

    Der Code wird i.d.R. länger (was du auch im übernächsten Satz sagst 😕 ) und kann deshalb instruction caching negativ beeinflussen, was sich auf Performance auswirkt.

    Ja, sehr verwirrend nicht wahr. Entspann dich und lies das ganze nochmal.

    Der Code wird kleiner (kein Epilog und Prolog für die Funktion). Aber er wird größer ( 😮 ) weil ich dafür den Inhalt der Funktion mehrfach habe (falls ich die Funktion mehrfach aufrufe).

    Inlining kann gut oder schlecht für die Caches sein, deshalb sollte man es dem Compiler überlassen.


  • Mod

    Und was hat das mit inline zu tun?

    Wenn ich eine recht kurze Funktion sehe, bin ich dazu verleitet, sie im Header als inline zu definieren, da so inlining erleichtert wird. Wenn nicht, pack ich sie womöglich in irgendeine TU. Genug Verbindung?

    Klar, führen wir noch extra komplexität in die Beschreibung ein. Wieso pushen wir überhaupt auf einen Stack? Einfach die Variablen per Register übergeben.

    Warum hast du nicht einfach eine korrekte Beschreibung eines Callstacks gegeben, oder sie gleich weggelassen, anstatt soweit zu vereinfachen, dass es Blödsinn wird?

    Der Code wird kleiner… Aber er wird größer…

    Nein, der Code wird größer.



  • Arcoth schrieb:

    Und was hat das mit inline zu tun?

    Wenn ich eine recht kurze Funktion sehe, bin ich dazu verleitet, sie im Header als inline zu definieren, da so inlining erleichtert wird. Wenn nicht, pack ich sie womöglich in irgendeine TU. Genug Verbindung?

    Was hat das mit inline zu tun?
    Du erfindest eine Verbindung wo keine ist. Lass dich von dem Wort "inline" nicht verwirren. Kurze Funktionen als inline im Header zu definieren ist eine sinnvolle Sache, aber das hat mit inlining von Funktionen absolut nichts zu tun.

    inline hat genausoviel mit inlining zu tun wie for().

    Nochmal: inline ist ein Keyword das nichts aber auch rein gar nichts mit inlining von Funktionen zu tun hat. Es hat mit dem "Linken" zu tun.

    Ob eine Funktion geinlined wird oder nicht hat nichts mit inline zu tun. Es gibt Faktoren die das inlining erleichtern und wenn die Funktion in jeder ÜE definiert ist, ist das natürlich eine Erleichterung. Aber zB eine Schleife ist eine Erschwernis. Hat for also für dich etwas mit inlinen zu tun? for erschwert das inlinen der Funktion ja, genauso wie inline es "erleichtert". Vor allem da ich das "in jeder ÜE definiert" ja auch ganz ohne inline erreichen kann 😉

    Und ich weiß genau dass du das weißt. Also worauf willst du hinaus?

    Klar, führen wir noch extra komplexität in die Beschreibung ein. Wieso pushen wir überhaupt auf einen Stack? Einfach die Variablen per Register übergeben.

    Warum hast du nicht einfach eine korrekte Beschreibung eines Callstacks gegeben, oder sie gleich weggelassen, anstatt soweit zu vereinfachen, dass es Blödsinn wird?

    Wo habe ich denn einen Fehler gemacht? Nirgendwo. Ich habe lediglich ein simples Beispiel genommen und den Callstack einfach weggelassen.

    Es ist vollkommen gültig für Funktionen selber zu popen. Ist es üblich? Nein, da man idR nicht pascal calling convention sondern cdecl verwendet. Aber Falsch ist hier nichts.

    Oft ist es viel besser gewisse Komplexitäten einfach wegzulassen bei der Erklärung und ein vereinfachteres Beispiel zu nehmen. Fachlich ist meine Aussage vollkommen korrekt.

    Der Code wird kleiner… Aber er wird größer…

    Nein, der Code wird größer.

    Nein, der Code wird kleiner.
    Stell dich bitte nicht so doof.

    #include<iostream>
    int foo() { return 5; }
    int main() {
      std::cout<<foo()<<'\n';
    }
    

    Vergleich den Code einmal mit foo geinlined und einmal nicht.

    Sag worauf du wirklich hinaus willst. Ich bin mir sicher du kennst dich mit inline mindestens genauso gut aus wie ich. Deshalb verwirrt mich dein "doof stellen" hier etwas.

    Wir verbringen jetzt hier übrigens mehr Zeit über deine Spitzfindigkeiten zu "diskutieren" anstatt Leuten zu helfen.


  • Mod

    Shade Of Mine schrieb:

    Arcoth schrieb:

    Und was hat das mit inline zu tun?

    Wenn ich eine recht kurze Funktion sehe, bin ich dazu verleitet, sie im Header als inline zu definieren, da so inlining erleichtert wird. Wenn nicht, pack ich sie womöglich in irgendeine TU. Genug Verbindung?

    Was hat das mit inline zu tun?
    Du erfindest eine Verbindung wo keine ist. Lass dich von dem Wort "inline" nicht verwirren. Kurze Funktionen als inline im Header zu definieren ist eine sinnvolle Sache, aber das hat mit inlining von Funktionen absolut nichts zu tun.

    Wenn du sie im Header definierst, erleichterst du das Inlining durch den Compiler erheblich. Bis zu dem Punkt, dass es bis vor wenigen Jahren die einzige Möglichkeit war. Um sie im Header definieren zu können, muss die Funktion inline (oder static¹) sein. Wo ist da kein Zusammenhang?

    ¹: Welches aber eine leicht andere Bedeutung hat.



  • Shade Of Mine schrieb:

    Nochmal: inline ist ein Keyword das nichts aber auch rein gar nichts mit inlining von Funktionen zu tun hat. Es hat mit dem "Linken" zu tun.

    Inline hat schon etwas mit inlining zu tun. Das Keyword beinflusst zwar das Linken, was ja auch notwendig ist damit es funktioniert, aber es ist gleichzeitig die Aussage das man die Funktion gerne inline hätte, was der Compiler ignorieren kann.

    The intent of the inline keyword is to serve as an indicator to the optimizer that inline substitution of the function is preferred over function call [...]

    Since this meaning of the keyword inline is non-binding, compilers are free to use inline substitution for any function that's not marked inline, and are free to generate function calls to any function marked inline.

    Quelle



  • Ich sehe es so (schon immer), daß ich nicht gegen aktuelle Compiler optimiere, sondern gegen die nächste Generation.

    Shade 👍


  • Mod

    Was hat das mit inline zu tun?

    Siehe SeppJ's Antwort. Ich hoffe, du siehst es jetzt ein, anstatt noch weiter abstruse Vergleiche mit for zu ziehen.

    Es ist vollkommen gültig für Funktionen selber zu popen

    Du hast impliziert, dass man eine Variable vom Call Stack pop'ed um auf sie zuzugreifen. Was eben doppelt Quatsch ist. Und womöglich von einem weniger erfahrenen Leser falsch aufgegriffen werden kann, weshalb es von mir korrigiert wurde. Stattdessen hättest du das pop auf das frame beziehen können - die Erklärung wäre kaum komplizierter, aber definitiv richtiger gewesen. Nicht sonderlich wichtig - aber warum hast du mir jetzt widersprechen müssen? Sieh doch meinen Post einfach als Ergänzung zu deinem, um mögliche Missverständnisse aufzuklären.

    Vergleich den Code einmal mit foo geinlined und einmal nicht.

    Lies doch bitte mal was ich ursprünglich geschrieben habe. Der Code wird i.d.R. länger. Nicht kürzer und länger. Das macht keinen Sinn. Und er wird nicht per se länger (er könnte sich auch in Größe gar nicht ändern). Meine zweite Antwort war eher ein entnervter Versuch, dir deine unsinnige Schreibweise aufzuzeigen. Du bist aber anscheinend nicht daran interessiert, Verwirrung zu mindern. Schade.

    volkard schrieb:

    Ich sehe es so (schon immer), daß ich nicht gegen aktuelle Compiler optimiere, sondern gegen die nächste Generation.

    Bist ganz und gar Architekt!



  • SeppJ schrieb:

    Wenn du sie im Header definierst, erleichterst du das Inlining durch den Compiler erheblich. Bis zu dem Punkt, dass es bis vor wenigen Jahren die einzige Möglichkeit war. Um sie im Header definieren zu können, muss die Funktion inline (oder static¹) sein. Wo ist da kein Zusammenhang?

    ¹: Welches aber eine leicht andere Bedeutung hat.

    Das ist fachlich falsch. Das template Keyword hat schon immer erlaubt eine Funktion in jeder ÜE zu definieren und dadurch inlining zu ermöglichen. Weiters konnte man auch schon immer Funktionen innerhalb einer Klasse im Header definieren um inlining einfach zu ermöglichen.

    Aber gut, dann sagen wir einfach die folgenden Schlüsselworte haben einen direkten Zusammenhang mit inlining von Funktionen. Darauf können wir uns ja hoffentlich einigen, oder?
    asm, catch, do, extern, for, goto, inline, static, template, throw, try, virtual, while.

    Arcoth schrieb:

    Du hast impliziert, dass man eine Variable vom Call Stack pop'ed um auf sie zuzugreifen. Was eben doppelt Quatsch ist.

    Nein, ist es nicht. Die Funktion darf popen. Zeig mir bitte einfach die Stelle im C++ Standard wo steht dass die Funktion das nicht darf. Oh, gibt es nicht. Interessant.

    Fachlich ist mein Post 100% korrekt.

    Lies doch bitte mal was ich ursprünglich geschrieben habe. Der Code wird i.d.R. länger.

    Aber manchmal nicht.
    Und du hast beim 2 mal nicht idR geschrieben sondern ein absolutes Statement gemacht. Das ist falsch. Tut mir Leid.

    Aber warum hast du mir jetzt widersprechen müssen? Sieh doch meinen Post einfach als Ergänzung zu deinem, um mögliche Missverständnisse aufzuklären. 🙂


  • Mod

    Shade Of Mine schrieb:

    SeppJ schrieb:

    Wenn du sie im Header definierst, erleichterst du das Inlining durch den Compiler erheblich. Bis zu dem Punkt, dass es bis vor wenigen Jahren die einzige Möglichkeit war. Um sie im Header definieren zu können, muss die Funktion inline (oder static¹) sein. Wo ist da kein Zusammenhang?

    ¹: Welches aber eine leicht andere Bedeutung hat.

    Das ist fachlich falsch. Das template Keyword hat schon immer erlaubt eine Funktion in jeder ÜE zu definieren und dadurch inlining zu ermöglichen. Weiters konnte man auch schon immer Funktionen innerhalb einer Klasse im Header definieren um inlining einfach zu ermöglichen.

    WTF? Willst du aus jeder inline-Funktion ein template machen? Willst du uns verarschen?

    Aber gut, dann sagen wir einfach die folgenden Schlüsselworte haben einen direkten Zusammenhang mit inlining von Funktionen. Darauf können wir uns ja hoffentlich einigen, oder?
    asm, catch, do, extern, for, goto, inline, static, template, throw, try, virtual, while.

    Also Verarsche. Hätte ich inhaltlich natürlich sofort erkannt, hätte ich bloß nicht von dir erwartet. Tschüss.


  • Mod

    Fachlich ist mein Post 100% korrekt.

    Nein, er ist nicht korrekt. Weil wir hier nicht mehr vom Standard sprechen, da dieser überhaupt kein Konzept von Inlining hat. As-if und so.

    Und du hast beim 2 mal nicht idR geschrieben sondern ein absolutes Statement gemacht. Das ist falsch. Tut mir Leid.

    "Meine zweite Antwort war eher ein entnervter Versuch, dir deine unsinnige Schreibweise aufzuzeigen." Meine Fresse.

    Aber warum hast du mir jetzt widersprechen müssen?

    Den Fehler werde ich hier nicht mehr machen.



  • SeppJ schrieb:

    WTF? Willst du aus jeder inline-Funktion ein template machen? Willst du uns verarschen?

    Nein. Aber inline und template haben sehr ähnliche Semantiken. Ist uU zu kompliziert für dich.

    Wusstest du dass man mittels template Funktionen in einem Header definieren kann?

    Aber gut, dann sagen wir einfach die folgenden Schlüsselworte haben einen direkten Zusammenhang mit inlining von Funktionen. Darauf können wir uns ja hoffentlich einigen, oder?
    asm, catch, do, extern, for, goto, inline, static, template, throw, try, virtual, while.

    Also Verarsche. Hätte ich inhaltlich natürlich sofort erkannt, hätte ich bloß nicht von dir erwartet. Tschüss.

    Nein. Es ist deine Argumentation.

    Wenn du sie im Header definierst, erleichterst du das Inlining durch den Compiler erheblich. Bis zu dem Punkt, dass es bis vor wenigen Jahren die einzige Möglichkeit war. Um sie im Header definieren zu können, muss die Funktion inline (oder static¹) sein. Wo ist da kein Zusammenhang?

    Das kann ich nahezu 1:1 für jedes dieser Keywords auch sagen:

    "Wenn du asm in der Funktion verwendest, erschwerst du das Inlining durch den Compiler erheblich. Bis zu dem Punkt, dass es bis vor wenigen Jahren die garkeine Möglichkeit mehr war. [...] Wo ist da kein Zusammenhang?"

    Arcoth schrieb:

    Fachlich ist mein Post 100% korrekt.

    Nein, er ist nicht korrekt. Weil wir hier nicht mehr vom Standard sprechen, da dieser überhaupt kein Konzept von Inlining hat. As-if und so.

    Einzig ein handfestes Argument fehlt dir.



  • Shade Of Mine schrieb:

    Nein. Aber inline und template haben sehr ähnliche Semantiken. Ist uU zu kompliziert für dich.

    Ähnlichkeiten machen Dinge nicht gleich und alles mögliche zusammenzuwerfen macht das ganze auch nicht besser. Das wäre ja so als würde ich sagen union und class sind gleich nur weil sie sich einige Ähnlichkeiten teilen.

    Im wesentlichen geht es doch hier einfach nur darum das das keyword inline eine explizite Bitte um inlining ist. Es ist somit das einzige keyword das mit inlining direkt zu tun hat, ab das inlining dabei stattfindet oder nicht spielt dabei keine Rolle. Wichtig ist nur das jeder auch weiß das es eben eine Bitte und keine Garantie ist. Das jetzt mit irgendwelchen wilden anderen keywords zusammen zu werfen und template ins spiel zu bringen ist absolut falsch. Du vergleichst im Endeffekt hier ein keyword das eine explizite Bitte ohne Garantie darstellt mit einem keyword das etwas total anderes darstellt und lediglich die implizite Möglichkeit besitzt. Das sollte man schon sauber trennen, nicht zuletzt weil ein Anfänger der das hier list nach 3 Zitaten garnichtmehr mitkommt.


Log in to reply