2 Stimmen

Fragen zur Inline-Leistung

Ich hatte einige Fragen zur Verwendung von inline bei Funktionen in C und C++. Man hat mir gesagt, ich solle es für kleine Funktionen verwenden, die ich häufig benutze, aber ich möchte genau verstehen, wie es funktioniert. Hier ist nur ein Ausschnitt aus einem Beispiel.

static inline point3D createPoint3D(float x, float y, float z){
   point3D newPosition;
   newPosition.x = x;
   newPosition.y = y;
   newPosition.z = z;
   return newPosition;
}
  1. Was genau tut es und warum trägt es dazu bei, dass der Code schneller läuft? Ist dies eine veraltete Optimierung aus den 90er Jahren?

  2. Warum soll ich es nur für kleine Aufgaben verwenden? Wäre es schlecht, wenn ich es für große Funktionen verwenden würde?

  3. Ist es schlecht, sie für eine große Anzahl von Funktionen zu verwenden?

5voto

Jerry Coffin Punkte 452852
  1. Es handelt sich eher um eine veraltete Optimierung aus den 70er oder (höchstens) 80er Jahren. Nahezu jeder kompetente Compiler kann Funktionen für die Inline-Expansion auswählen, ohne dass Sie etwas anderes tun müssen, als die Optimierung von vornherein zu aktivieren.

  2. Es soll den Overhead des Funktionsaufrufs eliminieren. Dies ist vor allem für kleine Funktionen wichtig, die so gut wie nichts tun. Zufälligerweise sind diese so weit verbreitet, dass es für eine auch nur halbwegs anständige Leistung von C++ fast erforderlich ist, dass der Compiler die Funktionen mehr oder weniger automatisch inline erweitert.

  3. Im Allgemeinen ist es sinnlos, sie überhaupt zu verwenden.

  4. Normalerweise nicht - wie oben, wenn es einen Vorteil für die Funktion gibt, inline zu sein, kann der Compiler dies normalerweise automatisch tun.

Zwei Dinge sind zu beachten: 1) Die meisten Compiler können/werden Funktionen inline ohne die inline Schlüsselwort, und 2) die meisten Compiler können/werden das inline Schlüsselwort, wenn sie die Funktion als ungeeignet für eine Inline-Erweiterung betrachten (obwohl, nur zur Information, Microsoft hat eine __forceinline letzteres zu überwinden, wenn Sie wirklich sicher, dass Sie es besser wissen als der Compiler).

4voto

t0mm13b Punkte 33393

Bitte beachten Sie diese ausführliche Information in den C++ FAQ ici . Um über diese Inline-Funktionen zu zitieren

Wenn der Compiler einen Funktionsaufruf inline-expandiert, wird der Code der Funktion der Funktion in den Code des Aufrufers eingefügt eingefügt (konzeptionell ähnlich wie bei was mit einem #define-Makro geschieht). Diese kann, abhängig von einer Zillion anderer anderen Dingen, die Leistung verbessern, weil der Optimierer kann prozedural den aufgerufenen Code prozedural integrieren - optimieren des aufgerufenen Codes in den Aufrufer optimieren.

Abschnitt 9.3

Inline-Funktionen könnten es schneller machen: Wie oben gezeigt, kann die prozedurale Integration eine Reihe von unnötigen Anweisungen entfernt werden, was die Dinge schneller laufen.

Inline-Funktionen könnten es langsamer machen: Zu viel Inlining kann den Code aufblähen, was zu "Thrashing" führen kann auf bedarfsgesteuerten Systemen mit virtuellem Arbeitsspeicher Systemen führen kann. Mit anderen Worten, wenn die Größe der ausführbaren Datei zu groß ist, wird das System möglicherweise die meiste Zeit damit verbringen auf die Festplatte, um das nächste Stück Code zu holen Code zu holen.

Inline-Funktionen könnten es größer machen: Dies ist der Begriff der Codeaufblähung, wie oben beschrieben. Zum Beispiel, wenn ein System 100 Inline-Funktionen hat, von denen jede von denen jede 100 Bytes an ausführbarem Code und wird an 100 Stellen aufgerufen aufgerufen wird, ist das ein Zuwachs von 1 MB. Wird diese 1MB Probleme verursachen? Wer weiß es nicht, aber es ist möglich, dass diese dass die letzten 1 MB das System zum zum "Thrash" führen, und das könnte die Dinge verlangsamen.

Inline-Funktionen könnten es ermöglichen kleiner machen: Der Compiler erzeugt oft mehr Code für Push/Pop Registern/Parametern als bei einer Inline-Erweiterung des Funktionskörpers. Dies geschieht bei sehr kleinen Funktionen, und es passiert auch mit großen Funktionen, wenn der Optimierer in der Lage ist in der Lage ist, eine Menge redundanten Code zu entfernen durch prozedurale Integration zu entfernen - das heißt d.h. wenn der Optimierer in der Lage ist, die die große Funktion klein zu machen.

Inline-Funktionen können dazu führen, dass Thrashing verursachen: Inlining kann die Größe der ausführbaren Binärdatei erhöhen, und dies kann zu Thrashing führen.

Inline-Funktionen könnten verhindern, dass Thrashing: Die Größe der Arbeitsmenge (Anzahl der Seiten, die gleichzeitig im Speicher sein müssen Speicher sein müssen) kann sich verringern, auch wenn die Größe der ausführbaren Datei ansteigt. Wenn f() g() aufruft, befindet sich der Code oft auf zwei verschiedenen Seiten; wenn der Compiler prozedural den Code von g() in f() integriert, befindet sich der Code oft auf der Seite gleichen Seite.

Inline-Funktionen könnten die Anzahl der Cache-Fehlversuche: Inlining kann dazu führen, dass sich eine innere Schleife über mehrere Zeilen des Speicher-Caches erstreckt, und das kann zu einer Überlastung des Speicher-Cache verursachen.

Inline-Funktionen können die Anzahl der Cache-Fehlversuche: Inlining verbessert normalerweise die Lokalität der Referenz innerhalb des Binärcodes, was die die Anzahl der Cache-Zeilen verringern Cache-Zeilen, die für die Speicherung des Codes einer inneren Schleife zu speichern. Dies könnte letztlich zu einer CPU-gebundene Anwendung schneller laufen.

Inline-Funktionen könnten irrelevant sein für die Geschwindigkeit: Die meisten Systeme sind nicht CPU-gebunden. Die meisten Systeme sind I/O-gebunden, datenbankgebunden oder netzwerkgebunden, was bedeutet, dass der Engpass im System Gesamtleistung des Systems ist das Dateisystem Dateisystem, die Datenbank oder das Netzwerk. Es sei denn, Ihr "CPU-Zähler" steht auf 100% steht, werden Inline-Funktionen wahrscheinlich nicht Ihr System nicht schneller machen. (Selbst bei CPU-gebundenen Systemen, helfen Inline-Funktionen nur, wenn sie innerhalb des Engpasses verwendet werden selbst verwendet wird, und der Engpass ist typischerweise nur in einem kleinen Prozentsatz des Codes.)

Es gibt keine einfachen Antworten: Man muss man muss damit spielen, um herauszufinden, was am besten ist. Geben Sie sich nicht mit simplen Antworten zufrieden wie "Verwende niemals Inline-Funktionen" oder "Verwende immer Inline-Funktionen" oder "Verwende Inline-Funktionen, wenn und nur wenn die Funktion weniger als N Zeilen Code ist." Diese allgemeingültigen Regeln sind vielleicht einfach aufzuschreiben, aber sie führen aber zu suboptimalen Ergebnissen.

3voto

pmg Punkte 102904

Machen Sie sich keine Gedanken darüber. Es ist alles gleich, bis man misst. Und wenn Sie einmal messen, werden Sie keinen großen Unterschied zwischen den Versionen mit und ohne Kompilierung feststellen. inline .

1) inline ist eine Anregung an den Compiler, die Funktion direkt in den Codefluss "einzubinden", anstatt sie "aufzurufen". Dadurch wird die Notwendigkeit umgangen, einen Stack einzurichten und andere Aufgaben zu erledigen, die für den Aufruf einer Funktion erforderlich sind

        NOT INLINE                    INLINE
        ...                           ...
        code                          code
        call fx    -\\                 code from fx
        code        |                 code from fx
        call fx   --|                 code from fx
        ...         |                 code
                    |                 code from fx
        code <------/                 code from fx
        ...                           code from fx
        return                        ...

2) Verwenden Sie es, wo immer Sie wollen. Der Compiler wird Ihren Vorschlag höchstwahrscheinlich ignorieren

3) wie 2)

4) messen. experimentieren und vergleichen

2voto

RBerteig Punkte 39719

El inline zeigt an, dass Sie diese Funktion für einen guten Kandidaten halten, um sie anstelle eines Funktionsaufrufs einzufügen. Es wird am besten für kleine Funktionen verwendet, da bei jeder Verwendung eine neue Kopie des Funktionskörpers an den Verwendungsort gestellt wird. Eine übermäßige Verwendung könnte die Größe des aufrufenden Codes erheblich erhöhen.

Sie ist wertvoll, weil der Optimierer manchmal bessere Arbeit leisten könnte, wenn er in eine kleine Funktion hineinsehen könnte. Indem der Funktionsrumpf inline gestellt wird, erhält der Optimierer diese Chance. Außerdem wird die Lokalität des Verweises auf den Ausführungsfaden verbessert, was die Leistung des Befehlscaches und der Pipeline steigern kann.

In klassischem C war die einzige Möglichkeit, diesen Effekt mit einem Makro zu erzielen, aber Makros haben den großen Nachteil, dass sie eine reine Textersetzung sind und daher jedes ihrer Argumente jedes Mal ausgewertet wird, wenn sie im Ersetzungstext erscheinen. Es ist auch nicht ersichtlich, wie man einem Makro sicher erlauben kann, lokale Variablen zu haben.

In C++ ist es oft von großem Vorteil, wenn die kleinen Zugriffsfunktionen, die ein gängiges Idiom der Sprache sind, inline sein können, und zwar so sehr, dass Funktionen, deren Körper in der Klassendefinition definiert sind, implizit markiert werden inline .

Ein guter Optimierer entscheidet selbst, wann er die Funktion tatsächlich inline verwendet und wann er sie normal aufruft, so dass es in der Regel keine negativen Auswirkungen hat, wenn Funktionen großzügig als inline .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X