Chapitre 5: Conception du système de mémoire GPU
Les unités de traitement graphique (GPU) sont devenues des accélérateurs hautement parallèles et programmables capables d'atteindre des performances élevées et une efficacité énergétique sur une large gamme d'applications. Le système de mémoire est un composant critique des architectures de GPU modernes, car il doit fournir un accès rapide aux données à un grand nombre de threads simultanés. Dans ce chapitre, nous explorerons les principaux éléments de la conception du système de mémoire GPU, y compris les technologies DRAM utilisées dans les GPU, les contrôleurs de mémoire et l'arbitrage, la mémoire partagée et les caches, ainsi que les techniques d'utilisation efficace de la mémoire.
Technologies DRAM pour les GPU
La mémoire d'accès aléatoire dynamique (DRAM) est la principale technologie utilisée pour mettre en œuvre la mémoire principale dans les systèmes informatiques modernes, y compris les GPU. La DRAM offre une densité élevée et un coût relativement faible par rapport à d'autres technologies de mémoire. Cependant, la DRAM présente également une latence d'accès plus élevée et une bande passante plus faible par rapport aux mémoires intégrées telles que les caches et les registres.
Les GPU utilisent généralement des technologies DRAM spécialisées optimisées pour une bande passante élevée plutôt qu'une latence faible. Certaines des technologies DRAM couramment utilisées dans les GPU sont:
-
GDDR (Graphics Double Data Rate): GDDR est une technologie DRAM spécialisée conçue pour les cartes graphiques et les consoles de jeux. Elle offre une bande passante supérieure à la DRAM DDR standard en utilisant un bus plus large et des vitesses d'horloge plus élevées. Les versions les plus récentes, GDDR5 et GDDR6, offrent des bandes passantes respectives allant jusqu'à 512 Go/s et 768 Go/s.
-
HBM (High Bandwidth Memory): HBM est une technologie de mémoire DRAM en 3D à haut rendement qui offre une bande passante très élevée et une faible consommation d'énergie. HBM empile plusieurs matrices de mémoire DRAM les unes sur les autres et les connecte à l'aide de traversées de silicium (TSV), ce qui permet des taux de transfert de données beaucoup plus élevés que ceux de la DRAM traditionnelle. HBM2 peut fournir des bandes passantes allant jusqu'à 1 To/s.
La figure 5.1 illustre la différence entre la mémoire GDDR traditionnelle et la mémoire HBM en 3D.
Mémoire GDDR Mémoire HBM
____________ ______________________
| | | ___________________ |
| DRAM | | | | |
| Chips | | | Matrices | |
| | | | DRAM | |
| | | |___________________| |
| | | . |
| | | . |
| | | . |
|____________| | ___________________ |
| | | | |
PCB | | Circuit Logique | |
| |___________________| |
|______________________|
Figure 5.1: Comparaison des architectures de mémoire GDDR et HBM.
Le choix de la technologie DRAM dépend des exigences spécifiques du GPU, telles que le budget d'alimentation, le facteur de forme et les applications cibles. Les GPU haut de gamme pour les jeux et les graphismes professionnels utilisent souvent le GDDR6 pour sa bande passante élevée, tandis que le HBM2 est plus courant dans les GPU pour centres de données et calcul haute performance, où l'efficacité énergétique est une préoccupation majeure.
Contrôleurs de mémoire et arbitrage
Les contrôleurs de mémoire sont responsables de la gestion du flux de données entre le GPU et la DRAM hors-chip. Ils traitent les demandes de mémoire des cœurs du GPU, planifient les commandes de DRAM et optimisent les motifs d'accès à la mémoire pour maximiser l'utilisation de la bande passante et minimiser la latence.
Les contrôleurs de mémoire GPU utilisent généralement une conception multi-canaux pour fournir une bande passante élevée et un accès parallèle à la DRAM. Chaque canal mémoire est connecté à une ou plusieurs matrices de mémoire DRAM et dispose de ses propres bus de commande et de données. Le contrôleur de mémoire répartit les demandes de mémoire sur les canaux disponibles pour maximiser le parallélisme et éviter les conflits de canaux.
La figure 5.2 montre un diagramme simplifié d'un contrôleur de mémoire GPU avec quatre canaux.
Cœurs du GPU
|
______|______
| |
| Contrôleur |
| de |
| mémoire |
|_____________|
| | | |
Ch0 Ch1 Ch2 Ch3
| | | |
DRAM DRAM DRAM DRAM
Figure 5.2: Contrôleur de mémoire GPU avec quatre canaux.
L'arbitrage de la mémoire est le processus de décision des demandes de mémoire qui doivent être traitées en premier en présence de demandes multiples en attente. Les GPU utilisent différentes politiques d'arbitrage pour optimiser les performances et l'équité du système de mémoire:
-
Premier arrivé, premier servi (FIFO): La politique d'arbitrage la plus simple, où les demandes sont traitées dans l'ordre d'arrivée. La politique FIFO est équitable mais peut entraîner des performances sous-optimales en raison de l'absence de réarrangement des demandes.
-
Round-Robin (RR): Les demandes sont traitées dans un ordre cyclique, assurant une priorité égale pour tous les demandeurs. RR garantit l'équité mais peut ne pas optimiser la localité ou l'urgence des demandes.
-
Basé sur la priorité: Les demandes se voient attribuer des priorités en fonction de critères divers, tels que le type de demande (lecture vs écriture), la source (texture vs cache L2) ou l'âge de la demande. Les demandes de haute priorité sont traitées en premier.
-
Basé sur les délais: Les demandes sont planifiées en fonction de leurs délais pour garantir une exécution en temps opportun. Cela est particulièrement important pour les applications graphiques en temps réel.
-
Conscient de la localité: Le contrôleur de mémoire tente de planifier les demandes qui accèdent à des emplacements de mémoire voisins afin de maximiser les hits de tampon de lignes et de minimiser les coûts de précharge et d'activation de la DRAM.
Les contrôleurs de mémoire GPU avancés utilisent souvent une combinaison de ces politiques d'arbitrage pour atteindre le meilleur équilibre entre les performances, l'équité et les exigences en temps réel.
Mémoire partagée et caches
Les GPU utilisent un système de mémoire hiérarchique qui comprend à la fois des caches gérés par logiciel et des caches gérés par matériel pour réduire la latence et la bande passante demandées par la mémoire principale.
Mémoire partagée
La mémoire partagée est un espace mémoire géré par logiciel sur puce qui est partagé entre les threads d'un bloc de threads (NVIDIA) ou d'un groupe de travail (OpenCL). Elle agit comme un cache contrôlé par l'utilisateur, permettant aux programmeurs de gérer explicitement le déplacement et la réutilisation des données au sein d'un bloc de threads.
La mémoire partagée est généralement mise en œuvre à l'aide de bancs de SRAM à accès multiport pour fournir un accès à faible latence et à large bande passante. Chaque banc peut traiter une demande de mémoire par cycle, il est donc nécessaire que le matériel arbitre entre les accès concurrents au même banc pour éviter les conflits.
La figure 5.3 illustre l'organisation de la mémoire partagée dans un cœur de GPU.
Bloc de threads
______________________
| _________________ |
| | Thread 0 | |
| |_________________| |
| . |
| . |
| . |
| _________________ |
| | Thread N-1 | |
| |_________________| |
|______________________|
|
________|________
| |
| Mémoire |
| partagée |
| ____________ |
| | Banc 0 | |
| |____________| |
| | Banc 1 | |
| |____________| |
| . |
| . |
| . |
| | Banc M-1 | |
| |____________| |
|_________________|
Figure 5.3: Organisation de la mémoire partagée dans un cœur de GPU.
Une utilisation appropriée de la mémoire partagée peut améliorer considérablement les performances des noyaux de GPU en réduisant le nombre d'accès à la DRAM plus lente hors-chip. Cependant, cela nécessite une programmation soignée pour assurer un partage efficace des données et éviter les conflits de bancs.
Caches gérés par matériel
En plus de la mémoire partagée gérée par logiciel, les GPU utilisent également des caches gérés par matériel pour exploiter automatiquement la localité des données et réduire les accès à la DRAM. Les types les plus courants de caches gérés par matériel dans les GPU sont:
-
Cache de données L1: Un petit cache par cœur qui stocke les données de mémoire globale récemment accédées. Le cache L1 est généralement privé à chaque cœur de GPU et est utilisé pour réduire la latence des accès mémoire globaux.
-
Cache de textures: Un cache spécialisé conçu pour optimiser l'accès aux données de texture en lecture seule. Le cache de textures est optimisé pour la localité spatiale en 2D et prend en charge les opérations de filtrage et d'interpolation accélérées par matériel.
-
Cache de constantes: Un petit cache en lecture seule qui stocke les données constantes fréquemment accédées. Le cache de constantes est diffusé à tous les threads d'un warp, ce qui le rend efficace pour les données partagées entre de nombreux threads.
-
Cache L2: Un cache plus grand et partagé qui se trouve entre les cœurs du GPU et la mémoire principale. Le cache L2 stocke les données qui sont évacuées des caches L1 et est utilisé pour réduire le nombre d'accès à la DRAM.
La figure 5.4 montre une hiérarchie mémoire GPU typique avec des caches gérés par matériel.
GPU Core 0 GPU Core 1 GPU Core N-1
________________ ________________ ________________
| | | | | |
| Cache L1 | | Cache L1 | | Cache L1 |
| de | | de | | de |
| données | | données | | données |
|________________| |________________| |________________|
| | | | | |
| Cache | | Cache | | Cache |
| de textures | | de textures | | de textures |
|________________| |________________| |________________|
| | | | | |
| Cache | | Cache | | Cache |
| de constantes | | de constantes | | de constantes |
|________________| |________________| |________________|
| | |
|_____________________|_____________________|
|
_______|_______
| |
| Cache L2 |
|_______________|
|
Mémoire principale
Figure 5.4: Hiérarchie de la mémoire GPU avec des caches gérés par le matériel.
Les caches gérés par le matériel permettent d'améliorer les performances des applications GPU en exploitant automatiquement la localité des données et en réduisant le nombre d'accès à la DRAM. Cependant, ils peuvent également introduire des problèmes de cohérence et de consistance du cache, en particulier dans le contexte des modèles de programmation parallèle tels que CUDA et OpenCL.
Techniques pour une utilisation efficace de la mémoire
Une utilisation efficace du système de mémoire GPU est essentielle pour obtenir des performances élevées et une efficacité énergétique. Certaines techniques clés permettant d'optimiser l'utilisation de la mémoire dans les applications GPU incluent :
-
Regroupement: Arranger les accès à la mémoire des threads dans un warp vers des emplacements mémoire adjacents, permettant au matériel de les combiner en une seule transaction mémoire plus large. Le regroupement permet de maximiser l'utilisation de la bande passante de la DRAM et de réduire le nombre de transactions mémoire.
-
Optimisation de la structure des données: Organiser les structures de données en mémoire de manière à maximiser la localité spatiale et à minimiser les défauts de cache. Cela comprend des techniques telles que l'agencement en structure de tableaux (SoA), qui regroupe les éléments de données du même type, et l'agencement en tableau de structures (AoS), qui regroupe les éléments de données appartenant à la même structure.
-
Mise en cache et prélecture: Utiliser efficacement les caches gérés par le matériel en exploitant la localité temporelle et spatiale des schémas d'accès à la mémoire. Cela peut être réalisé grâce à des techniques telles que le découpage des données, qui divise les données en petits morceaux adaptés au cache, et la prélecture logicielle, qui charge explicitement les données dans le cache avant qu'elles ne soient nécessaires.
-
Ordonnancement des accès mémoire: Réorganiser les accès mémoire afin de maximiser les hits dans les tampons de lignes et de minimiser les surcharges de précharge et d'activation de la DRAM. Cela peut être réalisé grâce à des mécanismes matériels dans le contrôleur de mémoire ou grâce à des techniques logicielles telles que l'optimisation des schémas d'accès et les transformations de la structure des données.