begin process at 2008 07 05 13:27:48
1 205 163 membres
139 nouveaux aujourd'hui
14 118 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

Les bienfaits de l’option "Whole Program Optimisation" du compilateur C++ de Visual Studio 2002 et supérieur


Information sur le tutorial

Catégorie :Tutoriaux Date de création : 29/12/2007 15:20:25 Vu : 2 182 fois

Note :
Aucune note

Commentaire sur cette source (2)
Ajouter un commentaire et/ou une note

Description

Cet article explique le fonctionnement et l'intérêt de la nouvelle optimisation "Whole Program Optimisation" introduite dans le compilateur C++ de Microsoft Visual C++ 2002

Tutorial

Les bienfaits de l’option « Whole Program Optimisation » de Visual Studio .Net

Par Gilles Vollant

info@winimage.com

Depuis Visual Studio 2002, le compilateur du Visual C++ comporte une option d’optimisation pouvant produire des résultats très intéressant : l’option« Whole Program Optimisation ».

En activant cette option, le compilateur n’utilise plus la séparation des tâches en deux temps bien distinct : la compilation séparée de chaque source C++ (ou C) en un fichier .obj par cl.exe, puis le liens entre toutes les fonctions et autres symboles par l’édition des liens par link.exe.

Au contraire, cl.exe ne génère d’abord qu’un code intermédiaire, et la génération du code binaire proprement dit n’a lieu que lors de l’édition des liens, en une seule fois. C’est un peu comme si on concaténait tous les fichiers .cpp (en remettant juste à zéro l’espace des symboles entre chaque) et que l’on compilait le résultat final.

Résultat : un code à la fois plus court et plus rapide, sans aucun autre inconvénient qu’une phase de compilation peut être un peu plus longue (et consommatrice d’un peu plus de mémoire).

Un seul défaut : si vous distribué des .lib comprenant vos fonctions et compilé avec l’option /GL, les .lib seront spécifique à la version de Visual C++. Aucun problème évidemment si vous distribué des EXE ou des DLL (y compris bien sur avec leur .LIB d’import de fonction, qui ne contient pas de code).

Pour montrer tout cela, un petit exemple :

Une application C++ simpliste composée de deux fichiers sources.

/* democgl.h */

typedef struct
{
long l1;
long l2;
} DEMOSTRUCT;


void DemoGL_DispL(DEMOSTRUCT* pds);

void DemoGL_IncL2(DEMOSTRUCT* pds);

/* demofnc.cpp */
#include <stdlib.h>
#include <stdio.h>
#include "democgl.h"

void DemoGL_DispL(DEMOSTRUCT* pds)
{
long l3,i;
l3=0;
for (i=0;i<pds->l1;i++)
l3 -= pds->l1 + pds->l2;

for (i=0;i<pds->l1;i++)
l3 *= pds->l1 + pds->l2;

for (i=0;i<pds->l1;i++)
l3 += pds->l1 + pds->l2;

for (i=0;i<pds->l1;i++)
l3 /= pds->l1;

printf("l1 is %u, l2 is %u\n",pds->l1,pds->l2,l3);

}

void DemoGL_IncL2(DEMOSTRUCT* pds)
{
pds->l2+=7;
}

/* democgl.cpp */
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include "democgl.h"

void main()
{
DEMOSTRUCT ds;
ds.l1 = GetTickCount();
ds.l2 = GetVersion();

DemoGL_DispL(&ds);
ds.l1+=2;
DemoGL_DispL(&ds);
ds.l1+=3;

DemoGL_IncL2(&ds);
DemoGL_IncL2(&ds);
DemoGL_DispL(&ds);
}

Evidemment, ce programme ne fait que des calculs inutiles. Mais il permet de démontrer le travail de l’optimisation. Analysons le.

Notre fonction DemoGL_IncL2 modifie le membre l2 de la structure DEMOSTRUCT, mais laisse l1 constant. Par contre DemoGL_DispL ne modifie en rien la structure passée en paramètre. Un bon programmeur aurait du déclarer le type const DEMOSTRUCT* pour le paramètre, mais il était superflus de mettre la puce à l’oreille du compilateur qui (on le verra) se débrouille très bien tout seul !

Ensuite, dans le main qui se trouve dans un autre fichier, on initialise la structure avec des API qui retourne des valeurs apparemment suffisamment aléatoire pour que le compilateur ne puisse faire aucune supposition sur elle.

Nous créons le projet avec Visual Studio 2003 (mais toutes ces opérations sont valables avec le 2002 ou 2005)

Nous activons bien, pour la plateforme « Release », les optimisations classiques du Visual C++

Pour observer le résultats des optimisations, nous demandons la générations des fichiers assembleurs et d’un .map au link

Pour établir notre comparaison, nous allons établir la configuration ReleaseGL en y activant « Whole Program Optimisation ».

L’option /GL a donc été ajoutée lors de l’appel du compilateur

Et l’option « /LTCG » lors de l’appel de l’édition des liens.

Au passage, pour gagner un peu de place sur la taille l’exécutable, nous désactivons « Optimize for Windows 98 », qui permet d’avoir un plus petit de 8 ko au pris d’une consommation mémoire légèrement plus importante sous Windows 95/98.

Comparons le fichier .map : dans la version « whole optimised », la petite fonction DemoGL_IncL2 n’apparaît pas : elle a été fondu dans la fonction appelante, comme une fonction « inline ». C’est pour cela que nous avons mis autant de calcul étrange dans DemoGL_DispL : elle est devenu trop grosse pour être recopiée en inline à chaque fois qu’elle est utilisée.

Regardons maintenant le cœur du code généré pour le main, et observons tout ce que le compilateur a optimisé :


; 9 : DEMOSTRUCT ds;
; 10 : ds.l1 = GetTickCount();

call DWORD PTR __imp__GetTickCount@0
mov esi, eax
mov DWORD PTR _ds$[esp+20], esi

; 11 : ds.l2 = GetVersion();

call DWORD PTR __imp__GetVersion@0
mov ebx, eax

; 12 :
; 13 : DemoGL_DispL(&ds);

lea edi, DWORD PTR _ds$[esp+20]
mov DWORD PTR _ds$[esp+24], ebx
call ?DemoGL_DispL@@YAXPAUDEMOSTRUCT@@@Z ; DemoGL_DispL

; 14 : ds.l1+=2;

add esi, 2
mov DWORD PTR _ds$[esp+20], esi

; 15 : DemoGL_DispL(&ds);

call ?DemoGL_DispL@@YAXPAUDEMOSTRUCT@@@Z ; DemoGL_DispL

; 16 : ds.l1+=3;

add esi, 3

; 17 :
; 18 : DemoGL_IncL2(&ds);
; 19 : DemoGL_IncL2(&ds);

add ebx, 14 ; 0000000eH
mov DWORD PTR _ds$[esp+20], esi
mov DWORD PTR _ds$[esp+24], ebx

; 20 : DemoGL_DispL(&ds);

call ?DemoGL_DispL@@YAXPAUDEMOSTRUCT@@@Z ; DemoGL_DispL
pop edi
pop esi

Première remarque : avant d’appeler le premier DemoGL_DispL (ligne 13), la valeur de ds.l1 figurait dans un registre (esi), en plus d’avoir été mise dans la structure (pour être utilisée en lecture par DemoGL_DispL). Au retour de la fonction, le compilateur utilise esi pour y trouver la valeur de ds.l1 : l’analyse globale de l’optimisateur lui a permis de savoir que ds.l1 n’était pas modifié par la fonction, et donc que le registre contient toujours la bonne variable.

Seconde remarque : la fonction DemoGL_IncL2 est non seulement fondue dans la fonction appelante, mais réinterprété : ainsi, un double appel à cette fonction qui ajoute 7 à ds.l2 se traduit par un unique « add ebx,14 ». Dans la version sans « whole optimisation » ; chaque appel se traduit par 3 instructions dans la fonction principal, dont un call.

Ces exemples montrent ce que peut apporter cette option à la qualité de l’optimisation. En 64 bits, avec l’augmentation du nombre de registres généraux, les bénéfices peuvent être plus important (connaissance des registres non modifiés par une fonction, adaptation du nombre de paramètres passés par registre, sans tenir compte des norme de type cdecl ou fastcall pour une fonction non exportée…)

N’hésitez pas à l’adopter !

Pour en savoir plus :

http://msdn.microsoft.com/library/en-us/vccore/html/vcgrfglwholeprogramoptimization.asp

http://msdn.microsoft.com/library/en-us/vcext/html/vxlrfWholeProgramOptimizationProperty.asp

Un article de Matt Pietrek présentant également, en anglais, le Link-time Code Generation / Whole Program Optimisation :

http://msdn.microsoft.com/msdnmag/issues/02/05/Hood/

Et plus loin en Visual Studio 2005 :

En français, sur les Optimisation guidée par profil : http://www.microsoft.com/france/msdn/technologies/outils/visualc/info/2004-06-02-profileguidedoptimization.html

http://msdn.microsoft.com/library/en-us/dv_vstechart/html/profileguidedoptimization.asp (même article en anglais).


J’ai également écrit un tutorial pour automatiser l’utilisateur de cette nouvelle optimisation.

  • signaler à un administrateur
    Commentaire de zeratul67 le 10/01/2008 21:53:21

    Merci pour ces explications, c'est sympa :)
    je trouve toujours intéressants les articles s'intéressant à la compilation

    Dommage que quelques liens soient morts

  • signaler à un administrateur
    Commentaire de gvollant le 10/01/2008 23:54:10 administrateur CS

    on récupère le contenu du dernier lien avec
    http://msdn2.microsoft.com/en-us/library/aa289170(VS.71).aspx
    http://msdn2.microsoft.com/fr-fr/library/e7k32f4k(vs.80).aspx

Ajouter un commentaire

Pub



Appels d'offres

Plugin Dialer outlook
Budget : 2 000€
Redaction texte pour s...
Budget : 180€
Travail graphique- ill...
Budget : 1 000€

CalendriCode

Juillet 2008
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

VS Express FR Gratuit !

VS Express en français et 100% gratuit !

Boutique

Boutique de goodies CodeS-SourceS