SlideShare une entreprise Scribd logo
Rapport de stage de DEA 
´Evaluation de la quantit´e de travail utile 
dans l’ex´ecution des programmes 
Benjamin Vidal 
Responsable de stage : Pierre Michaud 
Projet CAPS
Sujet de stage 
La recherche en architecture de processeur est confront´ee actuellement `a des contraintes qui 
rendent de plus en plus difficile l’augmentation des performances des processeurs. Ces contraintes 
sont multiples : consommation ´electrique, latence de propagation des signaux sur les connexions, 
temps et coˆut de developpement, etc. . . Pour esp´erer trouver d’´eventuelles solutions permettant 
d’augmenter les performances de mani`ere significative sur une large gamme d’applications, il faut 
trouver de nouveaux paradigmes d’architecture. Pour cela, il faut d’abord avoir une bonne compr´e-hension 
du comportement des programmes. 
Le sujet propos´e a pour but d’´evaluer la quantit´e de travail r´eellement utile dans l’ex´ecution des 
programmes. L’id´ee sous-jacente est que si une fraction importante de l’ex´ecution d’un programme 
consiste en du travail inutile, il peut ˆetre int´eressant de chercher un paradigme architectural per-mettant 
d’exploiter cette propri´et´e. 
Le probl`eme consiste `a donner une d´efinition de l’utilit´e d’un travail. Par exemple, dans la 
r´ef´erence [1], un r´esultat interm´ediaire est consid´er´e inutile s’il est ´ecrit dans un registre et est 
´ecras´e sans avoir ´et´e utilis´e. Dans la r´ef´erence [5], un store `a une adresse m´emoire est consid´er´e 
inutile s’il ´ecrit une valeur ´egale `a la valeur d´ej`a stock´ee `a cette adresse. Nous proposons d’´etudier 
une autre d´efinition, selon laquelle une instruction dynamique est consid´er´ee utile si 
– Elle produit un r´esultat ´emis en sortie du programme (ex. printf) 
– Elle produit un r´esultat utilis´e comme op´erande d’une instruction utile 
– C’est un branchement dominant une instruction utile 
La partie recherche du stage consiste `a concevoir un algorithme efficace en temps et en m´emoire 
permettant d’´evaluer la quantit´e d’instructions dynamiques utiles. La partie mise-en-oeuvre consiste 
`a ´ecrire le programme correspondant, et `a l’utiliser pour obtenir des statistiques sur la fraction de 
travail utile, et d’autres statistiques, `a d´efinir, permettant de mieux appr´ehender le comportement 
des programmes. La mise en oeuvre se fera `a l’aide des outils d´evelopp´es au sein du projet CAPS. 
On travaillera sur des traces d’ex´ecution des programmes de la suite SPEC CPU2000. 
2
Remerciements 
Au cours de ce stage au sein de l’´equipe CAPS de l’IRISA, il m’a ´et´e possible de rencontrer 
un grand nombre de personnes qui m’ont aid´e `a comprendre le fonctionnement d’un laboratoire de 
recherche en informatique et surtout `a acqu´erir le recul n´ecessaire pour mieux appr´ehender le monde 
de l’architecture des microprocesseurs. Je voudrais donc remercier Ronan Amicel, Laurent Bertaux, 
Fran¸cois Bodin, Henri-Pierre Charles, Assia Djabelkhir, Romain Dolbeau, Antony Fraboulet, Karine 
Heydemann, Thierry Lafage, Antoine Monsifrot, Laurent Morin, Gilles Pokam, Olivier Rochecouste, 
Andr´e Seznec et ´Eric Toullec. 
Je tiens aussi `a remercier Yannos Sazeides (Enseignant `a l’universit´e de Chypre) avec qui j’ai eu 
l’occasion d’´echanger des id´ees sur la fa¸con d’´elaborer automatiquement un graphe de d´ependance 
de donn´ee `a partir de l’ex´ecution d’un programme. 
Et enfin je tiens `a remercier tr`es chaleureusement mon maˆıtre de stage, Pierre Michaud, qui m’a 
donn´e la libert´e de travail que j’aurais aim´e trouver tout au long de mon exp´erience universitaire 
et professionnelle et m’a permis ainsi de suivre les pistes que je souhaitais. Je tiens ´egalement `a le 
remercier pour tous les conseils qu’il a pu me donner concernant le monde de la recherche (publique 
ou priv´ee) et de m’avoir fait partager sa vision des choses sur de nombreux sujets. 
3
Table des mati`eres 
1 Bibliographie 9 
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 
1.2 Compilation et travail inutile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 
1.2.1 Vous avez dit « instructions inutiles » ? . . . . . . . . . . . . . . . . . . . . . 10 
1.2.2 Instructions statiques inutiles . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 
1.3 Premi`ere approche : 
Instructions inutiles d´etect´ees dynamiquement . . . . . . . . . . . . . . . . . . . . . . 11 
1.3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 
1.3.2 Description du principe de d´etection et d’´elimination des instructions inutiles 11 
1.3.3 Id´ees d’impl´ementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 
1.3.4 Conclusion sur cette approche . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 
1.4 Deuxi`eme approche : 
´Ecritures silencieuses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 
1.4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 
1.4.2 Le ph´enom`ene d’´ecriture silencieuse . . . . . . . . . . . . . . . . . . . . . . . 13 
1.4.3 Les cons´equences de l’´elimination des ´ecritures silencieuses . . . . . . . . . . . 14 
1.4.4 Id´ees d’impl´ementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 
1.4.5 Conclusion sur cette approche . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 
4
1.5 Troisi`eme approche : 
Travail inutile global lors de l’ex´ecution d’un programme . . . . . . . . . . . . . . . . 16 
1.5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 
1.5.2 Evaluer l’utilit´e d’une instruction ? . . . . . . . . . . . . . . . . . . . . . . . . 16 
1.5.3 Mise en oeuvre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 
1.5.4 Conclusion sur cette approche . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 
1.6 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 
2 Compte rendu du stage 20 
2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 
2.1.1 Le travail inutile, qu’est ce que c’est ? . . . . . . . . . . . . . . . . . . . . . . 20 
2.1.2 Notre protocole de test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 
2.2 La m´ethode utilis´ee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 
2.2.1 L’algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 
2.2.2 L’optimisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 
2.2.3 Le r´esultat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 
2.3 L’environnement de travail : Les choix de mise en oeuvre . . . . . . . . . . . . . . . . 29 
2.3.1 Les Outils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 
2.3.2 L’instrumentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 
2.3.3 Le choix de la Plateforme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 
2.3.4 SPARC : Le Meilleur des Mondes ? . . . . . . . . . . . . . . . . . . . . . . . . 32 
2.3.5 S’affranchir de la num´erotation des registres faite par Salto . . . . . . . . . . 34 
2.3.6 Les expressions r´eguli`eres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 
2.3.7 La gestion des fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 
5
2.4 R´esultats & Analyse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 
2.4.1 Les chiffres. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 
2.4.2 Le doute. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 
2.4.3 La r´epartition du travail inutile . . . . . . . . . . . . . . . . . . . . . . . . . . 39 
2.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 
3 Annexes 46 
3.1 Petit historique du stage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 
3.2 A propos de la description machine Salto du Sparc . . . . . . . . . . . . . . . . . . . 47 
3.2.1 Gestion des instructions Save et Restore . . . . . . . . . . . . . . . . . . . . . 47 
3.2.2 L’instruction call & link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 
3.2.3 L’instruction addx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 
3.2.4 Un d´etail : les instructions nop, ba et bn . . . . . . . . . . . . . . . . . . . . . 47 
3.3 R´esultat de l’´evaluation du travail inutile sur un exemple simple . . . . . . . . . . . 49 
3.3.1 Code source en C de l’exemple . . . . . . . . . . . . . . . . . . . . . . . . . . 49 
3.3.2 Code source en assembleur Sparc de l’exemple . . . . . . . . . . . . . . . . . 49 
3.3.3 Identifiant d’instruction statique . . . . . . . . . . . . . . . . . . . . . . . . . 51 
3.3.4 Trace d’ex´ecution dynamique . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 
3.3.5 Graphe de d´ependance de donn´ee . . . . . . . . . . . . . . . . . . . . . . . . . 56 
3.3.6 Trace d’ex´ecution dynamique 2 . . . . . . . . . . . . . . . . . . . . . . . . . . 57 
3.4 Exemple de donn´ees stock´ees en cours d’ex´ecution . . . . . . . . . . . . . . . . . . . 59 
3.5 Code source du programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 
6
Table des figures 
1.1 Mise en ´evidence de l’inutilit´e des instructions ne produisant des r´esultats utilis´es 
que par des instructions inutiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 
2.1 La structure de donn´ee d’un noeud du graphe . . . . . . . . . . . . . . . . . . . . . . 24 
2.2 Exemple de graphe g´en´er´e par l’algorithme 1 & 3 . . . . . . . . . . . . . . . . . . . . 25 
2.3 Du code source en langage de haut niveau au graphe de d´ependance de donn´ee 
dynamique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 
2.4 Instrumentation de code source en assembleur . . . . . . . . . . . . . . . . . . . . . . 30 
2.5 Principe de l’instrumentation faite par le programme d’´evaluation de la quantit´e de 
travail inutile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 
2.6 Le principe de la fenˆetre de registres du Sparc . . . . . . . . . . . . . . . . . . . . . . 33 
2.7 Quantit´e d’instructions assembleurs inutiles lors de l’ex´ecution de gzip dans diff´erentes 
conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 
2.8 Mise en ´evidence d’un probl`eme d’impl´ementation par divergence du flot de contrˆole 38 
2.9 ´Evolution de la quantit´e de travail inutile en fonction du temps . . . . . . . . . . . . 40 
3.1 Graphe d’exemple g´en´er´e par l’utilitaire « dot » . . . . . . . . . . . . . . . . . . . . . 56 
3.2 Les structures de donn´ees utilis´ees par le programme pour construire le graphe de 
d´ependance de donn´ee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 
7
Liste des Algorithmes 
1 Construction du graphe de d´ependance de donn´ee . . . . . . . . . . . . . . . . . . . 23 
2 Parcours du graphe (Noeud) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 
3 D´etection des instructions inutiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 
8
Chapitre 1 
Bibliographie 
1.1 Introduction 
Aujourd’hui, pour am´eliorer les performances d’un programme, il ne suffit plus seulement d’ajou-ter 
du mat´eriel dans un syst`eme donn´e. Il faut avant tout ´etudier le comportement de ce programme 
afin d’adapter au mieux les ajouts qui doivent ˆetre faits au syst`eme. De ce constat, les architectes 
des microprocesseurs ont tir´e des id´ees aujourd’hui fondamentales (tels les diff´erents niveaux de 
m´emoires caches qui exploitent la propri´et´e de localit´e temporelle et spatiale d’acc`es aux donn´ees 
dans les programmes). 
En ce sens, certains travaux de recherche s’int´eressent aujourd’hui au probl`eme du travail ef-fectu 
´e inutilement par un microprocesseur. Ils mettent en ´evidence une quantit´e non n´egligeable 
de travail inutile. Dans cette bibliographie, trois approches principales de travail inutile ont ´et´e 
retenues. 
1. Une instruction produisant un r´esultat jamais utilis´e par une autre instruction est consid´er´ee 
comme inutile (approche de « l’instruction morte » retenue par l’article [1]). 
2. Une instruction d’´ecriture est consid´er´ee comme inutile si cette derni`ere ne modifie pas l’´etat 
de la m´emoire (i.e. la mˆeme valeur est ´ecrite `a la mˆeme adresse m´emoire) (approche de 
« l’´ecriture silencieuse » retenue dans de nombreux articles [5, 3, 7]). 
3. Une instruction est consid´er´ee comme utile si elle produit un r´esultat en sortie (affichage d’un 
r´esultat par exemple) ou qu’elle est elle mˆeme utile `a une instruction utile (approche retenue 
pour le stage). 
Apr`es un bref tour d’horizon des travaux d´ej`a effectu´es dans le domaine au niveau des compila-teurs, 
chacun des trois aspects d´ecrits ci-dessus du travail inutile sera d´evelopp´e dans un paragraphe 
de cette bibliographie. S’en suivra un paragraphe de discussion sur la possibilit´e de mˆeler ces deux 
approches pour essayer d’obtenir une coop´eration compilation/ex´ecution dans l’´elimination des 
instructions inutiles. 
9
1.2 Compilation et travail inutile 
1.2.1 Vous avez dit « instructions inutiles » ? 
Il peut paraˆıtre surprenant au premier abord d’entendre parler de travail inutile dans un pro-gramme. 
En effet, `a partir du moment ou le programmeur demande d’effectuer un travail `a la 
machine, (encore que celui-ci ne soit pas infaillible. . .) ce travail doit avoir une utilit´e (au sens 
informatique du terme bien entendu. . .). Cependant, au del`a du programmeur, il existe toute une 
chaˆıne de m´ecanismes permettant de passer du langage de haut niveau (i.e. langage de program-mation 
classique) au code machine ex´ecutable. Ainsi ce programme va passer par toute sortes de 
transformations qui vont introduire du travail inutile. De plus, il est possible de trouver, dans la 
fa¸con dont sont con¸cus les programmes, du travail inutile (redondance de calculs par exemple). 
1.2.2 Instructions statiques inutiles 
Pour commencer, il est important de rappeler ce que sont les instructions statiques et les ins-tructions 
dynamiques. Une instruction statique est une instruction telle qu’on peut la trouver dans 
le code source d’un programme. Une instruction dynamique est une instance d’instruction statique. 
A chaque instruction statique peut correspondre plusieurs instructions dynamiques (autant que de 
fois o`u l’on ex´ecute cette instruction statique). 
Exemple simple : 
pour i de 1 à n faire 
t[i] := 0; 
fpour 
Instruction statique : t[i] := 0 
Instructions dynamiques associées : t[1] := 0, t[2] := 0, …, t[n] := 0 
Dans l’exemple suivant, il est important de noter que si n n’est pas fix´e lors de la compilation, la 
seule connaissance du compilateur est l’instruction statique. Il ne pourra donc pas, `a priori se servir 
de la valeur de n `a des fins d’optimisation. Supposons maintenant qu’un programme ne soit compos´e 
que des instructions de l’exemple et n’affiche aucun r´esultat. Le compilateur peut en d´eduire que 
l’ensemble du travail `a effectuer pour ex´ecuter cette boucle est inutile. Cependant, il suffit d’ajouter 
une instruction qui utilise t[m] en lecture (m ´etant un param`etre d’entr´ee du programme inconnu 
`a la compilation) pour que, potentiellement, l’ensemble du travail de la boucle devienne utile. En 
effet, le compilateur ne sachant pas quelle case du tableau t va ˆetre acc´ed´e, il est oblig´e de consid´erer 
que l’ensemble de la boucle fournit du travail utile. 
Il existe de nombreuses autres mani`eres d’´eliminer du travail inutile lors de la compilation [2, 4] 
que nous n’aborderons pas ici car seul l’aspect d´ecrit ci-dessus se rapproche des travaux vis´es dans 
cette ´etude. 
Dans la suite de cette bibliographie, nous ne nous int´eresserons qu’aux instructions inutiles 
dynamiques (i.e. qui ne peuvent pas ˆetre d´etect´ees par le compilateur puisqu’elles d´ependent de 
valeurs d’entr´ees du programme non connues au moment de la compilation). 
10
1.3 Premi`ere approche : 
Instructions inutiles d´etect´ees dynamiquement 
1.3.1 Introduction 
Les auteurs de l’article [1] se sont aper¸cus que le r´earrangement des instructions fait par les com-pilateurs 
lors des phases d’optimisations cr´e´e des instructions inutiles. En effet, comme le montre 
leurs r´esultats, une compilation faite sans optimisations montre un niveau faible d’instructions in-utiles 
alors qu’une compilation avec un fort niveau d’optimisation montre un taux d’instructions 
inutiles relativement ´elev´e (parfois sup´erieur `a 10 %). Cependant, malgr´e ce travail effectu´e inuti-lement, 
il est bon de rappeler que globalement, le temps d’ex´ecution de ces programmes diminue 
(i.e. on a bien l’effet d´esir´e). La question qui vient alors est : 
« Comment conserver ces optimisations tout en r´eduisant le travail inutile qui leur est associ´e ? » 
1.3.2 Description du principe de d´etection et d’´elimination des instructions 
inutiles 
Dans un premier temps, l’important est d’analyser les instructions ex´ecut´ees inutilement afin 
de savoir comment les d´etecter. Les auteurs de l’article [1] se sont ainsi aper¸cus que les instructions 
dynamiques inutiles ´etaient tr`es souvent des instances d’un nombre r´eduit d’instructions statiques. 
Ces instructions statiques sont appel´ees des instructions partiellement inutiles. En marquant ces 
instructions particuli`eres comme ´etant propices `a g´en´erer des instructions dynamiques inutiles, 
il est possible de ne faire un traitement particulier que sur ces derni`eres afin de savoir si une 
instance pr´ecise sera r´eellement inutile. Lors de l’ex´ecution, pour chaque instance d’une instruction 
partiellement inutile, une estimation de l’utilit´e de cette instruction dynamique sera faite. De cette 
estimation d´ecoulera son ex´ecution ou non. Dans le cas d’une mauvaise pr´ediction, un m´ecanisme 
de r´ecup´eration permet de lancer l’ex´ecution de cette instruction au moment ou l’on apprend que 
la pr´ediction est ´erron´ee. 
1.3.3 Id´ees d’impl´ementation 
Les auteurs de l’article [1] ont donn´e quelques id´ees d’impl´ementation qui pourraient ˆetre mises 
en oeuvre pour la d´etection de ce type d’instructions. La plus simple consiste `a m´emoriser dans un 
cache totalement associatif les instructions statiques ayant d´ej`a g´en´er´e des r´esultats inutiles par le 
pass´e. Du fait qu’un faible nombre de ces instructions g´en`erent un grand nombre des instructions 
dynamiques inutiles, ce cache permettra de « suspecter » la prochaine instance d’une instruction 
statique ayant d´ej`a g´en´er´e des r´esultats inutiles. 
Par la suite, lors de la d´etection d’une instruction dynamique « suspect´ee » d’ˆetre inutile, son 
ex´ecution sera suspendue jusqu’au « verdict » final permettant de savoir si il ´etait juste de la sus-pecter. 
Si tel est le cas, cette instruction ne sera pas ex´ecut´ee, dans le cas contraire, cette instruction 
sera ex´ecut´ee ajoutant ainsi un surcoˆut dˆu au retard d’ex´ecution pris par cette instruction. Il est 
11
donc tr`es important d’avoir une estimation la plus fine possible afin d’´eviter ce genre de cas et afin 
d’augmenter le nombre d’instruction inutiles suspect´ees `a juste titre. Pour cela, des optimisations 
sont propos´ees : utilisation de l’information de flot de contrˆole et ajout d’un compteur deux bits `a 
saturation principalement. 
Il est important de noter que ces impl´ementations ne tiennent pas compte des r´esultats calcul´es 
qui ne servent qu’`a des instructions inutiles. Autrement dit, cette impl´ementation ne prend pas en 
compte le caract`ere transitif que peuvent avoir certaines instructions inutiles. 
Instruction 
produisant un résultat R 
Instruction 
utilisant R et produisant R’ 
Instruction 
utilisant R’ et produisant R’’ 
Si R’’ est un résultat inutile R’ et R auront été produits inutilement 
Fig. 1.1 – Mise en ´evidence de l’inutilit´e des instructions ne produisant des r´esultats utilis´es que 
par des instructions inutiles 
1.3.4 Conclusion sur cette approche 
En conclusion, nous pouvons dire que les auteurs de l’article [1] ont mis en ´evidence une quantit´e 
non n´egligeable de travail inutile mˆeme si elle reste, aujourd’hui, difficile `a exploiter. En effet, dans 
un environnement o`u les ressources sont peu limit´ees, l’efficacit´e de l’impl´ementation d´ecrite ci-dessus 
offre des gains en performance n´egligeables. En revanche, dans des conditions de ressources 
plus limit´ees, les gains peuvent atteindre 10 % d’am´elioration des performances. De plus le fait 
d’ex´ecuter moins d’instructions permet une diminution de la charge des Unit´es Arithm´etiques et 
Logiques (UAL) et de la consommation ´electrique relativement importante. D’apr`es les auteurs, un 
m´ecanisme mat´eriel diminuant l’impact des instructions inutiles sur la performance et la consom-mation 
´electrique permettrait d’appliquer des optimisations de code plus pouss´ees `a la compilation. 
12
1.4 Deuxi`eme approche : 
´Ecritures silencieuses 
1.4.1 Introduction 
D’apr`es les auteurs de l’article [5], il existe principalement deux types d’´ecritures silencieuses. 
D’une part les mises `a jours de valeurs silencieuses (qui ne changent pas l’´etat de la m´emoire dans 
laquelle elles ´ecrivent) et d’autre part les ´ecritures silencieuses stochastiques qui mettent `a jour la 
m´emoire de mani`ere pr´evisible. Dans la suite de ce chapitre, nous nous concentrerons sur les mises 
`a jour de valeurs silencieuses et parlerons, par abus de langage, d’´ecritures silencieuses pour les 
d´esigner. 
1.4.2 Le ph´enom`ene d’´ecriture silencieuse 
Au vu de la d´efinition de ce qu’est une ´ecriture silencieuse, il parait difficile de croire que ces 
instructions puissent avoir un impact n´egatif important sur les performances d’un programme. 
Pourtant, les articles sur le sujet montrent que souvent plus de 30 % des ´ecritures sont silencieuses 
dans les applications test´ees. En effet, il existe de nombreux cas o`u, lors du parcours des ´el´ements 
d’un tableau, les modifications apport´ees par ce parcours ne concernent qu’un petit nombre des 
´el´ements de ce tableau. 
Exemples simples : 
pour i de 1 à n faire 
b := (b & t[i]); 
fpour 
pour i de 1 à n faire 
t[i] := (t[i] & b); 
fpour 
(a) (b) (c) 
t étant un tableau de booléens 
b étant un booléen 
l'opération & étant un "ET" logique 
pour i de 1 à n faire 
t[i] := t[i] + e(i); 
fpour 
t étant un tableau d'entiers 
e étant une fonction 
Dans l’exemple (a), nous pouvons voir que pour chaque case du tableau t dont le bool´een est `a 
vrai, l’ex´ecution du corps de la boucle ne produit aucun travail utile (la mˆeme valeur sera r´e-´ecrite 
dans b). Dans l’exemple (b), le simple fait que b soit ´egal `a vrai entraˆıne une inutilit´e de l’ensemble 
de la boucle. Dans l’exemple (c), lorsque "(i) renvoi z´ero, le corps de la boucle peut-ˆetre consid´er´e 
comme inutile. Un autre cas assez fr´equent de travail inutile est celui o`u un tableau est initialis´e 
apr`es avoir ´et´e utilis´e une premi`ere fois. Si lors de la premi`ere utilisation de ce tableau, toutes ses 
valeurs n’ont pas ´et´e modifi´ees, il est inutile de r´e-initialiser l’ensemble des cases de ce tableau. 
Il existe d’autres situations dans lesquelles un grand nombre d’´ecritures silencieuses peuvent ˆetre 
observ´ees : lors de l’appel d’un sous-programme, si les registres sauvegard´es n’ont pas ´et´e utilis´es 
dans ce sous-programme, leur restauration sera inutile. Ce mˆeme ph´enom`ene peut-ˆetre observ´e lors 
de la sauvegarde/restauration de contexte d’un processus par un syst`eme d’exploitation. 
13
1.4.3 Les cons´equences de l’´elimination des ´ecritures silencieuses 
Au del`a du gain ´evident que provoquerait un m´ecanisme fiable de suppression des ´ecritures 
silencieuses, un tel syst`eme permettrait ´egalement de supprimer une certaine quantit´e de travail 
assez importante li´ee `a ces instructions. En premier lieu, les informations de contrˆole li´ees `a ces 
instructions ne sont plus n´ecessaires (Ex : si une s´erie d’´ecritures silencieuses se trouve dans une 
boucle, il est inutile d’ex´ecuter la boucle). De plus, lors de l’ex´ecution d’une instruction de range-ment 
en m´emoire, tout un m´ecanisme lourd de rapatriement de la ligne de cache concern´ee vers la 
m´emoire est mis en place (´ecriture de la donn´ee dans le cache, marquage de la ligne de cache comme 
´etant modifi´ee puis, lors du chargement de nouvelles donn´ees dans cette ligne de cache, ´ecriture 
de l’ancienne ligne de cache consid´er´ee comme modifi´ee en m´emoire). De fait, la suppression d’une 
´ecriture ´evite d’avoir `a passer par toute ces op´erations d’acc`es `a la m´emoire tr`es coˆuteuses. Comme 
expliqu´e dans l’article [3], cette remarque prend encore plus d’importance dans un syst`eme multi-processeur 
puisque `a chaque ´ecriture m´emoire est associ´e un message d’invalidation `a destination 
des autres processeurs provoquant un d´efaut de cache lors du prochain acc`es `a ces donn´ees. . . Il 
est ´egalement important de noter que si certaines ´ecritures ne sont pas effectu´ees, de fait, certaines 
d´ependances de donn´ees n’existent plus. De cette fa¸con, le processeur n’est plus oblig´e d’attendre 
que ces valeurs soient ´ecrites pour pouvoir les utiliser. Le rendement du pipeline du processeur est 
alors am´elior´e. 
1.4.4 Id´ees d’impl´ementation 
Les auteurs de l’article [5] ont propos´e une impl´ementation basique permettant de supprimer 
les ´ecritures silencieuses. Cette impl´ementation consiste `a remplacer toute les op´erations de ran-gement 
en m´emoire par trois op´erations : Chargement de l’ancienne valeur pr´esente en m´emoire, 
comparaison avec la valeur qui doit y ˆetre ´ecrite et enfin, dans le cas o`u ces deux valeurs ne seraient 
pas ´egales, ´ecriture de la nouvelle valeur en m´emoire. Cette m´ethode est sˆure et permet de d´etecter 
l’ensemble des ´ecritures silencieuses. De plus, les lectures pouvant ˆetre servies en parall`eles, il peut 
ˆetre int´eressant de remplacer les ´ecritures par des lectures suivies de comparaisons. Cependant, 
dans la mesure ou le nombre d’´ecritures silencieuses ne repr´esente pas la majorit´e des ´ecritures 
m´emoire, les auteurs ont ajout´e une « impl´ementation parfaite » dans laquelle un m´ecanisme per-met 
de savoir si une ´ecriture va ˆetre utile et, dans ce cas, n’effectuera que l’´ecriture en m´emoire 
sans avoir `a comparer la nouvelle valeur `a la valeur pr´ec´edente. 
D’autres id´ees d’impl´ementations apparaissent ´egalement dans l’article [5] comme par exemple 
la possibilit´e que la ligne de cache ne soit pas marqu´ee comme modifi´ee lorsqu’elle re¸coit une ´ecriture 
silencieuse ´evitant ainsi d’avoir `a propager l’´ecriture en m´emoire centrale (avantage principal de 
l’´elimination des ´ecriture silencieuses). 
L’impl´ementation retenue pour les simulations faites par les auteurs de [5] est la premi`ere 
propos´ee avec pour caract´eristique suppl´ementaire que seules les ´ecritures mises en attente vont 
subir une v´erification de leur utilit´e. Ce qui veut dire qu’une ´ecriture survenant `a un moment o`u au 
moins un port d’´ecriture de la m´emoire est disponible sera servie avant que la v´erification de son 
utilit´e n’ai pu ˆetre faite. De cette fa¸con, les performances des ´ecritures ne sont jamais d´egrad´ees 
puisque le m´ecanisme n’agit que sur la file d’attente des ´ecritures afin de la r´eduire. 
14
1.4.5 Conclusion sur cette approche 
Les auteurs de l’article [5] ont mis en ´evidence une grande quantit´e de travail inutile `a travers les 
´ecritures silencieuses. En effet, les proportions d’´ecritures silencieuses obtenues lors des tests sont 
parfois tr`es importantes et laissent penser qu’elles pourraient avoir une influence tr`es importante 
sur les performances, notamment dans les syst`emes dont la purge des lignes de cache en m´emoire est 
un goulet d’´etranglement. Les auteurs mettent ´egalement en avant la r´eduction du trafic sur le bus 
d’un syst`eme multiprocesseur `a m´emoire partag´ee qui est souvent un point critique dans ce type de 
syst`emes (ce trafic limite le nombre de processeurs sur un mˆeme bus). D’autres travaux ´elargissant le 
th`eme de l’´ecriture silencieuse ont ´egalement ´et´e pr´esent´es comme celui sur les ´ecritures silencieuses 
temporaires [6] consid´erant que si une valeur en m´emoire est modifi´ee puis remise `a son ancienne 
valeur et qu’aucune lecture ne soit intervenue sur la valeur transitoire, elle peut-ˆetre consid´er´ee 
comme silencieuse. Ce mod`ele semble bien s’adapter aux cas d´ecrits ci-dessus de sauvegarde et 
de restauration de contexte fr´equents (appel de sous-programmes, passage d’un processus `a un 
autre. . .). 
15
1.5 Troisi`eme approche : 
Travail inutile global lors de l’ex´ecution d’un programme 
1.5.1 Introduction 
Dans cette approche, la probl´ematique est un peu diff´erente de celle vue dans les deux premiers 
paragraphes. En effet, le but de ces deux approches ´etait de d´etecter (soit par pr´evision, soit de 
mani`ere dynamique) une cat´egorie d’instructions inutiles afin d’´eviter leur ex´ecution « au vol ». 
Dans l’approche retenue pour le stage, il s’agit d’abord de regarder quelle est la quantit´e de travail 
inutile de fa¸con globale (essayer d’´evaluer l’ensemble du travail fait inutilement par un programme) 
afin d’avoir ensuite une id´ee du type de comportement ou d’application ex´ecut´e par un processeur 
qui produit le plus de travail inutile. De cette fa¸con, si certains r´esultats montrent une quantit´e non 
n´egligeable de travail inutile dans certains types d’applications, il sera ensuite possible d’´etudier 
pourquoi ce travail inutile est si important et si il peut ˆetre ´evit´e d’une mani`ere ou d’une autre. 
1.5.2 Evaluer l’utilit´e d’une instruction ? 
La m´ethode retenue ici pour ´evaluer l’utilit´e d’une instruction est assez simple : Une valeur qui 
est affich´ee en sortie d’un programme est consid´er´ee comme un r´esultat utile. Toute instruction 
ayant servi `a calculer ce r´esultat est une instruction utile. Ainsi, les instructions utiles `a un r´esultat 
peuvent ˆetre repr´esent´ees par un arbre de d´ependance entre ces derni`eres dont la racine est le 
r´esultat lui-mˆeme et chaque noeud repr´esente les instructions utiles au calcul de ce r´esultat (aussi 
bien les instructions de rangement/r´ecup´eration en m´emoire, de calcul et de branchement). Les 
feuilles seront alors les valeurs d’entr´ees (param`etres fix´es lors de la compilation ou de l’ex´ecution) 
du programme. En regroupant l’ensemble des arbres ainsi obtenus pour chaque r´esultat en un graphe 
orient´e dont les sources sont les r´esultats et les puits sont les valeurs d’entr´ee du programme, il 
est possible d’identifier quelles sont les instructions r´eellement utiles au programme. En effet, les 
instructions et les valeurs d’entr´ees inutiles au programme n’appartiendront pas `a ce graphe et 
seront ainsi mises en ´evidence. 
16
Exemple simple : 
a := lire(); 
b := VRAI; 
c := 0; 
si a=0 faire 
b := FAUX; 
c := 5; 
fsi 
si b alors écrire(c) 
sinon écrire(a) 
Exemple de graphe d’exécution si a vaut 0 : 
écrire(a) 
nécessite b 
b := FAUX 
branchement 
correspondant 
Test a=0 
nécessite a 
nécessite a 
a := lire() 
Valeur d’entrée 
du programme 
a := lire() 
Valeur d’entrée 
du programme 
c := 5 
c := 0 
b := VRAI 
Instructions exécutées 
inutilement 
Exemple de graphe d’exécution si a vaut 1 : 
nécessite b nécessite c 
Test a=0 
nécessite a 
a := lire() 
Valeur d’entrée 
du programme 
écrire(c) 
c := 0 
Valeur d’entrée 
du programme 
Aucune instruction n’est 
exécutée inutilement 
b := VRAI 
Valeur d’entrée 
du programme 
Cet exemple permet de mettre en ´evidence le fait que selon les valeurs d’entr´ees du programme, 
il peut y avoir du travail inutile ou pas. De plus, il met en lumi`ere (dans le cas o`u a vaut 1) le 
fait que le test a=0 correspondant au branchement du « si » doit ˆetre pris en compte comme ´etant 
du travail utile puisque de ce branchement vont d´ependre les instructions qui vont suivre (Nous 
pouvons dire que ces instructions « exigent » l’ex´ecution de ce branchement et donc du test qui 
permet de savoir si ce branchement doit ˆetre pris). 
Cette m´ethode d’identification des instructions inutiles semble parfaite (mˆeme si elle ne prend 
pas en compte certaines ´ecritures silencieuses). Cependant, elle n´ecessite le d´eroulement complet du 
programme afin de savoir si oui ou non une instruction dynamique du programme sera utile pour 
un r´esultat final. De fait, cette m´ethode ne peut pas ˆetre utilis´ee directement pour ´eliminer « au 
vol » les instructions inutiles. En revanche, elle permet d’exhiber de nombreux cas d’instructions 
inutiles que les autres m´ethodes ne d´etectent pas. Par exemple, le cas d’une instruction inutile par 
transitivit´e mis en ´evidence figure 1.1 sera d´etect´e par cette m´ethode. 
1.5.3 Mise en oeuvre 
Comme d´ecrit dans le sujet de stage, la mise en oeuvre de cette approche du travail inutile consis-tera 
`a ´elaborer un programme permettant de d´etecter les instructions dynamiques inutiles, d’apr`es 
la d´efinition donn´ee ci-dessus, afin de faire des statistiques sur la quantit´e de travail inutile dans un 
ensemble de programmes `a tester. Diff´erentes cat´egories de travail inutile pourront ´egalement ˆetre 
mises en ´evidence (Ex : chargements inutiles, rangements en m´emoire inutiles, calculs inutiles. . .). 
Une fois les tests effectu´es, un travail de regroupement des applications test´ees selon les r´esultats 
pourra ˆetre fait afin de d´egager, ´eventuellement, des « motifs » de comportements permettant en-suite 
de savoir quelles applications sont le plus concern´ees par quel type de travail inutile. Nous 
pouvons imaginer, `a partir de l`a, que des ´ebauches de solutions mat´erielles et/ou logicielles ne soient 
17
trouv´ees pour r´eduire cette quantit´e de travail inutile. Cependant, l’objet du stage reste celui-ci : 
« Concevoir et ´ecrire un programme permettant de calculer la quantit´e de travail inutile dans un 
programme particulier apr`es son ex´ecution » . 
Dans ce sens, le travail `a effectuer en stage sera, dans un premier temps, de r´efl´echir `a la mani`ere 
de d´etecter quelles sont les instructions qui ont ´et´e ex´ecut´ees inutilement lorsque l’ex´ecution d’un 
programme sera termin´ee (algorithme de construction puis d’exploration du graphe de d´ependance 
des instructions d´ecrit dans cette section). Ces r´esultats devront ensuite ˆetre mis en forme afin de 
d´egager des statistiques sur la quantit´e de travail inutile (pourcentage d’instructions inutiles) et 
sur la nature de ces instructions (de quel type d’instructions s’agit-il ?). Une fois cet algorithme 
impl´ement´e, il sera int´eressant de le tester sur diff´erent type de programme afin de savoir quelle 
est la quantit´e de travail r´eellement inutile (d’apr`es la d´efinition donn´ee en introduction de cette 
section) dans ces programmes. 
1.5.4 Conclusion sur cette approche 
En conclusion nous pouvons dire que l’approche retenue pour le stage est une d´emarche scien-tifique 
exp´erimentale permettant de savoir quelle est la proportion globale de travail inutile dans 
un programme. Si les r´esultats r´ev`elent une grande quantit´e de travail inutile, de nombreuses 
ouvertures paraissent possibles : D´etection de ces instructions grˆace `a des compilateurs « intel-ligents 
», d´etection de ces instructions « au vol » (approche d´ej`a retenue par [1]), coop´eration 
compilateur/mat´eriel ou encore ajout de nouvelles instructions afin de faciliter leur d´etection. 
18
1.6 Conclusion 
En conclusion, nous pouvons dire que plusieurs mani`eres d’´eliminer le travail inutile ont d´ej`a ´et´e 
abord´ees (tant dans le domaine de la compilation qu’en architecture). En effet, lors de la compila-tion, 
une certaine quantit´e de travail inutile peut d´ej`a ˆetre supprim´ee (en fonction des informations 
que le compilateur peut exploiter). Cependant, nous avons ´egalement vu que certaines optimisa-tions 
de ces mˆemes compilateurs g´en`erent des instructions inutiles. De fait, diff´erentes m´ethodes ont 
´et´e propos´ees pour ´eliminer ce travail inutile lors de l’ex´ecution (instructions dynamiques inutiles). 
Une autre approche int´eressante consistait `a ´eliminer les ´ecritures silencieuses, une autre forme de 
travail inutile. 
Apr`es ce tour d’horizon global, il est assez difficile de savoir de mani`ere pr´ecise quelle est la 
quantit´e de travail inutile effectu´ee par un microprocesseur lors de l’ex´ecution d’un programme. 
C’est `a cette question que va tenter de r´epondre le travail `a venir en stage. . . 
19
Chapitre 2 
Compte rendu du stage 
2.1 Introduction 
2.1.1 Le travail inutile, qu’est ce que c’est ? 
Le travail inutile est une notion difficile `a cerner. Il existe diff´erentes approches pour traiter le 
probl`eme du travail effectu´e inutilement par un programme. Tout d’abord, le travail inutile peut- 
ˆetre de nature statique (d´etectable et supprimable lors de la compilation) ou de nature dynamique 
(visible uniquement lors de l’ex´ecution). L’´elimination du travail inutile statique est d´ej`a bien 
connue et fait partie int´egrante de toute chaˆıne de compilation optimis´ee digne de ce nom. Ici nous 
nous int´eresserons seulement au travail inutile de nature dynamique puisque ce dernier n’est pas 
exploit´e par les processeurs ou les langages de programmation actuels. 
Une fois le cadre du travail inutile dynamique pos´e, il est n´ecessaire de se donner une d´efinition 
pr´ecise du travail inutile afin de pouvoir en ´evaluer la quantit´e lors de l’ex´ecution d’un programme 
sur un jeu de donn´ees particulier de fa¸con automatique. Cette d´efinition, dans un premier temps 
tr`es large, a ´et´e restreinte pour des raisons d’impl´ementation. 
La d´efinition prise comme base de d´epart `a cette ´evaluation ´etait la suivante : 
Tout travail qui ne sert, ni directement, ni indirectement, `a produire un r´esultat est jug´e inutile. 
De fa¸con plus pr´ecise : 
Une instruction dynamique est consid´er´ee comme utile si 
- Elle produit un r´esultat ´emis en sortie du programme (ex : affichage `a l’´ecran). 
- Elle produit un r´esultat utilis´e comme op´erande d’une instruction utile. 
- C’est un branchement dominant une instruction utile. 
20
Exemple simple : 
instruction 1; 
si booléen faire 
instruction 2; 
instruction 3; 
fpour 
instruction 4; 
Dans cet exemple, le branchement conditionnel « domine » les instructions 2 et 3. Si le bool´een 
est vrai et que les instructions 2 et 3 sont inutiles, alors on peut consid´erer le branchement comme 
inutile. 
Note 
Par abus de langage, dans la suite de ce document, nous d´esignerons toutes les instructions de 
transfert de contrˆole (branchement conditionnels et inconditionnels, sauts, appels de fonctions. . .) 
par l’expression « instruction de branchement ». 
En regardant cette d´efinition de plus pr`es, un probl`eme se pose dans le cas g´en´eral : Supposons 
que l’instruction 2 soit un « store » qui range une valeur `a une adresse m´emoire, que l’instruction 
4 soit un « load » et que le bool´een soit `a faux. Dans ce cas, si l’instruction 4 est consid´er´ee 
comme utile et si les deux acc`es pointent sur la mˆeme adresse m´emoire, alors le branchement devra 
ˆetre consid´er´e comme utile. Cependant, l’adresse de l’acc`es `a la m´emoire qui aurait pu ˆetre fait 
par l’instruction 2 n’est pas connue puisque cette instruction n’a pas ´et´e ex´ecut´ee. A cause de ce 
type d’acc`es `a la m´emoire (dont l’adresse acc´ed´ee n’est connue qu’`a l’ex´ecution) nous avons du 
faire l’hypoth`ese conservatrice suivante : Toutes les instructions de branchements sont consid´er´ees 
comme utiles. 
Ce qui nous donne la d´efinition suivante : 
Une instruction dynamique est consid´er´ee comme utile si 
- Elle produit un r´esultat ´emis en sortie du programme (ex : affichage `a l’´ecran). 
- Elle produit un r´esultat utilis´e comme op´erande d’une instruction utile. 
- C’est un branchement. 
Note 
Par abus de langage, dans la suite de ce document, nous utiliserons le mot « ressource » pour 
d´esigner soit un registre soit un emplacement m´emoire. 
Partant de cette nouvelle d´efinition, l’objectif ´etait de construire un graphe de d´ependance de 
donn´ee en reliant les instructions lisant une ressource `a la derni`ere instruction ayant ´ecrit dans cette 
mˆeme ressource. De cette fa¸con, lorsqu’une ressource apparaˆıt comme utile (lorsque sa valeur est 
´ecrite en sortie ou qu’elle est utilis´ee par une instruction de branchement), il devient possible, en 
parcourant les arcs de ce graphe, de trouver toutes les instructions qui ont ´et´e utiles pour produire 
21
ce r´esultat (le r´esultat est un graphe ressemblant `a la figure 2.2 page 25). 
2.1.2 Notre protocole de test 
A partir de cette d´efinition, nous avons essay´e de mesurer la quantit´e de travail inutile dans des 
petits programmes d’exemple, puis, une fois ces exemples valid´es, nous avons test´e notre protocole 
pour mesurer le travail inutile sur un programme plus cons´equent et surtout n’ayant pas ´et´e con¸cu 
dans le but d’en mesurer la quantit´e de travail inutile. Pour faire nos tests, nous avons choisi 
l’utilitaire de compression/d´ecompression de donn´ees gzip. 
22
2.2 La m´ethode utilis´ee 
2.2.1 L’algorithme 
Pour construire notre graphe de d´ependance de donn´ee, nous avons choisi d’instrumenter chaque 
instruction assembleur afin de contrˆoler de fa¸con pr´ecise les entr´ees et les sorties de chacune d’elles. 
Les entr´ees ´etant les op´erandes d’une instruction (les ressources ´etant lues par l’instruction) et les 
sorties ´etant les r´esultats d’une instruction (les ressources ´etant ´ecrites par l’instruction). 
Dans le cas g´en´eral, notre impl´ementation de la d´etection de d´ependance de donn´ee peut se 
r´esumer par l’algorithme 1. 
Algorithme 1: Construction du graphe de d´ependance de donn´ee 
Entr´ee : Programme dont on veut ´evaluer la quantit´e de travail inutile. 
Donn´ees `a fournir en entr´ee `a ce programme. 
Sortie : Graphe de d´ependance de donn´ee dynamique. 
1 pour chaque instruction ex´ecut´ee faire 
2 Cr´eer une repr´esentation interne de cette instruction; 
3 L’ajouter `a la liste des instructions dynamiques ex´ecut´ees; 
{Cette repr´esentation interne contient des informations concernant l’instruction : son 
num´ero dynamique, le fichier source auquel elle appartient, son num´ero statique dans ce 
fichier, son type. . . } 
4 pour chaque op´erande de l’instruction {ressource lue} faire 
5 Lire dans la table des ressources quelle est la derni`ere instruction qui a ´ecrit dans 
cette ressource; 
6 Cr´eer un lien de d´ependance {arc dans le graphe} entre l’instruction courante et la 
derni`ere instruction ayant ´ecrit dans la ressource en question; 
{Associe `a l’op´erande le num´ero de l’instruction dynamique qui l’a produit} 
fin 
7 pour chaque r´esultat de l’instruction {ressource ´ecrite} faire 
8 Ecrire dans la table des ressources que l’instruction courante a modifi´ee l’´etat de 
cette ressource; 
fin 
fin 
Une fois cet algorithme ex´ecut´e sur un programme particulier, il est possible de connaˆıtre les 
d´ependances directes entre les instructions grˆace aux arcs construits mais aussi les d´ependances 
indirectes grˆace aux chemins form´es par des suites d’arcs dans le graphe (le graphe de la figure 2.2 
page 25 en est un exemple). 
En ajoutant `a l’algorithme pr´ec´edent une condition dans la boucle principale permettant de 
parcourir le graphe construit lorsqu’on rencontre une instruction de sortie (affichage), il devient 
23
possible de connaˆıtre les instructions utiles lors de l’ex´ecution d’un programme (d’apr`es la premi`ere 
d´efinition donn´ee ci-dessus) (cf. algorithme 3). 
Proc´edure Parcours du graphe (Noeud) 
1 si le noeud est marqu´e inutile alors 
2 Marquer ce noeud {repr´esentant une instruction} comme ´etant utile; 
pour chaque noeud op´erande de ce noeud faire 
3 Appeler la proc´edure Parcours du graphe (Noeud op´erande); 
fin 
fin 
Algorithme 3: D´etection des instructions inutiles 
Entr´ee : Graphe de d´ependance de donn´ee dynamique. 
Sortie : Quantit´e d’instructions dynamiques inutiles. 
Localisation de ces instructions dans le code source. 
pour chaque noeud du graphe faire 
si le noeud repr´esente une instruction de sortie ou de branchement alors 
Appeler la proc´edure Parcours du graphe (Noeud); 
fin 
fin 
Numéro d'instruction dynamique 
Identificateur d'instruction statique 
Type de l'instruction 
Nombre d'opérandes 
Liste des instructions ayant écrit en dernier dans les opérandes 
Fig. 2.1 – La structure de donn´ee d’un noeud du graphe 
Un point int´eressant de cet algorithme, dont nous nous sommes rendu compte une fois l’impl´e-mentation 
op´erationnelle, est qu’il permet de d´etecter les acc`es fait en lecture `a une zone m´emoire 
non initialis´ee pr´ealablement. Par exemple, si un tableau de taille n est d´eclar´e et initialis´e, le fait 
de tenter d’acc´eder `a l’adresse de la zone m´emoire n+1, qui n’a donc pas ´etait initialis´ee, provoque 
une incoh´erence dans l’algorithme puisqu’il est impossible de trouver la derni`ere instruction ayant 
´ecrit dans cette zone m´emoire (ligne 5 dans l’algorithme 1 page pr´ec´edente). De cette fa¸con, il est 
possible de trouver, lors de l’ex´ecution, une erreur d’acc`es `a la m´emoire. 
24
39 
40 38 
36 
37 
35 
34 
3 
14 
33 
0 
13 
25 
24 
32 
31 
30 
29 
28 
26 
27 
23 
17 
16 
22 
21 
20 19 
18 
15 
9 
12 11 
8 
10 
7 
2 
6 
5 
4 
1 
Dans ce graphe, les noeuds sont ´etiquet´es par les num´eros dynamiques des instructions (ordre 
d’ex´ecution). Les noeuds en gris sont des instructions inutiles alors que les noeuds en noir sont des 
instructions utiles. 
Les instructions dynamiques 4, 12 et 20 sont issues d’une seule et mˆeme instruction statique de 
rangement en m´emoire dont seulement une instance est utile : l’instruction dynamique num´ero 12. 
Fig. 2.2 – Exemple de graphe g´en´er´e par l’algorithme 1 & 3 
25
2.2.2 L’optimisation 
Le gros probl`eme de cette approche est que le graphe devient tr`es rapidement ´enorme, mˆeme 
avec des programmes de petite taille. En effet, ´etant donn´e qu’il faut conserver des informations 
concernant chaque instruction dynamique jusqu’`a la fin de l’ex´ecution, seule une ex´ecution ayant 
un nombre r´eduit d’instructions dynamiques peut ˆetre envisag´ee (aux alentours de 300 000 dans 
notre impl´ementation). 
Nous avons donc tent´e de r´eduire le graphe au maximum en ´eliminant au cours de l’ex´ecution 
les informations qui ne nous ´etaient plus n´ecessaires. 
Ce qui est fait. . . 
Dans un premier temps, pour r´eduire ce graphe et donc augmenter la taille des programmes 
testables, nous avons d´ecid´e de supprimer `a la vol´ee les informations concernant les instructions 
« certifi´ees » utiles. Ces informations ´etant le noeud repr´esentant cette instruction et les arcs sor-tant 
de celle-ci. Ces informations ne sont plus d’aucune utilit´e une fois que le parcours de l’arbre 
dont cette instruction est la racine est effectu´e. Il est alors possible de les supprimer sans perdre 
d’information utile `a notre calcul de quantit´e de travail inutile. Cette m´ethode permet, `a mesure 
que le programme se d´eroule et envoi des informations en sortie, (affichage. . .) de r´eduire le graphe. 
Il est alors d’autant plus r´eduit que la quantit´e de travail utile est importante (sur nos tests, le gain 
r´eel en occupation m´emoire est d’un facteur trois `a quatre ce qui permet de tester des programmes 
d´epassant le million d’instructions dynamiques sans avoir un temps d’ex´ecution r´edhibitoire). 
La courbe de l’occupation m´emoire de l’algorithme au cours du temps devient alors identique 
(`a quelques d´etails d’impl´ementation pr`es) `a la courbe repr´esentant la quantit´e de travail inutile 
cumul´e (figure 2.9 page 40). 
Quelques petites optimisations ont aussi ´etaient apport´ees au programme concernant le temps 
d’ex´ecution. Bien que ce facteur ne soit pas le point crucial de notre algorithme, il semblait 
int´eressant de s’y pencher pour ´eviter d’avoir des dur´ees de tests trop importantes. 
Nous avons par exemple, `a la ligne 1 de la proc´edure Parcours du graphe page 24, supprim´e le 
parcours d’une branche lorsque cette derni`ere poss`ede comme racine une instruction utile. En effet, 
si tel est le cas, cela signifie que cette branche a d´ej`a ´et´e enti`erement explor´ee et qu’il est inutile de 
la parcourir `a nouveau. 
Ce qu’il reste `a faire. . . 
Dans un second temps, il est int´eressant de voir que si une instruction ´ecrit dans une ou plu-sieurs 
ressources, puis que ces ressources sont de nouveau ´ecrites sans ˆetre lues entre temps, les 
informations concernant cette instruction inutile ne nous serviront jamais puisque cette instruction 
ne sera jamais rendue utile (notion de « valeur morte »). De cette fa¸con, il est possible, ici encore, 
26
de r´eduire notre graphe en supprimant les noeuds repr´esentant ce type d’instructions ainsi que leurs 
arcs sortants. 
Une mani`ere simple d’impl´ementer un tel m´ecanisme serait de consid´erer que chaque instruction 
inutile est un objet et que les ressources (registres et zones m´emoire) sont des moyens d’acc´eder `a ces 
objets. Si une instruction est accessible depuis au moins une ressource, alors il n’est pas possible 
de supprimer les informations concernant cette instruction. En revanche, si aucune ressource ne 
« r´ef´erence » l’objet, alors cet objet est inaccessible depuis les ressources et le restera jusqu’`a la fin 
de l’ex´ecution du programme. Cet objet peut donc ˆetre supprim´e (noeud ainsi que ses arcs sortants). 
Cette m´ethode s’apparente `a un syst`eme de ramasse-miettes comme il est souvent mis en place dans 
un environnement d’ex´ecution pour lib´erer des zones m´emoires n’´etant plus r´ef´erenc´ees par aucun 
pointeur. 
2.2.3 Le r´esultat 
La figure 2.3 page suivante est un exemple simple permettant de comprendre comment est 
construit le graphe de d´ependance de donn´ee `a partir du code assembleur du programme dont on 
veut ´evaluer la quantit´e de travail inutile. 
Dans la figure 2.3 page suivante, les noeuds sources sont les instruction utiles par hypoth`ese (en 
caract`ere gras). Ces instructions sont soit des instructions de sortie (print %valeur dans l’exemple) 
soit des instructions de branchement (bne boucle dans l’exemple). Une fois ces instructions jug´ees 
comme ´etant utile au programme, nous pouvons appliquer la d´efinition r´ecursive permettant de 
trouver toutes les instructions ayant servi `a produire les valeurs utiles `a ces instructions. Ainsi, 
dans notre exemple, l’instruction dynamique num´ero 18 (print %valeur) poss`ede comme entr´ee le 
registre %valeur. Il est donc n´ecessaire de trouver la derni`ere instruction ayant ´ecrit dans ce registre. 
Cette instruction est l’instruction dynamique num´ero 17 (load [@tab+2],%valeur). Ainsi de suite 
r´ecursivement, l’instruction dynamique num´ero 17 poss`ede comme entr´ee la seconde case du tableau 
rang´e `a l’adresse m´emoire @tab dont la derni`ere ´ecriture a ´et´e faite par l’instruction dynamique 
num´ero 8 et ainsi de suite jusqu’`a n’arriver qu’`a des instructions n’ayant aucune entr´ee (copie 
d’une constante dans un registre (mov 1,%indice dans l’exemple), instruction d’entr´ee au clavier 
par l’utilisateur. . .). 
De cette mani`ere, en parcourant le graphe, il est possible d’identifier le travail utile. Les ins-tructions 
n’´etant accessible depuis aucune des sources (instructions de sorties ou de branchement) 
sont identifi´ees comme ´etant du travail inutile (instructions dynamiques 2, 3, 12 et 13 dans notre 
exemple). 
Grˆace `a cet exemple, nous avons mis en ´evidence un cas simple comportant peu de travail inutile. 
En revanche, il est facile de prendre conscience de l’importance que peut atteindre ce travail inutile 
d`es lors que le traitement `a l’int´erieur d’une boucle du type de celle pr´esent´ee dans l’exemple devient 
important. En effet, dans notre exemple, seule la multiplication par 10 et le rangement en m´emoire 
sont inutiles mais si la valeur `a ranger dans le tableau avait ´et´e un calcul effectu´e par une fonction 
comportant 10 000 instructions, les chiffres auraient ´et´e diff´erents. De mˆeme, si la taille du tableau 
avait ´et´e de 10 000 cases dont seulement une aurait ´et´e utilis´ee, la quantit´e de travail inutile aurait 
´et´e beaucoup plus importante. En revanche si, dans notre exemple, les trois cases du tableau avaient 
27
1: mov 1,%indice 
boucle: 
2: mul %indice,10,%valeur 
3: store %valeur,[%indice+@tab-1] 
4: add %indice,1,%indice 
5: cmp 4,%indice 
6: bne boucle 
7: load [@tab+2],%valeur 
8: print %valeur 
Code en assembleur RISC 
(code statique) 
Dépendances de données permettant d’identifier le travail 
utile (arcs du graphe parcourus par l’algorithme). 
Dépendance de donnée n’étant pas parcourues par 
l'algorithme. 
Trace d’exécution des instructions 
(dynamique) 
1ère itération de la boucle 
2ème itération de la boucle 
3ème itération de la boucle 
Numéro 
Dynamique 
Numéro 
Statique 
123456789 
10 
11 
12 
13 
14 
15 
16 
17 
18 
123456234562345678 
n Numéro d’instruction statique utile par essence 
(instructions de sorties ou de branchement). 
n Numéro d’instruction statique utile après parcours du 
graphe de dépendance (définition récursive). 
n Numéro d’instruction dynamique (indique l’ordre 
d’éxécution des instructions dans le temps) 
n 
Numéro d’instruction statique jugés comme étant inutile 
d’après la définition (instruction n’appartenant pas au 
graphe de dépendance de données). 
Compilation 
Pour i de 1 à 3 faire 
t[i] := i*10; 
Finpour 
Ecrire (t[2]); 
Code source original 
Fig. 2.3 – Du code source en langage de haut niveau au graphe de d´ependance de donn´ee dynamique 
´et´e affich´ees (instruction print), la quantit´e de travail inutile aurait ´et´e nulle. 
Un exemple plus complet montrant dans le d´etail comment l’algorithme a ´et´e impl´ement´e est 
en annexe (figure 3.2 page 59). 
28
2.3 L’environnement de travail : Les choix de mise en oeuvre 
2.3.1 Les Outils 
Pour la mise au point de notre programme d’´evaluation de la quantit´e de travail inutile, plusieurs 
outils ont ´et´e mis `a contribution : 
- Salto : Salto est une biblioth`eque de fonctions permettant d’analyser du code source en 
assembleur pour en extraire les informations s´emantiques sous une forme exploitable en C++. 
Ces informations peuvent ˆetre de diff´erentes natures : Il est possible de connaˆıtre le d´ecoupage 
en blocs de base du code source, les ressources utilis´ees par une instruction pr´ecise (dans notre 
cas, ce qui nous int´eresse sont les acc`es `a la m´emoire et aux diff´erents registres). De plus, 
une des fonctionnalit´e indispensable `a notre r´ealisation disponible dans Salto est la possibilit´e 
d’instrumenter le code source (figure 2.4 page suivante). 
- Le compilateur GCC pour processeur Sparc : Compilateur C/C++ gratuit sous licence GNU. 
- Le compilateur CC pour processeur Sparc : Compilateur C propri´etaire de Sun disponible 
seulement pour la plateforme Sparc. 
- Les expressions r´eguli`eres en C. 
2.3.2 L’instrumentation 
L’instrumentation c’est quoi ? 
L’instrumentation d’instruction est un m´ecanisme qui consiste `a ins´erer des instructions suppl´e-mentaires 
entre les instructions du code source d’un programme d´ej`a ´etabli afin « d’ausculter » ce 
dernier. Les informations qu’il est possible de r´ecup´erer par ce m´ecanisme sont de nature dynamique 
puisque les instructions rajout´ees par instrumentation sont ex´ecut´ees autant de fois que le sont les 
instructions appartenant au code source d’origine. Prenons comme exemple le cas d’une boucle 
dont le corps est ex´ecut´e n fois, alors le code rajout´e par instrumentation du code source d’origine 
dans le corps de cette boucle sera lui aussi ex´ecut´e n fois. Ceci permet de savoir de fa¸con pr´ecise 
quelles sont les instructions statiques qui ont ´et´e ex´ecut´ees par le processeur s´equentiellement. De 
plus, l’instrumentation permet de r´ecup´erer d’autres informations dynamiques comme les adresses 
des acc`es `a la m´emoire. 
Dans l’exemple de la figure 2.4 page suivante, le code source original est instrument´e afin de 
r´ecup´erer la valeur du r´esultat produit par l’instruction `a instrumenter et pour le traiter dans la 
fonction fct (tmp ´etant par exemple un registre de d´ebuggage dont le code source original ne fait 
jamais usage mais qui peut ˆetre utilis´e par la fonction fct pour effectuer son traitement). 
29
mov r1,r2 
add r2,3,r2 
store r2,[a0] 
Code source 
mov r1,r2 
mov r2,tmp 
call fct 
add r2,3,r2 
mov r2,tmp 
call fct 
store r2,[a0] 
load [a0],tmp 
call fct 
Code source 
instrumenté 
instrumentation 
Fig. 2.4 – Instrumentation de code source en assembleur 
Note 
Dans l’exemple de la figure 2.4, les instructions sont instrument´ees apr`es leur ex´ecution, ce 
qui n’est pas le cas dans notre impl´ementation : l’instrumentation se trouve avant l’ex´ecution de 
l’instruction pour des raisons de suivi des branchements (pour pouvoir instrumenter correctement 
les branchements, il est n´ecessaire de placer le code d’instrumentation avant ceux-ci). 
L’instrumentation dans notre programme 
L’instrumentation, dans le cas g´en´eral, permet d’ins´erer des instructions dans un programme. A 
partir de ce concept simple, nous avons d´ecid´e d’utiliser l’instrumentation pour ins´erer des appels 
de fonctions (´ecrites en C et compil´ees par ailleurs). De fait, les appels de fonctions en assembleur 
ne faisant pas de sauvegarde des registres globaux (accessible de n’importe o`u dans le programme). 
Il nous a fallu ajouter `a cette instrumentation une sauvegarde de contexte avant l’appel `a cette 
fonction puis une restauration apr`es (figure 2.5 page suivante). Mais ce n’est pas tout : Chaque 
instruction assembleur ayant un nombre variable d’op´erandes et de r´esultats, il nous a fallu ajouter 
une instruction d’appel `a une fonction pour chaque op´erande et pour chaque r´esultat. De plus, 
chaque acc`es `a la m´emoire n´ecessitant la r´ecup´eration de l’adresse de cet acc`es, il nous a fallu 
r´ecup´erer des informations sur la valeur des registres utilis´es par l’instruction `a instrumenter afin 
de savoir quelle ´etait l’adresse de cet acc`es m´emoire. 
L’instrumentation d’une instruction dans notre programme d’´evaluation de la quantit´e de travail 
inutile peut-ˆetre r´esum´ee en sept phases : 
– Sauvegarde : Une phase de sauvegarde du contexte (registres globaux, d´ecalage de la fenˆetre 
de registres. . .). 
– D´ebut : Une phase de cr´eation de la structure de donn´ee repr´esentant une instruction (fi-gure 
2.1 page 24). 
– Op´erandes : Une phase permettant de cr´eer les arcs vers les instructions ayant ´ecrit en 
dernier dans les ressources op´erandes de l’instruction. 
30
inst1 
inst2 
inst3 
Code source 
sauvegarde 
call fct 
restauration 
inst1 
sauvegarde 
call fct 
restauration 
inst2 
sauvegarde 
call fct 
restauration 
inst3 
Code source 
instrumenté 
instrumentation 
Fig. 2.5 – Principe de l’instrumentation faite par le programme d’´evaluation de la quantit´e de 
travail inutile 
– Milieu : Une phase, utile seulement pour les instruction « save » et « restore », permettant 
de mettre `a jour le niveau de la fenˆetre de registres. 
– R´esultats : Une phase permettant de mettre `a jour l’´etat des ressources en fonction des 
r´esultats produits par l’instruction. 
– Fin : Une phase permettant d’´evaluer l’utilit´e de l’instruction courante. Si cette derni`ere est 
utile, on parcour son arbre de d´ependance de donn´ee. 
– Restauration : Une phase de restauration du contexte. 
2.3.3 Le choix de la Plateforme 
Pour choisir notre plateforme de travail, nous avons pris en compte plusieurs param`etres. Nous 
avions le choix entre le jeu d’instruction x86 (CISC) et le jeu d’instruction Sparc (RISC). En premier 
lieu, l’outil mis `a notre disposition (Salto) semblait plus adapt´e `a un jeu d’instruction r´eduit. 
En effet, Salto ´etant bas´e sur la reconnaissance des instructions assembleur par des expressions 
r´eguli`eres, il est tr`es difficile de supporter un jeu d’instruction aussi vaste que le x86 d’Intel (CISC). 
De fait, le support d’un tel jeu d’instruction par Salto est apparu comme ´etant insuffisant. De plus, 
le travail `a effectuer ´etant, entre autre, d’identifier les acc`es `a la m´emoire, un jeu d’instruction 
r´eduit avec seulement une instruction pour le chargement et une pour le rangement en m´emoire 
nous est apparu plus simple `a manipuler. Cependant, le Sparc poss`ede quelques inconv´enients qui, 
nous le verrons plus loin, ne nous ont pas facilit´e la tˆache. Nous avons donc d´ecid´e de travailler 
avec un jeu d’instruction RISC pleinement support´e par Salto : le Sparc de Sun. 
31
2.3.4 SPARC : Le Meilleur des Mondes ? 
Le Sparc est une architecture RISC assez classique ce qui signifie que le nombre d’instructions 
est assez r´eduit, qu’elles ont toutes la mˆeme taille (quatre octets pour le Sparc) et que, chose 
relativement importante pour notre impl´ementation, les instructions d’acc`es `a la m´emoire sont au 
nombre de deux (load pour charger une valeur de la m´emoire vers un registre et store pour ranger 
une valeur d’un registre vers la m´emoire). Tout aurait ´et´e parfait si la description du Sparc s’´etait 
arrˆet´ee l`a. . . 
- Le delay slot est une des particularit´es de l’architecture Sparc. Il s’agit d’ex´ecuter l’instruc-tion 
qui suit imm´ediatement une instruction de branchement avant que cette instruction de 
branchement ne modifie le flot de contrˆole de l’ex´ecution du programme. Pour r´esumer, l’ins-truction 
qui se trouve dans le delay slot d’un branchement (elle se trouve juste apr`es dans le 
code source) se comporte comme si elle se trouvait avant le branchement pour ce qui est du 
contrˆole mais comme si elle ´etait apr`es pour ce qui est des donn´ees. 
- L’annul bit est une autre particularit´e « amusante » du Sparc qui est en relation directe avec le 
delay slot. Lorsqu’une instruction se trouve dans le delay slot d’un branchement dont l’annul 
bit est activ´e, (be,a : la virgule et le a indique que l’annul bit est activ´e) cette instruction ne 
s’ex´ecute que lorsque le branchement est pris. Dans le cas contraire, l’instruction se trouvant 
dans le delay slot n’est pas ex´ecut´ee (on dit qu’elle est annul´ee). 
- La fenˆetre de registres tournante est une fa¸con de pallier `a la lenteur des acc`es `a la pile lors du 
passage de param`etres `a une fonction. En effet, le Sparc se propose de r´esoudre le probl`eme 
du passage de param`etres `a une fonction de mani`ere originale au moyen de cette fenˆetre de 
registres tournante. Il s’agit de ranger les valeurs que l’on souhaite passer en param`etres `a 
la fonction qui va ˆetre appel´ee dans des registres sp´eciaux nomm´es registres de sortie (%o0 
`a %o5) qui, une fois la fonction appel´ee, seront renomm´es en registres d’entr´ee (%i0 `a %i5) 
(cf. figure 2.6 page suivante). De cette fa¸con, la fonction appel´ee peut se servir de ces valeurs 
sans qu’elles n’aient ´et´e recopi´ees dans une quelconque pile (`a l’exception du cas o`u la taille 
de la fenˆetre de registres tournante n’est pas suffisante). 
Le delay slot 
Dans notre impl´ementation, nous avons du prendre en compte cette particularit´e de l’archi-tecture 
Sparc. En effet, afin d’instrumenter les instructions se trouvant dans le delay slot d’un 
branchement, nous avons du utiliser diff´erentes techniques consistant `a « remonter » notre instru-mentation 
de ce type d’instructions avant le branchement. Ceci `a conduit `a pas mal de probl`emes 
de coh´erence entre la repr´esentation des instructions cr´e´ees par l’instrumentation et les instructions 
r´eellement ex´ecut´ees. 
Mais le cas o`u le delay slot nous a pos´e le plus de probl`eme est celui o`u il nous a fallu ajouter des 
sauts afin d’´eviter l’ex´ecution de certaines instructions. En effet, dans ce cas, si l’instruction que l’on 
veut « sauter » se trouve dans le delay slot d’un branchement, il faut dupliquer cette instruction 
des branchement : mettre dans le code source une version normale avec l’instruction qui se trouvait 
dans son delay slot dans le code source d’origine et une seconde version du mˆeme branchement 
contenant un nop dans son delay slot. De cette fa¸con, selon que l’instruction se trouvant dans le 
32
delay slot de ce branchement doit ˆetre ex´ecut´ee ou non, le flot de contrˆole est aiguill´ee vers l’une 
ou l’autre des deux versions de ce branchement. Il faut ensuite faire converger les deux versions en 
un mˆeme point repr´esentant la suite du programme. 
La fenˆetre de registres du Sparc 
La fenˆetre de registre tournante est une des particularit´e du processeur Sparc. Nous allons en 
expliquer rapidement le principe afin d’exposer la mani`ere dont nous avons trait´e cette particularit´e 
dans notre programme. 
Registres de sortie 
%o0 à %o7 
Registres locaux 
%l0 à %l7 
Registres d’entrée 
%i0 à %i7 
Registres accessibles 
au niveau n+1 
niveau n 
Registres de sortie 
%o0 à %o7 
Registres locaux 
%l0 à %l7 
Registres d’entrée 
%i0 à %i7 
Désigne les mêmes 
registres physiques 
Registres de sortie 
%o0 à %o7 
Registres locaux 
%l0 à %l7 
Registres d’entrée 
%i0 à %i7 
niveau n+2 
Désigne les mêmes 
registres physiques 
L’instruction « save » permet de passer d’un niveau n `a un niveau n+1 (utilis´e g´en´eralement comme 
une sauvegarde de contexte avec en plus la possibilit´e de passer des param`etres d’un contexte `a 
l’autre au niveau de la zone de recouvrement de la fenˆetre n et n+1). 
L’instruction « restore » permet de passer d’un niveau n `a un niveau n-1 (utilis´e g´en´eralement 
comme une restauration de contexte avec en plus la possibilit´e de passer des r´esultats d’un contexte 
`a l’autre au niveau de la zone de recouvrement de la fenˆetre n et n-1). 
Fig. 2.6 – Le principe de la fenˆetre de registres du Sparc 
Lorsque le nombre de registres utilis´es d´epasse le nombre de registres physiques r´eellement 
pr´esents dans le processeur, un m´ecanisme invisible pour l’utilisateur utilise une pile en m´emoire 
pour sauvegarder la fenˆetre de registres la plus ancienne et r´eutiliser ainsi cette derni`ere comme 
une nouvelle fenˆetre vierge. De cette fa¸con, le nombre de registres virtuellement utilisables par 
l’utilisateur n’est limit´e que par la taille de la pile et non par la taille du fichier de registres dans le 
processeur. Cette fenˆetre est souvent repr´esent´ee, dans les diff´erentes documentations sur le Sparc, 
de fa¸con circulaire pour montrer que la plus ancienne fenˆetre et la plus r´ecente peuvent se recouvrir 
si le nombre de fenˆetres disponibles dans le fichier de registres est insuffisant pour l’ex´ecution d’un 
programme donn´e. 
33
2.3.5 S’affranchir de la num´erotation des registres faite par Salto 
Les registres du Sparc s’organisent en deux parties. D’une part, des registres dit globaux qui se 
comportent de mani`ere classique, et d’autre part une fenˆetre de registres coulissante comme d´ecrit 
sur la figure 2.6 page pr´ec´edente. Pour les registres globaux, nous avons utilis´e la num´erotation 
propos´ee par Salto qui convenait tout `a fait ´etant donn´e qu’un nom de registre d´esigne toujours le 
mˆeme registre physique. 
En revanche, pour la fenˆetre de registres coulissante, nous avons du mettre en place notre propre 
syst`eme d’identification de registres : 
En effet, Salto ´etant un outil qui travaille sur du code assembleur, il lui est impossible d’avoir 
acc`es `a des informations concernant l’ex´ecution du programme (les seules informations disponible 
au niveau de Salto sont les informations statiques sur le programme). De fait, les informations 
que nous donne Salto concernant les acc`es aux registres sont les noms de ces registres. Il lui est 
impossible de connaˆıtre le niveau de la fenˆetre de registre en un point donn´e du code et donc de 
d´esigner un registre physique de mani`ere unique. Afin d’identifier de mani`ere unique chacun des 
registres physiques, il a donc fallu s’affranchir du syst`eme de num´erotation des registres propos´e 
par Salto pour le remplacer par un calcul fait de mani`ere dynamique (au cours de l’ex´ecution du 
programme) permettant de savoir `a quel registre physique correspondait chaque acc`es `a un registre 
appartenant `a la fenˆetre de registre courante. 
Pour ce faire, nous avons instrument´e les instructions save qui d´ecalent la fenˆetre de registre 
vers le haut et les instructions restore qui d´ecalent la fenˆetre de registre vers le bas (cf. figure 2.6 
page pr´ec´edente). De cette fa¸con, il est possible de tenir `a jour une variable globale indiquant le 
niveau actuel de la fenˆetre de registre. En utilisant ce niveau comme d´ecalage par rapport `a un 
point de r´ef´erence, (la premi`ere fenˆetre disponible lors du lancement du programme) il est possible 
de savoir dans quelle fenˆetre de registre seront fait les acc`es aux registres de la fenˆetre courante 
indiqu´es par Salto. 
Grˆace `a cette m´ethode, il est possible d’identifier de mani`ere unique chacun des registres d’une 
fenˆetre pr´ecise mˆeme si celle-ci peut avoir ´et´e sauvegard´ee dans la pile par manque de place dans 
le fichier de registres. Les acc`es `a ces registres restent ce qu’ils sont puisque cette op´eration est 
transparente pour l’utilisateur du processeur (en l’occurrence notre programme). 
2.3.6 Les expressions r´eguli`eres 
L’utilisation des expressions r´eguli`eres est particuli`erement utile pour analyser une chaˆıne de 
caract`eres ayant un motif fixe et une partie variable. C’est justement le cas d’une instruction 
assembleur dont la partie fixe est le mn´emonique de cette instruction et dont les parties variables 
sont les arguments. 
De cette fa¸con, nous avons utilis´e les expressions r´eguli`eres pour « d´ecouper » les instructions 
load et store en plusieurs parties : le mn´emonique d’une part (permettant de connaˆıtre la taille de 
l’acc`es `a la m´emoire : octet, mot, double mot ou quadruple mot) et les arguments d’autre part. Une 
34
fois chaque argument r´ecup´er´e, il est possible d’acc´eder aux valeurs contenues dans les registres 
et aux ´eventuelles constantes. Il est donc possible de connaˆıtre de fa¸con exacte `a quelle adresse 
m´emoire va acc´eder l’instruction et `a combien d’octets elle va acc´eder. 
De plus, les expressions r´eguli`eres nous ont ´et´e utiles pour r´ecup´erer les ´etiquettes des appels 
de fonctions afin de savoir si ces fonctions ´etaient d´efinies en local (dans le code source du pro-gramme 
´etudi´e) ou si elles appartenaient `a une biblioth`eque externe au programme (stdio en C 
par exemple). 
2.3.7 La gestion des fonctions 
Une fois notre d´efinition impl´ement´ee et test´ee, il reste encore de nombreux probl`emes `a r´esoudre 
pour pouvoir confronter cet algorithme au « monde r´eel » (`a des programmes classiques tel que 
gzip). En effet, ce mod`ele th´eorique serait parfait si l’ensemble du code source assembleur d’une 
application ´etait visible par le programme d’´evaluation. Or les programmes classiques utilisent des 
fonctions d´efinies dans des biblioth`eques dont on n’a pas le code source (Un programme en C 
travaillant sur des fichiers utilisera par exemple stdio pour lire et ´ecrire dans un fichier). Afin de 
r´egler cette difficult´e, nous avons du utiliser l’options de compilation -SO de cc permettant de savoir 
quels sont les registres du Sparc et les adresses m´emoires utilis´ees dans la pile comme param`etres 
lors de l’appel `a une fonction. Ainsi, il nous a ´et´e possible de rajouter « artificiellement » des arcs 
de d´ependance entre l’appel `a une fonction d´efinie dans une biblioth`eque externe (call printf 
par exemple) et les param`etres pass´es `a cette fonction. Pour cette raison, cc pour Sparc est apparu 
comme ´etant id´eal dans notre protocole de test. 
Afin de r´esoudre ce probl`eme, les fonctions appel´ees par le programme ´etudi´e ont ´et´e class´ees 
en trois cat´egories, chacune correspondant `a un traitement particulier `a faire pour les prendre en 
compte correctement : 
Les fonctions « internes » 
Les fonctions internes sont les fonctions dont le code source est disponible (peut-ˆetre utilis´e par 
notre programme d’´evaluation). Les appels `a ce type de fonctions peuvent donc ˆetre trait´es comme 
de simple branchements inconditionnels puisque les arcs du graphe de d´ependance peuvent tr`es bien 
relier une instruction appartenant `a cette fonction `a une instruction appartenant au programme 
appelant. Le graphe de d´ependance de donn´ee n’est donc pas interrompu par un tel appel de 
fonction. 
Les fonctions « externes » utilisant des pointeurs 
Les fonctions externes sont les fonctions dont le code source n’est pas disponible (code source 
d’une biblioth`eque d’entr´ee/sortie par exemple). Dans ces cas l`a, il est n´ecessaire de consid´erer que 
les param`etres pass´es `a la fonction sont lus par l’instruction d’appel de la fonction et que le r´esultat 
35
est ´ecrit par cette instruction. 
Cependant, dans le cas g´en´eral, il est n´ecessaire de d´etourner l’appel `a une telle fonction pour 
faire ajouter « artificiellement » des arcs de d´ependance de donn´ee pour traiter les donn´ees qui 
vont ˆetre lues et ´ecrites `a l’int´erieur de cette fonction. En effet, notre programme est incapable 
de connaˆıtre le type des param`etres d’une fonction (si il s’agit d’entiers, de pointeurs. . .) et donc, 
de savoir si une fonction d´efinie dans une biblioth`eque dont on n’a pas le code source acc`ede ou 
non `a une zone m´emoire dont l’adresse est un de ses param`etres. De plus, mˆeme en sachant qu’un 
param`etre est un pointeur, rien ne dit si la fonction dont on n’a pas le code source va y acc´eder 
en lecture, en ´ecriture ou pire encore, `a combien d’´el´ements elle va acc´eder ! (Il ne faut pas oublier 
qu’en C les tableaux sont implicites et que, par cons´equent, on ne connaˆıt pas leur taille simplement 
en connaissant l’adresse de leur premier ´el´ement). Afin de r´egler cette difficult´e, nous avons choisi de 
d´etourner les appels `a ces fonctions (au nombre de trente cinq dans gzip) afin de leur faire ex´ecuter 
du code permettant de simuler leur comportement en mati`ere d’acc`es `a la m´emoire. Ces fonctions 
sont, le plus souvent des fonctions d’entr´ees/sorties (ex : read, write, fflush. . .), des fonctions de 
lecture/´ecriture dans des chaˆınes de caract`eres (ex : strcat, strcpy, strcmp. . .) ou des fonctions 
de lecture/´ecriture de zones m´emoire en g´en´eral (ex : memset, memcpy, memcmp. . .). 
Exemple simple : 
char *my_strcpy(char *c1, const char *c2) 
{ 
/* On simule un acc`es en lecture `a une zone m´emoire d´ebutant `a l’adresse 
contenue dans le pointeur c2 et de longueur strlen(c2)+1 (taille de la 
cha^ıne de caract`ere `a lire avec son terminateur) */ 
instrumentationEntreeMemoire((int)c2, strlen(c2)+1); 
/* On simule un acc`es en ´ecriture `a une zone m´emoire d´ebutant `a l’adresse 
contenue dans le pointeur c1 et de longueur strlen(c2)+1 (taille de la 
cha^ıne de caract`ere `a copier avec son terminateur) */ 
instrumentationSortieMemoire((int)c1, strlen(c2)+1); 
/* On retourne la valeur retourn´ee par la vraie fonction strcpy */ 
return strcpy(c1, c2); 
} 
Les fonctions « externes » n’utilisant pas de pointeurs 
Les fonctions externes n’utilisant pas de pointeurs sont des fonctions dites externes d’apr`es la 
d´efinition ci-dessus `a la diff´erence qu’elles ne font pas d’acc`es `a la m´emoire `a partir de pointeur. 
Elles peuvent donc ˆetre trait´ees simplement en consid´erant que les param`etres pass´es `a la fonction 
sont lus et que le r´esultat est ´ecrit. 
36
2.4 R´esultats & Analyse 
2.4.1 Les chiffres. . . 
Une fois l’´evaluation de la quantit´e de travail inutile effectu´ee de cette mani`ere, nous obtenons 
les chiffres suivants (cf. figure 2.7). 
gzipa gzipb gzipc 
O0d 11.03 % 9.53 % 11.03 % 
O1 12.05 % 10.73 % 16.44 % 
O2 11.40 % 10.28 % 16.17 % 
O3 12.77 % 12.10 % 21.83 % 
O4 12.66 % 12.55 % 23.35 % 
O5 12.66 % 12.55 % 23.35 % 
gunzipe gunzipf gunzipg 
O0 1.09 % 1.14 % 0.21 % 
O1 2.94 % 3.10 % 0.29 % 
O2 3.51 % 4.28 % 0.41 % 
O3 10.01 % 10.51 % 0.47 % 
O4 9.83 % 10.26 % 0.52 % 
O5 9.83 % 10.26 % 0.52 % 
aCompression d’un fichier texte (RTF) de 2127 octets avec gzip (fort taux de compression (facteur : 1.9)) 
bCompression d’un fichier image (GIF) de 1704 octets avec gzip (faible taux de compression (facteur : 1.4)) 
cRe-compression d’un fichier compress´e par gzip de 1506 octets avec gzip (taux de compression nul (facteur : 0.98)) 
dSeuls ces r´esultats ont ´et´e valid´es avec le programme de v´erification pour des raisons d’impl´ementation 
eD´ecompression du fichier texte de 2127 octets 
fD´ecompression du fichier image de 1704 octets 
gD´ecompression du fichier compress´e deux fois par gzip de 1506 octets 
Conditions de test : gzip version 1.2.4 recompil´e avec cc de Sun pour le processeur Sparc version 
v8plus. Ces chiffres s’entendent en ne comptant pas les ´eventuelles instructions nop qui se trouvent 
dans le delay slot de certaines instructions de branchement. 
Fig. 2.7 – Quantit´e d’instructions assembleurs inutiles lors de l’ex´ecution de gzip dans diff´erentes 
conditions 
2.4.2 Le doute. . . 
Introduction 
Ces chiffres n’´etant qu’une ´evaluation, rien ne permet de dire avec certitude que ce travail est 
effectivement inutile. D’autant plus que l’impl´ementation laisse souvent apparaˆıtre des failles que 
l’on n’imagine pas lorsqu’on raisonne de fa¸con abstraite sur les d´ependances de donn´ees (la gestion 
des fonctions dont on n’a pas le code source en est un exemple). Afin de valider notre programme 
et d’avoir la certitude que le travail inutile ´evalu´e en ´etait bien, nous avons mis au point un second 
programme r´e-ex´ecutant exactement le mˆeme programme de test (gzip dans notre cas) sur le mˆeme 
jeu de donn´ees (avec le mˆeme fichier en entr´ee) en n’ex´ecutant pas les instructions qui avaient ´et´e 
jug´ees comme ´etant inutiles lors de la premi`ere ex´ecution. Ainsi, si la seconde ex´ecution donne 
rigoureusement le mˆeme r´esultat que la premi`ere (le mˆeme fichier compress´e dans le cas de gzip), 
nous pouvons dire que les deux ex´ecutions sont ´equivalentes et que, par cons´equent, les instructions 
qui n’ont pas ´et´e ex´ecut´ees lors de la seconde ex´ecution n’´etaient effectivement pas utiles. 
37
somewhere : 
sub r3,r4,r5 
... 
mov r1,r2 
add r2,3,r2 
cmp 0,r2 
be somewhere 
store r2,(a0) 
... 
Code source 
mov r1,r2 
add r2,3,r2 
cmp 0,r2 
be somewhere 
sub r3,r4,r5 
... 
Trace dynamique de la 
première exécution 
(détection du travail inutile) 
mov r1,r2 
add r2,3,r2 
cmp 0,r2 
be somewhere 
store r2,(a0) 
... 
Trace dynamique de la 
deuxième exécution (non 
exécution du travail inutile) 
L'instruction add est jugée inutile : 
elle ne sera donc pas exécutée 
lors de la seconde exécution 
Fig. 2.8 – Mise en ´evidence d’un probl`eme d’impl´ementation par divergence du flot de contrˆole 
Note 
Reproduire une ex´ecution `a l’identique ne fonctionne que sur un programme d´eterministe : deux 
ex´ecutions successives sur un mˆeme jeu de donn´ee doivent s’ex´ecuter rigoureusement de la mˆeme 
mani`ere. De fait, il serait complexe de traiter des programmes utilisant des fonctions de tirages 
al´eatoires ou conservant des informations d’une ex´ecution sur l’autre (cache dans un fichier par 
exemple). Ce n’est pas le cas de gzip ce qui nous a permis de mener nos tests de fa¸con correcte 
sur ce programme. 
L’int´erˆet 
Un aspect tr`es int´eressant de l’utilisation de ce programme de v´erification est qu’il a permis 
d’affiner le programme d’´evaluation de la quantit´e de travail inutile. En effet, en observant les 
divergences entre la premi`ere et la seconde ex´ecution (figure 2.8), il a ´et´e possible de trouver les 
points faibles du programme d’´evaluation de la quantit´e de travail inutile et de les consolider afin de 
rendre les deux ex´ecutions ´equivalentes. Par exemple, lorsque la seconde ex´ecution du programme 
de test divergeait de la premi`ere (un branchement pris alors qu’il n’aurait pas du par exemple), cela 
signifiait qu’une instruction utile au flot de contrˆole avait ´etait jug´ee comme ´etant inutile `a tort. De 
cette mani`ere, il a ´et´e possible de trouver les incorrections du programme d’´evaluation du travail 
inutile et surtout de mettre en lumi`ere les lacunes d’une impl´ementation trop « na¨ıve » par rapport 
aux appels de fonctions d´efinies dans des biblioth`eques dont le code source n’est pas disponible. 
Dans l’exemple de la figure 2.8, le branchement be (branch if equal) est pris lors de la premi`ere 
ex´ecution alors qu’il n’est pas pris lors de la seconde, ce qui entraˆıne une incoh´erence entre les deux 
38
ex´ecutions qui ne sont alors plus ´equivalentes. Ceci se produit en raison d’un mauvais jugement 
port´e sur l’instruction add. En effet, celle-ci est utile au bon d´eroulement du programme alors 
qu’elle a ´et´e jug´ee comme ne l’´etant pas par le programme de d´etection du travail inutile. Grˆace `a 
ce syst`eme, il est facile de corriger les incorrections et impr´ecisions que comporte le programme de 
d´etection du travail inutile. Par processus incr´emental, il est alors possible de corriger ces erreurs 
une `a une jusqu’`a l’obtention d’un programme qui ne juge inutile que du travail r´eellement inutile 
(Ce qui ne prouve pas pour autant qu’il d´etecte tout le travail inutile que peut comporter un 
programme). 
La M´ethode 
Pour pouvoir mettre au point ce deuxi`eme programme, il faut tout d’abord que le programme 
d’´evaluation de la quantit´e de travail inutile laisse une trace des instructions inutiles dans un 
fichier qui sera utilis´e par le programme de v´erification. Pour la mise au point de ce programme de 
v´erification, Salto a, l`a encore, ´et´e sollicit´e afin d’instrumenter chaque instruction. Lorsque cette 
instruction est jug´ee inutile (d’apr`es la trace de la premi`ere ex´ecution) alors cette instruction est 
saut´ee au moyen d’un jump d’une valeur constante puisque, dans les processeurs Sparc, toutes les 
instructions ont une taille de quatre octets (« merci » les jeux d’instructions RISC). De cette fa¸con, 
il est assez facile de « sauter » une instruction lorsqu’elle apparaˆıt dans la trace des instructions 
inutiles. 
Conclusion 
Ce programme `a permis, sur des exemples simples, de v´erifier que la quantit´e de travail inutile 
´evalu´ee ´etait bien du travail inutile quelque soit le niveau d’optimisation utilis´e et les cas de figure 
rencontr´es. Cependant, par manque de temps, nous n’avons r´eussi `a le faire fonctionner que sur gzip 
compil´e avec un niveau d’optimisation de 0. N´eanmoins, cette v´erification nous `a permis d’accroˆıtre 
la confiance en nos r´esultats (figures 2.7 page 37 et 2.9 page suivante). 
2.4.3 La r´epartition du travail inutile 
Une fois les informations sur le travail inutile lors de l’ex´ecution d’un programme r´ecup´er´ees, 
il est n´ecessaire de les organiser afin de pouvoir analyser d’ou provient ce travail inutile. Dans 
un premier temps, nous avons essay´e de voir `a quelles instructions statiques correspondaient nos 
instructions dynamiques inutiles. Nous avons trouv´e, sans surprise ´etant donn´e les r´esultats de 
l’article [1], que seul un petit nombre d’instructions statiques ´etaient concern´ees. Ce qui signifie 
que la plupart des instructions dynamiques inutiles sont concentr´ees sur un nombre d’instructions 
statiques r´eduit (de l’ordre de 12.4 % des instructions statiques totales g´en`erent au moins une 
instance dynamique inutile). Une fois ces instructions statiques en assembleur identifi´ees, nous 
avons cherch´e `a « remonter », lorsque c’´etait possible, au code source en C correspondant afin 
de mieux comprendre la raison pour laquelle ce travail est jug´e comme ´etant inutile par notre 
d´efinition. 
39
108876.0 
90730.0 
72584.0 
54438.0 
36292.0 
18146.0 
0.0 
Compression d’un fichier RTF de 2127 octets 
Algorithme GZIP compile avec cc et un niveau d’optimisation de 0 
0.0 268685.0 537370.0 806055.0 1074740.0 
(a) Sans optimisations de compilation 
53388.0 
44490.0 
35592.0 
26694.0 
17796.0 
8898.0 
0.0 
Compression d’un fichier RTF de 2127 octets 
Algorithme GZIP compile avec cc et un niveau d’optimisation de 5 
0.0 105695.0 211390.0 317085.0 422780.0 
(b) Avec optimisations de compilation 
Abscisse : Num´ero d’instruction dynamiques : repr´esente le temps ´ecoul´e en nombre d’instructions 
Ordonn´ee : Quantit´e d’instructions inutiles (cumul´ees) 
Fig. 2.9 – ´Evolution de la quantit´e de travail inutile en fonction du temps 
Travail inutile algorithmique 
Introduction En observant les courbes de la figure 2.9 on s’aper¸coit que l’algorithme de gzip, 
dans nos conditions de test, se d´ecompose en plusieurs phases g´en´erant chacune des quantit´es de 
travail inutile diff´erentes. En premier lieu, il est int´eressant de noter que la phase d’initialisation 
comporte une grande proportion de travail inutile (presque 50 % avec un niveau d’optimisation 
de 0 et plus de 50 % avec un niveau de 5). Ensuite, vient une courte phase durant laquelle aucun 
travail inutile n’est pr´esent (quelque soit le niveau d’optimisation). 
Vient ensuite un ensemble de phases que nous appellerons le coeur de l’algorithme durant lequel 
on observe une quantit´e de travail inutile moyen non n´egligeable avec un niveau d’optimisation de 
0 (de l’ordre de 6,9 %) et plus important encore avec un niveau d’optimisation de 5 (de l’ordre de 
9,9 %). 
La phase d’initialisation Dans certains cas, le travail inutile semble ˆetre d’origine algorith-mique. 
En effet, en observant le code source en C de gzip, il apparaˆıt parfois du travail inutile qu’il 
serait simple d’´eviter en modifiant une petite partie du code. De fait, nous pouvons dire que ce 
travail inutile est inh´erent `a la fa¸con dont l’algorithme de gzip est impl´ement´e. 
De plus, ´etant donn´e une tr`es forte proportion de travail inutile durant la phase d’initialisation 
des structures de donn´ees utiles `a l’algorithme de gzip (aux alentours de 50%), il semble raisonnable 
de penser qu’une tr`es grande partie de ces structures de donn´ees sont initialis´ees puis jamais utilis´ees 
ou r´eutilis´ees pour ˆetre ´ecrites (ce qui g´en`ere des valeurs mortes). Ce type de travail inutile semble 
40
ˆetre r´eellement inh´erent `a l’algorithme et non du `a une mauvaise impl´ementation de celui-ci. 
Exemple simple : 
Dans la fonction local void gen codes (tree, max code), on observe que le code source 
suivant est inutile la plupart du temps (lors de l’ex´ecution sur un fichier de test) : 
for (bits = 1; bits <= MAX_BITS; bits++) { 
next_code[bits] = code = (code + bl_count[bits-1]) << 1; 
} 
L’affectation dans le tableau next code est inutile 52 fois sur 60 dans l’exemple test´e (le nombre 
d’it´erations de la boucle est MAX BITS et est ´egal `a 60). Le fait que cette affectation soit inutile un 
certain nombre de fois engendre qu’une partie des calculs fait dans la boucle devient inutile. Ce 
qui nous donne, pour l’ensemble de la boucle, un nombre de 824 instructions inutiles pour 1440 au 
total (soit une proportion de 57 %). 
Etant donn´e ces r´esultats, il est int´eressant de se pencher sur le cas de l’initialisation des 
structures de donn´ees en g´en´eral. En effet, le premier r´eflexe d’un programmeur, lorsqu’il d´eclare 
une structure de donn´ee (tableau, liste. . .) est de l’initialiser pour ´eviter, par la suite, d’y faire 
un acc`es en lecture sans y avoir pr´ealablement rang´e une valeur. Or ce r´eflexe de programmation 
est probablement ce que nous observons ici ´etant donn´e que les structures de donn´ees de gzip 
n’´echappent apparemment pas `a cette r`egle. 
Le coeur de l’algorithme Au coeur de l’algorithme, nous observons diff´erents cas d’instructions 
dynamiques inutiles. Parfois, nous observons que le travail inutile est du `a l’initialisation de va-riables 
locales dont le contenu est, la plupart du temps, r´e-´ecrit avant d’ˆetre lu. Parfois, il s’agit de 
param`etres pass´es `a une fonction et qui ne servent que dans certaines conditions. Et enfin, un cas 
assez fr´equent ´egalement est celui des variables globales qui sont maintenues `a jour de fa¸con inutile. 
En effet, si une telle variable refl`ete une valeur lors du dernier passage dans une certaine fonction, 
il est possible que cette fonction soit appel´ee plusieurs fois sans que cette valeur n’ai ´et´e lue entre 
temps. 
Exemples : 
L’affectation prev match = match start ; peut-ˆetre inutile car la seule utilisation de la variable 
prev match en lecture est le cas suivant : 
if (prev_length >= MIN_MATCH && match_length <= prev_length) { 
check_match(strstart-1, prev_match, prev_length); 
flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH); 
... 
} 
41
Ce qui signifie que lorsque la condition ci-dessus sera fausse, l’affectation de la variable prev match 
sera inutile (c’est le cas 78 fois 82 dans notre test). En supposant que le calcul de la valeur de la 
variable match start puisse ˆetre coˆuteux, et que cette variable ne soit pas r´e-utilis´ee en lecture 
entre temps, on prend conscience de la port´ee que peut avoir le travail inutile. 
Note 
Dans l’exemple pr´ec´edent, il est int´eressant de noter que le d´eplacement de l’instruction d’affec-tation 
prev match = match start ; dans le corps de la conditionnelle aurait suffit `a ´eliminer 
ce travail inutile (dans la mesure o`u on ne fait pas d’´ecriture dans match start entre temps). 
En effet, la variable prev match n’´etant utilis´ee que dans ce bloc, il est inutile de faire cette 
affectation si la condition n’est pas vraie. 
Une macro un peu particuli`ere a ´egalement retenu notre attention. Elle se trouve au coeur de 
l’algorithme de compression, dans la fonction deflate(). Il s’agit de la macro INSERT STRING qui 
ins`ere une chaˆıne de caract`ere dans la liste des chaˆınes de caract`eres qu’utilise gzip pour trouver 
les chaˆınes les plus fr´equemment pr´esentes dans le fichier `a compresser. 
Voici le code de cette macro apr`es passage du pr´e-processeur : 
((ins_h = (((ins_h)<<((15+3-1)/3)) ^ 
( window[(strstart) + 3-1])) & 
((unsigned)(1<<15)-1)), 
prev[(strstart) & (0x8000-1)] = hash_head = (prev+0x8000)[ins_h], 
(prev+0x8000)[ins_h] = (strstart)); 
Pour des raisons de lisibilit´e, nous avons r´e-´ecrit ce code : 
ins_h = ( ins_h<<5 ^ window[strstart+2] & (unsigned)(1<<15)-1 ); 
hash_head = (prev+0x8000)[ins_h]; 
prev[strstart & (0x8000-1)] = hash_head; 
(prev+0x8000)[ins_h] = strstart; 
Dans cette macro, qui se trouve au coeur de l’algorithme de compression, les deux derni`eres 
instructions (remplissage du tableau prev) se trouvent ˆetre tr`es souvent inutile (77 fois sur 82 dans 
notre exemple). Ceci tend `a montrer que l’algorithme de compression utilis´e par gzip contient, par 
nature, du travail inutile. 
Travail inutile introduit par le compilateur. . . 
. . . lors des phases d’optimisation de compilation On observe ´egalement que la version 
compil´ee avec un niveau d’optimisation de 0 pr´esente une quantit´e globale de travail inutile moins 
important (proportionnellement) `a la version compil´ee avec un niveau d’optimisation de 5. De plus, 
42
l’´ecart entre les deux versions s’accentue dans le coeur de l’algorithme. En effet, durant la phase 
d’initialisation, les deux versions se comportent `a peu pr`es de la mˆeme fa¸con (aux alentours de 
50 % de travail inutile) alors que dans le coeur de l’ex´ecution, la version non optimis´ee comporte en 
moyenne 6.9 % de travail inutile `a comparer aux 9.9 % observ´e dans le cas de la version optimis´ee. 
Ce ph´enom`ene avait d´ej`a ´et´e constat´e dans l’article [1] mais uniquement au sujet des valeurs mortes. 
. . . du au jeu d’instruction du processeur Cette ´etude n’est absolument pas exhaustive sur 
les diverses causes que peut avoir le travail inutile. Cependant, mˆeme si cet aspect n’a pu ˆetre 
explor´e pour des raisons de temps, il parait raisonnable de penser qu’une partie du travail inutile 
pourrait avoir ´et´e introduit en raison des contraintes impos´ees par le jeu d’instructions utilis´e. En 
effet, dans un jeu d’instruction RISC (comme le Sparc) une instruction de haut niveau (en langage 
C par exemple) peut ˆetre convertie par le compilateur en une suite tr`es importante d’instructions 
comme en une seule. Ceci d´epend de l’´eloignement de cette instruction en langage C par rapport aux 
instructions disponibles dans le jeu d’instruction assembleur utilis´e. A contrario, un jeu d’instruction 
CISC (comme le x86) aura des instructions assembleur plus proche des instructions en langage de 
haut niveau. De cette fa¸con, les proportions d’instructions assembleur inutiles peuvent ne pas ˆetre 
identiques aux proportions d’instructions inutiles de haut niveau (en langage C par exemple). 
De plus, certaines optimisations de compilation effectuant un r´e-ordonnancement des instructions 
assembleur, il est parfois difficile de savoir quel ensemble d’instructions assembleur repr´esente quelle 
instruction de haut niveau. 
Conclusion 
En conclusion, nous pouvons dire que les proportions de travail inutile trouv´ees se rattachent 
majoritairement au travail inutile pr´esent dans l’algorithme en langage de haut niveau. De fait, une 
piste qui pourrait ˆetre int´eressante pour r´eduire ce travail inutile serait de signaler au programmeur, 
lors des premi`eres ex´ecutions d’un prototype de programme, que certaines parties de l’algorithme 
g´en`erent une grande quantit´e de travail inutile et que, par cons´equent, une r´e-´ecriture en prenant en 
compte cet ´etat de fait pourrait ´eviter ce travail. Il est mˆeme possible d’imaginer un outil proposant 
au programmeur une ´ebauche de solution pour l’aider `a restructurer une partie de son code afin 
d’´eviter ce travail inutile. Cependant, ce type d’outils ne peut rien pour aider `a ´eliminer le travail 
inutile intrins`eque `a l’algorithme. 
43
2.5 Conclusion 
Cette ´etude est, en premier lieu, une ´etude permettant de comprendre un ph´enom`ene, `a priori, 
contre intuitif : Le travail inutile. Pour ce faire, nous nous sommes bas´e sur des r´esultats existants 
qui ont d´ej`a ´et´e publi´es et qui montre que le travail inutile existe bel et bien dans des programmes 
classiques. 
Le but de ce stage ´etait d’´elargir les d´efinitions donn´ees dans ces articles afin d’avoir une 
id´ee du travail inutile global qui peut se trouver dans un programme. Cette ´etude, contrairement 
`a celles cit´ees ci-contre, n’avait pas pour but de trouver un moyen d’exploiter ce travail inutile 
pour en r´eduire l’impact sur le temps d’ex´ecution ou la consommation ´electrique mais seulement 
de comprendre ce ph´enom`ene et de savoir pourquoi ce travail inutile est pr´esent (est-ce du au 
compilateur ?, au programmeur ?. . .). 
En conclusion, nous pouvons dire que cette ´etude `a permis de confirmer l’existence du travail 
inutile et de comprendre, en partie, d’o`u il provient. 
44
Bibliographie 
[1] G. Sohi A. Butt. Dynamic dead-instruction detection and elimination. ASPLOS X, October 
2002. 
[2] Jeffrey D. Ullman Alfred V. Aho, Ravi Sethi. Compilers : Principles, Techniques and Tools. 
Addison-Wesley, 1986. 
[3] Gordon B. Bell. Characterization of silent stores. Submitted in partial fulfillment of the M.S. 
Degree in Electrical and Computer Engineering, May 2001. 
[4] F. Bodin. Cours d’optimisation : Transformer pour la performance. Septembre 2002. 
[5] M. Lipasti K. Lepak, G. Bell. Silent stores and store value locality. IEEE Transactions on 
Computers, 50(11), November 2001. 
[6] Mikko H. Lipasti Kevin M. Lepak. Temporally silent stores. ASPLOS X, October 2002. 
[7] Kevin M. Lepak. Silent stores for free : Reducing the cost of store verification. Submitted in 
partial fulfillment of the M.S. Degree in Electrical and Computer Engineering, December 2000. 
[8] Charles N. Fischer Milo M. Martin, Amir Roth. Exploiting dead value information. Proceedings 
of Micro-30, December 1997. 
45
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes

Contenu connexe

Tendances

Conception et developpement d'un site web pour la suggestion et notification ...
Conception et developpement d'un site web pour la suggestion et notification ...Conception et developpement d'un site web pour la suggestion et notification ...
Conception et developpement d'un site web pour la suggestion et notification ...
Mohamed Boubaya
 
Projet de conception et de développement
Projet de conception et de développementProjet de conception et de développement
Projet de conception et de développement
Glei Hadji
 
iRecruite
iRecruiteiRecruite
iRecruite
Donia Hammami
 
Projet Passerelle sécurisée intelligente pour l'internet des objets
Projet Passerelle sécurisée intelligente pour l'internet des objetsProjet Passerelle sécurisée intelligente pour l'internet des objets
Projet Passerelle sécurisée intelligente pour l'internet des objets
Université de Rennes 1
 
Belwafi bilel
Belwafi bilelBelwafi bilel
Belwafi bilel
Belwafi Bilel
 
PROJET JAVA BD MySQL
PROJET JAVA BD MySQLPROJET JAVA BD MySQL
PROJET JAVA BD MySQL
Wilfried Tiani
 
Deep Learning : Application à la reconnaissance d’objets de classes multiples...
Deep Learning : Application à la reconnaissance d’objets de classes multiples...Deep Learning : Application à la reconnaissance d’objets de classes multiples...
Deep Learning : Application à la reconnaissance d’objets de classes multiples...
Haytam EL YOUSSFI
 
Mémoire fin d'étude gestion des interventions
Mémoire fin d'étude gestion des interventionsMémoire fin d'étude gestion des interventions
Mémoire fin d'étude gestion des interventions
Mohamed Arar
 
Outpatient Department System (OPD)
Outpatient Department System (OPD) Outpatient Department System (OPD)
Outpatient Department System (OPD)
Ben Ahmed Zohra
 
PFE :: Application de gestion des dus d'enseignement
PFE :: Application de gestion des dus d'enseignementPFE :: Application de gestion des dus d'enseignement
PFE :: Application de gestion des dus d'enseignement
Nassim Bahri
 
Conception et développement d&rsquo;une place de marché B2C
Conception et développement d&rsquo;une place de marché B2CConception et développement d&rsquo;une place de marché B2C
Conception et développement d&rsquo;une place de marché B2C
Nassim Bahri
 
rapport de projet de fin d'étude_PFE
rapport de projet de fin d'étude_PFErapport de projet de fin d'étude_PFE
rapport de projet de fin d'étude_PFE
Donia Hammami
 
These
TheseThese
eQ Services PFE
eQ Services PFEeQ Services PFE
eQ Services PFE
fayway
 
Rappport PFE 2012 Ghodhbane Hani - OpenSNC
Rappport PFE 2012 Ghodhbane Hani - OpenSNCRappport PFE 2012 Ghodhbane Hani - OpenSNC
Rappport PFE 2012 Ghodhbane Hani - OpenSNC
Ghodbane Heni
 
Cours gestion-de-production
Cours gestion-de-productionCours gestion-de-production
Cours gestion-de-production
Rachid Rachido
 
Conception et developpement d'une application mobile Android e-location
Conception et developpement d'une application mobile Android e-locationConception et developpement d'une application mobile Android e-location
Conception et developpement d'une application mobile Android e-location
ALALSYSE
 
Rapport Projet Application Web De Domotique Arduino - Liotard Roulleau
Rapport Projet Application Web De Domotique Arduino - Liotard RoulleauRapport Projet Application Web De Domotique Arduino - Liotard Roulleau
Rapport Projet Application Web De Domotique Arduino - Liotard Roulleau
Nicolas Roulleau
 

Tendances (19)

Conception et developpement d'un site web pour la suggestion et notification ...
Conception et developpement d'un site web pour la suggestion et notification ...Conception et developpement d'un site web pour la suggestion et notification ...
Conception et developpement d'un site web pour la suggestion et notification ...
 
Projet de conception et de développement
Projet de conception et de développementProjet de conception et de développement
Projet de conception et de développement
 
iRecruite
iRecruiteiRecruite
iRecruite
 
Projet Passerelle sécurisée intelligente pour l'internet des objets
Projet Passerelle sécurisée intelligente pour l'internet des objetsProjet Passerelle sécurisée intelligente pour l'internet des objets
Projet Passerelle sécurisée intelligente pour l'internet des objets
 
Belwafi bilel
Belwafi bilelBelwafi bilel
Belwafi bilel
 
PROJET JAVA BD MySQL
PROJET JAVA BD MySQLPROJET JAVA BD MySQL
PROJET JAVA BD MySQL
 
Deep Learning : Application à la reconnaissance d’objets de classes multiples...
Deep Learning : Application à la reconnaissance d’objets de classes multiples...Deep Learning : Application à la reconnaissance d’objets de classes multiples...
Deep Learning : Application à la reconnaissance d’objets de classes multiples...
 
Mémoire fin d'étude gestion des interventions
Mémoire fin d'étude gestion des interventionsMémoire fin d'étude gestion des interventions
Mémoire fin d'étude gestion des interventions
 
Outpatient Department System (OPD)
Outpatient Department System (OPD) Outpatient Department System (OPD)
Outpatient Department System (OPD)
 
PFE :: Application de gestion des dus d'enseignement
PFE :: Application de gestion des dus d'enseignementPFE :: Application de gestion des dus d'enseignement
PFE :: Application de gestion des dus d'enseignement
 
Conception et développement d&rsquo;une place de marché B2C
Conception et développement d&rsquo;une place de marché B2CConception et développement d&rsquo;une place de marché B2C
Conception et développement d&rsquo;une place de marché B2C
 
rapport de projet de fin d'étude_PFE
rapport de projet de fin d'étude_PFErapport de projet de fin d'étude_PFE
rapport de projet de fin d'étude_PFE
 
These
TheseThese
These
 
eQ Services PFE
eQ Services PFEeQ Services PFE
eQ Services PFE
 
Rappport PFE 2012 Ghodhbane Hani - OpenSNC
Rappport PFE 2012 Ghodhbane Hani - OpenSNCRappport PFE 2012 Ghodhbane Hani - OpenSNC
Rappport PFE 2012 Ghodhbane Hani - OpenSNC
 
Rapport pfev7
Rapport pfev7Rapport pfev7
Rapport pfev7
 
Cours gestion-de-production
Cours gestion-de-productionCours gestion-de-production
Cours gestion-de-production
 
Conception et developpement d'une application mobile Android e-location
Conception et developpement d'une application mobile Android e-locationConception et developpement d'une application mobile Android e-location
Conception et developpement d'une application mobile Android e-location
 
Rapport Projet Application Web De Domotique Arduino - Liotard Roulleau
Rapport Projet Application Web De Domotique Arduino - Liotard RoulleauRapport Projet Application Web De Domotique Arduino - Liotard Roulleau
Rapport Projet Application Web De Domotique Arduino - Liotard Roulleau
 

En vedette

Le logiciel libre dans le secteur public : philosophie, enjeux et perspectives
Le logiciel libre dans le secteur public : philosophie, enjeux et perspectivesLe logiciel libre dans le secteur public : philosophie, enjeux et perspectives
Le logiciel libre dans le secteur public : philosophie, enjeux et perspectives
Benjamin Vidal
 
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmesEvaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Benjamin Vidal
 
1 ou 2 ?
1 ou 2 ?1 ou 2 ?
1 ou 2 ?
Benjamin Vidal
 
Artist quotes 2
Artist quotes 2Artist quotes 2
Artist quotes 2
asugrue518
 
Présentation Les aides par le réseau des CCI de France
Présentation Les aides par le réseau des CCI de FrancePrésentation Les aides par le réseau des CCI de France
Présentation Les aides par le réseau des CCI de France
Julie Province
 
Guide Exposants PROVEMPLOI 2012
Guide Exposants PROVEMPLOI 2012Guide Exposants PROVEMPLOI 2012
Guide Exposants PROVEMPLOI 2012
Julie Province
 
Schema regional de_developpement_de_l_occitan_2015-2020
Schema regional de_developpement_de_l_occitan_2015-2020Schema regional de_developpement_de_l_occitan_2015-2020
Schema regional de_developpement_de_l_occitan_2015-2020
blogVAP
 
Présentation skill2 invest
Présentation skill2 investPrésentation skill2 invest
Présentation skill2 invest
Julie Province
 
Abcédaire, école de Pont en Royans
Abcédaire, école de Pont en RoyansAbcédaire, école de Pont en Royans
Abcédaire, école de Pont en Royans
epn Royans
 
Diapo youtube
Diapo youtubeDiapo youtube
Diapo youtube
drrivedroite
 
Tutorial formation ecomotors IPM
Tutorial formation ecomotors IPMTutorial formation ecomotors IPM
Tutorial formation ecomotors IPM
Araceli Hendrix
 
BROCHURE JSG Technologies
BROCHURE JSG Technologies BROCHURE JSG Technologies
BROCHURE JSG Technologies
Camille Obligis
 
"Crowdsourcing et Business, Mythe ou réalité" article écrit suite au débat
"Crowdsourcing et Business, Mythe ou réalité" article écrit suite au débat "Crowdsourcing et Business, Mythe ou réalité" article écrit suite au débat
"Crowdsourcing et Business, Mythe ou réalité" article écrit suite au débat
Caroline VALENT
 
Jean luc boeuf - Séance 5 - Les niveaux d'administration locale
Jean luc boeuf - Séance 5 - Les niveaux d'administration localeJean luc boeuf - Séance 5 - Les niveaux d'administration locale
Jean luc boeuf - Séance 5 - Les niveaux d'administration locale
Jean Luc Boeuf
 
Business plan jau done 03
Business plan jau   done 03Business plan jau   done 03
Business plan jau done 03
Graphics & Web 24
 
LE BULLETIN DE L'INFOLETTTRE DE L'AMBASSADE D'HAITI A MEXICO SEPTEMBRE 2013
LE BULLETIN DE L'INFOLETTTRE DE L'AMBASSADE D'HAITI A MEXICO SEPTEMBRE 2013 LE BULLETIN DE L'INFOLETTTRE DE L'AMBASSADE D'HAITI A MEXICO SEPTEMBRE 2013
LE BULLETIN DE L'INFOLETTTRE DE L'AMBASSADE D'HAITI A MEXICO SEPTEMBRE 2013
#LeReCit @ReseauCitadelle
 

En vedette (20)

Le logiciel libre dans le secteur public : philosophie, enjeux et perspectives
Le logiciel libre dans le secteur public : philosophie, enjeux et perspectivesLe logiciel libre dans le secteur public : philosophie, enjeux et perspectives
Le logiciel libre dans le secteur public : philosophie, enjeux et perspectives
 
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmesEvaluation de la quantité de travail (in)utile dans l’exécution des programmes
Evaluation de la quantité de travail (in)utile dans l’exécution des programmes
 
1 ou 2 ?
1 ou 2 ?1 ou 2 ?
1 ou 2 ?
 
Artist quotes 2
Artist quotes 2Artist quotes 2
Artist quotes 2
 
Croquis 2 mte3 013
Croquis 2 mte3 013Croquis 2 mte3 013
Croquis 2 mte3 013
 
Présentation Les aides par le réseau des CCI de France
Présentation Les aides par le réseau des CCI de FrancePrésentation Les aides par le réseau des CCI de France
Présentation Les aides par le réseau des CCI de France
 
Tab lycee gen
Tab lycee genTab lycee gen
Tab lycee gen
 
Guide Exposants PROVEMPLOI 2012
Guide Exposants PROVEMPLOI 2012Guide Exposants PROVEMPLOI 2012
Guide Exposants PROVEMPLOI 2012
 
Schema regional de_developpement_de_l_occitan_2015-2020
Schema regional de_developpement_de_l_occitan_2015-2020Schema regional de_developpement_de_l_occitan_2015-2020
Schema regional de_developpement_de_l_occitan_2015-2020
 
Présentation skill2 invest
Présentation skill2 investPrésentation skill2 invest
Présentation skill2 invest
 
Abcédaire, école de Pont en Royans
Abcédaire, école de Pont en RoyansAbcédaire, école de Pont en Royans
Abcédaire, école de Pont en Royans
 
Diapo youtube
Diapo youtubeDiapo youtube
Diapo youtube
 
Tutorial formation ecomotors IPM
Tutorial formation ecomotors IPMTutorial formation ecomotors IPM
Tutorial formation ecomotors IPM
 
Quelques
QuelquesQuelques
Quelques
 
Tilly2
Tilly2Tilly2
Tilly2
 
BROCHURE JSG Technologies
BROCHURE JSG Technologies BROCHURE JSG Technologies
BROCHURE JSG Technologies
 
"Crowdsourcing et Business, Mythe ou réalité" article écrit suite au débat
"Crowdsourcing et Business, Mythe ou réalité" article écrit suite au débat "Crowdsourcing et Business, Mythe ou réalité" article écrit suite au débat
"Crowdsourcing et Business, Mythe ou réalité" article écrit suite au débat
 
Jean luc boeuf - Séance 5 - Les niveaux d'administration locale
Jean luc boeuf - Séance 5 - Les niveaux d'administration localeJean luc boeuf - Séance 5 - Les niveaux d'administration locale
Jean luc boeuf - Séance 5 - Les niveaux d'administration locale
 
Business plan jau done 03
Business plan jau   done 03Business plan jau   done 03
Business plan jau done 03
 
LE BULLETIN DE L'INFOLETTTRE DE L'AMBASSADE D'HAITI A MEXICO SEPTEMBRE 2013
LE BULLETIN DE L'INFOLETTTRE DE L'AMBASSADE D'HAITI A MEXICO SEPTEMBRE 2013 LE BULLETIN DE L'INFOLETTTRE DE L'AMBASSADE D'HAITI A MEXICO SEPTEMBRE 2013
LE BULLETIN DE L'INFOLETTTRE DE L'AMBASSADE D'HAITI A MEXICO SEPTEMBRE 2013
 

Similaire à Evaluation de la quantité de travail (in)utile dans l’exécution des programmes

Fourth year internship report
Fourth year internship reportFourth year internship report
Fourth year internship report
Slimane Akaliâ , سليمان أقليع
 
Conception et développement d'une marketplace basée sur l'architecture micros...
Conception et développement d'une marketplace basée sur l'architecture micros...Conception et développement d'une marketplace basée sur l'architecture micros...
Conception et développement d'une marketplace basée sur l'architecture micros...
Adem Amen Allah Thabti
 
RapportPFE_IngenieurInformatique_ESPRIT
RapportPFE_IngenieurInformatique_ESPRITRapportPFE_IngenieurInformatique_ESPRIT
RapportPFE_IngenieurInformatique_ESPRIT
Lina Meddeb
 
Belwafi bilel
Belwafi bilelBelwafi bilel
Belwafi bilel
Belwafi Bilel
 
pfe_rapport_poste_licence_LFIG.pdf
pfe_rapport_poste_licence_LFIG.pdfpfe_rapport_poste_licence_LFIG.pdf
pfe_rapport_poste_licence_LFIG.pdf
nesrine haloui
 
Rapport PFE BIAT Conception et mise en place d’une plate-forme de gestion des...
Rapport PFE BIAT Conception et mise en place d’une plate-forme de gestion des...Rapport PFE BIAT Conception et mise en place d’une plate-forme de gestion des...
Rapport PFE BIAT Conception et mise en place d’une plate-forme de gestion des...
Yasmine Lachheb
 
OpenERP - Gestion de prix de revient
OpenERP - Gestion de prix de revientOpenERP - Gestion de prix de revient
OpenERP - Gestion de prix de revient
Taieb Kristou
 
Rapport Projet De Fin D'étude de Conception et développement d’une applicatio...
Rapport Projet De Fin D'étude de Conception et développement d’une applicatio...Rapport Projet De Fin D'étude de Conception et développement d’une applicatio...
Rapport Projet De Fin D'étude de Conception et développement d’une applicatio...
mouafekmazia
 
Rapport Projet De Fin D'étude Développent d'une application web avec Symfony2
Rapport Projet De Fin D'étude Développent d'une application web avec Symfony2Rapport Projet De Fin D'étude Développent d'une application web avec Symfony2
Rapport Projet De Fin D'étude Développent d'une application web avec Symfony2
Sofien Benrhouma
 
Rapport PFE Ilef Ben Slima
Rapport PFE Ilef Ben SlimaRapport PFE Ilef Ben Slima
Rapport PFE Ilef Ben Slima
Ilef Ben Slima
 
Rapport pfe isi_Big data Analytique
Rapport pfe isi_Big data AnalytiqueRapport pfe isi_Big data Analytique
Rapport pfe isi_Big data Analytique
Yosra ADDALI
 
Rapport (Mémoire de Master) de stage PFE pour l’obtention du Diplôme Nationa...
Rapport (Mémoire de Master) de stage PFE pour  l’obtention du Diplôme Nationa...Rapport (Mémoire de Master) de stage PFE pour  l’obtention du Diplôme Nationa...
Rapport (Mémoire de Master) de stage PFE pour l’obtention du Diplôme Nationa...
Mohamed Amine Mahmoudi
 
Deploy automatic in the cloud
Deploy automatic in the cloudDeploy automatic in the cloud
Deploy automatic in the cloud
Abdelhalim KADDOUR GUETTAOUI
 
Conception et réalisation d’un Système d’information des étudiants du départe...
Conception et réalisation d’un Système d’information des étudiants du départe...Conception et réalisation d’un Système d’information des étudiants du départe...
Conception et réalisation d’un Système d’information des étudiants du départe...
Ilyas CHAOUA
 
Conception et développement d'une application de gestion de production et de ...
Conception et développement d'une application de gestion de production et de ...Conception et développement d'une application de gestion de production et de ...
Conception et développement d'une application de gestion de production et de ...
Mohamed Aziz Chetoui
 
Android VoIP/SIP Softphone
Android VoIP/SIP SoftphoneAndroid VoIP/SIP Softphone
Android VoIP/SIP Softphone
Hamza Lazaar
 
Report Master
Report MasterReport Master
Report Master
Bilel Trabelsi
 
Mise en place d'une Plateforme de Supervision et de Détection d'Intrusion Sys...
Mise en place d'une Plateforme de Supervision et de Détection d'Intrusion Sys...Mise en place d'une Plateforme de Supervision et de Détection d'Intrusion Sys...
Mise en place d'une Plateforme de Supervision et de Détection d'Intrusion Sys...
Alaaeddine Tlich
 
Mémoire Parallélisation d'algorithmes de graphes avec MapReduce sur un cluste...
Mémoire Parallélisation d'algorithmes de graphes avec MapReduce sur un cluste...Mémoire Parallélisation d'algorithmes de graphes avec MapReduce sur un cluste...
Mémoire Parallélisation d'algorithmes de graphes avec MapReduce sur un cluste...
Hadjer BENHADJ DJILALI
 
Architectures logicielles et materielles
Architectures logicielles et materiellesArchitectures logicielles et materielles
Architectures logicielles et materielles
Adnane Farid
 

Similaire à Evaluation de la quantité de travail (in)utile dans l’exécution des programmes (20)

Fourth year internship report
Fourth year internship reportFourth year internship report
Fourth year internship report
 
Conception et développement d'une marketplace basée sur l'architecture micros...
Conception et développement d'une marketplace basée sur l'architecture micros...Conception et développement d'une marketplace basée sur l'architecture micros...
Conception et développement d'une marketplace basée sur l'architecture micros...
 
RapportPFE_IngenieurInformatique_ESPRIT
RapportPFE_IngenieurInformatique_ESPRITRapportPFE_IngenieurInformatique_ESPRIT
RapportPFE_IngenieurInformatique_ESPRIT
 
Belwafi bilel
Belwafi bilelBelwafi bilel
Belwafi bilel
 
pfe_rapport_poste_licence_LFIG.pdf
pfe_rapport_poste_licence_LFIG.pdfpfe_rapport_poste_licence_LFIG.pdf
pfe_rapport_poste_licence_LFIG.pdf
 
Rapport PFE BIAT Conception et mise en place d’une plate-forme de gestion des...
Rapport PFE BIAT Conception et mise en place d’une plate-forme de gestion des...Rapport PFE BIAT Conception et mise en place d’une plate-forme de gestion des...
Rapport PFE BIAT Conception et mise en place d’une plate-forme de gestion des...
 
OpenERP - Gestion de prix de revient
OpenERP - Gestion de prix de revientOpenERP - Gestion de prix de revient
OpenERP - Gestion de prix de revient
 
Rapport Projet De Fin D'étude de Conception et développement d’une applicatio...
Rapport Projet De Fin D'étude de Conception et développement d’une applicatio...Rapport Projet De Fin D'étude de Conception et développement d’une applicatio...
Rapport Projet De Fin D'étude de Conception et développement d’une applicatio...
 
Rapport Projet De Fin D'étude Développent d'une application web avec Symfony2
Rapport Projet De Fin D'étude Développent d'une application web avec Symfony2Rapport Projet De Fin D'étude Développent d'une application web avec Symfony2
Rapport Projet De Fin D'étude Développent d'une application web avec Symfony2
 
Rapport PFE Ilef Ben Slima
Rapport PFE Ilef Ben SlimaRapport PFE Ilef Ben Slima
Rapport PFE Ilef Ben Slima
 
Rapport pfe isi_Big data Analytique
Rapport pfe isi_Big data AnalytiqueRapport pfe isi_Big data Analytique
Rapport pfe isi_Big data Analytique
 
Rapport (Mémoire de Master) de stage PFE pour l’obtention du Diplôme Nationa...
Rapport (Mémoire de Master) de stage PFE pour  l’obtention du Diplôme Nationa...Rapport (Mémoire de Master) de stage PFE pour  l’obtention du Diplôme Nationa...
Rapport (Mémoire de Master) de stage PFE pour l’obtention du Diplôme Nationa...
 
Deploy automatic in the cloud
Deploy automatic in the cloudDeploy automatic in the cloud
Deploy automatic in the cloud
 
Conception et réalisation d’un Système d’information des étudiants du départe...
Conception et réalisation d’un Système d’information des étudiants du départe...Conception et réalisation d’un Système d’information des étudiants du départe...
Conception et réalisation d’un Système d’information des étudiants du départe...
 
Conception et développement d'une application de gestion de production et de ...
Conception et développement d'une application de gestion de production et de ...Conception et développement d'une application de gestion de production et de ...
Conception et développement d'une application de gestion de production et de ...
 
Android VoIP/SIP Softphone
Android VoIP/SIP SoftphoneAndroid VoIP/SIP Softphone
Android VoIP/SIP Softphone
 
Report Master
Report MasterReport Master
Report Master
 
Mise en place d'une Plateforme de Supervision et de Détection d'Intrusion Sys...
Mise en place d'une Plateforme de Supervision et de Détection d'Intrusion Sys...Mise en place d'une Plateforme de Supervision et de Détection d'Intrusion Sys...
Mise en place d'une Plateforme de Supervision et de Détection d'Intrusion Sys...
 
Mémoire Parallélisation d'algorithmes de graphes avec MapReduce sur un cluste...
Mémoire Parallélisation d'algorithmes de graphes avec MapReduce sur un cluste...Mémoire Parallélisation d'algorithmes de graphes avec MapReduce sur un cluste...
Mémoire Parallélisation d'algorithmes de graphes avec MapReduce sur un cluste...
 
Architectures logicielles et materielles
Architectures logicielles et materiellesArchitectures logicielles et materielles
Architectures logicielles et materielles
 

Dernier

A1- Compréhension orale - présentations.pdf
A1- Compréhension orale - présentations.pdfA1- Compréhension orale - présentations.pdf
A1- Compréhension orale - présentations.pdf
lebaobabbleu
 
GUIDE POUR L’EVRAS BALISES ET APPRENTISSAGES
GUIDE POUR L’EVRAS BALISES ET APPRENTISSAGESGUIDE POUR L’EVRAS BALISES ET APPRENTISSAGES
GUIDE POUR L’EVRAS BALISES ET APPRENTISSAGES
DjibrilToure5
 
Compréhension orale La famille de Sophie (12).pdf
Compréhension orale  La famille de Sophie (12).pdfCompréhension orale  La famille de Sophie (12).pdf
Compréhension orale La famille de Sophie (12).pdf
lebaobabbleu
 
La Révolution Bénédictine Casadéenne du Livradois-Forez: De Charlemagne à Fra...
La Révolution Bénédictine Casadéenne du Livradois-Forez: De Charlemagne à Fra...La Révolution Bénédictine Casadéenne du Livradois-Forez: De Charlemagne à Fra...
La Révolution Bénédictine Casadéenne du Livradois-Forez: De Charlemagne à Fra...
Editions La Dondaine
 
1e geo metropolisation metropolisation x
1e geo metropolisation metropolisation x1e geo metropolisation metropolisation x
1e geo metropolisation metropolisation x
NadineHG
 
MÉDIATION ORALE - MON NOUVEL APPARTEMENT.pdf
MÉDIATION ORALE - MON NOUVEL APPARTEMENT.pdfMÉDIATION ORALE - MON NOUVEL APPARTEMENT.pdf
MÉDIATION ORALE - MON NOUVEL APPARTEMENT.pdf
lebaobabbleu
 
Auguste Herbin.pptx Peintre français
Auguste   Herbin.pptx Peintre   françaisAuguste   Herbin.pptx Peintre   français
Auguste Herbin.pptx Peintre français
Txaruka
 
Techno Revo et nations (1789-1848) ).pdf
Techno Revo et nations (1789-1848) ).pdfTechno Revo et nations (1789-1848) ).pdf
Techno Revo et nations (1789-1848) ).pdf
NadineHG
 
1e Espaces productifs 2024.Espaces productif
1e Espaces productifs 2024.Espaces productif1e Espaces productifs 2024.Espaces productif
1e Espaces productifs 2024.Espaces productif
NadineHG
 

Dernier (9)

A1- Compréhension orale - présentations.pdf
A1- Compréhension orale - présentations.pdfA1- Compréhension orale - présentations.pdf
A1- Compréhension orale - présentations.pdf
 
GUIDE POUR L’EVRAS BALISES ET APPRENTISSAGES
GUIDE POUR L’EVRAS BALISES ET APPRENTISSAGESGUIDE POUR L’EVRAS BALISES ET APPRENTISSAGES
GUIDE POUR L’EVRAS BALISES ET APPRENTISSAGES
 
Compréhension orale La famille de Sophie (12).pdf
Compréhension orale  La famille de Sophie (12).pdfCompréhension orale  La famille de Sophie (12).pdf
Compréhension orale La famille de Sophie (12).pdf
 
La Révolution Bénédictine Casadéenne du Livradois-Forez: De Charlemagne à Fra...
La Révolution Bénédictine Casadéenne du Livradois-Forez: De Charlemagne à Fra...La Révolution Bénédictine Casadéenne du Livradois-Forez: De Charlemagne à Fra...
La Révolution Bénédictine Casadéenne du Livradois-Forez: De Charlemagne à Fra...
 
1e geo metropolisation metropolisation x
1e geo metropolisation metropolisation x1e geo metropolisation metropolisation x
1e geo metropolisation metropolisation x
 
MÉDIATION ORALE - MON NOUVEL APPARTEMENT.pdf
MÉDIATION ORALE - MON NOUVEL APPARTEMENT.pdfMÉDIATION ORALE - MON NOUVEL APPARTEMENT.pdf
MÉDIATION ORALE - MON NOUVEL APPARTEMENT.pdf
 
Auguste Herbin.pptx Peintre français
Auguste   Herbin.pptx Peintre   françaisAuguste   Herbin.pptx Peintre   français
Auguste Herbin.pptx Peintre français
 
Techno Revo et nations (1789-1848) ).pdf
Techno Revo et nations (1789-1848) ).pdfTechno Revo et nations (1789-1848) ).pdf
Techno Revo et nations (1789-1848) ).pdf
 
1e Espaces productifs 2024.Espaces productif
1e Espaces productifs 2024.Espaces productif1e Espaces productifs 2024.Espaces productif
1e Espaces productifs 2024.Espaces productif
 

Evaluation de la quantité de travail (in)utile dans l’exécution des programmes

  • 1. Rapport de stage de DEA ´Evaluation de la quantit´e de travail utile dans l’ex´ecution des programmes Benjamin Vidal Responsable de stage : Pierre Michaud Projet CAPS
  • 2. Sujet de stage La recherche en architecture de processeur est confront´ee actuellement `a des contraintes qui rendent de plus en plus difficile l’augmentation des performances des processeurs. Ces contraintes sont multiples : consommation ´electrique, latence de propagation des signaux sur les connexions, temps et coˆut de developpement, etc. . . Pour esp´erer trouver d’´eventuelles solutions permettant d’augmenter les performances de mani`ere significative sur une large gamme d’applications, il faut trouver de nouveaux paradigmes d’architecture. Pour cela, il faut d’abord avoir une bonne compr´e-hension du comportement des programmes. Le sujet propos´e a pour but d’´evaluer la quantit´e de travail r´eellement utile dans l’ex´ecution des programmes. L’id´ee sous-jacente est que si une fraction importante de l’ex´ecution d’un programme consiste en du travail inutile, il peut ˆetre int´eressant de chercher un paradigme architectural per-mettant d’exploiter cette propri´et´e. Le probl`eme consiste `a donner une d´efinition de l’utilit´e d’un travail. Par exemple, dans la r´ef´erence [1], un r´esultat interm´ediaire est consid´er´e inutile s’il est ´ecrit dans un registre et est ´ecras´e sans avoir ´et´e utilis´e. Dans la r´ef´erence [5], un store `a une adresse m´emoire est consid´er´e inutile s’il ´ecrit une valeur ´egale `a la valeur d´ej`a stock´ee `a cette adresse. Nous proposons d’´etudier une autre d´efinition, selon laquelle une instruction dynamique est consid´er´ee utile si – Elle produit un r´esultat ´emis en sortie du programme (ex. printf) – Elle produit un r´esultat utilis´e comme op´erande d’une instruction utile – C’est un branchement dominant une instruction utile La partie recherche du stage consiste `a concevoir un algorithme efficace en temps et en m´emoire permettant d’´evaluer la quantit´e d’instructions dynamiques utiles. La partie mise-en-oeuvre consiste `a ´ecrire le programme correspondant, et `a l’utiliser pour obtenir des statistiques sur la fraction de travail utile, et d’autres statistiques, `a d´efinir, permettant de mieux appr´ehender le comportement des programmes. La mise en oeuvre se fera `a l’aide des outils d´evelopp´es au sein du projet CAPS. On travaillera sur des traces d’ex´ecution des programmes de la suite SPEC CPU2000. 2
  • 3. Remerciements Au cours de ce stage au sein de l’´equipe CAPS de l’IRISA, il m’a ´et´e possible de rencontrer un grand nombre de personnes qui m’ont aid´e `a comprendre le fonctionnement d’un laboratoire de recherche en informatique et surtout `a acqu´erir le recul n´ecessaire pour mieux appr´ehender le monde de l’architecture des microprocesseurs. Je voudrais donc remercier Ronan Amicel, Laurent Bertaux, Fran¸cois Bodin, Henri-Pierre Charles, Assia Djabelkhir, Romain Dolbeau, Antony Fraboulet, Karine Heydemann, Thierry Lafage, Antoine Monsifrot, Laurent Morin, Gilles Pokam, Olivier Rochecouste, Andr´e Seznec et ´Eric Toullec. Je tiens aussi `a remercier Yannos Sazeides (Enseignant `a l’universit´e de Chypre) avec qui j’ai eu l’occasion d’´echanger des id´ees sur la fa¸con d’´elaborer automatiquement un graphe de d´ependance de donn´ee `a partir de l’ex´ecution d’un programme. Et enfin je tiens `a remercier tr`es chaleureusement mon maˆıtre de stage, Pierre Michaud, qui m’a donn´e la libert´e de travail que j’aurais aim´e trouver tout au long de mon exp´erience universitaire et professionnelle et m’a permis ainsi de suivre les pistes que je souhaitais. Je tiens ´egalement `a le remercier pour tous les conseils qu’il a pu me donner concernant le monde de la recherche (publique ou priv´ee) et de m’avoir fait partager sa vision des choses sur de nombreux sujets. 3
  • 4. Table des mati`eres 1 Bibliographie 9 1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.2 Compilation et travail inutile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.2.1 Vous avez dit « instructions inutiles » ? . . . . . . . . . . . . . . . . . . . . . 10 1.2.2 Instructions statiques inutiles . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.3 Premi`ere approche : Instructions inutiles d´etect´ees dynamiquement . . . . . . . . . . . . . . . . . . . . . . 11 1.3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.3.2 Description du principe de d´etection et d’´elimination des instructions inutiles 11 1.3.3 Id´ees d’impl´ementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.3.4 Conclusion sur cette approche . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.4 Deuxi`eme approche : ´Ecritures silencieuses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.4.2 Le ph´enom`ene d’´ecriture silencieuse . . . . . . . . . . . . . . . . . . . . . . . 13 1.4.3 Les cons´equences de l’´elimination des ´ecritures silencieuses . . . . . . . . . . . 14 1.4.4 Id´ees d’impl´ementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.4.5 Conclusion sur cette approche . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4
  • 5. 1.5 Troisi`eme approche : Travail inutile global lors de l’ex´ecution d’un programme . . . . . . . . . . . . . . . . 16 1.5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.5.2 Evaluer l’utilit´e d’une instruction ? . . . . . . . . . . . . . . . . . . . . . . . . 16 1.5.3 Mise en oeuvre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 1.5.4 Conclusion sur cette approche . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 1.6 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2 Compte rendu du stage 20 2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.1.1 Le travail inutile, qu’est ce que c’est ? . . . . . . . . . . . . . . . . . . . . . . 20 2.1.2 Notre protocole de test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.2 La m´ethode utilis´ee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.2.1 L’algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.2.2 L’optimisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 2.2.3 Le r´esultat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.3 L’environnement de travail : Les choix de mise en oeuvre . . . . . . . . . . . . . . . . 29 2.3.1 Les Outils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.3.2 L’instrumentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.3.3 Le choix de la Plateforme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.3.4 SPARC : Le Meilleur des Mondes ? . . . . . . . . . . . . . . . . . . . . . . . . 32 2.3.5 S’affranchir de la num´erotation des registres faite par Salto . . . . . . . . . . 34 2.3.6 Les expressions r´eguli`eres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 2.3.7 La gestion des fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 5
  • 6. 2.4 R´esultats & Analyse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 2.4.1 Les chiffres. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 2.4.2 Le doute. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 2.4.3 La r´epartition du travail inutile . . . . . . . . . . . . . . . . . . . . . . . . . . 39 2.5 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3 Annexes 46 3.1 Petit historique du stage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.2 A propos de la description machine Salto du Sparc . . . . . . . . . . . . . . . . . . . 47 3.2.1 Gestion des instructions Save et Restore . . . . . . . . . . . . . . . . . . . . . 47 3.2.2 L’instruction call & link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.2.3 L’instruction addx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.2.4 Un d´etail : les instructions nop, ba et bn . . . . . . . . . . . . . . . . . . . . . 47 3.3 R´esultat de l’´evaluation du travail inutile sur un exemple simple . . . . . . . . . . . 49 3.3.1 Code source en C de l’exemple . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.3.2 Code source en assembleur Sparc de l’exemple . . . . . . . . . . . . . . . . . 49 3.3.3 Identifiant d’instruction statique . . . . . . . . . . . . . . . . . . . . . . . . . 51 3.3.4 Trace d’ex´ecution dynamique . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 3.3.5 Graphe de d´ependance de donn´ee . . . . . . . . . . . . . . . . . . . . . . . . . 56 3.3.6 Trace d’ex´ecution dynamique 2 . . . . . . . . . . . . . . . . . . . . . . . . . . 57 3.4 Exemple de donn´ees stock´ees en cours d’ex´ecution . . . . . . . . . . . . . . . . . . . 59 3.5 Code source du programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 6
  • 7. Table des figures 1.1 Mise en ´evidence de l’inutilit´e des instructions ne produisant des r´esultats utilis´es que par des instructions inutiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.1 La structure de donn´ee d’un noeud du graphe . . . . . . . . . . . . . . . . . . . . . . 24 2.2 Exemple de graphe g´en´er´e par l’algorithme 1 & 3 . . . . . . . . . . . . . . . . . . . . 25 2.3 Du code source en langage de haut niveau au graphe de d´ependance de donn´ee dynamique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.4 Instrumentation de code source en assembleur . . . . . . . . . . . . . . . . . . . . . . 30 2.5 Principe de l’instrumentation faite par le programme d’´evaluation de la quantit´e de travail inutile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.6 Le principe de la fenˆetre de registres du Sparc . . . . . . . . . . . . . . . . . . . . . . 33 2.7 Quantit´e d’instructions assembleurs inutiles lors de l’ex´ecution de gzip dans diff´erentes conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 2.8 Mise en ´evidence d’un probl`eme d’impl´ementation par divergence du flot de contrˆole 38 2.9 ´Evolution de la quantit´e de travail inutile en fonction du temps . . . . . . . . . . . . 40 3.1 Graphe d’exemple g´en´er´e par l’utilitaire « dot » . . . . . . . . . . . . . . . . . . . . . 56 3.2 Les structures de donn´ees utilis´ees par le programme pour construire le graphe de d´ependance de donn´ee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 7
  • 8. Liste des Algorithmes 1 Construction du graphe de d´ependance de donn´ee . . . . . . . . . . . . . . . . . . . 23 2 Parcours du graphe (Noeud) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 3 D´etection des instructions inutiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 8
  • 9. Chapitre 1 Bibliographie 1.1 Introduction Aujourd’hui, pour am´eliorer les performances d’un programme, il ne suffit plus seulement d’ajou-ter du mat´eriel dans un syst`eme donn´e. Il faut avant tout ´etudier le comportement de ce programme afin d’adapter au mieux les ajouts qui doivent ˆetre faits au syst`eme. De ce constat, les architectes des microprocesseurs ont tir´e des id´ees aujourd’hui fondamentales (tels les diff´erents niveaux de m´emoires caches qui exploitent la propri´et´e de localit´e temporelle et spatiale d’acc`es aux donn´ees dans les programmes). En ce sens, certains travaux de recherche s’int´eressent aujourd’hui au probl`eme du travail ef-fectu ´e inutilement par un microprocesseur. Ils mettent en ´evidence une quantit´e non n´egligeable de travail inutile. Dans cette bibliographie, trois approches principales de travail inutile ont ´et´e retenues. 1. Une instruction produisant un r´esultat jamais utilis´e par une autre instruction est consid´er´ee comme inutile (approche de « l’instruction morte » retenue par l’article [1]). 2. Une instruction d’´ecriture est consid´er´ee comme inutile si cette derni`ere ne modifie pas l’´etat de la m´emoire (i.e. la mˆeme valeur est ´ecrite `a la mˆeme adresse m´emoire) (approche de « l’´ecriture silencieuse » retenue dans de nombreux articles [5, 3, 7]). 3. Une instruction est consid´er´ee comme utile si elle produit un r´esultat en sortie (affichage d’un r´esultat par exemple) ou qu’elle est elle mˆeme utile `a une instruction utile (approche retenue pour le stage). Apr`es un bref tour d’horizon des travaux d´ej`a effectu´es dans le domaine au niveau des compila-teurs, chacun des trois aspects d´ecrits ci-dessus du travail inutile sera d´evelopp´e dans un paragraphe de cette bibliographie. S’en suivra un paragraphe de discussion sur la possibilit´e de mˆeler ces deux approches pour essayer d’obtenir une coop´eration compilation/ex´ecution dans l’´elimination des instructions inutiles. 9
  • 10. 1.2 Compilation et travail inutile 1.2.1 Vous avez dit « instructions inutiles » ? Il peut paraˆıtre surprenant au premier abord d’entendre parler de travail inutile dans un pro-gramme. En effet, `a partir du moment ou le programmeur demande d’effectuer un travail `a la machine, (encore que celui-ci ne soit pas infaillible. . .) ce travail doit avoir une utilit´e (au sens informatique du terme bien entendu. . .). Cependant, au del`a du programmeur, il existe toute une chaˆıne de m´ecanismes permettant de passer du langage de haut niveau (i.e. langage de program-mation classique) au code machine ex´ecutable. Ainsi ce programme va passer par toute sortes de transformations qui vont introduire du travail inutile. De plus, il est possible de trouver, dans la fa¸con dont sont con¸cus les programmes, du travail inutile (redondance de calculs par exemple). 1.2.2 Instructions statiques inutiles Pour commencer, il est important de rappeler ce que sont les instructions statiques et les ins-tructions dynamiques. Une instruction statique est une instruction telle qu’on peut la trouver dans le code source d’un programme. Une instruction dynamique est une instance d’instruction statique. A chaque instruction statique peut correspondre plusieurs instructions dynamiques (autant que de fois o`u l’on ex´ecute cette instruction statique). Exemple simple : pour i de 1 à n faire t[i] := 0; fpour Instruction statique : t[i] := 0 Instructions dynamiques associées : t[1] := 0, t[2] := 0, …, t[n] := 0 Dans l’exemple suivant, il est important de noter que si n n’est pas fix´e lors de la compilation, la seule connaissance du compilateur est l’instruction statique. Il ne pourra donc pas, `a priori se servir de la valeur de n `a des fins d’optimisation. Supposons maintenant qu’un programme ne soit compos´e que des instructions de l’exemple et n’affiche aucun r´esultat. Le compilateur peut en d´eduire que l’ensemble du travail `a effectuer pour ex´ecuter cette boucle est inutile. Cependant, il suffit d’ajouter une instruction qui utilise t[m] en lecture (m ´etant un param`etre d’entr´ee du programme inconnu `a la compilation) pour que, potentiellement, l’ensemble du travail de la boucle devienne utile. En effet, le compilateur ne sachant pas quelle case du tableau t va ˆetre acc´ed´e, il est oblig´e de consid´erer que l’ensemble de la boucle fournit du travail utile. Il existe de nombreuses autres mani`eres d’´eliminer du travail inutile lors de la compilation [2, 4] que nous n’aborderons pas ici car seul l’aspect d´ecrit ci-dessus se rapproche des travaux vis´es dans cette ´etude. Dans la suite de cette bibliographie, nous ne nous int´eresserons qu’aux instructions inutiles dynamiques (i.e. qui ne peuvent pas ˆetre d´etect´ees par le compilateur puisqu’elles d´ependent de valeurs d’entr´ees du programme non connues au moment de la compilation). 10
  • 11. 1.3 Premi`ere approche : Instructions inutiles d´etect´ees dynamiquement 1.3.1 Introduction Les auteurs de l’article [1] se sont aper¸cus que le r´earrangement des instructions fait par les com-pilateurs lors des phases d’optimisations cr´e´e des instructions inutiles. En effet, comme le montre leurs r´esultats, une compilation faite sans optimisations montre un niveau faible d’instructions in-utiles alors qu’une compilation avec un fort niveau d’optimisation montre un taux d’instructions inutiles relativement ´elev´e (parfois sup´erieur `a 10 %). Cependant, malgr´e ce travail effectu´e inuti-lement, il est bon de rappeler que globalement, le temps d’ex´ecution de ces programmes diminue (i.e. on a bien l’effet d´esir´e). La question qui vient alors est : « Comment conserver ces optimisations tout en r´eduisant le travail inutile qui leur est associ´e ? » 1.3.2 Description du principe de d´etection et d’´elimination des instructions inutiles Dans un premier temps, l’important est d’analyser les instructions ex´ecut´ees inutilement afin de savoir comment les d´etecter. Les auteurs de l’article [1] se sont ainsi aper¸cus que les instructions dynamiques inutiles ´etaient tr`es souvent des instances d’un nombre r´eduit d’instructions statiques. Ces instructions statiques sont appel´ees des instructions partiellement inutiles. En marquant ces instructions particuli`eres comme ´etant propices `a g´en´erer des instructions dynamiques inutiles, il est possible de ne faire un traitement particulier que sur ces derni`eres afin de savoir si une instance pr´ecise sera r´eellement inutile. Lors de l’ex´ecution, pour chaque instance d’une instruction partiellement inutile, une estimation de l’utilit´e de cette instruction dynamique sera faite. De cette estimation d´ecoulera son ex´ecution ou non. Dans le cas d’une mauvaise pr´ediction, un m´ecanisme de r´ecup´eration permet de lancer l’ex´ecution de cette instruction au moment ou l’on apprend que la pr´ediction est ´erron´ee. 1.3.3 Id´ees d’impl´ementation Les auteurs de l’article [1] ont donn´e quelques id´ees d’impl´ementation qui pourraient ˆetre mises en oeuvre pour la d´etection de ce type d’instructions. La plus simple consiste `a m´emoriser dans un cache totalement associatif les instructions statiques ayant d´ej`a g´en´er´e des r´esultats inutiles par le pass´e. Du fait qu’un faible nombre de ces instructions g´en`erent un grand nombre des instructions dynamiques inutiles, ce cache permettra de « suspecter » la prochaine instance d’une instruction statique ayant d´ej`a g´en´er´e des r´esultats inutiles. Par la suite, lors de la d´etection d’une instruction dynamique « suspect´ee » d’ˆetre inutile, son ex´ecution sera suspendue jusqu’au « verdict » final permettant de savoir si il ´etait juste de la sus-pecter. Si tel est le cas, cette instruction ne sera pas ex´ecut´ee, dans le cas contraire, cette instruction sera ex´ecut´ee ajoutant ainsi un surcoˆut dˆu au retard d’ex´ecution pris par cette instruction. Il est 11
  • 12. donc tr`es important d’avoir une estimation la plus fine possible afin d’´eviter ce genre de cas et afin d’augmenter le nombre d’instruction inutiles suspect´ees `a juste titre. Pour cela, des optimisations sont propos´ees : utilisation de l’information de flot de contrˆole et ajout d’un compteur deux bits `a saturation principalement. Il est important de noter que ces impl´ementations ne tiennent pas compte des r´esultats calcul´es qui ne servent qu’`a des instructions inutiles. Autrement dit, cette impl´ementation ne prend pas en compte le caract`ere transitif que peuvent avoir certaines instructions inutiles. Instruction produisant un résultat R Instruction utilisant R et produisant R’ Instruction utilisant R’ et produisant R’’ Si R’’ est un résultat inutile R’ et R auront été produits inutilement Fig. 1.1 – Mise en ´evidence de l’inutilit´e des instructions ne produisant des r´esultats utilis´es que par des instructions inutiles 1.3.4 Conclusion sur cette approche En conclusion, nous pouvons dire que les auteurs de l’article [1] ont mis en ´evidence une quantit´e non n´egligeable de travail inutile mˆeme si elle reste, aujourd’hui, difficile `a exploiter. En effet, dans un environnement o`u les ressources sont peu limit´ees, l’efficacit´e de l’impl´ementation d´ecrite ci-dessus offre des gains en performance n´egligeables. En revanche, dans des conditions de ressources plus limit´ees, les gains peuvent atteindre 10 % d’am´elioration des performances. De plus le fait d’ex´ecuter moins d’instructions permet une diminution de la charge des Unit´es Arithm´etiques et Logiques (UAL) et de la consommation ´electrique relativement importante. D’apr`es les auteurs, un m´ecanisme mat´eriel diminuant l’impact des instructions inutiles sur la performance et la consom-mation ´electrique permettrait d’appliquer des optimisations de code plus pouss´ees `a la compilation. 12
  • 13. 1.4 Deuxi`eme approche : ´Ecritures silencieuses 1.4.1 Introduction D’apr`es les auteurs de l’article [5], il existe principalement deux types d’´ecritures silencieuses. D’une part les mises `a jours de valeurs silencieuses (qui ne changent pas l’´etat de la m´emoire dans laquelle elles ´ecrivent) et d’autre part les ´ecritures silencieuses stochastiques qui mettent `a jour la m´emoire de mani`ere pr´evisible. Dans la suite de ce chapitre, nous nous concentrerons sur les mises `a jour de valeurs silencieuses et parlerons, par abus de langage, d’´ecritures silencieuses pour les d´esigner. 1.4.2 Le ph´enom`ene d’´ecriture silencieuse Au vu de la d´efinition de ce qu’est une ´ecriture silencieuse, il parait difficile de croire que ces instructions puissent avoir un impact n´egatif important sur les performances d’un programme. Pourtant, les articles sur le sujet montrent que souvent plus de 30 % des ´ecritures sont silencieuses dans les applications test´ees. En effet, il existe de nombreux cas o`u, lors du parcours des ´el´ements d’un tableau, les modifications apport´ees par ce parcours ne concernent qu’un petit nombre des ´el´ements de ce tableau. Exemples simples : pour i de 1 à n faire b := (b & t[i]); fpour pour i de 1 à n faire t[i] := (t[i] & b); fpour (a) (b) (c) t étant un tableau de booléens b étant un booléen l'opération & étant un "ET" logique pour i de 1 à n faire t[i] := t[i] + e(i); fpour t étant un tableau d'entiers e étant une fonction Dans l’exemple (a), nous pouvons voir que pour chaque case du tableau t dont le bool´een est `a vrai, l’ex´ecution du corps de la boucle ne produit aucun travail utile (la mˆeme valeur sera r´e-´ecrite dans b). Dans l’exemple (b), le simple fait que b soit ´egal `a vrai entraˆıne une inutilit´e de l’ensemble de la boucle. Dans l’exemple (c), lorsque "(i) renvoi z´ero, le corps de la boucle peut-ˆetre consid´er´e comme inutile. Un autre cas assez fr´equent de travail inutile est celui o`u un tableau est initialis´e apr`es avoir ´et´e utilis´e une premi`ere fois. Si lors de la premi`ere utilisation de ce tableau, toutes ses valeurs n’ont pas ´et´e modifi´ees, il est inutile de r´e-initialiser l’ensemble des cases de ce tableau. Il existe d’autres situations dans lesquelles un grand nombre d’´ecritures silencieuses peuvent ˆetre observ´ees : lors de l’appel d’un sous-programme, si les registres sauvegard´es n’ont pas ´et´e utilis´es dans ce sous-programme, leur restauration sera inutile. Ce mˆeme ph´enom`ene peut-ˆetre observ´e lors de la sauvegarde/restauration de contexte d’un processus par un syst`eme d’exploitation. 13
  • 14. 1.4.3 Les cons´equences de l’´elimination des ´ecritures silencieuses Au del`a du gain ´evident que provoquerait un m´ecanisme fiable de suppression des ´ecritures silencieuses, un tel syst`eme permettrait ´egalement de supprimer une certaine quantit´e de travail assez importante li´ee `a ces instructions. En premier lieu, les informations de contrˆole li´ees `a ces instructions ne sont plus n´ecessaires (Ex : si une s´erie d’´ecritures silencieuses se trouve dans une boucle, il est inutile d’ex´ecuter la boucle). De plus, lors de l’ex´ecution d’une instruction de range-ment en m´emoire, tout un m´ecanisme lourd de rapatriement de la ligne de cache concern´ee vers la m´emoire est mis en place (´ecriture de la donn´ee dans le cache, marquage de la ligne de cache comme ´etant modifi´ee puis, lors du chargement de nouvelles donn´ees dans cette ligne de cache, ´ecriture de l’ancienne ligne de cache consid´er´ee comme modifi´ee en m´emoire). De fait, la suppression d’une ´ecriture ´evite d’avoir `a passer par toute ces op´erations d’acc`es `a la m´emoire tr`es coˆuteuses. Comme expliqu´e dans l’article [3], cette remarque prend encore plus d’importance dans un syst`eme multi-processeur puisque `a chaque ´ecriture m´emoire est associ´e un message d’invalidation `a destination des autres processeurs provoquant un d´efaut de cache lors du prochain acc`es `a ces donn´ees. . . Il est ´egalement important de noter que si certaines ´ecritures ne sont pas effectu´ees, de fait, certaines d´ependances de donn´ees n’existent plus. De cette fa¸con, le processeur n’est plus oblig´e d’attendre que ces valeurs soient ´ecrites pour pouvoir les utiliser. Le rendement du pipeline du processeur est alors am´elior´e. 1.4.4 Id´ees d’impl´ementation Les auteurs de l’article [5] ont propos´e une impl´ementation basique permettant de supprimer les ´ecritures silencieuses. Cette impl´ementation consiste `a remplacer toute les op´erations de ran-gement en m´emoire par trois op´erations : Chargement de l’ancienne valeur pr´esente en m´emoire, comparaison avec la valeur qui doit y ˆetre ´ecrite et enfin, dans le cas o`u ces deux valeurs ne seraient pas ´egales, ´ecriture de la nouvelle valeur en m´emoire. Cette m´ethode est sˆure et permet de d´etecter l’ensemble des ´ecritures silencieuses. De plus, les lectures pouvant ˆetre servies en parall`eles, il peut ˆetre int´eressant de remplacer les ´ecritures par des lectures suivies de comparaisons. Cependant, dans la mesure ou le nombre d’´ecritures silencieuses ne repr´esente pas la majorit´e des ´ecritures m´emoire, les auteurs ont ajout´e une « impl´ementation parfaite » dans laquelle un m´ecanisme per-met de savoir si une ´ecriture va ˆetre utile et, dans ce cas, n’effectuera que l’´ecriture en m´emoire sans avoir `a comparer la nouvelle valeur `a la valeur pr´ec´edente. D’autres id´ees d’impl´ementations apparaissent ´egalement dans l’article [5] comme par exemple la possibilit´e que la ligne de cache ne soit pas marqu´ee comme modifi´ee lorsqu’elle re¸coit une ´ecriture silencieuse ´evitant ainsi d’avoir `a propager l’´ecriture en m´emoire centrale (avantage principal de l’´elimination des ´ecriture silencieuses). L’impl´ementation retenue pour les simulations faites par les auteurs de [5] est la premi`ere propos´ee avec pour caract´eristique suppl´ementaire que seules les ´ecritures mises en attente vont subir une v´erification de leur utilit´e. Ce qui veut dire qu’une ´ecriture survenant `a un moment o`u au moins un port d’´ecriture de la m´emoire est disponible sera servie avant que la v´erification de son utilit´e n’ai pu ˆetre faite. De cette fa¸con, les performances des ´ecritures ne sont jamais d´egrad´ees puisque le m´ecanisme n’agit que sur la file d’attente des ´ecritures afin de la r´eduire. 14
  • 15. 1.4.5 Conclusion sur cette approche Les auteurs de l’article [5] ont mis en ´evidence une grande quantit´e de travail inutile `a travers les ´ecritures silencieuses. En effet, les proportions d’´ecritures silencieuses obtenues lors des tests sont parfois tr`es importantes et laissent penser qu’elles pourraient avoir une influence tr`es importante sur les performances, notamment dans les syst`emes dont la purge des lignes de cache en m´emoire est un goulet d’´etranglement. Les auteurs mettent ´egalement en avant la r´eduction du trafic sur le bus d’un syst`eme multiprocesseur `a m´emoire partag´ee qui est souvent un point critique dans ce type de syst`emes (ce trafic limite le nombre de processeurs sur un mˆeme bus). D’autres travaux ´elargissant le th`eme de l’´ecriture silencieuse ont ´egalement ´et´e pr´esent´es comme celui sur les ´ecritures silencieuses temporaires [6] consid´erant que si une valeur en m´emoire est modifi´ee puis remise `a son ancienne valeur et qu’aucune lecture ne soit intervenue sur la valeur transitoire, elle peut-ˆetre consid´er´ee comme silencieuse. Ce mod`ele semble bien s’adapter aux cas d´ecrits ci-dessus de sauvegarde et de restauration de contexte fr´equents (appel de sous-programmes, passage d’un processus `a un autre. . .). 15
  • 16. 1.5 Troisi`eme approche : Travail inutile global lors de l’ex´ecution d’un programme 1.5.1 Introduction Dans cette approche, la probl´ematique est un peu diff´erente de celle vue dans les deux premiers paragraphes. En effet, le but de ces deux approches ´etait de d´etecter (soit par pr´evision, soit de mani`ere dynamique) une cat´egorie d’instructions inutiles afin d’´eviter leur ex´ecution « au vol ». Dans l’approche retenue pour le stage, il s’agit d’abord de regarder quelle est la quantit´e de travail inutile de fa¸con globale (essayer d’´evaluer l’ensemble du travail fait inutilement par un programme) afin d’avoir ensuite une id´ee du type de comportement ou d’application ex´ecut´e par un processeur qui produit le plus de travail inutile. De cette fa¸con, si certains r´esultats montrent une quantit´e non n´egligeable de travail inutile dans certains types d’applications, il sera ensuite possible d’´etudier pourquoi ce travail inutile est si important et si il peut ˆetre ´evit´e d’une mani`ere ou d’une autre. 1.5.2 Evaluer l’utilit´e d’une instruction ? La m´ethode retenue ici pour ´evaluer l’utilit´e d’une instruction est assez simple : Une valeur qui est affich´ee en sortie d’un programme est consid´er´ee comme un r´esultat utile. Toute instruction ayant servi `a calculer ce r´esultat est une instruction utile. Ainsi, les instructions utiles `a un r´esultat peuvent ˆetre repr´esent´ees par un arbre de d´ependance entre ces derni`eres dont la racine est le r´esultat lui-mˆeme et chaque noeud repr´esente les instructions utiles au calcul de ce r´esultat (aussi bien les instructions de rangement/r´ecup´eration en m´emoire, de calcul et de branchement). Les feuilles seront alors les valeurs d’entr´ees (param`etres fix´es lors de la compilation ou de l’ex´ecution) du programme. En regroupant l’ensemble des arbres ainsi obtenus pour chaque r´esultat en un graphe orient´e dont les sources sont les r´esultats et les puits sont les valeurs d’entr´ee du programme, il est possible d’identifier quelles sont les instructions r´eellement utiles au programme. En effet, les instructions et les valeurs d’entr´ees inutiles au programme n’appartiendront pas `a ce graphe et seront ainsi mises en ´evidence. 16
  • 17. Exemple simple : a := lire(); b := VRAI; c := 0; si a=0 faire b := FAUX; c := 5; fsi si b alors écrire(c) sinon écrire(a) Exemple de graphe d’exécution si a vaut 0 : écrire(a) nécessite b b := FAUX branchement correspondant Test a=0 nécessite a nécessite a a := lire() Valeur d’entrée du programme a := lire() Valeur d’entrée du programme c := 5 c := 0 b := VRAI Instructions exécutées inutilement Exemple de graphe d’exécution si a vaut 1 : nécessite b nécessite c Test a=0 nécessite a a := lire() Valeur d’entrée du programme écrire(c) c := 0 Valeur d’entrée du programme Aucune instruction n’est exécutée inutilement b := VRAI Valeur d’entrée du programme Cet exemple permet de mettre en ´evidence le fait que selon les valeurs d’entr´ees du programme, il peut y avoir du travail inutile ou pas. De plus, il met en lumi`ere (dans le cas o`u a vaut 1) le fait que le test a=0 correspondant au branchement du « si » doit ˆetre pris en compte comme ´etant du travail utile puisque de ce branchement vont d´ependre les instructions qui vont suivre (Nous pouvons dire que ces instructions « exigent » l’ex´ecution de ce branchement et donc du test qui permet de savoir si ce branchement doit ˆetre pris). Cette m´ethode d’identification des instructions inutiles semble parfaite (mˆeme si elle ne prend pas en compte certaines ´ecritures silencieuses). Cependant, elle n´ecessite le d´eroulement complet du programme afin de savoir si oui ou non une instruction dynamique du programme sera utile pour un r´esultat final. De fait, cette m´ethode ne peut pas ˆetre utilis´ee directement pour ´eliminer « au vol » les instructions inutiles. En revanche, elle permet d’exhiber de nombreux cas d’instructions inutiles que les autres m´ethodes ne d´etectent pas. Par exemple, le cas d’une instruction inutile par transitivit´e mis en ´evidence figure 1.1 sera d´etect´e par cette m´ethode. 1.5.3 Mise en oeuvre Comme d´ecrit dans le sujet de stage, la mise en oeuvre de cette approche du travail inutile consis-tera `a ´elaborer un programme permettant de d´etecter les instructions dynamiques inutiles, d’apr`es la d´efinition donn´ee ci-dessus, afin de faire des statistiques sur la quantit´e de travail inutile dans un ensemble de programmes `a tester. Diff´erentes cat´egories de travail inutile pourront ´egalement ˆetre mises en ´evidence (Ex : chargements inutiles, rangements en m´emoire inutiles, calculs inutiles. . .). Une fois les tests effectu´es, un travail de regroupement des applications test´ees selon les r´esultats pourra ˆetre fait afin de d´egager, ´eventuellement, des « motifs » de comportements permettant en-suite de savoir quelles applications sont le plus concern´ees par quel type de travail inutile. Nous pouvons imaginer, `a partir de l`a, que des ´ebauches de solutions mat´erielles et/ou logicielles ne soient 17
  • 18. trouv´ees pour r´eduire cette quantit´e de travail inutile. Cependant, l’objet du stage reste celui-ci : « Concevoir et ´ecrire un programme permettant de calculer la quantit´e de travail inutile dans un programme particulier apr`es son ex´ecution » . Dans ce sens, le travail `a effectuer en stage sera, dans un premier temps, de r´efl´echir `a la mani`ere de d´etecter quelles sont les instructions qui ont ´et´e ex´ecut´ees inutilement lorsque l’ex´ecution d’un programme sera termin´ee (algorithme de construction puis d’exploration du graphe de d´ependance des instructions d´ecrit dans cette section). Ces r´esultats devront ensuite ˆetre mis en forme afin de d´egager des statistiques sur la quantit´e de travail inutile (pourcentage d’instructions inutiles) et sur la nature de ces instructions (de quel type d’instructions s’agit-il ?). Une fois cet algorithme impl´ement´e, il sera int´eressant de le tester sur diff´erent type de programme afin de savoir quelle est la quantit´e de travail r´eellement inutile (d’apr`es la d´efinition donn´ee en introduction de cette section) dans ces programmes. 1.5.4 Conclusion sur cette approche En conclusion nous pouvons dire que l’approche retenue pour le stage est une d´emarche scien-tifique exp´erimentale permettant de savoir quelle est la proportion globale de travail inutile dans un programme. Si les r´esultats r´ev`elent une grande quantit´e de travail inutile, de nombreuses ouvertures paraissent possibles : D´etection de ces instructions grˆace `a des compilateurs « intel-ligents », d´etection de ces instructions « au vol » (approche d´ej`a retenue par [1]), coop´eration compilateur/mat´eriel ou encore ajout de nouvelles instructions afin de faciliter leur d´etection. 18
  • 19. 1.6 Conclusion En conclusion, nous pouvons dire que plusieurs mani`eres d’´eliminer le travail inutile ont d´ej`a ´et´e abord´ees (tant dans le domaine de la compilation qu’en architecture). En effet, lors de la compila-tion, une certaine quantit´e de travail inutile peut d´ej`a ˆetre supprim´ee (en fonction des informations que le compilateur peut exploiter). Cependant, nous avons ´egalement vu que certaines optimisa-tions de ces mˆemes compilateurs g´en`erent des instructions inutiles. De fait, diff´erentes m´ethodes ont ´et´e propos´ees pour ´eliminer ce travail inutile lors de l’ex´ecution (instructions dynamiques inutiles). Une autre approche int´eressante consistait `a ´eliminer les ´ecritures silencieuses, une autre forme de travail inutile. Apr`es ce tour d’horizon global, il est assez difficile de savoir de mani`ere pr´ecise quelle est la quantit´e de travail inutile effectu´ee par un microprocesseur lors de l’ex´ecution d’un programme. C’est `a cette question que va tenter de r´epondre le travail `a venir en stage. . . 19
  • 20. Chapitre 2 Compte rendu du stage 2.1 Introduction 2.1.1 Le travail inutile, qu’est ce que c’est ? Le travail inutile est une notion difficile `a cerner. Il existe diff´erentes approches pour traiter le probl`eme du travail effectu´e inutilement par un programme. Tout d’abord, le travail inutile peut- ˆetre de nature statique (d´etectable et supprimable lors de la compilation) ou de nature dynamique (visible uniquement lors de l’ex´ecution). L’´elimination du travail inutile statique est d´ej`a bien connue et fait partie int´egrante de toute chaˆıne de compilation optimis´ee digne de ce nom. Ici nous nous int´eresserons seulement au travail inutile de nature dynamique puisque ce dernier n’est pas exploit´e par les processeurs ou les langages de programmation actuels. Une fois le cadre du travail inutile dynamique pos´e, il est n´ecessaire de se donner une d´efinition pr´ecise du travail inutile afin de pouvoir en ´evaluer la quantit´e lors de l’ex´ecution d’un programme sur un jeu de donn´ees particulier de fa¸con automatique. Cette d´efinition, dans un premier temps tr`es large, a ´et´e restreinte pour des raisons d’impl´ementation. La d´efinition prise comme base de d´epart `a cette ´evaluation ´etait la suivante : Tout travail qui ne sert, ni directement, ni indirectement, `a produire un r´esultat est jug´e inutile. De fa¸con plus pr´ecise : Une instruction dynamique est consid´er´ee comme utile si - Elle produit un r´esultat ´emis en sortie du programme (ex : affichage `a l’´ecran). - Elle produit un r´esultat utilis´e comme op´erande d’une instruction utile. - C’est un branchement dominant une instruction utile. 20
  • 21. Exemple simple : instruction 1; si booléen faire instruction 2; instruction 3; fpour instruction 4; Dans cet exemple, le branchement conditionnel « domine » les instructions 2 et 3. Si le bool´een est vrai et que les instructions 2 et 3 sont inutiles, alors on peut consid´erer le branchement comme inutile. Note Par abus de langage, dans la suite de ce document, nous d´esignerons toutes les instructions de transfert de contrˆole (branchement conditionnels et inconditionnels, sauts, appels de fonctions. . .) par l’expression « instruction de branchement ». En regardant cette d´efinition de plus pr`es, un probl`eme se pose dans le cas g´en´eral : Supposons que l’instruction 2 soit un « store » qui range une valeur `a une adresse m´emoire, que l’instruction 4 soit un « load » et que le bool´een soit `a faux. Dans ce cas, si l’instruction 4 est consid´er´ee comme utile et si les deux acc`es pointent sur la mˆeme adresse m´emoire, alors le branchement devra ˆetre consid´er´e comme utile. Cependant, l’adresse de l’acc`es `a la m´emoire qui aurait pu ˆetre fait par l’instruction 2 n’est pas connue puisque cette instruction n’a pas ´et´e ex´ecut´ee. A cause de ce type d’acc`es `a la m´emoire (dont l’adresse acc´ed´ee n’est connue qu’`a l’ex´ecution) nous avons du faire l’hypoth`ese conservatrice suivante : Toutes les instructions de branchements sont consid´er´ees comme utiles. Ce qui nous donne la d´efinition suivante : Une instruction dynamique est consid´er´ee comme utile si - Elle produit un r´esultat ´emis en sortie du programme (ex : affichage `a l’´ecran). - Elle produit un r´esultat utilis´e comme op´erande d’une instruction utile. - C’est un branchement. Note Par abus de langage, dans la suite de ce document, nous utiliserons le mot « ressource » pour d´esigner soit un registre soit un emplacement m´emoire. Partant de cette nouvelle d´efinition, l’objectif ´etait de construire un graphe de d´ependance de donn´ee en reliant les instructions lisant une ressource `a la derni`ere instruction ayant ´ecrit dans cette mˆeme ressource. De cette fa¸con, lorsqu’une ressource apparaˆıt comme utile (lorsque sa valeur est ´ecrite en sortie ou qu’elle est utilis´ee par une instruction de branchement), il devient possible, en parcourant les arcs de ce graphe, de trouver toutes les instructions qui ont ´et´e utiles pour produire 21
  • 22. ce r´esultat (le r´esultat est un graphe ressemblant `a la figure 2.2 page 25). 2.1.2 Notre protocole de test A partir de cette d´efinition, nous avons essay´e de mesurer la quantit´e de travail inutile dans des petits programmes d’exemple, puis, une fois ces exemples valid´es, nous avons test´e notre protocole pour mesurer le travail inutile sur un programme plus cons´equent et surtout n’ayant pas ´et´e con¸cu dans le but d’en mesurer la quantit´e de travail inutile. Pour faire nos tests, nous avons choisi l’utilitaire de compression/d´ecompression de donn´ees gzip. 22
  • 23. 2.2 La m´ethode utilis´ee 2.2.1 L’algorithme Pour construire notre graphe de d´ependance de donn´ee, nous avons choisi d’instrumenter chaque instruction assembleur afin de contrˆoler de fa¸con pr´ecise les entr´ees et les sorties de chacune d’elles. Les entr´ees ´etant les op´erandes d’une instruction (les ressources ´etant lues par l’instruction) et les sorties ´etant les r´esultats d’une instruction (les ressources ´etant ´ecrites par l’instruction). Dans le cas g´en´eral, notre impl´ementation de la d´etection de d´ependance de donn´ee peut se r´esumer par l’algorithme 1. Algorithme 1: Construction du graphe de d´ependance de donn´ee Entr´ee : Programme dont on veut ´evaluer la quantit´e de travail inutile. Donn´ees `a fournir en entr´ee `a ce programme. Sortie : Graphe de d´ependance de donn´ee dynamique. 1 pour chaque instruction ex´ecut´ee faire 2 Cr´eer une repr´esentation interne de cette instruction; 3 L’ajouter `a la liste des instructions dynamiques ex´ecut´ees; {Cette repr´esentation interne contient des informations concernant l’instruction : son num´ero dynamique, le fichier source auquel elle appartient, son num´ero statique dans ce fichier, son type. . . } 4 pour chaque op´erande de l’instruction {ressource lue} faire 5 Lire dans la table des ressources quelle est la derni`ere instruction qui a ´ecrit dans cette ressource; 6 Cr´eer un lien de d´ependance {arc dans le graphe} entre l’instruction courante et la derni`ere instruction ayant ´ecrit dans la ressource en question; {Associe `a l’op´erande le num´ero de l’instruction dynamique qui l’a produit} fin 7 pour chaque r´esultat de l’instruction {ressource ´ecrite} faire 8 Ecrire dans la table des ressources que l’instruction courante a modifi´ee l’´etat de cette ressource; fin fin Une fois cet algorithme ex´ecut´e sur un programme particulier, il est possible de connaˆıtre les d´ependances directes entre les instructions grˆace aux arcs construits mais aussi les d´ependances indirectes grˆace aux chemins form´es par des suites d’arcs dans le graphe (le graphe de la figure 2.2 page 25 en est un exemple). En ajoutant `a l’algorithme pr´ec´edent une condition dans la boucle principale permettant de parcourir le graphe construit lorsqu’on rencontre une instruction de sortie (affichage), il devient 23
  • 24. possible de connaˆıtre les instructions utiles lors de l’ex´ecution d’un programme (d’apr`es la premi`ere d´efinition donn´ee ci-dessus) (cf. algorithme 3). Proc´edure Parcours du graphe (Noeud) 1 si le noeud est marqu´e inutile alors 2 Marquer ce noeud {repr´esentant une instruction} comme ´etant utile; pour chaque noeud op´erande de ce noeud faire 3 Appeler la proc´edure Parcours du graphe (Noeud op´erande); fin fin Algorithme 3: D´etection des instructions inutiles Entr´ee : Graphe de d´ependance de donn´ee dynamique. Sortie : Quantit´e d’instructions dynamiques inutiles. Localisation de ces instructions dans le code source. pour chaque noeud du graphe faire si le noeud repr´esente une instruction de sortie ou de branchement alors Appeler la proc´edure Parcours du graphe (Noeud); fin fin Numéro d'instruction dynamique Identificateur d'instruction statique Type de l'instruction Nombre d'opérandes Liste des instructions ayant écrit en dernier dans les opérandes Fig. 2.1 – La structure de donn´ee d’un noeud du graphe Un point int´eressant de cet algorithme, dont nous nous sommes rendu compte une fois l’impl´e-mentation op´erationnelle, est qu’il permet de d´etecter les acc`es fait en lecture `a une zone m´emoire non initialis´ee pr´ealablement. Par exemple, si un tableau de taille n est d´eclar´e et initialis´e, le fait de tenter d’acc´eder `a l’adresse de la zone m´emoire n+1, qui n’a donc pas ´etait initialis´ee, provoque une incoh´erence dans l’algorithme puisqu’il est impossible de trouver la derni`ere instruction ayant ´ecrit dans cette zone m´emoire (ligne 5 dans l’algorithme 1 page pr´ec´edente). De cette fa¸con, il est possible de trouver, lors de l’ex´ecution, une erreur d’acc`es `a la m´emoire. 24
  • 25. 39 40 38 36 37 35 34 3 14 33 0 13 25 24 32 31 30 29 28 26 27 23 17 16 22 21 20 19 18 15 9 12 11 8 10 7 2 6 5 4 1 Dans ce graphe, les noeuds sont ´etiquet´es par les num´eros dynamiques des instructions (ordre d’ex´ecution). Les noeuds en gris sont des instructions inutiles alors que les noeuds en noir sont des instructions utiles. Les instructions dynamiques 4, 12 et 20 sont issues d’une seule et mˆeme instruction statique de rangement en m´emoire dont seulement une instance est utile : l’instruction dynamique num´ero 12. Fig. 2.2 – Exemple de graphe g´en´er´e par l’algorithme 1 & 3 25
  • 26. 2.2.2 L’optimisation Le gros probl`eme de cette approche est que le graphe devient tr`es rapidement ´enorme, mˆeme avec des programmes de petite taille. En effet, ´etant donn´e qu’il faut conserver des informations concernant chaque instruction dynamique jusqu’`a la fin de l’ex´ecution, seule une ex´ecution ayant un nombre r´eduit d’instructions dynamiques peut ˆetre envisag´ee (aux alentours de 300 000 dans notre impl´ementation). Nous avons donc tent´e de r´eduire le graphe au maximum en ´eliminant au cours de l’ex´ecution les informations qui ne nous ´etaient plus n´ecessaires. Ce qui est fait. . . Dans un premier temps, pour r´eduire ce graphe et donc augmenter la taille des programmes testables, nous avons d´ecid´e de supprimer `a la vol´ee les informations concernant les instructions « certifi´ees » utiles. Ces informations ´etant le noeud repr´esentant cette instruction et les arcs sor-tant de celle-ci. Ces informations ne sont plus d’aucune utilit´e une fois que le parcours de l’arbre dont cette instruction est la racine est effectu´e. Il est alors possible de les supprimer sans perdre d’information utile `a notre calcul de quantit´e de travail inutile. Cette m´ethode permet, `a mesure que le programme se d´eroule et envoi des informations en sortie, (affichage. . .) de r´eduire le graphe. Il est alors d’autant plus r´eduit que la quantit´e de travail utile est importante (sur nos tests, le gain r´eel en occupation m´emoire est d’un facteur trois `a quatre ce qui permet de tester des programmes d´epassant le million d’instructions dynamiques sans avoir un temps d’ex´ecution r´edhibitoire). La courbe de l’occupation m´emoire de l’algorithme au cours du temps devient alors identique (`a quelques d´etails d’impl´ementation pr`es) `a la courbe repr´esentant la quantit´e de travail inutile cumul´e (figure 2.9 page 40). Quelques petites optimisations ont aussi ´etaient apport´ees au programme concernant le temps d’ex´ecution. Bien que ce facteur ne soit pas le point crucial de notre algorithme, il semblait int´eressant de s’y pencher pour ´eviter d’avoir des dur´ees de tests trop importantes. Nous avons par exemple, `a la ligne 1 de la proc´edure Parcours du graphe page 24, supprim´e le parcours d’une branche lorsque cette derni`ere poss`ede comme racine une instruction utile. En effet, si tel est le cas, cela signifie que cette branche a d´ej`a ´et´e enti`erement explor´ee et qu’il est inutile de la parcourir `a nouveau. Ce qu’il reste `a faire. . . Dans un second temps, il est int´eressant de voir que si une instruction ´ecrit dans une ou plu-sieurs ressources, puis que ces ressources sont de nouveau ´ecrites sans ˆetre lues entre temps, les informations concernant cette instruction inutile ne nous serviront jamais puisque cette instruction ne sera jamais rendue utile (notion de « valeur morte »). De cette fa¸con, il est possible, ici encore, 26
  • 27. de r´eduire notre graphe en supprimant les noeuds repr´esentant ce type d’instructions ainsi que leurs arcs sortants. Une mani`ere simple d’impl´ementer un tel m´ecanisme serait de consid´erer que chaque instruction inutile est un objet et que les ressources (registres et zones m´emoire) sont des moyens d’acc´eder `a ces objets. Si une instruction est accessible depuis au moins une ressource, alors il n’est pas possible de supprimer les informations concernant cette instruction. En revanche, si aucune ressource ne « r´ef´erence » l’objet, alors cet objet est inaccessible depuis les ressources et le restera jusqu’`a la fin de l’ex´ecution du programme. Cet objet peut donc ˆetre supprim´e (noeud ainsi que ses arcs sortants). Cette m´ethode s’apparente `a un syst`eme de ramasse-miettes comme il est souvent mis en place dans un environnement d’ex´ecution pour lib´erer des zones m´emoires n’´etant plus r´ef´erenc´ees par aucun pointeur. 2.2.3 Le r´esultat La figure 2.3 page suivante est un exemple simple permettant de comprendre comment est construit le graphe de d´ependance de donn´ee `a partir du code assembleur du programme dont on veut ´evaluer la quantit´e de travail inutile. Dans la figure 2.3 page suivante, les noeuds sources sont les instruction utiles par hypoth`ese (en caract`ere gras). Ces instructions sont soit des instructions de sortie (print %valeur dans l’exemple) soit des instructions de branchement (bne boucle dans l’exemple). Une fois ces instructions jug´ees comme ´etant utile au programme, nous pouvons appliquer la d´efinition r´ecursive permettant de trouver toutes les instructions ayant servi `a produire les valeurs utiles `a ces instructions. Ainsi, dans notre exemple, l’instruction dynamique num´ero 18 (print %valeur) poss`ede comme entr´ee le registre %valeur. Il est donc n´ecessaire de trouver la derni`ere instruction ayant ´ecrit dans ce registre. Cette instruction est l’instruction dynamique num´ero 17 (load [@tab+2],%valeur). Ainsi de suite r´ecursivement, l’instruction dynamique num´ero 17 poss`ede comme entr´ee la seconde case du tableau rang´e `a l’adresse m´emoire @tab dont la derni`ere ´ecriture a ´et´e faite par l’instruction dynamique num´ero 8 et ainsi de suite jusqu’`a n’arriver qu’`a des instructions n’ayant aucune entr´ee (copie d’une constante dans un registre (mov 1,%indice dans l’exemple), instruction d’entr´ee au clavier par l’utilisateur. . .). De cette mani`ere, en parcourant le graphe, il est possible d’identifier le travail utile. Les ins-tructions n’´etant accessible depuis aucune des sources (instructions de sorties ou de branchement) sont identifi´ees comme ´etant du travail inutile (instructions dynamiques 2, 3, 12 et 13 dans notre exemple). Grˆace `a cet exemple, nous avons mis en ´evidence un cas simple comportant peu de travail inutile. En revanche, il est facile de prendre conscience de l’importance que peut atteindre ce travail inutile d`es lors que le traitement `a l’int´erieur d’une boucle du type de celle pr´esent´ee dans l’exemple devient important. En effet, dans notre exemple, seule la multiplication par 10 et le rangement en m´emoire sont inutiles mais si la valeur `a ranger dans le tableau avait ´et´e un calcul effectu´e par une fonction comportant 10 000 instructions, les chiffres auraient ´et´e diff´erents. De mˆeme, si la taille du tableau avait ´et´e de 10 000 cases dont seulement une aurait ´et´e utilis´ee, la quantit´e de travail inutile aurait ´et´e beaucoup plus importante. En revanche si, dans notre exemple, les trois cases du tableau avaient 27
  • 28. 1: mov 1,%indice boucle: 2: mul %indice,10,%valeur 3: store %valeur,[%indice+@tab-1] 4: add %indice,1,%indice 5: cmp 4,%indice 6: bne boucle 7: load [@tab+2],%valeur 8: print %valeur Code en assembleur RISC (code statique) Dépendances de données permettant d’identifier le travail utile (arcs du graphe parcourus par l’algorithme). Dépendance de donnée n’étant pas parcourues par l'algorithme. Trace d’exécution des instructions (dynamique) 1ère itération de la boucle 2ème itération de la boucle 3ème itération de la boucle Numéro Dynamique Numéro Statique 123456789 10 11 12 13 14 15 16 17 18 123456234562345678 n Numéro d’instruction statique utile par essence (instructions de sorties ou de branchement). n Numéro d’instruction statique utile après parcours du graphe de dépendance (définition récursive). n Numéro d’instruction dynamique (indique l’ordre d’éxécution des instructions dans le temps) n Numéro d’instruction statique jugés comme étant inutile d’après la définition (instruction n’appartenant pas au graphe de dépendance de données). Compilation Pour i de 1 à 3 faire t[i] := i*10; Finpour Ecrire (t[2]); Code source original Fig. 2.3 – Du code source en langage de haut niveau au graphe de d´ependance de donn´ee dynamique ´et´e affich´ees (instruction print), la quantit´e de travail inutile aurait ´et´e nulle. Un exemple plus complet montrant dans le d´etail comment l’algorithme a ´et´e impl´ement´e est en annexe (figure 3.2 page 59). 28
  • 29. 2.3 L’environnement de travail : Les choix de mise en oeuvre 2.3.1 Les Outils Pour la mise au point de notre programme d’´evaluation de la quantit´e de travail inutile, plusieurs outils ont ´et´e mis `a contribution : - Salto : Salto est une biblioth`eque de fonctions permettant d’analyser du code source en assembleur pour en extraire les informations s´emantiques sous une forme exploitable en C++. Ces informations peuvent ˆetre de diff´erentes natures : Il est possible de connaˆıtre le d´ecoupage en blocs de base du code source, les ressources utilis´ees par une instruction pr´ecise (dans notre cas, ce qui nous int´eresse sont les acc`es `a la m´emoire et aux diff´erents registres). De plus, une des fonctionnalit´e indispensable `a notre r´ealisation disponible dans Salto est la possibilit´e d’instrumenter le code source (figure 2.4 page suivante). - Le compilateur GCC pour processeur Sparc : Compilateur C/C++ gratuit sous licence GNU. - Le compilateur CC pour processeur Sparc : Compilateur C propri´etaire de Sun disponible seulement pour la plateforme Sparc. - Les expressions r´eguli`eres en C. 2.3.2 L’instrumentation L’instrumentation c’est quoi ? L’instrumentation d’instruction est un m´ecanisme qui consiste `a ins´erer des instructions suppl´e-mentaires entre les instructions du code source d’un programme d´ej`a ´etabli afin « d’ausculter » ce dernier. Les informations qu’il est possible de r´ecup´erer par ce m´ecanisme sont de nature dynamique puisque les instructions rajout´ees par instrumentation sont ex´ecut´ees autant de fois que le sont les instructions appartenant au code source d’origine. Prenons comme exemple le cas d’une boucle dont le corps est ex´ecut´e n fois, alors le code rajout´e par instrumentation du code source d’origine dans le corps de cette boucle sera lui aussi ex´ecut´e n fois. Ceci permet de savoir de fa¸con pr´ecise quelles sont les instructions statiques qui ont ´et´e ex´ecut´ees par le processeur s´equentiellement. De plus, l’instrumentation permet de r´ecup´erer d’autres informations dynamiques comme les adresses des acc`es `a la m´emoire. Dans l’exemple de la figure 2.4 page suivante, le code source original est instrument´e afin de r´ecup´erer la valeur du r´esultat produit par l’instruction `a instrumenter et pour le traiter dans la fonction fct (tmp ´etant par exemple un registre de d´ebuggage dont le code source original ne fait jamais usage mais qui peut ˆetre utilis´e par la fonction fct pour effectuer son traitement). 29
  • 30. mov r1,r2 add r2,3,r2 store r2,[a0] Code source mov r1,r2 mov r2,tmp call fct add r2,3,r2 mov r2,tmp call fct store r2,[a0] load [a0],tmp call fct Code source instrumenté instrumentation Fig. 2.4 – Instrumentation de code source en assembleur Note Dans l’exemple de la figure 2.4, les instructions sont instrument´ees apr`es leur ex´ecution, ce qui n’est pas le cas dans notre impl´ementation : l’instrumentation se trouve avant l’ex´ecution de l’instruction pour des raisons de suivi des branchements (pour pouvoir instrumenter correctement les branchements, il est n´ecessaire de placer le code d’instrumentation avant ceux-ci). L’instrumentation dans notre programme L’instrumentation, dans le cas g´en´eral, permet d’ins´erer des instructions dans un programme. A partir de ce concept simple, nous avons d´ecid´e d’utiliser l’instrumentation pour ins´erer des appels de fonctions (´ecrites en C et compil´ees par ailleurs). De fait, les appels de fonctions en assembleur ne faisant pas de sauvegarde des registres globaux (accessible de n’importe o`u dans le programme). Il nous a fallu ajouter `a cette instrumentation une sauvegarde de contexte avant l’appel `a cette fonction puis une restauration apr`es (figure 2.5 page suivante). Mais ce n’est pas tout : Chaque instruction assembleur ayant un nombre variable d’op´erandes et de r´esultats, il nous a fallu ajouter une instruction d’appel `a une fonction pour chaque op´erande et pour chaque r´esultat. De plus, chaque acc`es `a la m´emoire n´ecessitant la r´ecup´eration de l’adresse de cet acc`es, il nous a fallu r´ecup´erer des informations sur la valeur des registres utilis´es par l’instruction `a instrumenter afin de savoir quelle ´etait l’adresse de cet acc`es m´emoire. L’instrumentation d’une instruction dans notre programme d’´evaluation de la quantit´e de travail inutile peut-ˆetre r´esum´ee en sept phases : – Sauvegarde : Une phase de sauvegarde du contexte (registres globaux, d´ecalage de la fenˆetre de registres. . .). – D´ebut : Une phase de cr´eation de la structure de donn´ee repr´esentant une instruction (fi-gure 2.1 page 24). – Op´erandes : Une phase permettant de cr´eer les arcs vers les instructions ayant ´ecrit en dernier dans les ressources op´erandes de l’instruction. 30
  • 31. inst1 inst2 inst3 Code source sauvegarde call fct restauration inst1 sauvegarde call fct restauration inst2 sauvegarde call fct restauration inst3 Code source instrumenté instrumentation Fig. 2.5 – Principe de l’instrumentation faite par le programme d’´evaluation de la quantit´e de travail inutile – Milieu : Une phase, utile seulement pour les instruction « save » et « restore », permettant de mettre `a jour le niveau de la fenˆetre de registres. – R´esultats : Une phase permettant de mettre `a jour l’´etat des ressources en fonction des r´esultats produits par l’instruction. – Fin : Une phase permettant d’´evaluer l’utilit´e de l’instruction courante. Si cette derni`ere est utile, on parcour son arbre de d´ependance de donn´ee. – Restauration : Une phase de restauration du contexte. 2.3.3 Le choix de la Plateforme Pour choisir notre plateforme de travail, nous avons pris en compte plusieurs param`etres. Nous avions le choix entre le jeu d’instruction x86 (CISC) et le jeu d’instruction Sparc (RISC). En premier lieu, l’outil mis `a notre disposition (Salto) semblait plus adapt´e `a un jeu d’instruction r´eduit. En effet, Salto ´etant bas´e sur la reconnaissance des instructions assembleur par des expressions r´eguli`eres, il est tr`es difficile de supporter un jeu d’instruction aussi vaste que le x86 d’Intel (CISC). De fait, le support d’un tel jeu d’instruction par Salto est apparu comme ´etant insuffisant. De plus, le travail `a effectuer ´etant, entre autre, d’identifier les acc`es `a la m´emoire, un jeu d’instruction r´eduit avec seulement une instruction pour le chargement et une pour le rangement en m´emoire nous est apparu plus simple `a manipuler. Cependant, le Sparc poss`ede quelques inconv´enients qui, nous le verrons plus loin, ne nous ont pas facilit´e la tˆache. Nous avons donc d´ecid´e de travailler avec un jeu d’instruction RISC pleinement support´e par Salto : le Sparc de Sun. 31
  • 32. 2.3.4 SPARC : Le Meilleur des Mondes ? Le Sparc est une architecture RISC assez classique ce qui signifie que le nombre d’instructions est assez r´eduit, qu’elles ont toutes la mˆeme taille (quatre octets pour le Sparc) et que, chose relativement importante pour notre impl´ementation, les instructions d’acc`es `a la m´emoire sont au nombre de deux (load pour charger une valeur de la m´emoire vers un registre et store pour ranger une valeur d’un registre vers la m´emoire). Tout aurait ´et´e parfait si la description du Sparc s’´etait arrˆet´ee l`a. . . - Le delay slot est une des particularit´es de l’architecture Sparc. Il s’agit d’ex´ecuter l’instruc-tion qui suit imm´ediatement une instruction de branchement avant que cette instruction de branchement ne modifie le flot de contrˆole de l’ex´ecution du programme. Pour r´esumer, l’ins-truction qui se trouve dans le delay slot d’un branchement (elle se trouve juste apr`es dans le code source) se comporte comme si elle se trouvait avant le branchement pour ce qui est du contrˆole mais comme si elle ´etait apr`es pour ce qui est des donn´ees. - L’annul bit est une autre particularit´e « amusante » du Sparc qui est en relation directe avec le delay slot. Lorsqu’une instruction se trouve dans le delay slot d’un branchement dont l’annul bit est activ´e, (be,a : la virgule et le a indique que l’annul bit est activ´e) cette instruction ne s’ex´ecute que lorsque le branchement est pris. Dans le cas contraire, l’instruction se trouvant dans le delay slot n’est pas ex´ecut´ee (on dit qu’elle est annul´ee). - La fenˆetre de registres tournante est une fa¸con de pallier `a la lenteur des acc`es `a la pile lors du passage de param`etres `a une fonction. En effet, le Sparc se propose de r´esoudre le probl`eme du passage de param`etres `a une fonction de mani`ere originale au moyen de cette fenˆetre de registres tournante. Il s’agit de ranger les valeurs que l’on souhaite passer en param`etres `a la fonction qui va ˆetre appel´ee dans des registres sp´eciaux nomm´es registres de sortie (%o0 `a %o5) qui, une fois la fonction appel´ee, seront renomm´es en registres d’entr´ee (%i0 `a %i5) (cf. figure 2.6 page suivante). De cette fa¸con, la fonction appel´ee peut se servir de ces valeurs sans qu’elles n’aient ´et´e recopi´ees dans une quelconque pile (`a l’exception du cas o`u la taille de la fenˆetre de registres tournante n’est pas suffisante). Le delay slot Dans notre impl´ementation, nous avons du prendre en compte cette particularit´e de l’archi-tecture Sparc. En effet, afin d’instrumenter les instructions se trouvant dans le delay slot d’un branchement, nous avons du utiliser diff´erentes techniques consistant `a « remonter » notre instru-mentation de ce type d’instructions avant le branchement. Ceci `a conduit `a pas mal de probl`emes de coh´erence entre la repr´esentation des instructions cr´e´ees par l’instrumentation et les instructions r´eellement ex´ecut´ees. Mais le cas o`u le delay slot nous a pos´e le plus de probl`eme est celui o`u il nous a fallu ajouter des sauts afin d’´eviter l’ex´ecution de certaines instructions. En effet, dans ce cas, si l’instruction que l’on veut « sauter » se trouve dans le delay slot d’un branchement, il faut dupliquer cette instruction des branchement : mettre dans le code source une version normale avec l’instruction qui se trouvait dans son delay slot dans le code source d’origine et une seconde version du mˆeme branchement contenant un nop dans son delay slot. De cette fa¸con, selon que l’instruction se trouvant dans le 32
  • 33. delay slot de ce branchement doit ˆetre ex´ecut´ee ou non, le flot de contrˆole est aiguill´ee vers l’une ou l’autre des deux versions de ce branchement. Il faut ensuite faire converger les deux versions en un mˆeme point repr´esentant la suite du programme. La fenˆetre de registres du Sparc La fenˆetre de registre tournante est une des particularit´e du processeur Sparc. Nous allons en expliquer rapidement le principe afin d’exposer la mani`ere dont nous avons trait´e cette particularit´e dans notre programme. Registres de sortie %o0 à %o7 Registres locaux %l0 à %l7 Registres d’entrée %i0 à %i7 Registres accessibles au niveau n+1 niveau n Registres de sortie %o0 à %o7 Registres locaux %l0 à %l7 Registres d’entrée %i0 à %i7 Désigne les mêmes registres physiques Registres de sortie %o0 à %o7 Registres locaux %l0 à %l7 Registres d’entrée %i0 à %i7 niveau n+2 Désigne les mêmes registres physiques L’instruction « save » permet de passer d’un niveau n `a un niveau n+1 (utilis´e g´en´eralement comme une sauvegarde de contexte avec en plus la possibilit´e de passer des param`etres d’un contexte `a l’autre au niveau de la zone de recouvrement de la fenˆetre n et n+1). L’instruction « restore » permet de passer d’un niveau n `a un niveau n-1 (utilis´e g´en´eralement comme une restauration de contexte avec en plus la possibilit´e de passer des r´esultats d’un contexte `a l’autre au niveau de la zone de recouvrement de la fenˆetre n et n-1). Fig. 2.6 – Le principe de la fenˆetre de registres du Sparc Lorsque le nombre de registres utilis´es d´epasse le nombre de registres physiques r´eellement pr´esents dans le processeur, un m´ecanisme invisible pour l’utilisateur utilise une pile en m´emoire pour sauvegarder la fenˆetre de registres la plus ancienne et r´eutiliser ainsi cette derni`ere comme une nouvelle fenˆetre vierge. De cette fa¸con, le nombre de registres virtuellement utilisables par l’utilisateur n’est limit´e que par la taille de la pile et non par la taille du fichier de registres dans le processeur. Cette fenˆetre est souvent repr´esent´ee, dans les diff´erentes documentations sur le Sparc, de fa¸con circulaire pour montrer que la plus ancienne fenˆetre et la plus r´ecente peuvent se recouvrir si le nombre de fenˆetres disponibles dans le fichier de registres est insuffisant pour l’ex´ecution d’un programme donn´e. 33
  • 34. 2.3.5 S’affranchir de la num´erotation des registres faite par Salto Les registres du Sparc s’organisent en deux parties. D’une part, des registres dit globaux qui se comportent de mani`ere classique, et d’autre part une fenˆetre de registres coulissante comme d´ecrit sur la figure 2.6 page pr´ec´edente. Pour les registres globaux, nous avons utilis´e la num´erotation propos´ee par Salto qui convenait tout `a fait ´etant donn´e qu’un nom de registre d´esigne toujours le mˆeme registre physique. En revanche, pour la fenˆetre de registres coulissante, nous avons du mettre en place notre propre syst`eme d’identification de registres : En effet, Salto ´etant un outil qui travaille sur du code assembleur, il lui est impossible d’avoir acc`es `a des informations concernant l’ex´ecution du programme (les seules informations disponible au niveau de Salto sont les informations statiques sur le programme). De fait, les informations que nous donne Salto concernant les acc`es aux registres sont les noms de ces registres. Il lui est impossible de connaˆıtre le niveau de la fenˆetre de registre en un point donn´e du code et donc de d´esigner un registre physique de mani`ere unique. Afin d’identifier de mani`ere unique chacun des registres physiques, il a donc fallu s’affranchir du syst`eme de num´erotation des registres propos´e par Salto pour le remplacer par un calcul fait de mani`ere dynamique (au cours de l’ex´ecution du programme) permettant de savoir `a quel registre physique correspondait chaque acc`es `a un registre appartenant `a la fenˆetre de registre courante. Pour ce faire, nous avons instrument´e les instructions save qui d´ecalent la fenˆetre de registre vers le haut et les instructions restore qui d´ecalent la fenˆetre de registre vers le bas (cf. figure 2.6 page pr´ec´edente). De cette fa¸con, il est possible de tenir `a jour une variable globale indiquant le niveau actuel de la fenˆetre de registre. En utilisant ce niveau comme d´ecalage par rapport `a un point de r´ef´erence, (la premi`ere fenˆetre disponible lors du lancement du programme) il est possible de savoir dans quelle fenˆetre de registre seront fait les acc`es aux registres de la fenˆetre courante indiqu´es par Salto. Grˆace `a cette m´ethode, il est possible d’identifier de mani`ere unique chacun des registres d’une fenˆetre pr´ecise mˆeme si celle-ci peut avoir ´et´e sauvegard´ee dans la pile par manque de place dans le fichier de registres. Les acc`es `a ces registres restent ce qu’ils sont puisque cette op´eration est transparente pour l’utilisateur du processeur (en l’occurrence notre programme). 2.3.6 Les expressions r´eguli`eres L’utilisation des expressions r´eguli`eres est particuli`erement utile pour analyser une chaˆıne de caract`eres ayant un motif fixe et une partie variable. C’est justement le cas d’une instruction assembleur dont la partie fixe est le mn´emonique de cette instruction et dont les parties variables sont les arguments. De cette fa¸con, nous avons utilis´e les expressions r´eguli`eres pour « d´ecouper » les instructions load et store en plusieurs parties : le mn´emonique d’une part (permettant de connaˆıtre la taille de l’acc`es `a la m´emoire : octet, mot, double mot ou quadruple mot) et les arguments d’autre part. Une 34
  • 35. fois chaque argument r´ecup´er´e, il est possible d’acc´eder aux valeurs contenues dans les registres et aux ´eventuelles constantes. Il est donc possible de connaˆıtre de fa¸con exacte `a quelle adresse m´emoire va acc´eder l’instruction et `a combien d’octets elle va acc´eder. De plus, les expressions r´eguli`eres nous ont ´et´e utiles pour r´ecup´erer les ´etiquettes des appels de fonctions afin de savoir si ces fonctions ´etaient d´efinies en local (dans le code source du pro-gramme ´etudi´e) ou si elles appartenaient `a une biblioth`eque externe au programme (stdio en C par exemple). 2.3.7 La gestion des fonctions Une fois notre d´efinition impl´ement´ee et test´ee, il reste encore de nombreux probl`emes `a r´esoudre pour pouvoir confronter cet algorithme au « monde r´eel » (`a des programmes classiques tel que gzip). En effet, ce mod`ele th´eorique serait parfait si l’ensemble du code source assembleur d’une application ´etait visible par le programme d’´evaluation. Or les programmes classiques utilisent des fonctions d´efinies dans des biblioth`eques dont on n’a pas le code source (Un programme en C travaillant sur des fichiers utilisera par exemple stdio pour lire et ´ecrire dans un fichier). Afin de r´egler cette difficult´e, nous avons du utiliser l’options de compilation -SO de cc permettant de savoir quels sont les registres du Sparc et les adresses m´emoires utilis´ees dans la pile comme param`etres lors de l’appel `a une fonction. Ainsi, il nous a ´et´e possible de rajouter « artificiellement » des arcs de d´ependance entre l’appel `a une fonction d´efinie dans une biblioth`eque externe (call printf par exemple) et les param`etres pass´es `a cette fonction. Pour cette raison, cc pour Sparc est apparu comme ´etant id´eal dans notre protocole de test. Afin de r´esoudre ce probl`eme, les fonctions appel´ees par le programme ´etudi´e ont ´et´e class´ees en trois cat´egories, chacune correspondant `a un traitement particulier `a faire pour les prendre en compte correctement : Les fonctions « internes » Les fonctions internes sont les fonctions dont le code source est disponible (peut-ˆetre utilis´e par notre programme d’´evaluation). Les appels `a ce type de fonctions peuvent donc ˆetre trait´es comme de simple branchements inconditionnels puisque les arcs du graphe de d´ependance peuvent tr`es bien relier une instruction appartenant `a cette fonction `a une instruction appartenant au programme appelant. Le graphe de d´ependance de donn´ee n’est donc pas interrompu par un tel appel de fonction. Les fonctions « externes » utilisant des pointeurs Les fonctions externes sont les fonctions dont le code source n’est pas disponible (code source d’une biblioth`eque d’entr´ee/sortie par exemple). Dans ces cas l`a, il est n´ecessaire de consid´erer que les param`etres pass´es `a la fonction sont lus par l’instruction d’appel de la fonction et que le r´esultat 35
  • 36. est ´ecrit par cette instruction. Cependant, dans le cas g´en´eral, il est n´ecessaire de d´etourner l’appel `a une telle fonction pour faire ajouter « artificiellement » des arcs de d´ependance de donn´ee pour traiter les donn´ees qui vont ˆetre lues et ´ecrites `a l’int´erieur de cette fonction. En effet, notre programme est incapable de connaˆıtre le type des param`etres d’une fonction (si il s’agit d’entiers, de pointeurs. . .) et donc, de savoir si une fonction d´efinie dans une biblioth`eque dont on n’a pas le code source acc`ede ou non `a une zone m´emoire dont l’adresse est un de ses param`etres. De plus, mˆeme en sachant qu’un param`etre est un pointeur, rien ne dit si la fonction dont on n’a pas le code source va y acc´eder en lecture, en ´ecriture ou pire encore, `a combien d’´el´ements elle va acc´eder ! (Il ne faut pas oublier qu’en C les tableaux sont implicites et que, par cons´equent, on ne connaˆıt pas leur taille simplement en connaissant l’adresse de leur premier ´el´ement). Afin de r´egler cette difficult´e, nous avons choisi de d´etourner les appels `a ces fonctions (au nombre de trente cinq dans gzip) afin de leur faire ex´ecuter du code permettant de simuler leur comportement en mati`ere d’acc`es `a la m´emoire. Ces fonctions sont, le plus souvent des fonctions d’entr´ees/sorties (ex : read, write, fflush. . .), des fonctions de lecture/´ecriture dans des chaˆınes de caract`eres (ex : strcat, strcpy, strcmp. . .) ou des fonctions de lecture/´ecriture de zones m´emoire en g´en´eral (ex : memset, memcpy, memcmp. . .). Exemple simple : char *my_strcpy(char *c1, const char *c2) { /* On simule un acc`es en lecture `a une zone m´emoire d´ebutant `a l’adresse contenue dans le pointeur c2 et de longueur strlen(c2)+1 (taille de la cha^ıne de caract`ere `a lire avec son terminateur) */ instrumentationEntreeMemoire((int)c2, strlen(c2)+1); /* On simule un acc`es en ´ecriture `a une zone m´emoire d´ebutant `a l’adresse contenue dans le pointeur c1 et de longueur strlen(c2)+1 (taille de la cha^ıne de caract`ere `a copier avec son terminateur) */ instrumentationSortieMemoire((int)c1, strlen(c2)+1); /* On retourne la valeur retourn´ee par la vraie fonction strcpy */ return strcpy(c1, c2); } Les fonctions « externes » n’utilisant pas de pointeurs Les fonctions externes n’utilisant pas de pointeurs sont des fonctions dites externes d’apr`es la d´efinition ci-dessus `a la diff´erence qu’elles ne font pas d’acc`es `a la m´emoire `a partir de pointeur. Elles peuvent donc ˆetre trait´ees simplement en consid´erant que les param`etres pass´es `a la fonction sont lus et que le r´esultat est ´ecrit. 36
  • 37. 2.4 R´esultats & Analyse 2.4.1 Les chiffres. . . Une fois l’´evaluation de la quantit´e de travail inutile effectu´ee de cette mani`ere, nous obtenons les chiffres suivants (cf. figure 2.7). gzipa gzipb gzipc O0d 11.03 % 9.53 % 11.03 % O1 12.05 % 10.73 % 16.44 % O2 11.40 % 10.28 % 16.17 % O3 12.77 % 12.10 % 21.83 % O4 12.66 % 12.55 % 23.35 % O5 12.66 % 12.55 % 23.35 % gunzipe gunzipf gunzipg O0 1.09 % 1.14 % 0.21 % O1 2.94 % 3.10 % 0.29 % O2 3.51 % 4.28 % 0.41 % O3 10.01 % 10.51 % 0.47 % O4 9.83 % 10.26 % 0.52 % O5 9.83 % 10.26 % 0.52 % aCompression d’un fichier texte (RTF) de 2127 octets avec gzip (fort taux de compression (facteur : 1.9)) bCompression d’un fichier image (GIF) de 1704 octets avec gzip (faible taux de compression (facteur : 1.4)) cRe-compression d’un fichier compress´e par gzip de 1506 octets avec gzip (taux de compression nul (facteur : 0.98)) dSeuls ces r´esultats ont ´et´e valid´es avec le programme de v´erification pour des raisons d’impl´ementation eD´ecompression du fichier texte de 2127 octets fD´ecompression du fichier image de 1704 octets gD´ecompression du fichier compress´e deux fois par gzip de 1506 octets Conditions de test : gzip version 1.2.4 recompil´e avec cc de Sun pour le processeur Sparc version v8plus. Ces chiffres s’entendent en ne comptant pas les ´eventuelles instructions nop qui se trouvent dans le delay slot de certaines instructions de branchement. Fig. 2.7 – Quantit´e d’instructions assembleurs inutiles lors de l’ex´ecution de gzip dans diff´erentes conditions 2.4.2 Le doute. . . Introduction Ces chiffres n’´etant qu’une ´evaluation, rien ne permet de dire avec certitude que ce travail est effectivement inutile. D’autant plus que l’impl´ementation laisse souvent apparaˆıtre des failles que l’on n’imagine pas lorsqu’on raisonne de fa¸con abstraite sur les d´ependances de donn´ees (la gestion des fonctions dont on n’a pas le code source en est un exemple). Afin de valider notre programme et d’avoir la certitude que le travail inutile ´evalu´e en ´etait bien, nous avons mis au point un second programme r´e-ex´ecutant exactement le mˆeme programme de test (gzip dans notre cas) sur le mˆeme jeu de donn´ees (avec le mˆeme fichier en entr´ee) en n’ex´ecutant pas les instructions qui avaient ´et´e jug´ees comme ´etant inutiles lors de la premi`ere ex´ecution. Ainsi, si la seconde ex´ecution donne rigoureusement le mˆeme r´esultat que la premi`ere (le mˆeme fichier compress´e dans le cas de gzip), nous pouvons dire que les deux ex´ecutions sont ´equivalentes et que, par cons´equent, les instructions qui n’ont pas ´et´e ex´ecut´ees lors de la seconde ex´ecution n’´etaient effectivement pas utiles. 37
  • 38. somewhere : sub r3,r4,r5 ... mov r1,r2 add r2,3,r2 cmp 0,r2 be somewhere store r2,(a0) ... Code source mov r1,r2 add r2,3,r2 cmp 0,r2 be somewhere sub r3,r4,r5 ... Trace dynamique de la première exécution (détection du travail inutile) mov r1,r2 add r2,3,r2 cmp 0,r2 be somewhere store r2,(a0) ... Trace dynamique de la deuxième exécution (non exécution du travail inutile) L'instruction add est jugée inutile : elle ne sera donc pas exécutée lors de la seconde exécution Fig. 2.8 – Mise en ´evidence d’un probl`eme d’impl´ementation par divergence du flot de contrˆole Note Reproduire une ex´ecution `a l’identique ne fonctionne que sur un programme d´eterministe : deux ex´ecutions successives sur un mˆeme jeu de donn´ee doivent s’ex´ecuter rigoureusement de la mˆeme mani`ere. De fait, il serait complexe de traiter des programmes utilisant des fonctions de tirages al´eatoires ou conservant des informations d’une ex´ecution sur l’autre (cache dans un fichier par exemple). Ce n’est pas le cas de gzip ce qui nous a permis de mener nos tests de fa¸con correcte sur ce programme. L’int´erˆet Un aspect tr`es int´eressant de l’utilisation de ce programme de v´erification est qu’il a permis d’affiner le programme d’´evaluation de la quantit´e de travail inutile. En effet, en observant les divergences entre la premi`ere et la seconde ex´ecution (figure 2.8), il a ´et´e possible de trouver les points faibles du programme d’´evaluation de la quantit´e de travail inutile et de les consolider afin de rendre les deux ex´ecutions ´equivalentes. Par exemple, lorsque la seconde ex´ecution du programme de test divergeait de la premi`ere (un branchement pris alors qu’il n’aurait pas du par exemple), cela signifiait qu’une instruction utile au flot de contrˆole avait ´etait jug´ee comme ´etant inutile `a tort. De cette mani`ere, il a ´et´e possible de trouver les incorrections du programme d’´evaluation du travail inutile et surtout de mettre en lumi`ere les lacunes d’une impl´ementation trop « na¨ıve » par rapport aux appels de fonctions d´efinies dans des biblioth`eques dont le code source n’est pas disponible. Dans l’exemple de la figure 2.8, le branchement be (branch if equal) est pris lors de la premi`ere ex´ecution alors qu’il n’est pas pris lors de la seconde, ce qui entraˆıne une incoh´erence entre les deux 38
  • 39. ex´ecutions qui ne sont alors plus ´equivalentes. Ceci se produit en raison d’un mauvais jugement port´e sur l’instruction add. En effet, celle-ci est utile au bon d´eroulement du programme alors qu’elle a ´et´e jug´ee comme ne l’´etant pas par le programme de d´etection du travail inutile. Grˆace `a ce syst`eme, il est facile de corriger les incorrections et impr´ecisions que comporte le programme de d´etection du travail inutile. Par processus incr´emental, il est alors possible de corriger ces erreurs une `a une jusqu’`a l’obtention d’un programme qui ne juge inutile que du travail r´eellement inutile (Ce qui ne prouve pas pour autant qu’il d´etecte tout le travail inutile que peut comporter un programme). La M´ethode Pour pouvoir mettre au point ce deuxi`eme programme, il faut tout d’abord que le programme d’´evaluation de la quantit´e de travail inutile laisse une trace des instructions inutiles dans un fichier qui sera utilis´e par le programme de v´erification. Pour la mise au point de ce programme de v´erification, Salto a, l`a encore, ´et´e sollicit´e afin d’instrumenter chaque instruction. Lorsque cette instruction est jug´ee inutile (d’apr`es la trace de la premi`ere ex´ecution) alors cette instruction est saut´ee au moyen d’un jump d’une valeur constante puisque, dans les processeurs Sparc, toutes les instructions ont une taille de quatre octets (« merci » les jeux d’instructions RISC). De cette fa¸con, il est assez facile de « sauter » une instruction lorsqu’elle apparaˆıt dans la trace des instructions inutiles. Conclusion Ce programme `a permis, sur des exemples simples, de v´erifier que la quantit´e de travail inutile ´evalu´ee ´etait bien du travail inutile quelque soit le niveau d’optimisation utilis´e et les cas de figure rencontr´es. Cependant, par manque de temps, nous n’avons r´eussi `a le faire fonctionner que sur gzip compil´e avec un niveau d’optimisation de 0. N´eanmoins, cette v´erification nous `a permis d’accroˆıtre la confiance en nos r´esultats (figures 2.7 page 37 et 2.9 page suivante). 2.4.3 La r´epartition du travail inutile Une fois les informations sur le travail inutile lors de l’ex´ecution d’un programme r´ecup´er´ees, il est n´ecessaire de les organiser afin de pouvoir analyser d’ou provient ce travail inutile. Dans un premier temps, nous avons essay´e de voir `a quelles instructions statiques correspondaient nos instructions dynamiques inutiles. Nous avons trouv´e, sans surprise ´etant donn´e les r´esultats de l’article [1], que seul un petit nombre d’instructions statiques ´etaient concern´ees. Ce qui signifie que la plupart des instructions dynamiques inutiles sont concentr´ees sur un nombre d’instructions statiques r´eduit (de l’ordre de 12.4 % des instructions statiques totales g´en`erent au moins une instance dynamique inutile). Une fois ces instructions statiques en assembleur identifi´ees, nous avons cherch´e `a « remonter », lorsque c’´etait possible, au code source en C correspondant afin de mieux comprendre la raison pour laquelle ce travail est jug´e comme ´etant inutile par notre d´efinition. 39
  • 40. 108876.0 90730.0 72584.0 54438.0 36292.0 18146.0 0.0 Compression d’un fichier RTF de 2127 octets Algorithme GZIP compile avec cc et un niveau d’optimisation de 0 0.0 268685.0 537370.0 806055.0 1074740.0 (a) Sans optimisations de compilation 53388.0 44490.0 35592.0 26694.0 17796.0 8898.0 0.0 Compression d’un fichier RTF de 2127 octets Algorithme GZIP compile avec cc et un niveau d’optimisation de 5 0.0 105695.0 211390.0 317085.0 422780.0 (b) Avec optimisations de compilation Abscisse : Num´ero d’instruction dynamiques : repr´esente le temps ´ecoul´e en nombre d’instructions Ordonn´ee : Quantit´e d’instructions inutiles (cumul´ees) Fig. 2.9 – ´Evolution de la quantit´e de travail inutile en fonction du temps Travail inutile algorithmique Introduction En observant les courbes de la figure 2.9 on s’aper¸coit que l’algorithme de gzip, dans nos conditions de test, se d´ecompose en plusieurs phases g´en´erant chacune des quantit´es de travail inutile diff´erentes. En premier lieu, il est int´eressant de noter que la phase d’initialisation comporte une grande proportion de travail inutile (presque 50 % avec un niveau d’optimisation de 0 et plus de 50 % avec un niveau de 5). Ensuite, vient une courte phase durant laquelle aucun travail inutile n’est pr´esent (quelque soit le niveau d’optimisation). Vient ensuite un ensemble de phases que nous appellerons le coeur de l’algorithme durant lequel on observe une quantit´e de travail inutile moyen non n´egligeable avec un niveau d’optimisation de 0 (de l’ordre de 6,9 %) et plus important encore avec un niveau d’optimisation de 5 (de l’ordre de 9,9 %). La phase d’initialisation Dans certains cas, le travail inutile semble ˆetre d’origine algorith-mique. En effet, en observant le code source en C de gzip, il apparaˆıt parfois du travail inutile qu’il serait simple d’´eviter en modifiant une petite partie du code. De fait, nous pouvons dire que ce travail inutile est inh´erent `a la fa¸con dont l’algorithme de gzip est impl´ement´e. De plus, ´etant donn´e une tr`es forte proportion de travail inutile durant la phase d’initialisation des structures de donn´ees utiles `a l’algorithme de gzip (aux alentours de 50%), il semble raisonnable de penser qu’une tr`es grande partie de ces structures de donn´ees sont initialis´ees puis jamais utilis´ees ou r´eutilis´ees pour ˆetre ´ecrites (ce qui g´en`ere des valeurs mortes). Ce type de travail inutile semble 40
  • 41. ˆetre r´eellement inh´erent `a l’algorithme et non du `a une mauvaise impl´ementation de celui-ci. Exemple simple : Dans la fonction local void gen codes (tree, max code), on observe que le code source suivant est inutile la plupart du temps (lors de l’ex´ecution sur un fichier de test) : for (bits = 1; bits <= MAX_BITS; bits++) { next_code[bits] = code = (code + bl_count[bits-1]) << 1; } L’affectation dans le tableau next code est inutile 52 fois sur 60 dans l’exemple test´e (le nombre d’it´erations de la boucle est MAX BITS et est ´egal `a 60). Le fait que cette affectation soit inutile un certain nombre de fois engendre qu’une partie des calculs fait dans la boucle devient inutile. Ce qui nous donne, pour l’ensemble de la boucle, un nombre de 824 instructions inutiles pour 1440 au total (soit une proportion de 57 %). Etant donn´e ces r´esultats, il est int´eressant de se pencher sur le cas de l’initialisation des structures de donn´ees en g´en´eral. En effet, le premier r´eflexe d’un programmeur, lorsqu’il d´eclare une structure de donn´ee (tableau, liste. . .) est de l’initialiser pour ´eviter, par la suite, d’y faire un acc`es en lecture sans y avoir pr´ealablement rang´e une valeur. Or ce r´eflexe de programmation est probablement ce que nous observons ici ´etant donn´e que les structures de donn´ees de gzip n’´echappent apparemment pas `a cette r`egle. Le coeur de l’algorithme Au coeur de l’algorithme, nous observons diff´erents cas d’instructions dynamiques inutiles. Parfois, nous observons que le travail inutile est du `a l’initialisation de va-riables locales dont le contenu est, la plupart du temps, r´e-´ecrit avant d’ˆetre lu. Parfois, il s’agit de param`etres pass´es `a une fonction et qui ne servent que dans certaines conditions. Et enfin, un cas assez fr´equent ´egalement est celui des variables globales qui sont maintenues `a jour de fa¸con inutile. En effet, si une telle variable refl`ete une valeur lors du dernier passage dans une certaine fonction, il est possible que cette fonction soit appel´ee plusieurs fois sans que cette valeur n’ai ´et´e lue entre temps. Exemples : L’affectation prev match = match start ; peut-ˆetre inutile car la seule utilisation de la variable prev match en lecture est le cas suivant : if (prev_length >= MIN_MATCH && match_length <= prev_length) { check_match(strstart-1, prev_match, prev_length); flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH); ... } 41
  • 42. Ce qui signifie que lorsque la condition ci-dessus sera fausse, l’affectation de la variable prev match sera inutile (c’est le cas 78 fois 82 dans notre test). En supposant que le calcul de la valeur de la variable match start puisse ˆetre coˆuteux, et que cette variable ne soit pas r´e-utilis´ee en lecture entre temps, on prend conscience de la port´ee que peut avoir le travail inutile. Note Dans l’exemple pr´ec´edent, il est int´eressant de noter que le d´eplacement de l’instruction d’affec-tation prev match = match start ; dans le corps de la conditionnelle aurait suffit `a ´eliminer ce travail inutile (dans la mesure o`u on ne fait pas d’´ecriture dans match start entre temps). En effet, la variable prev match n’´etant utilis´ee que dans ce bloc, il est inutile de faire cette affectation si la condition n’est pas vraie. Une macro un peu particuli`ere a ´egalement retenu notre attention. Elle se trouve au coeur de l’algorithme de compression, dans la fonction deflate(). Il s’agit de la macro INSERT STRING qui ins`ere une chaˆıne de caract`ere dans la liste des chaˆınes de caract`eres qu’utilise gzip pour trouver les chaˆınes les plus fr´equemment pr´esentes dans le fichier `a compresser. Voici le code de cette macro apr`es passage du pr´e-processeur : ((ins_h = (((ins_h)<<((15+3-1)/3)) ^ ( window[(strstart) + 3-1])) & ((unsigned)(1<<15)-1)), prev[(strstart) & (0x8000-1)] = hash_head = (prev+0x8000)[ins_h], (prev+0x8000)[ins_h] = (strstart)); Pour des raisons de lisibilit´e, nous avons r´e-´ecrit ce code : ins_h = ( ins_h<<5 ^ window[strstart+2] & (unsigned)(1<<15)-1 ); hash_head = (prev+0x8000)[ins_h]; prev[strstart & (0x8000-1)] = hash_head; (prev+0x8000)[ins_h] = strstart; Dans cette macro, qui se trouve au coeur de l’algorithme de compression, les deux derni`eres instructions (remplissage du tableau prev) se trouvent ˆetre tr`es souvent inutile (77 fois sur 82 dans notre exemple). Ceci tend `a montrer que l’algorithme de compression utilis´e par gzip contient, par nature, du travail inutile. Travail inutile introduit par le compilateur. . . . . . lors des phases d’optimisation de compilation On observe ´egalement que la version compil´ee avec un niveau d’optimisation de 0 pr´esente une quantit´e globale de travail inutile moins important (proportionnellement) `a la version compil´ee avec un niveau d’optimisation de 5. De plus, 42
  • 43. l’´ecart entre les deux versions s’accentue dans le coeur de l’algorithme. En effet, durant la phase d’initialisation, les deux versions se comportent `a peu pr`es de la mˆeme fa¸con (aux alentours de 50 % de travail inutile) alors que dans le coeur de l’ex´ecution, la version non optimis´ee comporte en moyenne 6.9 % de travail inutile `a comparer aux 9.9 % observ´e dans le cas de la version optimis´ee. Ce ph´enom`ene avait d´ej`a ´et´e constat´e dans l’article [1] mais uniquement au sujet des valeurs mortes. . . . du au jeu d’instruction du processeur Cette ´etude n’est absolument pas exhaustive sur les diverses causes que peut avoir le travail inutile. Cependant, mˆeme si cet aspect n’a pu ˆetre explor´e pour des raisons de temps, il parait raisonnable de penser qu’une partie du travail inutile pourrait avoir ´et´e introduit en raison des contraintes impos´ees par le jeu d’instructions utilis´e. En effet, dans un jeu d’instruction RISC (comme le Sparc) une instruction de haut niveau (en langage C par exemple) peut ˆetre convertie par le compilateur en une suite tr`es importante d’instructions comme en une seule. Ceci d´epend de l’´eloignement de cette instruction en langage C par rapport aux instructions disponibles dans le jeu d’instruction assembleur utilis´e. A contrario, un jeu d’instruction CISC (comme le x86) aura des instructions assembleur plus proche des instructions en langage de haut niveau. De cette fa¸con, les proportions d’instructions assembleur inutiles peuvent ne pas ˆetre identiques aux proportions d’instructions inutiles de haut niveau (en langage C par exemple). De plus, certaines optimisations de compilation effectuant un r´e-ordonnancement des instructions assembleur, il est parfois difficile de savoir quel ensemble d’instructions assembleur repr´esente quelle instruction de haut niveau. Conclusion En conclusion, nous pouvons dire que les proportions de travail inutile trouv´ees se rattachent majoritairement au travail inutile pr´esent dans l’algorithme en langage de haut niveau. De fait, une piste qui pourrait ˆetre int´eressante pour r´eduire ce travail inutile serait de signaler au programmeur, lors des premi`eres ex´ecutions d’un prototype de programme, que certaines parties de l’algorithme g´en`erent une grande quantit´e de travail inutile et que, par cons´equent, une r´e-´ecriture en prenant en compte cet ´etat de fait pourrait ´eviter ce travail. Il est mˆeme possible d’imaginer un outil proposant au programmeur une ´ebauche de solution pour l’aider `a restructurer une partie de son code afin d’´eviter ce travail inutile. Cependant, ce type d’outils ne peut rien pour aider `a ´eliminer le travail inutile intrins`eque `a l’algorithme. 43
  • 44. 2.5 Conclusion Cette ´etude est, en premier lieu, une ´etude permettant de comprendre un ph´enom`ene, `a priori, contre intuitif : Le travail inutile. Pour ce faire, nous nous sommes bas´e sur des r´esultats existants qui ont d´ej`a ´et´e publi´es et qui montre que le travail inutile existe bel et bien dans des programmes classiques. Le but de ce stage ´etait d’´elargir les d´efinitions donn´ees dans ces articles afin d’avoir une id´ee du travail inutile global qui peut se trouver dans un programme. Cette ´etude, contrairement `a celles cit´ees ci-contre, n’avait pas pour but de trouver un moyen d’exploiter ce travail inutile pour en r´eduire l’impact sur le temps d’ex´ecution ou la consommation ´electrique mais seulement de comprendre ce ph´enom`ene et de savoir pourquoi ce travail inutile est pr´esent (est-ce du au compilateur ?, au programmeur ?. . .). En conclusion, nous pouvons dire que cette ´etude `a permis de confirmer l’existence du travail inutile et de comprendre, en partie, d’o`u il provient. 44
  • 45. Bibliographie [1] G. Sohi A. Butt. Dynamic dead-instruction detection and elimination. ASPLOS X, October 2002. [2] Jeffrey D. Ullman Alfred V. Aho, Ravi Sethi. Compilers : Principles, Techniques and Tools. Addison-Wesley, 1986. [3] Gordon B. Bell. Characterization of silent stores. Submitted in partial fulfillment of the M.S. Degree in Electrical and Computer Engineering, May 2001. [4] F. Bodin. Cours d’optimisation : Transformer pour la performance. Septembre 2002. [5] M. Lipasti K. Lepak, G. Bell. Silent stores and store value locality. IEEE Transactions on Computers, 50(11), November 2001. [6] Mikko H. Lipasti Kevin M. Lepak. Temporally silent stores. ASPLOS X, October 2002. [7] Kevin M. Lepak. Silent stores for free : Reducing the cost of store verification. Submitted in partial fulfillment of the M.S. Degree in Electrical and Computer Engineering, December 2000. [8] Charles N. Fischer Milo M. Martin, Amir Roth. Exploiting dead value information. Proceedings of Micro-30, December 1997. 45