Question

Récemment, un collègue m'a fait remarquer que tout compiler dans un seul fichier créait un code beaucoup plus efficace que de compiler des fichiers objet distincts - même avec l'optimisation du temps de liaison activée . En outre, le temps total de compilation du projet a considérablement diminué. Étant donné que l’efficacité du code est l’une des principales raisons de l’utilisation de C ++, cela m’a surpris.

Clairement, lorsque l’archiveur / éditeur de liens crée une bibliothèque à partir de fichiers d’objets ou les relie à un exécutable, même les optimisations les plus simples sont pénalisées. Dans l'exemple ci-dessous, l'intégration en ligne coûte 1,8% de performances lorsqu'elle est effectuée par l'éditeur de liens au lieu du compilateur. Il semble que la technologie du compilateur devrait être suffisamment avancée pour gérer des situations assez courantes comme celle-ci, mais cela ne se produit pas.

Voici un exemple simple d'utilisation de 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++; }

Résultats de l’exécution: 1,8% de performance sur l'utilisation du foo lié ??au lieu du foo2 en ligne.

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

Et oui, les indicateurs d'optimisation de l'éditeur de liens (/ LTCG) sont activés.

Était-ce utile?

La solution

Je ne suis pas un spécialiste du compilateur, mais je pense que le compilateur dispose de beaucoup plus d'informations à optimiser pour pouvoir fonctionner dans une arborescence de langues, par opposition à l'éditeur de liens qui doit se contenter d'opérer sur la sortie de l'objet. beaucoup moins expressif que le code que le compilateur a vu. Par conséquent, les équipes de développement de l'éditeur de liens et du compilateur consacrent moins d'efforts à l'optimisation de l'éditeur de liens pouvant correspondre, en théorie, aux astuces du compilateur.

BTW, je suis désolé d’avoir distrait votre question initiale dans la discussion à venir. Je comprends maintenant que votre question était un peu différente, plus centrée sur les optimisations statiques temps de compilation / temps de compilation possibles / disponibles.

Autres conseils

Votre collègue est obsolète. La technologie existe depuis 2003 (sur le compilateur MS C ++): / LTCG . La génération de code de temps de liaison traite exactement de ce problème. De ce que je sais, le GCC a déjà cette fonctionnalité en tête pour le compilateur de nouvelle génération.

LTCG n'optimise pas seulement le code comme des fonctions en ligne dans plusieurs modules, il réorganise le code pour optimiser l'emplacement du cache et la création de branches pour un chargement spécifique. Voir Optimisations guidées par le profil . Ces options sont généralement réservées aux versions Release car la construction peut prendre des heures: lier un exécutable instrumenté, exécuter une charge de profilage puis se lier à nouveau aux résultats du profilage. Le lien contient des détails sur ce qui est exactement optimisé avec LTCG:

  

Insertion en ligne & # 8211; Par exemple, s'il y a   existe une fonction A qui fréquemment   appelle la fonction B et la fonction B est   relativement petit, puis guidé par profil   optimisations en ligne fonction B   en fonction A.

     

Spéculation d'appels virtuels & # 8211; Si un   appel virtuel ou tout autre appel via un   pointeur de fonction, vise fréquemment un   certaine fonction, un profil guidé   l'optimisation peut insérer un   appel direct à exécution conditionnelle   la fonction fréquemment ciblée, et   l'appel direct peut être en ligne.

     

Enregistrer l'allocation & # 8211; Optimiser avec   les données de profil donnent de meilleurs résultats   enregistrer l'allocation.

     

Optimisation des blocs de base & # 8211; Bloc de base   l'optimisation permet couramment exécuté   blocs de base qui exécutent temporairement   dans un cadre donné pour être placé dans   le même ensemble de pages (localité). Ce   minimise le nombre de pages utilisées,   minimisant ainsi la surcharge de mémoire.

     

Optimisation taille / vitesse & # 8211; Les fonctions   où le programme passe beaucoup de temps   peut être optimisé pour la vitesse.

     

Présentation de la fonction & # 8211; Basé sur l'appel   graphique et profilé appelant / appelé   comportement, fonctions qui ont tendance à être   le même chemin d'exécution sont   placé dans la même section.

     

Optimisation conditionnelle des branches & # 8211; Avec   les sondes de valeur, guidées par profil   optimisations peuvent trouver si un donné   la valeur dans une instruction switch est utilisée   plus souvent que d'autres valeurs. Ce   la valeur peut alors être extraite de la   déclaration de commutateur. La même chose peut être faite   avec des instructions si / autre où le   optimiseur peut commander le si / sinon donc   que le bloc if ou else soit   placé en premier selon le bloc   est plus souvent vrai.

     

Séparation du code mort & # 8211; Code qui est   non appelé lors du profilage est déplacé   à une section spéciale qui est ajoutée   à la fin de l'ensemble des sections.   Ceci conserve efficacement cette section   sur les pages souvent utilisées.

     

Séparation du code EH & # 8211; Le code EH,   étant exceptionnellement exécuté, peut   souvent être déplacé vers une section séparée   lorsque les optimisations guidées par profil peuvent   déterminer que les exceptions se produisent   uniquement dans des conditions exceptionnelles.

     

Intrinsèques de la mémoire & # 8211; L'expansion de   les intrinsèques peuvent être mieux décidés si   peut être déterminé si un intrinsèque est   appelé fréquemment. Une boîte intrinsèque   également être optimisé en fonction du bloc   taille des déplacements ou des copies.

Votre collègue est plus intelligent que la plupart d'entre nous. Même si cela semble être une approche grossière au début, l’inclusion de projet dans un fichier .cpp unique a une chose que les autres approches, comme l’optimisation du temps de liaison, n’a pas et n’aura pas pour longtemps - fiabilité

Cependant, vous avez posé cette question il y a deux ans et je témoigne que beaucoup de choses ont changé depuis (avec g ++ au moins). La dévirtualisation est beaucoup plus fiable, par exemple.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top