Retour aux cours
AI032 Professional

Programmation de processeurs massivement parallèles : Approche pratique

Ce cours propose une introduction complète au calcul sur GPU et à la programmation parallèle en utilisant l'environnement CUDA C. Il couvre les architectures GPU, la parallélisation des données, la gestion des threads, l'optimisation de la mémoire et les considérations avancées liées aux performances, illustrées à travers des études de cas du monde réel telles que la reconstruction d'IRM et la visualisation moléculaire.

4.9
36.0h
569 étudiants
0 j'aime
Intelligence Artificielle
Commencer à apprendre

Aperçu du cours

📚 Résumé du contenu

Ce cours offre une introduction complète au calcul sur GPU et à la programmation parallèle en utilisant l’environnement CUDA C. Il couvre les architectures GPU, la parallélisation des données, la gestion des threads, l’optimisation de la mémoire et les considérations avancées sur les performances, illustrées à travers des études de cas réels comme la reconstruction d’IRM et la visualisation moléculaire.

Maîtrisez l’art du calcul parallèle haute performance grâce à un guide pratique et appliqué à CUDA et aux architectures GPU.

Auteur : David B. Kirk, Wen-mei W. Hwu

Remerciements : Ian Buck, John Nickolls, équipe NVIDIA DevTech, Jensen Huang, David Luebke, Bill Bean, Simon Green, Mark Harris, Manju Hedge, Nadeem Mohammad, Brent Oster, Peter Shirley, Eric Young et Cyril Zeller.

🎯 Objectifs d'apprentissage

  1. Différencier les philosophies de conception et les trajectoires de performance des CPUs multicœurs et des GPUs many-core.
  2. Identifier les composants clés d'une architecture GPU moderne, notamment les Streaming Multiprocessors (SMs) et les structures de mémoire.
  3. Appliquer la loi d'Amdahl pour calculer le gain théorique et identifier l'impact des goulets d'étranglement séquentiels.
  4. Contraire les différences architecturales entre pipelines fixes et tableaux de processeurs unifiés programmables.
  5. Expliquer le rôle du "GPGPU" comme étape intermédiaire et les limitations des premiers modèles de programmation shader.
  6. Analyser comment des fonctionnalités matérielles comme les opérations atomiques, la synchronisation par barrière et le support de la double précision ont permis la transition vers un calcul généralisé évolutif.
  7. Identifier et exploiter la parallélisation des données dans les algorithmes de multiplication matricielle.
  8. Mettre en œuvre la gestion de la mémoire périphérique, incluant l'allocation, le transfert de données entre hôte et périphérique, et la libération.
  9. Créer et exécuter des noyaux CUDA en utilisant des index de thread et des configurations appropriées de grille/bloc.
  10. Concevoir des hiérarchies de threads multidimensionnelles (grilles et blocs) pour mapper des structures de données complexes sur le matériel GPU.

🔹 Leçon 1 : Introduction au calcul parallèle et aux architectures GPU

Aperçu : Cette leçon explore le changement fondamental du calcul séquentiel vers le calcul parallèle, poussé par les divergences entre les philosophies de conception des CPUs et des GPUs. Les étudiants examineront les trajectoires « multicœur » versus « many-core », comprendront l’architecture matérielle qui permet aux GPUs d’atteindre un débit massif, et apprendront les contraintes mathématiques du gain de vitesse via la loi d’Amdahl.

Résultats d’apprentissage :

  • Différencier les philosophies de conception et les trajectoires de performance des CPUs multicœurs et des GPUs many-core.
  • Identifier les composants clés d’une architecture GPU moderne, y compris les Streaming Multiprocessors (SMs) et les structures de mémoire.
  • Appliquer la loi d’Amdahl pour calculer le gain théorique et identifier l’impact des goulets d’étranglement séquentiels.

🔹 Leçon 2 : Évolution et avenir du calcul GPU

Aperçu : Cette leçon suit l’évolution architecturale de l’unité de traitement graphique (GPU), depuis son origine comme matériel spécialisé à fonction fixe pour le rendu de triangles jusqu’à sa situation actuelle en tant que puissant processeur parallèle unifié et généraliste. Les étudiants exploreront le passage des pipelines rigides aux shaders programmables, l’émergence du mouvement GPGPU, et les architectures évolutives modernes qui alimentent les simulations scientifiques et ingénierie actuelles.

Résultats d’apprentissage :

  • Contraire les différences architecturales entre pipelines fixes et tableaux de processeurs unifiés programmables.
  • Expliquer le rôle du "GPGPU" comme étape intermédiaire et les limites des premiers modèles de programmation shader.
  • Analyser comment des fonctionnalités matérielles comme les opérations atomiques, la synchronisation par barrière et le support de la double précision ont permis la transition vers un calcul généralisé évolutif.

🔹 Leçon 3 : Structure des programmes CUDA et gestion de la mémoire

Aperçu : Cette leçon couvre l’architecture fondamentale d’un programme CUDA, en soulignant la distinction entre l’exécution hôte (CPU) et périphérique (GPU). Les étudiants apprendront à identifier la parallélisation des données dans les opérations matricielles, à gérer des espaces mémoire distincts à l’aide de l’API CUDA, et à organiser l’exécution parallèle à travers une hiérarchie de grilles, blocs et threads en utilisant le style Single-Program, Multiple-Data (SPMD).

Résultats d’apprentissage :

  • Identifier et exploiter la parallélisation des données dans les algorithmes de multiplication matricielle.
  • Mettre en œuvre la gestion de la mémoire périphérique, incluant l'allocation, le transfert de données entre hôte et périphérique, et la libération.
  • Créer et exécuter des noyaux CUDA en utilisant des index de thread et des configurations adaptées de grille/bloc.

🔹 Leçon 4 : Threading et planification avancés CUDA

Aperçu : Cette leçon explore l’organisation hiérarchique des threads dans CUDA, en mettant l’accent sur la façon dont l’indexation multidimensionnelle est mappée sur les données physiques et les ressources matérielles. Elle détaille les mécanismes de synchronisation par barrière et de scalabilité transparente, concluant par les principes architecturaux de l’attribution des threads et de la planification par warp utilisés pour atteindre la tolérance aux latences dans le calcul haute performance.

Résultats d’apprentissage :

  • Concevoir des hiérarchies de threads multidimensionnelles (grilles et blocs) pour mapper des structures de données complexes sur le matériel GPU.
  • Implémenter un indexage précis des données en utilisant les variables intégrées CUDA (blockIdx, threadIdx, blockDim).
  • Appliquer la synchronisation par barrière pour assurer l’intégrité des données tout en maintenant une scalabilité transparente sur différentes architectures GPU.

🔹 Leçon 5 : Optimisation de la mémoire et tiling de mémoire partagée

Aperçu : Cette leçon explore comment la bande passante mémoire et les contraintes des ressources agissent comme goulets d’étranglement principaux dans le calcul parallèle. Elle détaille l’utilisation du "tiling" pour réduire le trafic de mémoire globale et explique le rôle critique des barrières de synchronisation (__syncthreads()) ainsi que le choix stratégique entre registres et mémoire partagée pour optimiser les performances.

Résultats d’apprentissage :

  • Analyser comment les limites des registres et de la mémoire partagée déterminent le niveau de parallélisme (occupancy) dans un noyau.
  • Quantifier la réduction de la consommation de bande passante mémoire globale obtenue grâce aux techniques de tiling.
  • Identifier la nécessité de fonctions de synchronisation pour maintenir l’intégrité des données lors de l’accès à la mémoire partagée.

🔹 Leçon 6 : Analyse des performances et exécution SIMT

Aperçu : Cette leçon explore les considérations architecturales et algorithmiques essentielles pour optimiser les noyaux CUDA. Elle passe des modèles d’exécution basiques — spécifiquement l’unité Single-Instruction, Multiple-Thread (SIMT) et le partitionnement par warp — aux techniques avancées d’optimisation des performances, incluant le regroupement de mémoire, la multiplication matricielle par tiling et la partitionnement dynamique des ressources des Streaming Multiprocessors (SM).

Résultats d’apprentissage :

  • Analyser le mappage des blocs de threads multidimensionnels sur l’ordre linéaire d’exécution des warps du matériel.
  • Évaluer et minimiser la divergence de flux de contrôle dans les algorithmes de réduction parallèles.
  • Optimiser la bande passante mémoire globale en implémentant des motifs de regroupement de mémoire et d’accès par tiling.

🔹 Leçon 7 : Arithmétique en virgule flottante et précision numérique

Aperçu : Cette leçon traite de l’architecture fondamentale des nombres en virgule flottante, en se concentrant sur les composants standard IEEE 754 : signe, exposant encodé avec excès, et mantisse normalisée. Les étudiants exploreront comment ces motifs de bits sont mappés sur une ligne de nombres discrète et comment les limites de cette représentation affectent la précision des algorithmes complexes comme les sommes à grande échelle.

Résultats d’apprentissage :

  • Décomposer le format en virgule flottante pour calculer des valeurs numériques à partir de motifs de bits en utilisant la représentation normalisée et l’encodage avec excès.
  • Visualiser la distribution des nombres représentables sur une ligne numérique et expliquer l’impact de l’allocation des bits entre exposant et mantisse.
  • Quantifier l’imprécision numérique en utilisant les ULP (Unités de dernier bit) et identifier comment les différents modes d’arrondi contribuent à l’erreur.

🔹 Leçon 8 : Étude de cas : Parallélisation de la reconstruction d’IRM

Aperçu : Cette leçon explore la parallélisation de la reconstruction avancée d’IRM sur GPU. Elle se concentre sur le processus itératif de reconstruction pour les trajectoires non cartésiennes, en particulier sur l’optimisation du noyau très coûteux F^H d par des transformations de boucle, une gestion efficace de la mémoire constante, une restructuration des données et l’utilisation de fonctions trigonométriques accélérées matérièlement.

Résultats d’apprentissage :

  • Comprendre la transition de la reconstruction basée sur FFT cartésienne vers des algorithmes itératifs à solveur linéaire pour les données k-espace non cartésiennes.
  • Appliquer la fission de boucle et l’échange de boucles pour transformer du code C séquentiel en une structure adaptée à un mappage massif de threads CUDA.
  • Optimiser le débit mémoire en utilisant le chunking de mémoire constante et des dispositions de données Array-of-Structs (AoS).

🔹 Leçon 9 : Étude de cas : Visualisation moléculaire et exécution multi-GPU

Aperçu : Cette leçon explore l’application pratique du calcul GPU à la visualisation moléculaire, en particulier en utilisant la méthode de somme directe de Coulomb (DCS) pour calculer les cartes de potentiel électrostatique. Les étudiants passeront d’une implémentation de noyau de base à des versions hautement optimisées qui exploitent le déroulement d'instructions, le regroupement de mémoire et le remplissage.

Résultats d’apprentissage :

  • Implémenter un noyau de somme directe de Coulomb (DCS) en utilisant la mémoire constante CUDA et les techniques d’occlusion de latence mémoire globale.
  • Optimiser les performances du noyau par déroulement d’instructions et réutilisation des calculs coordonnés communs.
  • Appliquer des stratégies de regroupement de mémoire et de remplissage pour aligner les accès mémoire globale GPU afin de maximiser la bande passante.

🔹 Leçon 10 : Pensée computationnelle et sélection d’algorithmes parallèles

Aperçu : Cette leçon explore la transition du raisonnement séquentiel vers la résolution de problèmes parallèles en se concentrant sur les objectifs de la programmation parallèle et la sélection stratégique des algorithmes. Les étudiants apprendront à décomposer les problèmes en unités parallélisables, à appliquer la pensée computationnelle pour combler le fossé entre science du domaine et architecture matérielle, et à évaluer les performances des algorithmes.

Résultats d’apprentissage :

  • Identifier les objectifs principaux de la programmation parallèle et calculer le gain théorique en utilisant la loi d’Amdahl.
  • Différencier la décomposition au niveau des tâches et celle au niveau des données, et appliquer les stratégies centrées sur les atomes (scatter) ou centrées sur la grille (gather).
  • Évaluer et sélectionner des algorithmes parallèles selon des critères tels que la bande passante mémoire, la complexité computationnelle et les contraintes architecturales.

🔹 Leçon 11 : Introduction au modèle de programmation OpenCL

Aperçu : Cette leçon présente OpenCL comme un cadre pour le calcul parallèle hétérogène, en se concentrant sur son modèle de parallélisation des données et son abstraction hiérarchique du matériel. Les étudiants apprendront à mapper les structures NDRange et de mémoire d’OpenCL aux équivalents CUDA, et maîtriseront la gestion côté hôte des périphériques via un modèle de compilation dynamique.

Résultats d’apprentissage :

  • Mapper la parallélisation et les hiérarchies de mémoire d’OpenCL aux architectures spécifiques CUDA (ex : mapper les Work-groups aux Blocks et la mémoire locale à la mémoire partagée).
  • Implémenter des fonctions noyau OpenCL et gérer l’environnement d’exécution côté hôte à l’aide de Contexts et de Command Queues.
  • Exécuter le flux de compilation dynamique pour construire des noyaux à partir de code source en temps réel.

🔹 Leçon 12 : Fonctionnalités modernes des GPU et perspective future

Aperçu : Cette leçon explore l’évolution architecturale et fonctionnelle des GPU, en se concentrant sur la transition vers une gestion de mémoire sophistiquée, des capacités améliorées d’exécution de noyaux et une augmentation de la performance des cœurs. Les étudiants examineront comment des fonctionnalités comme l’Espace Mémoire Unifié et les appels de fonctions au niveau du noyau transforment le GPU en un processeur généraliste.

Résultats d’apprentissage :

  • Expliquer l’importance de l’évolution de l’architecture mémoire et du passage vers un Espace Mémoire Unifié 64 bits.
  • Analyser comment les opérations atomiques améliorées et les appels de fonctions au niveau du noyau permettent la mise en œuvre de structures et d’algorithmes complexes.
  • Évaluer les impacts de performance de l’exécution simultanée de noyaux, des améliorations de la vitesse en double précision et de l’efficacité du flux de contrôle dans les environnements GPU modernes.