Frage

Vor kurzem ein Kollege hat mich darauf hingewiesen, dass alles in einer einzigen Datei zusammenzustellen erstellt viel effizienter Code als separaten Objektdateien kompilieren - auch mit Optimierung Link Zeit eingeschaltet . Darüber hinaus ging die gesamte Kompilierung für das Projekt erheblich. Da einer der Hauptgründe für die Verwendung von C ++ Code-Effizienz ist, war das für mich überraschend.

ist klar, wenn die Archivierungs / Linker eine Bibliothek aus Objektdateien macht, oder verknüpft sie in eine ausführbare Datei, selbst einfache Optimierungen werden bestraft. Im Beispiel unten, trivial inlining kostet 1,8% in der Leistung, wenn sie durch den Linker anstelle des Compilers getan. Es scheint, wie Compiler-Technologie genug vorangetrieben werden soll ziemlich häufig Situationen wie diese zu behandeln, aber es ist nicht passiert.

Hier ist ein einfaches Beispiel mit Visual Studio 2008:

#include <cstdlib>
#include <iostream>
#include <boost/timer.hpp>

using namespace std;

int foo(int x);
int foo2(int x) { return x++; }

int main(int argc, char** argv)
{
  boost::timer t;

  t.restart();
  for (int i=0; i<atoi(argv[1]); i++)
    foo (i);
  cout << "time : " << t.elapsed() << endl;

  t.restart();
  for (int i=0; i<atoi(argv[1]); i++)
    foo2 (i);
  cout << "time : " << t.elapsed() << endl;
}

foo.cpp

int foo (int x) { return x++; }

Ergebnisse des Laufes: 1,8% Leistung getroffen mit verknüpften foo statt Inline foo2

.
$ ./release/testlink.exe  100000000
time : 13.375
time : 13.14

Und ja, die Linkeroptimierungsflags (/ LTCG) sind.

War es hilfreich?

Lösung

Ich bin kein Compiler-Spezialist, aber ich denke, der Compiler zur Verfügung viel mehr Informationen zur Verfügung hat zu optimieren, wie es auf einem Sprachbaum arbeitet, wie an den Linker gegenüber, die sich auf dem Objekt Ausgang für den Betrieb zum Inhalt hat, weit weniger ausdrucksvoll als der Code der Compiler gesehen. Daher weniger Aufwand durch Linker und Compiler-Entwicklungsteam (s) in der Herstellung Linker Optimierungen, könnte passen, in der Theorie ausgegeben, die Tricks die Compiler tun.

BTW, ich bin traurig, dass ich Ihre ursprüngliche Frage in die LTCG Diskussion abgelenkt. Ich verstehe jetzt Ihre Frage war ein bisschen anders, mehr mit der Verknüpfungszeit vs. Kompilierung statische Optimierungen möglich / zur Verfügung.

Andere Tipps

Ihre Mitarbeiter sind nicht mehr aktuell. Die Technologie hat sich seit 2003 (auf der MS C ++ Compiler) hier gewesen: / LTCG . Link Timecode-Generierung wird mit genau diesem Problem beschäftigen. Von dem, was ich weiß, die GCC diese Funktion für die nächste Generation Compiler auf dem Radar hat.

LTCG nicht nur den Code zu optimieren, wie Funktionen in Module inlining, aber eigentlich rearanges Code Cache Ort zu optimieren und für eine bestimmte Last Verzweigung finden Sie unter Profil-geführte Optimierung . Diese Optionen sind reserviert usualy nur für Release baut wie die Build-Stunden dauern kann, beenden: eine instrumentierten ausführbaren verknüpfen, eine Profilierung Last laufen und dann wieder verbinden mit den Profilierungs Ergebnisse. Der Link enthält ausführliche Informationen darüber, was genau mit LTCG optimiert:

  

Inlining - zum Beispiel, wenn es   existiert eine Funktion, A, die häufig   ruft Funktion B, und die Funktion B ist   relativ klein ist, dann das Profil gelenkten   Optimierungen Funktion B inline   in Funktion A.

     

Virtual Call Speculation - Wenn ein   virtueller Anruf oder anderer Anruf durch eine   Funktionszeiger zielt häufig ein   bestimmte Funktion, ein Profil-geführtes   Optimierung kann einfügen einer   bedingt ausgeführten direkten Aufruf   die häufig gezielte Funktion und   der direkte Aufruf inlined werden kann.

     

Register Allocation - Optimierung mit   Profildaten führt zu einer besseren   Registerzuweisung.

     

Basic Block Optimierung - Basisblock   Optimierung ermöglicht häufig ausgeführt   Basisblöcke, die zeitlich auszuführen   innerhalb eines gegebenen Rahmens in platziert werden   der gleiche Satz von Seiten (Lokalität). Diese   minimiert die Anzahl der Seiten verwendet wird,   somit Speicher-Overhead minimiert wird.

     

Größe / Performance-Optimierung - Funktionen   wo verbringt das Programm viel Zeit   kann auf Geschwindigkeit optimiert werden.

     

Funktion Layout- - Basierend auf den Anruf   Graph und Profil Anrufer / Angerufenen   Verhalten, das Funktionen neigen dazu,   entlang der gleichen Ausführungspfad sind   im selben Abschnitt platziert.

     

Conditional Branch-Optimierung - Mit   die Wert-Sonden, Profil-geführte   Optimierungen können, wenn ein bestimmte finden   Wert in einer Switch-Anweisung wird verwendet,   häufiger als andere Werte. Diese   Wert kann dann aus dem gezogen werden   switch-Anweisung. Das gleiche kann getan werden,   mit if / else Anweisungen, wo die   Optimierer kann die if / else bestellen so   dass entweder der, wenn sonst Block   erste Abhängigkeit davon, welcher Block platziert   ist häufiger der Fall.

     

Dead Code Trennung - Code, der ist   nicht während der Profilierung genannt wird bewegt   auf einen speziellen Abschnitt, der angehängt ist   bis zum Ende des Satzes von Abschnitten.   Dies hält effektiv diesen Abschnitt   aus den häufig verwendeten Seiten.

     

EH-Code Trennung - Der EH-Code,   Sein außergewöhnlich ausgeführt wird, kann   oft auf einem separaten Abschnitt bewegt werden   wenn Profil-geführte Optimierungen können   feststellen, dass die Ausnahmen auftreten   nur auf außergewöhnliche Bedingungen.

     

Speicher Intrinsics - Der Ausbau der   intrinsics kann besser, wenn entschieden wird,   kann bestimmt werden, wenn ein intrinsisches ist   häufig genannt. Eine intrinsische CAN-   auch optimiert werden auf dem Block basiert   Größe verschiebt oder kopiert.

Ihre Mitarbeiter sind intelligenter als die meisten von uns. Auch wenn es zunächst eine grobe Annäherung scheint, Projekt inlining in eine einzige CPP-Datei hat eine Sache, dass die anderen Ansätze, wie Link-Time-Optimierung hat nicht und wird nicht für während haben - Zuverlässigkeit

Allerdings bat Sie dies vor zwei Jahren, und ich bezeuge, dass viel hat sich seitdem verändert (mit g ++ zumindest). Devirtualization ist viel zuverlässiger, zum Beispiel.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top