Pourquoi quand je regarde la sortie de la version à partir d'un projet VC ++ dans VS, puis-je voir: p>
1> Compilation ...
1> A.CPP
1> B.cpp
1> C.cpp
1> D.CPP
1> E.CPP
[etc ...]
1> Code générateur ...
1> x.cpp
1> Y.CPP
[etc ...] p> blockQuote>La sortie semble si plusieurs unités de compilation sont traitées avant que tout code ne soit généré. Est-ce vraiment en cours? J'essaie d'améliorer les heures de construction et d'utiliser des en-têtes pré-compilés, j'ai obtenu de grandes écarts pour chaque fichier "CPPP", mais il existe une pause relativement longue pendant le message "Code générateur ...". Je n'ai pas "l'optimisation de l'ensemble du programme" ni "génération de code temporel de liaison" allumé. Si tel est le cas, alors pourquoi? Pourquoi VC ++ compila-t-il chaque "CPPP" individuellement (qui inclurait la phase de génération de code)? Si ce n'est pas juste une illusion de la production, existe-t-il une optimisation de la compilation-compilation potentiellement ici? Il ne semble pas y avoir d'options de compilateur pour contrôler ce comportement (je sais sur WPO et LTCG, comme mentionné ci-dessus). P>
edit: strong>
Le journal de construction montre simplement les fichiers ".OBJ" dans le répertoire de sortie, une par ligne. Il n'y a aucune indication de "compilation ..." VS. "Code générateur ...". P>edit: strong>
J'ai confirmé que ce comportement n'a rien à voir avec le paramètre "Nombre maximum de projets de projet parallèle" dans Outils -> Options -> Projets et solutions -> Construire et exécuter EM>. Il n'est pas non plus lié à la verbosité de la sortie de la sortie de la sortie EM>. En effet, si j'annule la construction avant le «code générateur ...», aucun des fichiers «.OBJ» n'existera pour l'ensemble le plus récent de fichiers «compilés». Cela implique que le compilateur manipule vraiment plusieurs unités de traduction ensemble. Pourquoi est-ce? P>
5 Réponses :
Il parallement la construction (ou au moins la compilée) si vous avez une CPU multicœur p>
EDIT: Je suis sûr que cela paralléglise était en même temps que "make -j", il compile plusieurs fichiers du CPP en même temps (car le RPC est généralement indépendant) - mais les relie évidemment une fois.
Sur ma machine Core-2, il affiche 2 travaux Devenv tout en compilant un seul projet. P>
En fait, en fonction de la version de Visual Studio, Projets i> va construire en parallèle (ce qui est clairement sur votre cas à cause du préfixe "1>" sur les lignes) par défaut, mais je crois que les fichiers individuels ne compilera pas en parallèle par défaut.
Oui, vous devez utiliser / MP pour obtenir des fichiers individuels pour compiler en parallèle.
Le compilateur ne génère pas de code de la source directement, il le compose d'abord dans une forme intermédiaire (voir Dans un processus de compilateur de construction Visual Studio (CL.EXE) est exécuté pour compiler plusieurs fichiers source partageant les mêmes options de ligne de commande dans une commande. Le compilateur d'abord effectue une "compilation" de manière séquentielle pour chaque fichier (ceci est probablement front-end), mais "Code générateur" (probablement back-end) est effectué ensemble pour tous les fichiers une fois la compilation effectuée avec eux. P>
Vous pouvez le confirmer en regardant cl.exe avec Explorateur de processus. P>
Je suppose que la génération de code est effectuée pour plusieurs fichiers à la fois effectuées pour rendre le processus de construction plus rapidement, car il inclut certaines choses qui ne peuvent être effectuées qu'une seule fois pour plusieurs sources, telles que des modèles instantanés - il n'a aucune utilité pour les instantiez Plusieurs fois, comme toutes les instances, mais on serait jeté quand même. p>
En théorie, il serait possible d'effectuer une certaine optimisation de l'unité croisée à ce stade, mais elle n'est pas faite - aucune optimisation de ce type n'est faite à moins d'être activée avec / LTCG et avec LTCG l'ensemble de la génération de code est fait pour tout le programme à la fois (d'où le nom de l'optimisation de l'ensemble du programme). P>
Remarque: il semble que le WPO soit terminé par Linker, car il produit EXE des fichiers OBJ, mais cette sorte d'illusion - les fichiers Obj ne sont pas de vrais fichiers d'objet, ils contiennent la représentation intermédiaire et la "Linker" n'est pas un véritable lieur, car il ne s'agit pas seulement du code existant, il génère et optimise le code. em> p> Processus de compilateur Visual Studio Catégorie H2>
Pourquoi la génération de code pour plusieurs fichiers à la fois h2>
Optimisation du programme entier h2>
Je pense que cette réponse est exacte. Lorsque Suma fait référence à une "optimisation", il ne se réfère pas à une version de la libération. Il signifie que cl.exe fait du travail commun à la fin une fois que tous les fichiers sont compilés.
@STINGRAYSC: Vous êtes correct, je l'ai testé et la phase de génération de code est effectuée dans une version non optimisée (par exemple de débogage]. La réponse doit être espère être précise maintenant.
Je sais d'une façon, et il peut y avoir d'autres moyens similaires à ceux: Xoreax Incredibuild intercepte le processus de construction et exécute CL.EXE seul. Il n'effectue aucun lot de type comme celui-ci. Vous pouvez télécharger une démonstration utilisable pendant environ un mois, ce qui devrait être suffisant pour vous si vous voulez juste effectuer quelques expériences.
@stingraysc, pourquoi voudriez-vous défaiter des lots de la frontale au backend?
Je pense que vous constateriez que si vous avez réussi à désactiver le loting, la construction serait même plus lente i> depuis lors, il faudrait faire les choses "communes" une fois pour chaque fichier, au lieu de chaque fois pour chaque fichier. grouper.
Merci d'accepter. Re: "Optimisation croisée" Cela dépend de ce que vous appelez l'optimisation. Il produit différents fichiers Obj, mais le résultat est finalement un exécutable identique. La CuR Cross-Cu de style LTCG fait beaucoup plus d'optimisation, y compris l'inlinage croisée Cu, les conventions d'appel personnalisées ou la substitution du paramètre const. Bien que certains soient parfois possibles dans la phase de «génération de code», rien de tout cela n'est fait.
Quant à savoir si l'expansion du modèle commun est terminée, il devrait être possible de vérifier cela en produisant des fichiers OBJ avec un code de génération commune, puis sans cela (par exemple avec incrédibuid) et de comparer les résultats - avec un exemple bien mais il devrait être évident si Le code modélisé est là ou non.
MSVC ne prend pas en charge l'exportation. Il n'y aurait donc aucune différence dans les fichiers .OBJ pour l'instanciation de modèles. Je serais très surpris (dans la mesure où je suppose que cela ne se produirait pas) si un fichier .obj compilé par lui-même était différent de la taille d'un lot de fichiers .OBJ compilé.
Même le code des modèles normaux (non exportés) doit être présent dans les fichiers OBJ. Si le même modèle est utilisé dans les deux fichiers Obj, si vous génèverez du code pour eux un par un, le code de modèle doit être présent dans les deux. Si vous générez du code dans le lot, vous pouvez mettre le code dans un fichier OBJ uniquement, sachant qu'ils seront liés de toute façon et plus de copies seront supprimées. Cela dit, ce que vous avez écrit m'a fait comprendre même si le code modélisé est généré une fois, il pourrait toujours être copié dans tous les fichiers OBJ produits. Je suppose que je vais devoir l'essayer.
Compilation à une fois, cela signifiait analyser la source et générer du code. Maintenant, la compilation signifie analyser la source et créer une base de données symbolique représentant le code. La base de données peut ensuite être transformée en références résolues entre les symboles. Plus tard, la base de données est utilisée comme source pour générer du code. P>
Vous n'avez pas d'optimisations allumées. Cela arrêtera le processus de construction d'optimiser le code généré (ou au moins indiquer que les optimisations ne devraient pas être faites ... Je ne voudrais pas garantir aucune optimisation n'est effectuée). Cependant, le processus de construction est toujours optimisé. Donc, plusieurs fichiers .CPP sont en train d'être associés pour le faire. P>
Je ne sais pas comment la décision est faite de la manière dont le nombre de fichiers .CPP sont associés ensemble. Peut-être que le compilateur commence à traiter des fichiers jusqu'à ce qu'il décide que la taille de la mémoire de la base de données soit suffisamment large de telle sorte que si elle augmente plus, le système devra commencer à effectuer une pagination excessive de données dans le disque et les gains de performances de la part de la performance. Les fichiers du CPP seraient annulés. P>
Quoi qu'il en soit, je ne travaille pas pour l'équipe de Compiler VC, je ne peux donc pas répondre de manière concluante, mais j'ai toujours supposé que cela le faisait pour cette raison. P>
Le long "code générateur ..." Phase pour plusieurs fichiers source remonte à VC6. Il se produit indépendamment des paramètres d'optimisation ou des CPU disponibles, même dans les bâtiments de débogage avec des optimisations désactivées. P>
Je n'ai pas analysé en détail, mais mes observations sont les suivantes: elles se produisent lors de la commutation entre les unités avec différentes options de compilation ou lorsque certaines quantités de code ont passé la partie "fichier par fichier". C'est aussi la scène où la plupart des collisions de compilateur ont eu lieu en VC6. p>
spéculation: em> J'ai toujours supposé que c'est la "partie difficile" qui est améliorée en traçant plusieurs articles à la fois, peut-être que le code et les données chargées dans le cache. Une autre possibilité est que la phase d'une seule étape mange une mémoire comme un libération folle et "générateur de code". p>
Pour améliorer la performance de construction: p>
Achetez la meilleure machine que vous pouvez vous permettre B> (Ne va pas bon marché sur les disques.) p>
divisé en projets distincts pour des constructions parallèles b>
C'est l'amélioration la plus rapide et la moins chère que vous puissiez faire. (sauf si vous en avez déjà un).
Déplacez-vous vers Windows 7 x64, achetez des charges de RAM et un I7 860 ou similaire. (Passer d'un noyau de Core2 Dual m'a donné un facteur de 6..8, bâtiment sur tous les processeurs.) P>
C'est là que 8 cpus (même si 4 physiques + HT) avec des charges de RAM viennent jouer. Vous pouvez activer la parallélisation par projet avec l'option / mp mp>, mais cela est incompatible avec de nombreuses autres fonctionnalités. p>
Il y a une nouvelle rémunération sur le blog Visual C ++ qui détaille certains commutateurs sans papiers pouvant être utilisés pour traiter / profiler différentes étapes du processus de construction (je ne suis pas sûr de combien, le cas échéant, de l'enregistrement S'applique aux versions de MSVC avant VS2010). Des trucs intéressants qui devraient fournir au moins un peu de perspicacité dans ce qui se passe dans les coulisses: P>
Si rien d'autre, il vous permet de savoir quels processus, DLL et au moins certaines des phases de traduction / traitement correspondent aux messages que vous voyez dans une sortie normale. P>
Je suppose que vous avez I> handicapé LTCG et WPO? Ils peuvent être activés par défaut.
Ou avez-vous récemment construit avec PGO?
Certains de vos fichiers sont-ils extrêmement importants ou ont-ils de grandes tables de données statiques?