7. Métriques de performance pour algorithmes et

publicité
7. Métriques de performance pour
algorithmes et programmes parallèles
7.1
Introduction : le temps d’exécution
suffit-il?
Algorithme/programme parallèle
⇒ Utilisation de plusieurs processeurs
⇒ Réduction du temps d’exécution ,
⇒ Augmentation du coût de la machine /
L’algorithme parallèle peut utiliser une mise en oeuvre qui augmente la quantité totale de travail effectuée /
Donc, non, le temps d’exécution ne suffit pas!
Dans ce qui suit :
• Métriques asymptotiques, pour des algorithmes
• Métriques réelles, pour des programmes
7.2
Temps d’exécution et profondeur
Définition 1 Le temps d’exécution TP (n) d’un algorithme parallèle A exécuté pour un problème
de taille n est le temps requis pour exécuter l’algorithme
en supposant qu’un nombre illimité de processeurs sont disponibles pour exécuter les diverses opérations.
Définition 2 La profondeur d’un calcul est définie
comme la longueur de la plus longue chaîne
de dépendances présentes dans ce calcul.
La profondeur représente le meilleur temps d’exécution
possible en supposant une machine idéale.
Nb.
d’UE
Temps
min.
1
2
3
4
...
9
6
6
6
...
Figure 7.1: Graphe de dépendances pour calcul d’une
racine d’un polynome de deuxième degré pour illustrer la
notion du meilleur temps parallèle comme longueur du plus
long chemin.
Figure 7.2: Graphe de dépendances pour calcul de la
somme d’un tableau de huit éléments, pour illustrer la notion du meilleur temps parallèle comme longueur du plus long
chemin.
Il s’agit de métriques asymptotiques (idéales).
En pratique, on mesurera le temps d’exécution
réel avec un nombre limité de processeurs
7.3
7.3.1
Coût, travail et optimalité
Coût
Définition 3 Soit un algorithme A utilisé pour résoudre, de façon parallèle, un problème de taille n
en temps TP (n).
Soit p(n) le nombre maximum de processeurs effectivement requis par l’algorithme.
Le coût de A est alors C(n) = p(n) × TP (n)
7.3.2
Travail
Définition 4 Le travail, W (n), dénote le nombre
total d’opérations effectuées par l’algorithme parallèle pour un problème de taille n sur une machine
à p(n) processeurs.
7.3.3
Coût vs. travail
Le travail est un estimé plus précis du nombre total exact d’opérations exécutées
Relation entre temps, travail et coût
• Séquentiel :
TS (n) = W (n) = C(n)
• Parallèle :
TP (n) ≤ W (n) ≤ C(n)
Figure 7.3: Le travail.
Figure 7.4: Le temps.
Figure 7.5: Le nombre de processeurs.
Figure 7.6: Le coût.
Soit le graphe suivant, qui représente les opérations et leurs
dépendances pour faire la somme d’un tableau v comptant
n éléments :
1. Quel est le temps d’exécution?
2. Quel est le travail?
3. Quel est le nombre maximal de processeurs requis?
4. Quel est le coût?
Exercice 7.1: Temps vs. coût vs. travail.
Solution :
1. Temps : O(lg n)
2. Travail : O(n)
3. Nb. processeurs : O(n)
4. Coût : O(n lg n)
Autre différence entre coût et travail :
le travail est une métrique compositionnelle,
pas le coût.
Soit S1 et S2 deux segments de code.
Travail(S1; S2) = Travail(S1) + Travail(S2)
Coût(S1; S2) ≥ Coût(S1) + Coût(S2)
Exemple illustrant la non-compositionalité
procedure foo( ref int a[*], int b[*], int n )
{
co [i = 1 to n]
a[i] = ... # Expression O(1)
oc
co [j = 1 to lg(n)]
proc( a, n )
oc
}
procedure proc( ref int a[*], int n )
{
for [i = 1 to n] {
a[i] = ...
# Expression O(1)
}
}
Algorithme 7.1: Petit algorithme pour illustrer que le coût
n’est pas une métrique compositionnelle. Quel est le temps
de cet algorithme? Quel est son travail? Quel est son coût?
7.3.4
Optimalité
Définition 5 Un algorithme parallèle est dit optimal en travail si le travail W (n) effectué par
l’algorithme est tel que W (n) ∈ Θ(TS∗(n)).
Définition 6 Un algorithme parallèle est dit optimal en coût si le coût C(n) de l’algorithme est tel
que C(n) ∈ Θ(TS∗(n)).
Question : L’algorithme avec le graphe de l’exercice
précédent est-il optimal en travail? En coût?
7.4
7.4.1
Accélération et efficacité
Accélération relative vs. absolue
Détermine combien fois un programme parallèle
est plus rapide qu’un programme séquentiel.
Notons TP (p, n) le temps pour un problème de taille
n avec p processeurs — TP (n) = TP (+∞, n).
Notons TS∗(n) le temps requis pour le meilleur programme séquentiel (pour taille n).
Définition 7 L’accélération relative Arp :
Arp
TP (1, n)
=
TP (p, n)
Définition 8 L’accélération absolue Aap :
Aap
TS∗(n)
=
TP (p, n)
Soit une machine avec p processeurs.
Quelle est en théorie la meilleure accélération absolue qu’il
est possible d’obtenir?
Aap
TS∗(n)
≤
=
TP (p, n)
?
Exercice 7.2: Meilleure accélération pour une machine avec
p processeurs.
Solution :
En théorie, la meilleure accélération est de p pour
p processeurs.
Accélération linéaire vs. superlinéaire
On parle d’accélération linéaire lorsque Ap = p.
En pratique, des accélérations linéaires sont rares /
Bizarrement, on rencontre parfois des accélérations
superlinéaires, où Ap > p.
7.4.2
Efficacité de l’utilisation des processeurs
L’efficacité nous indique dans quelle mesure les divers
processeurs sont utilisés ou non.
Définition 9 L’ efficacité d’un programme est le rapport entre le temps d’exécution séquentiel et le coût
d’exécution sur une machine à p processeurs :
TS∗(n) Aap(n)
TS∗(n)
Ep =
=
=
C(n)
p
p × TP (p, n)
7.5
Dimensionnement (scalability)
Un algorithme est dimensionnable lorsque le niveau
de parallélisme augmente au moins de façon linéaire
avec la taille du problème.
Une architecture est dimensionnable si la machine
continue à fournir les mêmes performances par processeur lorsque l’on accroît le nombre de processeurs.
7.6
Coûts des communications
Un algorithme est dit distribué lorsqu’il est conçu
pour être exécuté sur une architecture composée
d’un certain nombre de processeurs — reliés par un
réseau, où chaque processeur exécute un ou plusieurs
processus —, et que les processus coopèrent strictement en s’échangeant des messages.
Dans un tel algorithme, il arrive fréquemment que
le temps d’exécution soit largement dominé par le
temps requis pour effectuer les communications entre processeurs
En d’autres mots, les communications deviennent
les opérations «barométriques».
7.7
Sources des surcoûts d’exécution
parallèle
• Création des threads et changements de contexte
• Synchronisation et communication entre les threads
• Communications inter-processeurs
• Répartition de la charge de travail
(load balancing)
• Calculs supplémentaires
7.8
Lois d’Amdhal, de Gustafson–Barsis
et fraction séquentielle expérimentale
Remarques :
• La section qui suit est (en partie) une traduction
et (en partie) une adaptation du chapitre intitulé «Performance analysis» du livre de M.J. Quinn
«Parallel Programming in C with MPI and OpenMP »
• Parmi les modifications, certains éléments de
notation ont été simplifiés ou modifiés :
Notation de Quinn Notation utilisée
Temps
σ(n)
σ
partie
séquentielle
Temps
ϕ(n)
ϕ
partie
parallèle
Accélérationψ(n, p)
ψ
Temps
T (n, p)
pour
taille
n
et p processeurs
T (p, n)
7.8.1
Temps d’exécution, partie séquentielle,
partie parallèle et accélération
Le temps pour un problème de taille n avec p processeurs peut être décomposé en deux parties :
• σ = partie intrinsèquement séquentielle
• ϕ = partie pouvant s’exécuter en parallèle
Temps pour un processeur :
T (1, n) = σ + ϕ
(7.1)
Temps pour p processeurs :
ϕ
T (p, n) = σ +
p
Accélération :
σ+ϕ
ψ ≤
σ + ϕ/p
(7.2)
7.8.2
Loi d’Amdahl
f = fraction des opérations qui doivent être exécutées de façon séquentielle (0 ≤ f ≤ 1) :
σ
f =
σ+ϕ
On a alors :
σ
σ+ϕ =
f
Et :
σ
1
ϕ = − σ = σ( − 1)
f
f
Donc :
σ+ϕ
ψ ≤
σ + ϕ/p
σ/f
=
σ + σ(1/f − 1)/p
1/f
=
1 + (1/f − 1)/p
1
=
f + (1 − f )/p
Définition 10 (Loi d’Amdahl) Soit f la fraction
des opérations qui doivent être exécutées de façon
séquentielle, avec 0 ≤ f ≤ 1.
Alors, l’accélération maximale ψ pouvant être obtenue
avec p processeurs est :
1
ψ ≤
f + (1 − f )/p
Exemples :
• Un programme pour lequel 90 % pourrait s’exécuter
en parallèle.
Accélération maximale avec huit (8) processeurs :
ψ≤
1
≈ 4.7
0.1 + (1 − 0.1)/8
• Un programme pour lequel 75 % pourrait s’exécuter
en parallèle.
Accélération maximale sur une machine parallèle sans limite de processeurs :
1
lim
≈4
p→∞ 0.25 + (1 − 0.25)/p
Limites de la loi d’Amdahl
La formulation de la loi d’Amdahl ignore les surcoûts associés à l’exécution parallèle, c’est-à-dire,
les coûts des synchronisations et communications
entre processus.
ϕ(n)
+ κ(n, p)
T (p, n) = σ(n) +
p
L’effet Amdahl
Règle générale, la complexité de κ(n, p) est plus
faible que celle de ϕ(n). C’est-à-dire : le temps
d’exécution augmente plus rapidement que le
temps de synchronisation et communication.
Donc, pour un nombre fixe de processeurs, l’accélération va augmenter lorsqu’on augmente la taille du
problème.
En d’autres mots, plus la taille du problème est
grande, plus l’accélération est grande.
7.8.3
Loi de Gustafson–Barsis
La loi d’Amdahl suppose que l’objectif est de produire le résultat le plus rapidement possible.
Mais, souvent, l’objectif est plutôt de traiter un
problème de plus grande taille
Pour la loi de Gustafson–Barsis, on va supposer que
le temps d’exécution parallèle est fixe.
L’effet Amdahl s’explique par le fait que lorsqu’on
augmente la taille du problème, la fraction du temps
d’exécution de la partie intrinsèquement séquentielle diminue.
On ajoute des processeurs ⇒ On peut traiter des problèmes
plus gros
⇒ La fraction parallélisable augmente
⇒ La fraction séquentielle diminue
⇒ L’accélération augmente
s = fraction du temps d’exécution parallèle consacrée aux opérations séquentielles :
σ
s =
σ + ϕ/p
On a alors :
σ = (σ + ϕ/p)s
Et :
ϕ = (σ + ϕ/p)(1 − s)p
Donc :
ψ ≤
=
=
=
=
σ+ϕ
σ + ϕ/p
(σ + ϕ/p)(s + (1 − s)p)
σ + ϕ/p
s + (1 − s)p
s + p − sp
p + (1 − p)s
Définition 11 (Loi de Gustafson–Barsis) Pour
un problème de taille n traité avec p processeurs,
soit s la fraction du temps d’exécution (parallèle)
consacrée à la partie intrinsèquement séquentielle
(avec 0 ≤ s ≤ 1).
Alors, l’accélération maximale ψ pouvant être obtenue
est la suivante :
ψ ≤ p + (1 − p)s
L’accélération prédite par la loi de Gustafson–Barsis
est aussi appelée scaled speedup
Exemple :
• Un programme s’exécute en 220 secondes sur 64
processeurs.
Des mesures montrent que 5 % du temps d’exécution
est pour des parties séquentielles.
Quelle sera l’accélération (scaled speedup) obtenue
par ce programme?
ψ = 64 + (1 − 64)(0.05) = 64 − 3.15 = 60.85
7.8.4
Accélération selon la loi d’Amdhal vs.
selon la loi de Gustafson-Barsis
Nb.
Amdhal Gustafson Amdhal Gustafson Amdhal Gustafson
procs.
f ou s
0,05
0,05
0,10
0,10
0,20
0,20
2
1,90
1,95
1,82
1,90
1,67
1,80
4
3,48
3,85
3,08
3,70
2,50
3,40
8
5,93
7,65
4,71
7,30
3,33
6,60
16
9,14
15,25
6,40
14,50
4,00
13,00
32
12,55
30,45
7,80
28,90
4,44
25,80
64
15,42
60,85
8,77
57,70
4,71
51,40
128
17,41
121,65
9,34
115,30
4,85
102,60
Tableau 7.1: Accélération maximale possible pour diverses
valeurs de f ou s et divers nombres de processeurs.
Une autre façon de voir ces deux lois :
• Loi d’Amdhal
– Borne inférieure de l’accélération
– Hypothèse pessimiste = la fraction séquentielle reste constante, peu importe la taille du
problème = Le temps intrinséquement séquentiel augmente au même rythme que la taille
du problème /
• Gustafson-Barsis
– Borne supérieure de l’accélération
– Hypothèse optimiste = le temps intrinsèquement séquentiel reste constant, peu importe
la taille du problème
• La réalité. . . est quelque part entre les deux
– Le temps intrinsèquement séquentiel augmente,
mais beaucoup plus lentement que la taille
du problème
– ⇒ si on augmente la taille du problème, alors
on pourra augmenter le nombre de processeurs
pour obtenir une meilleure accélération ,
• Accélération Amdhal avec 4 processeurs
– 10 / (1 + (9/4)) = 10 / (1 + 2.25) = 3.08
• Accélération Gustafson–Barsis avec 4 processeurs
– (1 + 4*9) / 10 = 37 / 10 = 3.7
7.8.5
Fraction séquentielle déterminée expérimentalement
7.A
Mesures de performances : Un
exemple concret
public static int nbDansCercleSeq ( int nbLancers ) {
Random rnd = new Random ();
int nb = 0;
for ( int k = 0; k < nbLancers ; k ++ ) {
double x = rnd . nextDouble ();
double y = rnd . nextDouble ();
if ( x * x + y * y <= 1.0 ) {
nb += 1;
}
}
return nb ;
}
Programme Java 7.1 Une fonction parallèle evaluerPi (et sa fonction auxiliaire
nbDansCercleSeq) pour approximer la valeur de π à l’aide de la méthode de Monte
Carlo à plusieurs threads.
@SuppressWarnings ( " unchecked " )
public static double evaluerPi ( final int nbLancers ,
int nbThreads ) {
ExecutorService pool =
Executors . newFixedThreadPool ( nbThreads );
Future < Integer > lesNbs [] = new Future [ nbThreads ]; / / u n c h
for ( int k = 0; k < nbThreads ; k ++ ) {
lesNbs [ k ] = pool . submit ( () -> {
return nbDansCercleSeq ( nbLancers / nbThreads );
} );
}
int nbTotalDansCercle = 0;
for ( int k = 0; k < nbThreads ; k ++ ) {
try { nbTotalDansCercle += lesNbs [ k ]. get (); }
catch ( Exception ie ) {}
}
pool . shutdown ();
return 4.0 * nbTotalDansCercle / nbLancers ;
}
Figure 7.7: Graphe donnant le temps d’exécution du
programme Pi.java pour différents nombres de threads.
Les temps sont indiqués pour trois (3) séries différentes
d’exécution.
Figure 7.8: Graphe d’accélération du programme Pi.java
pour différents nombres de threads— moyenne de trois (3)
éxécutions.
Figure 7.9: Graphe d’efficacité du programme Pi.java
pour différents nombres de threads— moyenne de trois (3)
éxécutions, pour huit (8) processeurs.
Téléchargement