Télécharger le fichier pdf d’un mémoire de fin d’études
Ordonnancement dynamique
Un moyen de limiter l’impact des aléas sur l’IPC est de réorganiser les instructions afin d’éviter les stalls : c’est l’ordonnancement dynamique. Le processeur n’exécute alors plus les instructions dans l’ordre spécifié par le programme mais dans le désordre (Out-of-order execution, OOO). Pour cela, il gère une fenêtre d’instructions dans laquelle une instruction peut être exécutée dès que ses opérandes sont prêts. Par exemple, en cas de défaut de cache, des instructions ne dépendant pas de cet accès mémoire pourront être exécutées pendant le temps d’attente. Cependant, le processeur doit toujours s’assurer de respecter la sémantique du programme. Les instructions arithmétiques peuvent donc être réorganisées en respectant les diverses dépendances, mais pas les instructions d’accès à la mémoire et les branchements.
L’ordonnancement dynamique permet d’éviter les stalls mais a un coût important en ressources et en énergie à cause de sa complexité.
Exécution spéculative
Bien que l’exécution OOO permette d’augmenter l’IPC, celui-ci est limité par les bran-chements et les instructions d’accès à la mémoire. Les premières limitent l’IPC parce que le processeur ne peut réordonner uniquement les instructions qu’il est certain d’exécuter. Les instructions rentrent dans la fenêtre d’exécution seulement lorsque les branchements sont résolus. Les secondes parce que exécuter les accès à la mémoire dans l’ordre permet de s’assurer que la sémantique du programme (basée sur l’exécution dans l’ordre) est respectée.
L’exécution spéculative permet de lever ces limitations : le principe est d’autoriser l’exécution d’instructions qui peuvent être nécessaires et d’exécuter les instructions avec accès mémoire dans le désordre.
Pour les branchements, une branche est considérée comme prise et la fenêtre d’ins-tructions est remplie avec les instructions de cette branche, permettant leur exécution dans le désordre. Le processeur enregistre les instructions terminées dans une mémoire, le Re-Order Buffer (ROB). Finalement, le processeur sait si la branche prise était la bonne lors de la résolution du branchement. Dans ce cas, il valide les instructions cor-respondantes dans le ROB, dans l’ordre original du programme. Dans le cas contraire, il les annule, ainsi que la fermeture transitive des instructions ayant utilisé des résultats d’instructions invalides. Un mécanisme de prédiction de branchement permet de choisir la branche considérée comme prise selon diverses heuristiques afin d’augmenter le niveau l’IPC effectif.
Les opérations de lecture et d’écriture en mémoire des instructions sont gérées via une mémoire, la Load-Store Queue (LSQ), permettant de déterminer si des dépendances mé-moires ont été violées à cause de l’exécution dans le désordre. Cette mémoire enregistre les adresses des données accédées ainsi que leur valeur (dans le cas l’écriture) lors de l’exécution spéculative des instructions d’écriture (store) et de lecture (load). Les lectures récupèrent les données depuis la LSQ si une écriture correspondante a eu lieu et que cette écriture précède la lecture dans l’ordre original du programme, sinon depuis la mémoire.
Les écritures sont valides, sauf si une lecture correspondante suivant l’écriture dans l’ordre original a déjà eu lieu. Dans ce cas, l’instruction de la lecture ainsi que la fermeture tran-sitive des instructions ayant utilisé cette valeur sont annulées grâce au ROB et réinjectées dans la fenêtre d’exécution afin de les exécuter à nouveau ultérieurement. Les écritures spéculatives sont reportées en mémoire uniquement lorsque l’instruction correspondante est validée, permettant leur exécution séquentielle conformément à la sémantique du pro-gramme. Lors de la validation d’une instruction, les informations associées dans la LSQ sont retirées.
Tout comme l’ordonnancement dynamique, l’exécution spéculative augmente l’IPC mais a un coût important en mémoire, en logique et en énergie. Michaud et al. ont observé empiriquement que le nombre d’instructions exécutables parallèlement est proportionnel à la racine carrée de la taille de la fenêtre (Michaud, Seznec et Jourdan 2001). Aug-menter l’IPC exploitable via l’exécution spéculative est donc de plus en plus coûteux, plus que linéairement, pour le niveau d’IPC recherché.
Jeu d’instructions vectoriel
Plutôt que d’exploiter le parallélisme intrinsèque à un programme en l’analysant dy-namiquement, il est possible d’exposer celui-ci explicitement dans les instructions. Dans ce cas, c’est le compilateur et non le processeur, qui extrait le parallélisme du programme par des analyses statiques. Il faut alors que le jeu d’instructions du processeur soit conçu pour exprimer ce parallélisme.
Certains jeux d’instructions (comme les familles x86 et ARM) ont été étendus par des extensions vectorielles. Ces extensions (MMX, SSE, AVX, 3DNow!, NEON, etc.) ajoutent des instructions permettant de traiter des ensembles (vecteurs) de données, plutôt qu’une donnée unique. Par exemple, les extensions AVX-512 peuvent traiter des vecteurs de 512 bits, soit par exemple 16 nombres à virgule flottante simple précision, 64 entiers 8 bits, etc. Les calculs d’une instruction peuvent alors être traités efficacement par la microarchitecture du processeur et ordonnancés (statiquement) sur les ALU du processeur. Elle permet aussi d’améliorer la récupération des données en mémoire en requérant parfois que les données vectorisées soient contigües et alignées et en augmentant la densité des données « utiles » dans le programme (moins d’instructions sont utilisées pour autant d’adresses de données). La figure 1.3 donne un exemple de programme assembleur mettant en œuvre une telle extension pour un type de calcul intensément utilisé pour certains algorithmes d’intelligence artificielle.
|
Table des matières
Introduction
Contributions
Plan du document
1 Contexte
1.1 Compromis performance/puissance
1.1.1 Puissance et performance d’un transistor
1.1.2 Gestion dynamique de la fréquence et de la tension
1.2 Impact de la microarchitecture des processeurs sur les performances et l’énergie
1.2.1 Parallélisme d’instruction
1.2.2 Ordonnancement dynamique
1.2.3 Exécution spéculative
1.2.4 Jeu d’instructions vectoriel
1.2.5 Hiérarchie mémoire
1.2.6 Limites
1.3 Architectures explicitement parallèles
1.3.1 Processeur à jeu d’instruction explicitement parallèle
1.3.2 Processeur graphique
1.3.3 Processeur spécialisé pour l’intelligence artificielle
1.3.4 Discussion
1.4 Architectures dédiées
1.4.1 Architecture des FPGA
1.4.2 Modèle de programmation
1.4.3 Exploration de l’espace de conception
1.4.4 Intégration
1.5 Conclusion
2 Spéculation temporelle pour FPGA
2.1 Spéculation temporelle
2.1.1 Fréquence maximale d’un circuit
2.1.2 Overclocking et Undervolting
2.1.3 Variabilité
2.2 Tolérance aux fautes
2.2.1 Fautes, erreurs, pannes
2.2.2 Phénomènes physiques pouvant provoquer une faute
2.2.3 Erreurs temporelles
2.2.4 Comparaison des mécanismes de tolérance aux fautes existants
2.2.4.1 Redondance : duplication et triplication
2.2.4.2 Codes correcteurs d’erreur
2.2.4.3 Redondance basée sur l’arithmétique modulaire
2.2.4.4 Détection basée sur le double échantillonnage
2.2.4.5 Tolérance aux fautes logicielle
2.2.4.6 Tolérance aux fautes au niveau algorithmique
2.2.4.7 Synthèse
2.3 Conclusion
3 Réseaux de neurones convolutifs et FPGA
3.1 Réseaux de neurones convolutifs
3.1.1 Architecture
3.1.2 Types de couches
3.1.3 Optimisations algorithmiques
3.1.4 Représentation des données
3.1.5 Mises en œuvre sur FPGA
3.2 Spéculation temporelle pour accélérateurs de convolution
3.3 Impact des erreurs sur la précision
3.4 Détection d’erreur pour CNN
3.5 Conclusion
4 Spéculation temporelle sûre pour réseaux de neurones convolutifs
4.1 ABFT pour les CNN
4.1.1 Vue d’ensemble
4.1.2 ABFT pour convolution 1D
4.1.3 ABFT pour convolution 2D
4.1.4 ABFT pour sommes de convolution 2D (CNN)
4.1.5 ABFT pour convolution avec pas non unitaire
4.1.6 Autres couches de CNN
4.2 Accélérateur de convolution tolérant aux fautes
4.2.1 Accélérateur de référence
4.2.2 Détection d’erreur pour un accélérateur de convolution
4.2.3 Mise en œuvre des calculs de sommes de contrôle
4.2.3.1 Somme de contrôle de sortie
4.2.3.2 Somme de contrôle d’entrée
4.2.4 Intégration complète
4.2.4.1 Gestion de la fréquence
4.2.4.2 Architectures en streaming et moteur de calcul unique
4.3 Évaluation
4.3.1 Gains en performance et pénalités dues aux erreurs
4.3.2 Correction de la détection d’erreur
4.3.3 Convolution convertie en multiplication de matrice
4.3.4 Plateforme expérimentale
4.3.5 Amélioration des performances
4.3.6 Amélioration de l’efficacité énergétique
4.3.7 Gains en performance, en efficacité énergétique et surcoût dû à la détection d’erreur
4.3.8 Erreurs observées
4.3.9 Faux négatifs
4.4 Discussion
4.4.1 Overclocking et undervolting
4.4.2 Représentation des données
4.4.3 Variations algorithmiques de la convolution
4.4.4 Applicabilité à d’autres architectures
4.4.5 Applicabilité à d’autres algorithmes et génération automatique
4.4.6 Limites
4.5 Conclusion
Conclusion et travaux futurs
Perspectives de recherche
Liste des publications
Bibliographie
Télécharger le rapport complet
