Inline Function Definition/Declaration splitten!?



  • Hallo Leute,

    ich habe eine "static inline" Funktion in einer (public) header.

    #ifndef EXAMPLE_H
    #define EXAMPLE_H
    
    // Declaration of the inline function
    static inline void myFunction(void)
    {
     // do anything
    }
    
    #endif // EXAMPLE_H
    

    Nun möchte ich diese declaration/definition trennen, ungefähr so;

    header:

    #ifndef EXAMPLE_H
    #define EXAMPLE_H
    
    // Declaration of the inline function
    inline void myFunction(void);
    
    #endif // EXAMPLE_H
    

    c module

    #include "example.h"
    #include <stdio.h>
    
    // Definition of the inline function
    inline void myFunction(void) {
        printf("This is an inline function.\n");
    }
    
    // Provide an external definition
    extern inline void myFunction(void);
    

    Wenn ich nun die funktion benchmark (Google benchmark) sehe ich dass die 2te Variante viel langsamer ist, aslo vermutlich nicht inline assembliert wird..

    wie kan ich das dennoch lösen?


  • Mod

    Der ganze Zweck von inline ist doch gerade, dass du damit deine ursprüngliche Variante schreiben kannst (ohne Probleme mit doppelten Definitionen zu bekommen), so dass es dem Compiler leicht fällt, das tatsächlich inline einzusetzen, weil er den Code der Funktion zur Verfügung hat. Wenn du das aufteilst, hat der Compiler den Code der Funktion nicht zur Verfügung, und kann daher auch nicht einsetzen.

    Es gibt bei manchen Toolchains die Möglichkeit, zur Linkzeit Optimierungen vorzunehmen. Das braucht meistens etwas Erfahrung, das einzurichten. Das wäre daher nicht meine erste Empfehlung, wenn es nur um Inlining geht. Für Inlining ist dein ursprünglicher Code die vorgesehene und einfachste Variante.

    Ich muss noch aufklären, dass das Schlüsselwort inline in modernen Compilern (sagen wir, jünger als 15 Jahre) nichts mehr damit zu tun hat, Inlining zu erzwingen. Sein einziger Zweck ist das Ändern der Linkage und Regeln bezüglich doppelter Definitionen, so dass dein erster Code legal wird. Der optimierende Compiler trifft dann seine eigenen Entscheidungen, ob das ein guter Kandidat für Inlining ist. Du hast ihm damit nur die Mittel (sprich: den Code der Funktion) in die Hand gegeben, damit er diese Entscheidung treffen kann.



  • @SeppJ sagte in Inline Function Definition/Declaration splitten!?:

    Der ganze Zweck von inline ist doch gerade, dass du damit deine ursprüngliche Variante schreiben kannst (ohne Probleme mit doppelten Definitionen zu bekommen), so dass es dem Compiler leicht fällt, das tatsächlich inline einzusetzen, weil er den Code der Funktion zur Verfügung hat. Wenn du das aufteilst, hat der Compiler den Code der Funktion nicht zur Verfügung, und kann daher auch nicht einsetzen.

    Es gibt bei manchen Toolchains die Möglichkeit, zur Linkzeit Optimierungen vorzunehmen. Das braucht meistens etwas Erfahrung, das einzurichten. Das wäre daher nicht meine erste Empfehlung, wenn es nur um Inlining geht. Für Inlining ist dein ursprünglicher Code die vorgesehene und einfachste Variante.

    Ich muss noch aufklären, dass das Schlüsselwort inline in modernen Compilern (sagen wir, jünger als 15 Jahre) nichts mehr damit zu tun hat, Inlining zu erzwingen. Sein einziger Zweck ist das Ändern der Linkage und Regeln bezüglich doppelter Definitionen, so dass dein erster Code legal wird. Der optimierende Compiler trifft dann seine eigenen Entscheidungen, ob das ein guter Kandidat für Inlining ist. Du hast ihm damit nur die Mittel (sprich: den Code der Funktion) in die Hand gegeben, damit er diese Entscheidung treffen kann.

    danke für deine ausführungen. Es ging mir quasi nur darum, dass ich eben keine "code" in der public header habe.. und den gern ausgelagert hätte. aber das geht dann wohl so nicht!? was hat es denn mit

    extern inline void myFunction(void);
    

    auf sich? Ich habe mein beipspiel mit co-pilot ertellen lassen , und den sinn von der extern definution nicht kappert;)



  • @SoIntMan sagte in Inline Function Definition/Declaration splitten!?:

    Es ging mir quasi nur darum, dass ich eben keine "code" in der public header habe.. und den gern ausgelagert hätte. aber das geht dann wohl so nicht!?

    Eine Möglichkeit ist, das in einen zweiten "Header" auszulagern den man z.B. .inc oder .inl nennt und diesen am Ende des primären Headers einzubinden:

    example.h:

    #ifndef EXAMPLE_H
    #define EXAMPLE_H
    
    void myFunction(void);
    
    #include "example.inl"
    
    #endif // EXAMPLE_H
    

    example.inl:

    #ifndef EXAMPLE_INL
    #define EXAMPLE_INL
    
    // Declaration of the inline function
    inline void myFunction(void)
    {
     // do anything
    }
    
    #endif // EXAMPLE_INL
    

  • Mod

    @SoIntMan sagte in Inline Function Definition/Declaration splitten!?:

    danke für deine ausführungen. Es ging mir quasi nur darum, dass ich eben keine "code" in der public header habe.. und den gern ausgelagert hätte. aber das geht dann wohl so nicht!? was hat es denn mit

    extern inline void myFunction(void);
    

    auf sich? Ich habe mein beipspiel mit co-pilot ertellen lassen , und den sinn von der extern definution nicht kappert;)

    Das macht, dass zusätzlich noch eine extern sichtbare Version der inline-Funktion erstellt wird. Das kann in manchen grenzwertigen Szenarien (wie wenn deine Funktion zu groß ist, als dass der Compiler sie tatsächlich inlinen würde), vorteilhaft für die Größe der Executable sein. Und es ermöglicht dir halt auch, die Funktion zu nutzen, ohne die volle inline-Definition vorliegen zu haben, wenn du das aus irgendeinem Grund so haben möchtest. Beides sind aber eher Szenarien, wo es fragwürdig ist, ob die Funktion dann überhaupt inline sein sollte. Bei "normalen" Kandidaten für inline, also winzigen Trivialfunktionen, sollte das nicht nötig sein.



  • This post is deleted!


  • @Finnegan sagte in Inline Function Definition/Declaration splitten!?:

    @SoIntMan sagte in Inline Function Definition/Declaration splitten!?:

    Es ging mir quasi nur darum, dass ich eben keine "code" in der public header habe.. und den gern ausgelagert hätte. aber das geht dann wohl so nicht!?

    Eine Möglichkeit ist, das in einen zweiten "Header" auszulagern den man z.B. .inc oder .inl nennt und diesen am Ende des primären Headers einzubinden:

    example.h:

    #ifndef EXAMPLE_H
    #define EXAMPLE_H
    
    void myFunction(void);
    
    #include "example.inl"
    
    #endif // EXAMPLE_H
    

    example.inl:

    #ifndef EXAMPLE_INL
    #define EXAMPLE_INL
    
    // Declaration of the inline function
    inline void myFunction(void)
    {
     // do anything
    }
    
    #endif // EXAMPLE_INL
    

    interessant, aber wenn ich die die funktion welche in Lib A liegt in Lib B linke wird sie da ja nich ge-inlined?


  • Mod

    @SoIntMan sagte in Inline Function Definition/Declaration splitten!?:

    interessant, aber wenn ich die die funktion welche in Lib A liegt in Lib B linke wird sie da ja nich ge-inlined?

    Was meinst du in diesem Zusammenhang mit Lib A und Lib B? Wenn du wirklich vorcompilierte Bibliotheken meinst, bist du sowieso mehr oder weniger aufgeschmissen.



  • @SoIntMan sagte in Inline Function Definition/Declaration splitten!?:

    interessant, aber wenn ich die die funktion welche in Lib A liegt in Lib B linke wird sie da ja nich ge-inlined?

    Ein derartige Optimierung findet ich C nicht statt. Da dazu der Compiler die Funktion noch als präcompilierte Version vorliegen haben müsste. Das ist bei einer Library schon nicht mehr der Fall. Das heißt, es fehlen die notwendigen Informationen um solche Optimierungen vornehmen zu können. Daher kann der Compiler nur sehen, dass eine Funktion foo extern ist und später der Linker diese Funktion ins Binary einbindet. Das kann er entweder statisch machen, dann schaut er in der Archive Library nach dem Code und bindet in statisch in das Executable ein, oder er macht das dynamisch in dem gegen eine dynamische Library bindet.

    Für das Wegoptimieren des Funktionsaufrufs braucht der Compiler Informationen über die Funktion, diese kann es nur haben, wenn er den Header lesen kann oder diesen in Form eines Moduls als Präcompilat vorliegen hat. In C gibt es aber keine Module, so dass Du nur mit precompiled Headers die Übersetzung beschleunigen kannst. Die Sichtbarkeit lässt sich darüber nicht beeinflussen.


Log in to reply