Es ist allgemein bekannt, dass das Inlining von Funktionen nicht immer von Vorteil ist und sogar die Performance beeinträchtigen kann:
Ich verstehe, warum Inlining helfen soll - es eliminiert den Funktionsaufruf-Overhead, indem es die aufgerufene Funktion in den Aufrufer aufnimmt.
Ich verstehe auch, warum Leute behaupten, dass es Leistung beeinträchtigen kann - Inlining-Funktionen können in einigen Fällen die Code-Größe erhöhen, was schließlich Cache-Fehler erhöhen oder sogar zusätzliche Seitenfehler auslösen kann. Das macht alles Sinn.
Ich habe jedoch Schwierigkeiten, spezifische Beispiele zu finden, bei denen das Inlining tatsächlich die Leistung beeinträchtigt. Sicherlich, wenn es genug eines Problems ist, das es wert ist, davor gewarnt zu werden, muss jemand irgendwo ein Beispiel gefunden haben, bei dem Inlining ein Problem ist. Also frage ich ...
Was ist ein gutes, konkretes Beispiel für einen Code, bei dem die Leistung tatsächlich durch Inline-Funktionen beeinträchtigt wird?
Bei manchen Plattformen mit großen Funktionen mit Inlining kann die Leistung reduziert werden, indem ein "Weitsprung" anstatt eines relativen Sprungs verursacht wird. Inlining kann auch einen Seitenfehler verursachen, bei dem das Betriebssystem mehr Code in den Speicher einlesen muss, als Code auszuführen, der bereits existiert (als Unterprogramm).
Einige Plattformen haben möglicherweise optimierte Sprungbefehle für "naher Code". Diese Art von Sprung verwendet einen vorzeichenbehafteten Offset von der aktuellen Position. Die vorzeichenbehafteten Offsets können beschränkt sein, zum Beispiel 127 Bytes. Ein langer Sprung würde einen größeren Befehl erfordern, da der längere Sprung die absolute Adresse enthalten muss. Längere Anweisungen benötigen mehr Zeit für die Ausführung.
Long-inline-Funktionen können die Länge der ausführbaren Datei erweitern, so dass das Betriebssystem eine neue "Seite" in den Speicher einlesen muss, die als Seitenwechsel bezeichnet wird. Seitenwechsel verlangsamt die Ausführungsgeschwindigkeit einer Anwendung.
Dies sind "mögliche" Gründe, wie inline-Code die Leistung verlangsamen könnte. Die wahre Wahrheit wird durch Profiling erhalten.
Ich hatte den Fall in unserem Projekt in C (gcc). Mein Kollege missbraucht Inlines in seiner Bibliothek, wodurch -fno-inline
die CPU-Zeit um 10% reduzierte (auf SUN V890 mit Ultrasparc IV + -Prozessoren).
Etwas, das noch nicht erwähnt wurde, ist, dass das Einfügen von großen Funktionen in andere große Funktionen zu übermäßigem Registerüberlauf führen kann, was nicht nur die Qualität des kompilierten Codes beeinträchtigt, sondern auch mehr Overhead verursacht, als von der Inline-Schraube eliminiert wurde up globale und lokale Optimierung heurstics, Iirc msdn hat eine Warnung darüber unter __forceinline
). Andere "Konstrukte" wie Inline-Nicht-Naked-Asm, die in Inlines gesteckt werden, können unnötige Stack-Frames oder Inlines mit speziellen Alignment-Anforderungen erzeugen oder sogar diejenigen, die die Stack-Allocation nur in den Bereich schieben, in dem der Compiler die Stack-Checking-Zuweisung verschiebt % unter msvc).
Ich glaube nicht, dass Inlining die Leistung beeinträchtigt, außer dass es sich indirekt auf den Code bezieht, der größer ist, was ich denke, dass Sie ihn beschrieben haben.
Im Allgemeinen verbessert Inlining die Leistung, indem es den Aufruf eliminiert und zurückgibt.
[In Bezug auf Inline-Funktionen]
Die Funktion wird im Code platziert, anstatt wie ähnlich zu heißen Makros (konzeptionell) verwenden
Dies kann die Geschwindigkeit verbessern (keine Funktion) call), aber verursacht Code Bloat (wenn die Funktion wird 100 mal verwendet, Sie jetzt habe 100 Kopien)
Sie sollten beachten, dass dies nicht erzwingt der Compiler, um die Funktion zu machen Inline, und es wird Sie ignorieren, wenn es hält es für eine schlechte Idee. Ähnlich der Compiler kann beschlossen, normal zu machen funktioniert inline für Sie.
Damit können Sie auch die gesamte Funktion in einer Header-Datei, anstatt es in einem cpp zu implementieren Datei (die Sie sowieso nicht können, seit dann bekommst du ein ungelöstes externes if es wurde inline deklariert, es sei denn von natürlich nur diese cpp-datei benutzt es).
[Zitat von SO-Benutzer "Fire Lancer" so Kredit ihn]
Ich habe keine harten Daten, um dies zu untermauern, aber im Fall des Linux-Kernels (da der "Linux-Kernel-Style-Guide" in der Frage zitiert wurde) könnte die Code-Größe die Performance beeinträchtigen, da der Kernel-Code physisch besetzt ist Speicher unabhängig vom Befehl Caching (Kernel-Seiten werden nie ausgelagert).
Speicherseiten, die vom Kernel verwendet werden, sind für den virtuellen Benutzerspeicher nicht verfügbar. Wenn Sie also Speicherseiten für inline Code verwenden, die zweifelhaften Nutzen haben (der Anruf-Overhead ist bei großen Funktionen im Allgemeinen klein), haben Sie einen negativen Einfluss auf das System, ohne dass Sie davon profitieren.
Warum brauchen Sie konkrete Beispiele dafür, wo Inlining die Leistung beeinträchtigt? Es ist solch ein kontextsensitives Problem. Es hängt von einer Anzahl von Hardware-Faktoren ab, einschließlich der Geschwindigkeit des RAM, des CPU-Modells, der Compiler-Version und einer Anzahl anderer Faktoren. Es ist möglich, ein solches Beispiel auf meinem Computer zu erstellen, das aber immer noch schneller ist als die nicht-inline Version. Durch Inlining können wiederum dutzende von anderen Compileroptimierungen aktiviert werden, die andernfalls nicht ausgeführt würden. Selbst in einem Fall, in dem der Code-Bloat einen Leistungseinbruch verursacht, kann es einigen Compilern ermöglichen, eine Anzahl anderer Optimierungen durchzuführen, um sie zu kompensieren.
Sie werden also keine aussagekräftigere Antwort erhalten als die Theorie, warum sie langsameren Code produzieren könnte.
Wenn Sie ein konkretes Beispiel dafür brauchen, wo die Leistung durch Inlining beeinträchtigt werden kann, dann schreiben Sie weiter. Es ist nicht so schwierig, wenn du erst einmal die Theorie kennst.
Sie möchten eine Funktion, die groß genug ist, um den Cache zu verunreinigen, wenn sie inline ist, und Sie sie von mehreren verschiedenen, aber eng verwandten Orten aufrufen wollen (wenn Sie sie aus zwei völlig getrennten Modulen aufrufen, dann die beiden Instanziierungen des Die Funktion wird zwar nicht um den Cache-Platz konkurrieren, aber wenn Sie schnell zwischen mehreren verschiedenen Aufruf-Sites wechseln, kann jede Instanziierung die vorherige aus dem Cache zwingen.
Und natürlich muss die Funktion so geschrieben sein, dass wenig davon eliminiert werden kann, wenn es inline ist. Wenn der Compiler beim Inlining 80% des Codes eliminieren kann, mindert dies den Leistungseinbruch, den Sie sonst machen könnten.
Und schließlich müssen Sie es wahrscheinlich zwingen, inline zu sein. Im besten Fall behandeln Compiler das Schlüsselwort inline
als Hinweis (manchmal nicht einmal das). Daher müssen Sie wahrscheinlich nach Compiler-spezifischen Methoden suchen, um zu erzwingen, dass eine Funktion inline wird.
Sie können auch andere Optimierungen deaktivieren, da der Compiler ansonsten die Inline-Version optimieren könnte.
Es ist also ziemlich einfach, langsameren Code durch Inlining zu erzeugen, sobald Sie wissen, was zu tun ist. Aber es ist eine Menge Arbeit, besonders wenn Sie etwas in der Nähe von vorhersagbaren oder deterministischen Ergebnissen wollen. Und trotz Ihrer Bemühungen können die Compiler des nächsten Jahres oder die CPUs des nächsten Jahres wieder in der Lage sein, Sie auszutricksen und schneller Code von Ihrem absichtlich "über-inlined" Code zu produzieren.
Ich verstehe also nicht, warum Sie das tun müssen. Akzeptieren Sie, dass übermäßiges Inlining in einigen Fällen schaden kann, und verstehen Sie warum es schaden kann. Darüber hinaus, warum stören?
Ein letzter Punkt ist, dass diese Warnungen oft fehlgeleitet sind, weil es sehr wenig zu warnen gibt. Weil der Compiler normalerweise selbst wählt, was inline ist, und bestenfalls das Schlüsselwort inline
als Hinweis behandelt, ist es im Allgemeinen egal / ob Sie es tun oder nicht versuch alles zu inline.
Obwohl es zutrifft, dass übermäßiges Inlining die Leistung beeinträchtigen kann, ist die übermäßige Verwendung von inline
keyword normalerweise nicht der Fall.
Das Schlüsselwort inline
hat andere Effekte, die bei der Verwendung helfen sollten. Verwenden Sie diese Option, wenn Sie die Regel "Eine Definition" deaktivieren möchten, um Linkerfehler zu vermeiden, wenn eine Funktion in mehreren Übersetzungseinheiten definiert ist.