Architecture, hiérarchie mémoire

Transcription

Architecture, hiérarchie mémoire
07/09/2012
Programmation efficace :
un peu d’architecture
A. Théorie de la complexité
• Méthodologie pour analyser la complexité de calcul des algorithmes
– Complexité en temps (ou en nombre d’opérations)
– Complexité en mémoire (espace de stockage nécessaire)
A. Théorie de la complexité, élimination de Gauβ
B. Pipeline, SIMD, Prédication
C. Hiérarchie mémoire, niveaux de cache, Multiplication de matrices
D. Notion de processus, SMP, Hyperthreading
• Complexité exprimée comme fonction de la taille du paramètre
d’entrée
• Complexité d’un problème : complexité de l’algorithme permettant de
résoudre l’instance la plus difficile
• Classification :
– Problèmes solubles (en temps polynomial) : classe P
– Problèmes difficiles (solubles en temps exponentiels ) : classe NP
– Problèmes indécidables
[email protected]
Ordres de grandeur
• Taille d’un entier n : tn=log2(n) bits
–
n = O( exp( tn ) )
Complexité asymptotique
•
128 bits = 39 chiffres, 512 bits = 155 chiffres, 1024 bits = 309 chiffres
– Trier n “int”, S(n)=n
– Trier des noms de 20 caractères ASCII sur
machine 32bits, S(n)=5n
• Vitesse des ordinateurs
– 1 GHz = 10-9 secondes
– Lumière du projecteur à la salle : 3m à 300000 km/s = 10-8 s
– Ce portable fait donc 30 additions le temps que la lumière arrive du projecteur !
• Age de l’univers : 15 milliards * 365 * 24 * 3600 ≈ 5.1017 s
• Nombre d’électrons dans l’univers : 1061 * 1011 * 1012 ≈ 1084
• Complexité d’un algorithme pour des nombres de 128 bits
S(n) = nombre de mots mémoire
nécessaires à l’implantation de l’algorithme
•
T(n) = nombre d’opérations nécessaires à
l’exécution de l’algorithme
•
Équivalence asymtotique
– f(n) = O( g(n) ) ssi ∃ N, k tels que
– ∀n>N, f(n) ≤ k g(n) et g(n) ≤ k f(n)
– 5x²+3x+1 = O ( x² + 700 ) = O (x²)
– tn = 128 opérations, tn2 = 16384 ops, tn3 = 2.106 ops, tn4 = 3.108 ops
– n = 1039 opérations
2 millions de fois l’age de l’univers sur un million de PC à
1GHz
1
07/09/2012
B. 5 étapes pour calculer
L’exemple de l’algorithme de Gauß
1. Instruction fetch
•
• Matrice de taille n × n
Récupérer l’instruction assembleur nécessaire
2. Decode
• à l’étape k :
– Faire pour i=(k+1)..n
• pivot = aik/akk
• Li
Li – pivot * Lk
(n-k) fois
1 op.
2(n-k) op..
• Complexité : ∑ 2(n-k)(n-k+1) = 2/3 n3 - 2/3n2
• Complexité asymptotique : O(n3)
• Terme dominant : 2/3 n3
•
Lire les registres associés à l’instruction
3. Execute
•
Faire le calcul
4. Access
•
Synchronisation
5. Writeback
•
Execution
CALCUL1
SIMD (Single instruction, Multiple Data)
CALCUL2
• Depuis Pentium IV : un adressage des registres 128 bits à plat
–
Entrées du calcul 2 sont les sorties du
calcul 1 : PIPELINE
CALCUL1
CALCUL2
Écrire le résultat dans un registre
Chaque registre peut-être partagé en plusieurs données
• Entier de 16*8bits à 128 bits
• Flottants : 4*32 bits (SSE) ou 2*64 bits (SSE2)
– Par exemple : 4 add FP simple précision en une seule instruction
[F. Roch]
CALCUL3
2
07/09/2012
Prédication
[F. Roch]
Plusieurs unités arithmétiques
• Pentium IV, 32 bits
– SSE2 : 2 DP-flops/cycle
– Puissance de crête de 3*2 = 6 Gflops pour 3 GHz
• Itanium2, 64 bits
– 2 unités FMA (fused multiply-add, a*x+b) : 4 DP-flops/cycle
– Puissance de crête de 1.5*4 = 6 Gflops pour 1.5 GHz
• Power PC G5, 64 bits
– 2 unités DP FMA, 2 unités entières
– Puissance de crête de 2*2 = 4 Gflops pour 2 GHz
C. Hiérarchie Mémoire
Plusieurs niveaux de cache
• Bande passante maximum du bus frontal
[F. Roch]
– Vitesse d’horloge du Bus × largeur du Bus
Impossible d’afficher l’image.
Pénalités liées aux défauts de cache
3
07/09/2012
Contiguïté
SMP (Symmetric multi-processors)
• Mémoire physiquement partagée entre plusieurs processeurs
• Les processeurs communiquent facilement via leur mémoire
commune
• Contention au niveau du Bus lorsque le nombre de processeurs
augmente
[F. Roch]
• Listes
– éléments distants en mémoire
– Insertion, suppression au milieu rapides
– Parcours lent : a priori n remplissages de cache (1 pour chaque élément) !
• Tableaux
– éléments contigus en mémoire (pile ou tas)
– Parcours très rapide : ⌈ n/k ⌉ remplissages de cache au total (par exemple,
k=8000, si cache L1 = 32 ko et les éléments sont des int)
– Taille fixe
• Tableaux à taille variable
– Mémoire contiguë préallouée plus grande que la taille du tableau
– Parcours toujours très rapide
– Insertion, suppression en fin de tableau rapides
Exemple de l’algèbre linéaire (BLAS)
• En algèbre linéaire, les données manipulées sont grosses
(190Mo pour une matrice 5000×5000)
Les calculs ne sont pas locaux : besoin de parcourir toute une
dimension pour un produit scalaire
une implémentation naïve fait appel à la RAM pour chaque
opération arithmétique.
Charger une partie des données de la RAM au cache
faire le plus d'opérations possible sur ces données pour amortir le
coût de chargement
Les opérations doivent utiliser plusieurs fois les mêmes données.
Le nombre d'opérations doit être supérieur au nombre de données
Application au produit matriciel
☺ C'est le cas pour le produit matriciel en O(n3) pour O(n2) données
Mais pas pour le produit matrice vecteur ou le produit scalaire
• Problème 1 : localité des opérations
• Problème 2 : localité de la représentation des matrices
• Dans la RAM, les matrices sont
stoquées en 1D (par ligne en C et
par colonne en Fortran).
Problème de contiguïté de
certains éléments : A11 et A21 sont
espacés de n mots en C.
4
07/09/2012
Solution :
le découpage en blocs
Les matrices sont
découpées puis
recopiées en blocs
de taille fixe
☺ Un produit de deux
blocs peut alors
s'effectuer dans le
cache.
Produit de matrices par blocs
• Complexité : n2 produits scalaires, chacun en 2n-1
• Complexité asymptotique O(n3)
• Complexité pratique : 2n3
• Par blocs
– 2 × 2 blocs de taille n/2 × n/2 :
– Classique : C1 = A1 B1 + A2 B3 , etc.
– 8 multiplications de blocs et 4 additions de blocs
– Chaque multiplication d’un bloc est faite sur le même schéma,
récursivement
– Complexité : T(n) = 8 T(n/2) + 4 (n/2) 2
= 8log(n)
+ n2 (1+2+4+8+…+2log(n)-1)
= n3
+ n2 (n-1)
Les blocs : cache + complexité
• Diviser pour régner : [Strassen 1969] puis [Winograd 1971]
– Multiplication de 2 × 2 blocs en 7 multiplications et 15 additions !
– W(n) = 7 W(n/2) + 15 (n/2)2
= 7log(n) + 15/4 n2 (1+7/4+(7/4)2+…+(7/4)log(n)-1)
= n2.81 + 5 n2.81 - …
– Complexité asymptotique : O(n2.81)
– Complexité pratique : 6 n2.81
Algorithme performant doit faire quelques appels récursifs à
Strassen-Winograd puis faire les blocs de taille moyenne à l’aide du
produit classique.
Surtout utilisé en calcul exact (problèmes d’instabilité en numérique)
5
07/09/2012
D. Notion de Processus
FFLAS : 8.2 Gffops sur un XEON 3.6 GHz en 2008
5. Q-adique
4. Winograd
3. Cache-oblivious
SSE-aware
• Un processus (thread) est un programme en exécution
–
–
–
–
–
–
–
ID
Code
Données (statiques et dynamiques)
État (actif, prêt, bloqué)
Ressources (fichiers)
Signaux
Zone de sauvegarde
2. Cache-aware
• Utilise des portion de mémoire qui lui sont allouées par le système
1. Naïf
• Le ou les processeurs lui sont alloués/interrompus par le système en
fonction de leur priorité
– Plusieurs processus semblent s’exécuter « en même temps » sur un seul
processeur
partage du temps de calcul
Hyperthreading
• Le système et les applications perçoivent un seul
processeur comme 2 processeurs virtuels
• Un seul processeur exécute donc plus facilement 2
séquences d’instructions simultanément
• Efficace si les processus utilisent des unités fonctionnelles
différentes
• Inutile et même pénalisant pour les codes de calcul
intensif utilisant les unités FP
– l’HT n’accélère pas un thread seul
– l’HT n’augmente pas la quantité de ressources par CPU
– l’HT divise par 2 la puissance de crête !
6

Documents pareils