Vous êtes sur la page 1sur 20

ELE-784

Ordinateurs et programmation systme

Cours #8
Optimisation de code
Bruno De Kelper
Site internet :
http://www.ele.etsmtl.ca/academique/ele784/
Cours # 8

ELE784 - Ordinateurs et programmation systme

Plan daujourdhui

1. Optimisation de la performance du code


(chap. 5)
1.
Capacits et limitations doptimisation des compilateurs
2.
Exprimer la performance du code
3.
limination des inefficacits des boucles
4.
Rduire les appels de fonctions
5.
limination des rfrences inutiles la mmoire
6.
Comprhension des processeurs modernes
7.
Rduction de la charge des boucles
8.
Conversion lutilisation de pointeurs
9.
Amliorer le paralllisme
10. Rsum des rsultats doptimisation actuels
11. Prdiction des branchements et pnalits
12. Performance des accs la mmoire
13. Techniques damlioration des performances

Rf. : Computer Systems A Programmers Perspective, R.E. Bryant, D.R. OHallaron, Prentice Hall, chap. 5.

Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

Optimisation de la performance du code


- La performance du code est dicte dans une large mesure par le choix
dalgorithmes et des structures de donnes qui les supportent.
- Mais aussi, grce des techniques spciales, les compilateurs et matriels
modernes sont conus pour tirer le maximum de performance des algorithmes
utiliss.
- Malgr a, les choix faits par le programmeur ont un impact sur la capacit
doptimisation du compilateur et du matriel.
- Des changements anodins dans la faon dcrire le code peuvent avoir parfois
un impact considrable sur la facilit quaura le compilateur a en produire un
code performant.
- Ainsi, le programmeur doit aider le compilateur car celui-ci ne peut effectuer
que des transformations assez limites sur le code.
- Les compilateurs utilisent des techniques doptimisation dites :
Indpendantes de la machine

Qui peuvent sappliques nimporte


quelle machine

Dpendantes de la machine

Qui dpendent des particularits de


bas niveau de la machine

Cours # 8

ELE784 - Ordinateurs et programmation systme

Optimisation de la performance du code


- Les processeurs modernes utilisent des techniques sophistiques pour
excuter le code dun programme, tels que le paralllisme dexcution et
lexcution hors squence.
- Et le programmeur doit comprendre ces principes de fonctionnement pour tirer
le maximum de performance de son code.

1.1 - Capacits et limitations doptimisation des compilateurs


- Les compilateurs modernes exploitent chaque occasion les opportunits de :
- Simplifier les expressions.
- Utiliser un mme traitement plusieurs endroits.
- Rduire le nombre de fois quun traitement est effectu.
- Etc.
- Les capacits doptimisation des compilateurs sont limites par :
1 Lexigence quils ne doivent jamais modifier le comportement du code.
2 Leur comprhension limite du comportement du code et le contexte
dans lequel il sera utilis.
3 Le besoin deffectuer la compilation rapidement.
Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

Optimisation de la performance du code


1.1 - Capacits et limitations doptimisation des compilateurs
Par exemple : Ces deux fonctions semblent effectuer exactement le mme travail.
void AddXY_1 (int *Xp, int *Yp) {
*Xp += *Yp;
*Xp += *Yp;
}
1er cas :
A

A
5

2ime cas :
5

Xp Yp

AddXY_1

void AddXY_2 (int *Xp, int *Yp) {


*Xp += 2 * (*Yp);
Version
}
optimise ?

11

AddXY_2

Xp
Phnomne
dalias de mmoire
"memory aliasing"

AddXY_1

11

20

Yp

AddXY_2

15

Donc, lorsque ces deux fonctions reoivent des pointeurs vers la mme
variable, elles ne produisent pas le mme rsultat.
Cours # 8

ELE784 - Ordinateurs et programmation systme

Optimisation de la performance du code


1.1 - Capacits et limitations doptimisation des compilateurs
Par exemple : Ces deux fonctions semblent effectuer exactement le mme travail.
int AddF_1 (int X) {
return (f(X) + f(X) + f(X) + f(X));
}
Mais si : int n = 0;
effet
secondaire

int f (int A) {
n++;
return (A+n);
}

int AddF_2 (int X) {


return (4*f(X));
}
Version optimise ?

Alors, f() a des "effets secondaires".


Donc :

AddF_1

30

AddF_2

24

cause des "effets secondaires" de f(), ces deux fonctions reoivent la


mme valeur en entre, mais ne produisent pas le mme rsultat.
- Dans les deux cas, "memory aliasing" et "effets secondaires", ainsi que
bien dautres, le compilateur ne peut pas optimiser sans changer le
comportement du code.
Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

Optimisation de la performance du code


1.2 - Exprimer la performance du code
- La mesure de performance est un outil essentiel pour identifier les parties de
code qui doivent tre optimises ainsi que pour dterminer limpact des choix
doptimisation.
- La performance du code peut tre mesure de bien des faons, mais de cellesci, le nombre de cycles par lment (CPE) est particulirement utile pour
mesurer le code rptitif tel que les boucles.
Par exemple :

800

CPE = 4.0

600

0+
80.

400
200
Cours # 8

*n
4 .0

5+
83.

0
0

void Sum2 (int n) {


for (i = 0; i < n; i += 2) {
c[i] = a[i] + b[i];
c[i+1] = a[i+1] + b[i+1];
}
}
Utilise le droulement
partiel de boucle

void Sum1 (int n) {


for (i = 0; i < n; i++)
c[i] = a[i] + b[i];
}

40

80

*n
3.5

CPE = 3.5
120
160

Le CPE a lavantage dtre


indpendant du matriel
200

ELE784 - Ordinateurs et programmation systme

Optimisation de la performance du code


1.2 - Exprimer la performance du code
Par exemple : Soit la fonction Operation1() qui accumule les donnes dun
vecteur selon lopration OPER.
o

void Operation1 (vec_ptr v, data_t *dest) {


int i;
*dest = INIT;
for (i = 0; i < vec_len(v); i++) {
data_t val;
get_element (v, i, &val);
*dest = *dest OPER val;
}

typedef struct {
int len;
data_t *data;
} vec_rec, *vec_ptr

et
#define INIT 0 ou #define INIT 1
#define OPER *
#define OPER +

}
Mesure du CPE :
Entier

- Loption de compilation O2 amliore

Point flottant
la performance denviron 25 %.
*
*
+
+
Les multiplications en point-flottant
Pas doptimisation 42.06 41.86 41.44 160.0
consomment beaucoup plus de
Option O2
31.25 33.25 33.25 143.0
Optimisation

temps (presque 4 fois plus).

Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

Optimisation de la performance du code


1.3 - limination des inefficacits des boucles
- Dans lexemple prcdent, le code excute la fonction vec_len() chaque
itration, bien que la longueur du vecteur ne change pas.
- Une 1ire optimisation serait donc de dterminer la longueur du vecteur avant la
boucle afin dviter lappel trop frquent la fonction vec_len().
void Operation2 (vec_ptr v, data_t *dest) {
Mesure du CPE :
int i;
Entier
int length = vec_len(v);
Optimisation

Point flottant
*
*
+
+
31.25 33.25 33.25 143.0
22.61 21.25 21.15 135.0

*dest = INIT;
Operation1()
for (i = 0; i < length; i++) {
Operation2()
data_t val;
get_element (v, i, &val);
- Cette optimisation amliore la
*dest = *dest OPER val;
performance denviron 33 %.
}
}
- Ce type doptimisation sappelle "dplacement de code" (code motion).
- Le compilateur tente dutiliser le "dplacement de code" , mais cause
deffet secondaire potentiel, il vite de changer les appels de fonction.
Cours # 8

ELE784 - Ordinateurs et programmation systme

Optimisation de la performance du code


1.3 - limination des inefficacits des boucles
Autre exemple :

Les fonctions Minus1() et Minus2() convertissent une chaine de


caractres en minuscule.

void Minus1 (char *S) {


int i;
Longueur de la chaine
for (i = 0; i < strlen(S); i++) {
if ((S[i] >= A) && (S[i] <= Z))
S[i] -= (A a);

for (i = 0; i < length; i++) {


if ((S[i] >= A) && (S[i] <= Z))
S[i] -= (A a);

o
void strlen (const char *S) {
int len = 0;

200
160

120
while (*S != /0) {
S++;
80
len++;
Doit trouver la
}
fin de la chaine 40
return len; pour dterminer
0
}
0
sa longueur.
Cours # 8

Cours # 8

void Minus2 (char *S) { Longueur de la chaine


int i;
int length = strlen(S);

- La fonction Minus1
a un comportement
quadratique (
viter absolument).

Mesure du CPE :

in

l
cu
us

e1

Minuscule2
0.5

1.0

1.5

2.0

- La fonction Minus2
a un comportement
linaire.

2.5 3.0
x105

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

10

Optimisation de la performance du code


1.4 - Rduire les appels de fonctions
- Les appels de fonctions induisent une charge supplmentaire et empchent la
plupart des optimisations.
Par exemple :

- La fonction Operation2 () rcupre chaque lment du vecteur


laide de la fonction get_element ().
- Mais, en rcuprant les lments par un accs direct au vecteur,
comme dans la fonction Operation3 () ci-dessous :

void Operation3 (vec_ptr v, data_t *dest) {


int i;
int length = vec_len(v);
data_t *data = get_first(v);

*dest = INIT;
for (i = 0; i < length; i++)
*dest = *dest OPER data[i];

Cours # 8

Mesure du CPE :
Entier
Point flottant
*
*
+
+
Operation2() 22.61 21.25 21.15 135.0
Operation3() 6.00 9.00
8.00 117.0
Fonction

- Cette optimisation amliore la


performance par un facteur de 3.5

ELE784 - Ordinateurs et programmation systme

11

Optimisation de la performance du code


1.4 - Rduire les appels de fonctions
- Les appels de fonctions induisent une charge supplmentaire et empchent la
plupart des optimisations.
Par exemple :

- La fonction Operation2 () rcupre chaque lment du vecteur


laide de la fonction get_element ().
- Mais, en rcuprant les lments par un accs direct au vecteur,
comme dans la fonction Operation3 () ci-dessous :

void Operation3 (vec_ptr v, data_t *dest) {


int i;
int length = vec_len(v);
data_t *data = get_first(v);

*dest = INIT;
for (i = 0; i < length; i++)
*dest = *dest OPER data[i];

Cours # 8

Cours # 8

Mesure du CPE :
Entier
Point flottant
*
*
+
+
Operation2() 22.61 21.25 21.15 135.0
Operation3() 6.00 9.00
8.00 117.0
Fonction

- Cette optimisation amliore


la performance jusqu un
facteur de 3.7

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

12

Optimisation de la performance du code


1.5 - limination des rfrences inutiles la mmoire
- Laccs une variable en mmoire implique que le processeur doit effectuer un
cycle de lecture et un cycle dcriture pour rcuprer la donne et rafraichir la
variable modifie.
- cause du phnomne de "memory aliasing", le compilateur ne peut pas
toujours optimiser ce type dutilisation dune variable en lui attribuant un registre.
Par exemple : - La fonction Operation3 () accumule le rsultat de son calcul dans
la variable pointe par dest.
Mais
Mesure du CPE :
void Operation4 (vec_ptr v, data_t *dest) {
int i;
int length = vec_len(v);
data_t *data = get_first(v);
data_t x = INIT;

for (i = 0; i < length; i++) Variable servant


x = x OPER data[i];
a accumuler le
*dest = x;
rsultat
Cours # 8

Fonction
Operation3()
Operation4()

Entier
*
+
6.00
9.00
2.00
4.00

Point flottant
*
+
8.00 117.0
3.00 5.00

- Cette optimisation amliore la


performance jusqu un facteur
de 3
- Et plus encore pour le cas de la
multiplication point-flottant.

ELE784 - Ordinateurs et programmation systme

13

Optimisation de la performance du code


1.6 - Comprhension des processeurs modernes
- Loptimisation en profondeur du code require une comprhension en dtail des
particularits du processeur sur lequel le code sera excut.
- Les processeurs modernes incorporent de nombreux mcanismes qui leur
permettent dexcuter le code plus rapidement.
Par exemple : -

Utilisation de mmoire cache de donnes et dinstructions.


Utilisation dun pipeline dexcution.
Plusieurs units fonctionnelles (units de traitement).
Units de lecture et dcriture indpendantes.
Traitement "hors squence".
Mcanisme de prdiction des branchements.
Mcanisme dexcution spculative.

- En fait, lexcution relle des instructions par le processeur ne ressemble pas du


tout la squence exprime par le code, mme dans sa version "machine".
- Le processeur est capable dexcuter plusieurs instructions en mme temps
(certains jusqu 80 instructions simultanment), tout en assurant que le code se
comporte correctement.
Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

14

Optimisation de la performance du code


1.6 - Comprhension des processeurs modernes
Instruction
Instruction control
control
Address

Fetch
control

Retirement
unit
Register
file

Instruction
decode

Instruction
cache

Instructions

Operations
Register
updates

Prediction
OK?

Integer/
branch

General
integer

FP
add

FP
mult/div

Operation results

Load

Addr.

Functional
units

Store

Addr.
Data

Data

Data
cache

Execution
Execution
Cours # 8

ELE784 - Ordinateurs et programmation systme

15

Optimisation de la performance du code


1.6 - Comprhension des processeurs modernes
- La plupart des units fonctionnelles du processeur sont quipes dun pipeline qui
leur permet de commencer lexcution de la prochaine opration avant davoir
termin la prcdente.
- Le temps dexcution pour chaque opration est identifi par deux valeurs :
Latence :
Temps dmission :
Nombre de cycle ncessaire entre
Nombre de cycle ncessaire pour
deux oprations indpendantes
excuter lopration du dbut
conscutives.
jusqu la fin.
Par exemple :

Cours # 8

Cours # 8

Opration
Latence mission
Addition entire
1
1
Multiplication entire
4
1
Division entire
36
36
Addition point-flottant
3
1
Multiplication point-flottant
5
2
Division point-flottant
38
38
Lecture (en cache)
3
1
criture (en cache)
3
1
ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

Les oprations de
division ne sont pas
misent en pipeline
car elles ne sont
pas juges assez
frquentes.
16

Optimisation de la performance du code


1.6 - Comprhension des processeurs modernes
- Pour commencer notre analyse, prenons en exemple la boucle de traitement de
la fonction Operation4() (notre meilleur code jusqu prsent) :
Exemple :

En supposant que les variables sont stockes dans des registres


du processeur (sauf pour data qui se trouve en mmoire-cache).
Excution dune itration
cycles
for (i = 0; i < length; i++)
Code initial
x = x OPER data[i];
i
1

1 Lecture de data[i]
2 Multiplication de x et Reg
Dtail
dexcution 3 Incrment i
4 Compare i length
5 Branche 1 si plus petit
Notation
abrge

simultane

Reg

Reg = Data[i]
x = x * Reg
i=i+1
cond = i - length
GOTO 1 (cond = <)

Cours # 8

Load

++
i
i
comp
cond
excution
goto

Dure du
traitement

ELE784 - Ordinateurs et programmation systme

17

Optimisation de la performance du code


1
Load

2
3

++
i
comp
cond
goto
Load

Reg

Reg

En supposant des
ressources illimites
++
i
comp
cond
Load
goto

Reg

Traitement
spculatif

- Une nouvelle multiplication


est commence tous les
4 cycles, donc CPE = 4.0

10
x

11
Cours # 8

++
i
comp
cond
goto

- Les multiplications sont


effectues en squence
car elles requirent le
rsultat de la prcdente.

8
9

- Le traitement total des 3


itrations utilise 15 cycles.

ELE784 - Ordinateurs et programmation systme

18

Cours # 8

ELE784 - Ordinateurs et programmation systme

Optimisation de la performance du code


1
Load

2
3

++
i
comp
cond
goto
Load

Avec des ressources limites


i

Reg

Reg

++
i
comp
cond
Load
goto

Reg

Traitement
spculatif

- Les units General Integer


et Integer/Branch peuvent
commencer une opration
chaque cycle.

9
10

- Donc, la 3ime incrmentation


doit tre dcale.

11
Cours # 8

++
i
comp
cond
goto

ELE784 - Ordinateurs et programmation systme

19

Optimisation de la performance du code


1.6 - Comprhension des processeurs modernes
- En gnral, le processeur est limit par trois types de contraintes :
Dpendance de donne
Ressources limites
Prdiction de branchement

Force le retardement de certaines oprations


jusqu ce que les oprants soient disponibles.
Limite le nombre doprations qui peuvent tre
excutes en mme temps.
Limite le degr auquel le processeur peut prdire
lavance le traitement effectuer.

- Loptimisation en profondeur du code require ainsi de tenir compte de ces trois


contraintes.
- Dun autre ct, le gain de performance ainsi obtenu dpend des caractristiques
du processeur spcifique sur lequel le code sera excut.

Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

20

10

Optimisation de la performance du code


1.7 - Rduction de la charge des boucles
- Il est bien connu que le droulement, mme partiel, des boucles permet de
rduire limpact de la charge supplmentaire induite par la gestion de la boucle.
Par exemple : - La fonction Operation5 () reproduit la fonction Operation4 (),
mais en droulant la boucle par un facteur 3.
void Operation5 (vec_ptr v, data_t *dest) {
int length = vec_len(v);
data_t *data = get_first(v);
data_t x = INIT;
int limit = length-2;
Pour viter de dborder du tableau
int i;
for (i = 0; i < limit; i +=3)
x = x OPER data[i] OPER data[i+1] OPER data[i+2];

for (; i < length; i++)


x = x OPER data[i];
*dest = x;

Cours # 8

Pour terminer les


lments qui reste.

ELE784 - Ordinateurs et programmation systme

21

Optimisation de la performance du code


+
i
comp
cond
goto

1
Load

2
3

Load

Reg

7
8

+
i
i
comp
cond
goto

Reg
+

5
6

Load

Load

Reg
+

- Chaque Load prend 3 cycles


(latence) et un Load peut
dmarrer chaque cycle
(temps dmission).

Load

Reg

Load

Reg
+

Reg
+

9
Mesure de
CPE
CPE
Cours # 8

Cours # 8

1
2.00

Degr de droulement
2
3
4
8
1.50
1.33 1.50 1.25

16
1.06

On remarque que le
gain nest pas linaire.

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

22

11

Optimisation de la performance du code


1.7 - Rduction de la charge des boucles
- Avec le droulement de la boucle de la fonction Operation5(), leffet de
loptimisation se fait sentir de faon plus important lorsque le nombre de donnes
traiter augmente.
Par exemple :

Degr de droulement
2
3
4
8
1.50
1.33 1.50 1.25
3.57
3.39 3.84 3.91
1.56
1.40 1.56 1.31

Nombre
dlments
1
CPE (idal)
2.00
31 lments
4.02
1024 lments 2.06

16
1.06
3.66
1.12

- Le tableau ci-dessus montre le CPE net mesur sur la fonction Operation5 () au


complet, ce qui tient compte des autres parties non analyses prcdemment.
- Il est clair que pour de petites quantits de donnes (31 lments), lexcution est
domine par ces autres parties.
- Tandis que le gain pour le cas 1024 lments est suffisamment important pour
justifier laugmentation du nombre dinstruction issu du droulement de la boucle
(un degr de 16 produit 142 bytes dinstruction par rapport 63 bytes sans
droulement).
Cours # 8

ELE784 - Ordinateurs et programmation systme

23

Optimisation de la performance du code


1.8 - Conversion lutilisation de pointeurs
- Larithmtique de pointeur est frquemment utilise comme alternative plus
performante lindexation dans les tableaux, mais quen est-il rellement ?
Par exemple :
En convertissant les fonctions Operation4()
et Operation5() larithmtique de pointeur
void Operation5p (vec_ptr v, data_t *dest) {
data_t *data = get_first(v);
data_t *last = data+vec_len(v);
data_t x
= INIT;
int limit
= last-2;
for (; data < limit; data +=3)
x = x OPER data[0] OPER data[1]
OPER data[2];

for (; data < last; data++)


x = x OPER data[0];
*dest = x;

for (; data < last; data++)


x = x OPER (*data);
*dest = x;

Entier
*
+
Operation4() 2.00 4.00
Operation4p() 3.00 4.00
Operation5() 1.33 4.00
Operation5p() 1.33 4.00
Fonction

Point flottant
*
+
3.00 5.00
3.00 5.00
3.00 5.00
3.00 5.00

Les rsultats sont identiques, sauf un cas qui est pire.


Cours # 8

Cours # 8

void Operation4p (vec_ptr v, data_t *dest) {


data_t *data = get_first(v);
data_t *last = data+vec_len(v);
data_t x
= INIT;

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

24

12

Optimisation de la performance du code


1.9 - Amliorer le paralllisme
- Jusqu prsent, notre code est limit par la "latence" des oprations.
- Mais plusieurs units fonctionnelles du processeur possdent un pipeline qui
leur permet de traiter plusieurs oprations, diffrents stages de leur traitement,
en mme temps.
- Par contre, jusqu prsent, notre code ne nous permet pas den profiter car le
rsultat du traitement est accumul dans une seule variable.
- cause de a, la prochaine opration ne peut pas commencer avant que le
rsultat de la prcdente ait t obtenu.
- Cette constatation nous indique la prochaine optimisation :
Fractionnement de boucle :
- Certains types de traitement se prtent une optimisation qui prend avantage du
pipeline des oprations afin de parallliser le traitement.
- Par exemple, laddition et la multiplication de nombres entiers tant associative et
commutative, une srie de ces oprations peut tre effectue par morceaux.
Cours # 8

ELE784 - Ordinateurs et programmation systme

25

Optimisation de la performance du code


1.9 - Amliorer le paralllisme
Fractionnement de boucle :
Sachant que N
N
K
data[k]
data[n]
data[n]
*
=
X=
k=K
n=0
n=0

void Operation6 (vec_ptr v, data_t *dest) {


int length = vec_len(v);
int limit = length-1;
data_t *data = get_first(v);
data_t x0 = INIT, x1 = INIT;
int i;

Alors, pour une itration


i
Load
Load
x0
x1

++
i
i
comp
cond
goto

Reg0
Reg1

for (i = 0; i < limit; i += 2) {


x0 = x0 OPER data[i];
x1 = x1 OPER data[i+1];
}
Calcul divis en
x0
for (i; i < length; i++)
deux morceaux
x1
x0 = x0 OPER data[i];
*dest = x0 OPER x1;
Une nouvelle multiplication commence
}
avant que la prcdente termine.

Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

26

13

Optimisation de la performance du code


1.9 - Amliorer le paralllisme
Fractionnement de boucle :
- Avec cet optimisation, puisque chaque multiplication sexcute en 4 cycles
(latence), deux multiplications sont excutes chaque 4 cycles.
- Il nen va pas de mme avec laddition entire, comme le montre le tableau de
CPE ci-dessous, car cette addition sexcute en un seul cycle.
Mesure du CPE :

Fonction
Operation4()
Operation6()

Entier
*
+
1.50 4.00
1.50 2.00

Point flottant (avec droulement de


*
+
boucle de degr 2)
3.00 5.00
2.00 2.50

- Pour les autres oprations, le gain de performance est approximativement de 2.


- La plupart des compilateurs droulent les boucles, mais peu les fractionnent.
- Notons, par contre, que laddition et la multiplication point-flottante ne sont pas
vraiment associatives cause des erreurs darrondissement de ces calculs.
- Donc, en fait, lorsque les calculs sont effectus dans un ordre diffrent, le rsultat
peut tre diffrent.
Cours # 8

ELE784 - Ordinateurs et programmation systme

27

Optimisation de la performance du code


1.9 - Amliorer le paralllisme
Fractionnement de registre :
- Le fractionnement de boucle permet de tirer avantage du pipeline des units
fonctionnelles, mais utilise plus de registres internes du processeur.
- En fait, le processeur na quun nombre limit de registres internes.
- Lorsque le fractionnement de boucle est tel quil est cours de registre, le
processeur "fractionne les registres" en stockant temporairement les rsultats
intermdiaires sur la pile.
- Il en rsulte une perte de performance considrable.
Par exemple : Processeur standard = (8 registres entier) + (8 registres point-flottant)
Alors pour la fonction Operation6() :
En entiers
Reste
Length, i
2
registres
4 registres
data, Limit

X0, X1
Cours # 8

Cours # 8

2 registres

Reg0, Reg1

En point-flottant
X0, X1
Reste
6 registres

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

2 registres
Reg0, Reg1,
28

14

Optimisation de la performance du code


1.10 - Rsum des rsultats doptimisation actuels
- Aprs analyse, il apparat que les calculs point-flottant de nos tests utilisaient
des donnes qui produisaient un dbordement dont le rsultat est linfini.
- Le processeur prend de 110 120 cycles pour effectuer une multiplication avec
linfini, ce qui affecte la performance considrablement.
- Ainsi, la performance dpend aussi des donnes utilises et le tableau cidessous reproduit les mesures de CPE corriges.
Fonction

Mthode

Pas optimis
Option de compilation O2
vec_len() avant la boucle
Accs direct aux donnes
Accumulation dans variable locale
Droule la boucle (degr 4)
Operation5()
Droule la boucle (degr 16)
Droule (degr 2) et paralllisme (degr 2)
Operation6() Droule (degr 4) et paralllisme (degr 2)
Droule (degr 8) et paralllisme (degr 4)
Operation1()
Operation1()
Operation2()
Operation3()
Operation4()

Cours # 8

Entier
*
+
40.14
47.14
25.08
36.05
19.19
32.18
6.26
12.52
1.76
9.01
1.51
9.01
1.25
9.01
1.19
4.69
1.15
4.12
1.11
4.24

Point flottant
*
+
52.07 53.71
37.37 32.02
28.73 32.73
13.26 13.01
8.01
8.01
6.32
6.32
6.33
6.22
4.44
4.45
2.34
2.01
2.36
2.08

ELE784 - Ordinateurs et programmation systme

29

Optimisation de la performance du code


1.11 - Prdiction des branchements et pnalits
- Afin de garder les pipelines des units fonctionnelles le plus occup possible, le
processeur effectue du traitement spculatif, cest--dire quil commence le
traitement de plusieurs instructions en avance.
- Cette stratgie fonctionne bien en gnral; mais face un branchement, elle
exige que le processeur tente de prdire la destination final.
Types de branchement : - Prise de dcision (boucle, sialors, switch)
- Branchement inconditionnel (goto)
- Appel et retour de fonction
- Appel et retour dinterruption
- Lorsque la prdiction est correct, les rsultats du traitement spculatif est
conserv, cest--dire que les registres du processeur et la mmoire sont
modifis en consquence.
- Par contre, lorsque la prdiction savre tre inexacte, les rsultats du
traitement spculatif doivent tre rejet et les pipelines doivent tre rinitialiss
avec une nouvelle squence dinstructions.
- Il en rsulte une pnalit assez lourde, en terme de temps dexcution.
Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

30

15

Optimisation de la performance du code


1.11 - Prdiction des branchements et pnalits
- Souvent, les processeurs se basent sur lheuristique suivante pour prdire la
destination des branchements conditionnels :
- Si la destination du branchement est une adresse plus petite,
alors prend ce branchement.
- Si la destination du branchement est une adresse plus grande,
alors ne prend pas ce branchement.
- Cette heuristique favorise principalement les boucles car leur traitement rptitif
amne le processeur aux adresses plus basses et seule la sortie de boucle le fait
avancer vers les adresses plus hautes.
- Selon les tudes, cette heuristique est adquate dans 65 % des branchements.
- Une autre heuristique utilise suppose que tous les branchements seront pris, ce
qui savre tre correcte dans 60 % des cas.
- Une mesure de la pnalit des mauvaises prdictions de branchement montre un
cot de 14 cycles pour chaque mauvais choix.
- Ainsi, avec 65 % de succs, chaque branchement cote en moyenne 4.9 cycles.
Cours # 8

ELE784 - Ordinateurs et programmation systme

31

Optimisation de la performance du code


1.11 - Prdiction des branchements et pnalits
- Selon les tudes, les instructions de branchement constituent :
- Environ 15 % des instructions des programmes non-numriques.
- De 3 % 12 % des instructions des programmes numriques.
Programme qui fait beaucoup de calculs numriques
- Ainsi, les pnalits des erreurs de prdiction peuvent avoir un impact sur la
performance globale du code.
- Hlas, il ny a que peu de chose quun programmeur peut faire pour amliorer la
prdiction des branchements, sauf :
- Choisir des conditions de branchement
qui ont plus de chance dtre ralises.
Cond = ((A < 0) << 1) | ((A > 0) << 0);
- Rduire le nombre de branchements switch (Cond) {
case 1 : x = y + A;
conditionnels :
If (A > 0)
break;
x = A*y;
Par exemple :
case 2 : x = A*y;
else if (A < 0)
break;
x = y + A;
default : x = 0;
else x = 0;
}
Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

32

16

Optimisation de la performance du code


1.12 - Performance des accs la mmoire
- Jusqu prsent, nous avons pris en considration les temps de latence et
dmission des oprations, sauf pour les accs aux donnes en mmoire.
- Sans rentrer dans des considrations concernant les mouvements entre la
mmoire-cache et la mmoire-vive, supposons pour la suite que les donnes se
trouvent toujours en mmoire-cache.
Latence des lectures :
- Les exemples prcdents utilisaient uniquement lindexation pour accder aux
donnes en mmoire et selon un ordre strictement squentiel, donc facilement
prvisible.
- Dans ce cas, le processeur peut aisment utiliser le traitement spculatif sur la
lecture des donnes et profiter ainsi du pipeline de lunit de lecture.
- Lorsque lemplacement de la prochaine donne ne peut pas tre facilement
identifi, comme lors des accs une liste chaine ou des accs indirects
(pointeur), la latence de lecture prend le dessus et rduit la performance.

Cours # 8

ELE784 - Ordinateurs et programmation systme

33

Optimisation de la performance du code


1.12 - Performance des accs la mmoire
Latence des lectures :
Par exemple :

Soit la structure suivante :

typedef struct Elem {


struct Elem *next;
int data;
} list_elem, *list_ptr;
Et la fonction qui calcule la
longueur de la liste chaine :
int list_len (list_ptr ls) {
int len = 0;
for (; ls; ls->next)
len++;
return len;
}
Cours # 8

Cours # 8

3
4
5

++
i
Load

++
i
++

Reg
test
cond
jne

Reg

test
cond
jne

7
8
9

Chaque lecture
dpend de la
prcdente

Load

CPE = 3.0

10

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

Load
Reg
test
cond
jne

34

17

Optimisation de la performance du code


1.12 - Performance des accs la mmoire
Latence des critures :
- Comme pour la lecture, lcriture a une latence de 3 cycles et un temps
dmission dun cycle, permettant ainsi de dmarrer une criture par cycle.
- De plus, lcriture est indpendante de la lecture, puisque effectue par sa propre
unit fonctionnelle.
- Par contre, une diffrence fondamentale entre la lecture et lcriture est que la
1ire modifie toujours un registre du processeur tandis que lautre non.
- Aussi, les critures ne sont jamais dpendantes entre elles, contrairement aux
lectures, comme on la vu prcdemment.
- Ainsi, plusieurs critures conscutives peuvent aisment tre misent en pipeline.
- Dun autre ct, les lectures sont frquemment dpendantes des critures
puisque seules les lectures peuvent tre affectes par le rsultat des critures.
- Souvent les lectures et les critures ne peuvent tre paralllises entre elles.

Cours # 8

ELE784 - Ordinateurs et programmation systme

35

Optimisation de la performance du code


1.12 - Performance des accs la mmoire
Latence des critures :
- En
ralit,
lunit
fonctionnelle
dcriture contient 2 tampons (tampon
dadresse et tampon de donne) qui
peuvent tenir plusieurs oprations
dcriture successives.

Load Unit

Adresse

- Lors dune lecture, lunit doit vrifier si


une criture est en attente dans lunit
dcriture avant de rcuprer la donne
dans la mmoire-cache.

Store Unit
Adresse

Adresse Donne

Donne
Donne

Adresse

Donne

Cache-memory

- Si la lecture ne faisait pas cette vrification, elle pourrait lire une donne en
mmoire-cache qui na pas encore t mise jour par une criture qui a t
dclenche avant la lecture.
- Sil y a effectivement une criture en cours sur la case de mmoire-cache vise
par la lecture, celle-ci doit attendre la fin de cette criture.
- Lopration dcriture ne subit pas ce genre de contrainte de la part de la lecture.
Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

36

18

Optimisation de la performance du code


Par exemple :

void Write_Read (int *src, int *dest, int n) {


int cnt = n;
Opration
int val = 0;
dcriture
while (cnt--) {
*dest = val;
Opration
val = (*src + 1);
de lecture
}
}

Soit la fonction Write_Read qui effectue


une criture suivie dune lecture.
Cas 1 :

*dest *src

Dans ce cas, la lecture ne dpend pas


de lcriture
cnt
val

1
2

Store Store
data addr

6
7

cnt

Store
addr

src
++

4
5

-cond
Load
jnc

val

src
++

val
Store
data

CPE = 2.0
Cours # 8

cnt
-cond
Load
jnc

val

ELE784 - Ordinateurs et programmation systme

37

Optimisation de la performance du code


*dest = *src

Cas 2 :

Ici, la lecture dpend de lcriture

cnt
val

1
2
3

-cond
jnc

Store Store
data addr

cnt

cnt
-cond
jnc

=
Store
addr

Load

4
5
6
7
8

src
++
val

Dans ce cas-ci, la
lecture doit attendre
la fin de lcriture

Load

val
Store
data

9
10
Cours # 8

Cours # 8

11

CPE = 6.0
ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

src
val
++

38

19

Optimisation de la performance du code


1.13 - Techniques damlioration des performances
- Une bonne connaissance du comportement du processeur et du compilateur
permet de faire les bons choix lors de la conception et loptimisation du code.
Conception de haute niveau :
- Choisir des algorithmes et des structures de donnes adquates.
- viter les algorithmes ayant un comportement quadratique.
Principes de codage :
- viter les "bloqueurs" doptimisation du compilateur.
- viter les appels de fonction excessifs, tels que dans les boucles.
- liminer les rfrences inutiles la mmoire, par exemple avec
lutilisation de variables temporaires et en stockant en mmoire
seulement le rsultat final.
Optimisation de bas niveau :
- Essayer diffrentes combinaisons de pointeurs versus indexage.
- Rduire la charge des boucles en les droulant.
- Utiliser les pipelines des units fonctionnelles avec des techniques telles
que le "fractionnement" des boucles.
Cours # 8

ELE784 - Ordinateurs et programmation systme

39

Optimisation de la performance du code


1.13 - Techniques damlioration des performances
Utilisation de "profileur" :
- Les profileurs sont des outils qui permettent didentifier les parties du code o le
principal du traitement est effectu.
- En utilisant ce type doutil, il est possible de concentrer ses efforts doptimisation
l o ils sont vraiment utiles.
Loi dAmdahl :
- La loi dAmdahl dcrit leffet de loptimisation dun morceau de code sur la
performance globale du programme.
Soit T = (1-)T + (T )/k = T [(1-) + /k]
new
old
old
old
o

Told = Temps dexcution avant optimisation


Tnew = Temps dexcution aprs optimisation

= % de code optimis
k
= facteur doptimisation obtenu

Alors
S = Told/Tnew =

1
(1-) + /k

(Loi dAmdahl)

Cette loi montre quun gain de performance lev sur une petite partie de
code ne rsulte pas en un gain quivalent sur lensemble du code.
Cours # 8

Cours # 8

ELE784 - Ordinateurs et programmation systme

ELE784 - Ordinateurs et programmation systme

40

20

Vous aimerez peut-être aussi