Ich weiß, dass Inline ein Hinweis oder eine Anforderung an den Compiler ist und zur Vermeidung von Funktionsaufruf-Overheads verwendet wird.
Auf welcher Grundlage kann man also feststellen, ob eine Funktion ein Kandidat für Inlining ist oder nicht? In welchem Fall sollte man Inlining vermeiden?
inline
ist für den C ++ - Neuling das, wasCFLAGS
für den Gentoo-Neuling ist: Nein, das Kompilieren mit-O3 -funroll-loops -finline-functions
bringt Ihren alten Pentium nicht zum Fliegen;)Antworten:
Das Vermeiden der Kosten eines Funktionsaufrufs ist nur die halbe Wahrheit.
machen:
inline
statt#define
inline
: schnelleren Code und kleinere ausführbare Dateien (mehr Chancen, im Code-Cache zu bleiben)nicht:
Wenn Sie eine Bibliothek entwickeln, sollten Sie Folgendes tun, um eine Klasse in Zukunft erweiterbar zu machen:
Denken Sie daran, dass das
inline
Schlüsselwort ein Hinweis für den Compiler ist: Der Compiler kann entscheiden, eine Funktion nicht zu inlineieren, und er kann entscheiden, Funktionen inline zu setzen, die überhaupt nicht markiert wurdeninline
. Ich vermeide generell Markierungsfunktioneninline
(abgesehen davon, wenn ich sehr, sehr kleine Funktionen schreibe).In Bezug auf die Leistung besteht der kluge Ansatz (wie immer) darin, die Anwendung zu profilieren und schließlich
inline
eine Reihe von Funktionen, die einen Engpass darstellen.Verweise:
EDIT: Bjarne Stroustrup, Die C ++ - Programmiersprache:
EDIT2: ISO-IEC 14882-1998, 7.1.2 Funktionsspezifizierer
quelle
inline
ist viel mehr als ein Hinweis für den Compiler. Es ändert die Sprachregeln für mehrere Definitionen. Statische Daten sind auch kein Grund aus Gusseisen, um das Inlining einer Funktion zu vermeiden. Die Implementierung muss für jede statische Funktion ein einzelnes statisches Objekt zuweisen, unabhängig davon, ob die Funktion deklariert istinline
oder nicht. Klassen sind weiterhin erweiterbar, wenn sie Inline-Konstruktoren und virtuelle Destruktoren haben. Und ein leerer Klammer-Destruktor ist die einzige virtuelle Funktion, bei der es manchmal eine gute Idee ist, inline zu bleiben.inline
Funktionen führt dies dazu, dass die Funktion nicht inline wird: Sie zahlen den Preis für den Aufruf, und jede Übersetzungseinheit, die die Funktion enthält und aufruft, erhält eine eigene Kopie des Codes und der statischen Variablen. Der Grund dafür, Konstruktoren und Destruktoren beim Entwickeln einer Bibliothek nicht einzubinden, ist die Binärkompatibilität mit zukünftigen Versionen Ihrer Bibliothekinline
können Nichtfunktionen eingebunden werden, wenn der Compiler dies wünscht. Undinline
Funktionen werden nicht eingebunden, wenn der Compiler beschließt, sie nicht einzubinden. Wie Charles Bailey sagte, ändert es die Sprachregeln. Anstatt es als Optimierungshinweis zu betrachten, ist es genauer, es als ein völlig anderes Konzept zu betrachten. Dasinline
Schlüsselwort weist den Compiler an, mehrere Definitionen zuzulassen, und sonst nichts. Die "Inlining" -Optimierung kann auf fast jede Funktion angewendet werden, unabhängig davon, ob sie markiert ist oder nichtinline
.inline
, um Funktionsinlining zu erhalten. Manchmal wollen wir die anderen Vorteile, wie das Umgehen von ODR.inline
hat sehr wenig mit Optimierung zu tun.inline
ist eine Anweisung an den Compiler, keinen Fehler zu erzeugen, wenn die definierte Funktion mehrmals im Programm vorkommt, und ein Versprechen, dass die Definition in jeder verwendeten Übersetzung vorkommt und überall dort, wo sie erscheint, genau dieselbe Definition hat.In Anbetracht der oben genannten Regeln
inline
eignet es sich für kurze Funktionen, deren Hauptteil keine zusätzlichen Abhängigkeiten von dem erfordert, was nur eine Deklaration benötigen würde. Jedes Mal, wenn die Definition gefunden wird, muss sie analysiert werden, und es kann Code für ihren Text generiert werden, sodass ein gewisser Compiler-Overhead für eine Funktion entsteht, die nur einmal in einer einzelnen Quelldatei definiert ist.Ein Compiler kann jeden von ihm gewählten Funktionsaufruf inline (dh einen Aufruf der Funktion durch Code ersetzen, der diese Aktion dieser Funktion ausführt). Früher war es so, dass es "offensichtlich" nicht möglich war, eine Funktion zu integrieren, die nicht in derselben Übersetzungseinheit wie der Aufruf deklariert war, aber mit der zunehmenden Verwendung der Optimierung der Verbindungszeit ist auch dies jetzt nicht mehr der Fall. Ebenso wahr ist die Tatsache, dass markierte Funktionen
inline
möglicherweise nicht inline sind.quelle
inline
Schlüsselwort zu tun ? Und was ist ein glücklicher Zufall?Dem Compiler zu sagen, dass er eine Funktion einbinden soll, ist eine Optimierung, und die wichtigste Regel für die Optimierung ist, dass vorzeitige Optimierung die Wurzel allen Übels ist. Schreiben Sie immer klaren Code (mit effizienten Algorithmen), profilieren Sie dann Ihr Programm und optimieren Sie nur Funktionen, die zu lange dauern.
Wenn Sie feststellen, dass eine bestimmte Funktion sehr kurz und einfach ist und in einer engen inneren Schleife zehntausende Male aufgerufen wird, ist sie möglicherweise ein guter Kandidat.
Sie könnten jedoch überrascht sein - viele C ++ - Compiler integrieren automatisch kleine Funktionen für Sie - und ignorieren möglicherweise auch Ihre Anfrage nach Inline.
quelle
/FAcs
in Visual Studio,-s
in GCC) ausgibt, um genau zu sehen, was er tut. Nach meiner Erfahrung wiegen beide Compiler das Inline-Keyword ziemlich stark.inline
Schlüsselwort wiegen . Das heißt, wenn Sie sehen, dass die Funktion inline ist, und den Bezeichner daraus entferneninline
, wird sie weiterhin inline. Wenn Sie konkrete Beispiele für das Gegenteil haben, teilen Sie diese bitte mit!inline
Schlüsselwort "Code löschen"? Das Schlüsselwort in "vorzeitige Optimierung" ist verfrüht , nicht Optimierung. Zu sagen, dass Sie Optimierungen aktiv vermeiden sollten, ist nur Quatsch. Der Punkt dieses Zitats ist, dass Sie die Optimierungen vermeiden sollten, die möglicherweise nicht notwendig sind, und schädliche Nebenwirkungen auf den Code haben sollten (z. B. ihn weniger wartbar machen). Ich kann nicht erkennen, wie dasinline
Schlüsselwort den Code weniger wartbar macht oder wie schädlich es sein kann, ihn einer Funktion hinzuzufügen.Der beste Weg, dies herauszufinden, besteht darin, Ihr Programm zu profilieren und kleine Funktionen zu markieren, die häufig aufgerufen werden, und CPU-Zyklen durchzubrennen, die als
inline
. Das Schlüsselwort hier ist "klein" - sobald der Overhead des Funktionsaufrufs im Vergleich zu der in der Funktion verbrachten Zeit vernachlässigbar ist, ist es sinnlos, sie zu integrieren.Die andere Verwendung, die ich vorschlagen würde, ist, wenn Sie kleine Funktionen haben, die im leistungskritischen Code oft genug aufgerufen werden, um einen Cache-Miss relevant zu machen, sollten Sie diese wahrscheinlich auch inline setzen. Auch dies sollte der Profiler Ihnen sagen können.
quelle
Vorzeitige Optimierung ist die Wurzel allen Übels!
Als Faustregel habe ich normalerweise nur "Getter" und "Setter" inline. Sobald der Code funktioniert und stabil ist, kann die Profilerstellung zeigen, welche Funktionen vom Inlining profitieren können.
Auf der anderen Seite verfügen die meisten modernen Compiler über recht gute Optimierungsalgorithmen und geben an, was Sie für Sie hätten tun sollen.
Wiederaufnahme - Schreiben Sie Inline-Einzeilerfunktionen und sorgen Sie sich später um andere.
quelle
Inline-Funktionen können die Codeleistung verbessern, da keine Argumente mehr in den Stapel verschoben werden müssen. Wenn sich die betreffende Funktion in einem kritischen Teil Ihres Codes befindet, sollten Sie die Inline- und nicht Inline-Entscheidung im Optimierungsteil Ihres Projekts treffen.
Weitere Informationen zu Inlines finden Sie in der FA ++ - FAQ
quelle
Ich benutze Inline-Funktionen oft nicht als Optimierung, sondern um den Code besser lesbar zu machen. Manchmal ist der Code selbst kürzer und leichter zu verstehen als Kommentare, beschreibende Namen usw. Zum Beispiel:
Der Leser kennt sofort die vollständige Semantik des Codes.
quelle
Ich folge im Allgemeinen einer Daumenregel, bei der ich eine Funktion mit 3-4 einfachen Anweisungen als Inline mache. Es ist jedoch gut daran zu denken, dass dies nur ein Hinweis für den Compiler ist. Der letzte Aufruf, um es inline zu machen oder nicht, wird nur vom Compiler ausgeführt. Wenn es mehr als diese vielen Anweisungen gibt, werde ich nicht inline deklarieren, da dies bei einem dummen Compiler zu einem Aufblähen des Codes führen kann.
quelle
Der beste Weg wäre, die generierten Anweisungen für Inline und nicht Inline zu untersuchen und zu vergleichen. Es ist jedoch immer sicher, wegzulassen
inline
. Die Verwendunginline
kann zu Problemen führen, die Sie nicht möchten.quelle
Bei der Entscheidung, ob Inline verwendet werden soll, denke ich normalerweise an die folgende Idee: Auf modernen Maschinen kann die Speicherlatenz ein größerer Engpass sein als bei Rohberechnungen. Es ist bekannt, dass Inlining-Funktionen, die häufig aufgerufen werden, die Größe der ausführbaren Datei erhöhen. Darüber hinaus könnte eine solche Funktion im Code-Cache der CPU gespeichert werden, wodurch die Anzahl der Cache-Fehler verringert wird, wenn auf diesen Code zugegriffen werden muss.
Daher müssen Sie selbst entscheiden: Erhöht oder verringert Inlining die Größe des generierten Maschinencodes? Wie wahrscheinlich ist es, dass das Aufrufen der Funktion einen Cache-Fehler verursacht? Wenn es im gesamten Code verteilt ist, würde ich sagen, dass die Wahrscheinlichkeit hoch ist. Wenn es auf eine einzelne enge Schleife beschränkt ist, ist die Wahrscheinlichkeit hoffentlich gering.
Ich verwende normalerweise Inlining in den Fällen, in denen ich unten aufgeführt bin. Wenn Sie jedoch ernsthaft über die Leistung besorgt sind, ist die Profilerstellung unerlässlich. Außerdem möchten Sie möglicherweise überprüfen, ob der Compiler den Hinweis tatsächlich versteht.
quelle
Eine Inline-Methode hat auch schwerwiegende Nebenwirkungen bei der Verwaltung großer Projekte. Wenn der Inline-Code geändert wird, werden alle Dateien, die ihn verwenden, vom Compiler automatisch neu erstellt (es ist ein guter Compiler). Dies könnte viel Entwicklungszeit verschwenden.
Wenn eine
inline
Methode in eine Quelldatei übertragen und nicht mehr eingebunden wird, muss das gesamte Projekt neu erstellt werden (zumindest war dies meine Erfahrung). Und auch, wenn Methoden in Inline konvertiert werden.quelle
inline
oder nicht, spielt keine Rolle (außer ohne dasinline
Schlüsselwort werden Linker-Fehlerinline
Das Inline- Funktionsqualifikationsmerkmal sollte nur verwendet werden, wenn der Funktionscode klein ist. Wenn die Funktionen größer sind, sollten Sie die normalen Funktionen bevorzugen, da die Einsparung von Speicherplatz das vergleichsweise geringe Opfer an Ausführungsgeschwindigkeit wert ist.
quelle
Wenn Sie der Meinung sind, dass Ihr Code klein genug ist, um als Inline-Funktion verwendet zu werden, und sich daran erinnern, dass die Inline-Funktion Ihren Code dupliziert und dort einfügt, wo die Funktion aufgerufen wird, ist sie möglicherweise gut genug, um die Ausführungszeit zu erhöhen, erhöht aber auch den Speicherverbrauch. Sie können die Inline-Funktion nicht verwenden, wenn Sie eine Funktion loop / static variable / recursive / switch / goto / Virtual verwenden. Virtuelle Mittel warten bis zur Laufzeit und Inline bedeutet während der Kompilierung, sodass sie nicht gleichzeitig verwendet werden können.
quelle
Ich habe einige Antworten gelesen und sehe, dass einige Dinge fehlen.
Die Regel, die ich verwende, ist, Inline nicht zu verwenden, es sei denn, ich möchte, dass es Inline ist. Sieht albern aus, jetzt Erklärung.
Compiler sind intelligent genug und kurze Funktionen machen immer Inline. Und macht niemals lange Funktion als Inline, es sei denn, der Programmierer hat dies gesagt.
Eigentlich
inline
ist eine Bestellung für Compiler, es hat keine Auswahl und nachinline
Schlüsselwort macht der gesamte Code inline. Sie können also niemals eininline
Schlüsselwort verwenden und der Compiler entwirft den kürzesten Code.Also wann verwenden
inline
?Zu verwenden, wenn Sie Code inline haben möchten. Ich kenne nur ein Beispiel, weil ich es nur in einer Situation verwende. Es ist eine Benutzerauthentifizierung.
Zum Beispiel habe ich diese Funktion:
Egal wie groß diese Funktion ist, ich möchte sie als Inline haben, da meine Software dadurch schwerer zu knacken ist.
quelle