Partie 2 · Le modèle de programmation¶
Maintenant qu'on sait à quoi ressemble la machine, on lui parle. Cette partie
construit CUDA brique par brique, de hello world à la réduction parallèle
optimale.
Pourquoi CUDA et pas autre chose¶
Ce cours enseigne d'abord CUDA C++, pour trois raisons.
- C'est le modèle que tous les autres imitent. Triton, HIP, SYCL, Metal, WebGPU, Mojo : tous exposent une grille de blocs de threads avec une mémoire partagée par bloc. Comprendre CUDA, c'est comprendre les huit autres.
- C'est le seul niveau où tout est visible. Triton cache la disposition des données, ce qui est excellent pour produire et mauvais pour apprendre.
- Les megakernels s'écrivent en CUDA C++. La partie 8 en dépend directement.
Cela ne veut pas dire qu'il faut écrire ses noyaux de production en CUDA. Voir Écosystème · Panorama pour la discussion honnête.
Ce que vous allez apprendre¶
- Écrire, compiler et lancer un noyau.
- Calculer correctement l'indice global d'un thread (et pourquoi c'est la source de bug numéro un).
- Utiliser la mémoire partagée pour transformer un noyau limité par la mémoire en noyau limité par le calcul.
- Communiquer entre threads d'un warp sans passer par la mémoire.
- Écrire une réduction et un scan efficaces — les deux primitives dont tout le reste dérive.
- Recouvrir calcul et transferts avec des flux, et supprimer le coût de lancement avec les graphes CUDA.
- Utiliser les opérations atomiques sans détruire les performances.
Ordre de lecture¶
1 · Premier noyau CUDA¶
Le programme minimal, la chaîne de compilation, le modèle hôte/périphérique, la gestion des erreurs. Le chapitre qui donne le squelette de tout le reste.
2 · Grille, blocs, warps¶
Le calcul d'indices, le choix de la taille de bloc, les grilles à parcours (grid-stride loops), et pourquoi le nombre de blocs devrait rarement être exactement le nombre d'éléments.
3 · La mémoire partagée¶
Le motif charger-synchroniser-calculer, avec la multiplication matricielle par tuiles comme exemple fil rouge. Allocation statique et dynamique.
4 · Les primitives de warp¶
__shfl_*_sync, __ballot_sync, les groupes coopératifs, et comment
communiquer sans toucher la mémoire.
5 · Réductions et scans¶
Les deux algorithmes parallèles fondamentaux, construits pas à pas de la version naïve à la version optimale. La réduction est l'exercice de référence de la programmation GPU.
6 · Flux, événements et graphes¶
Le parallélisme au niveau des noyaux : recouvrir transferts et calcul, mesurer correctement, et supprimer le coût de lancement avec CUDA Graphs — l'étape qui précède directement les megakernels.
7 · Atomiques et synchronisation¶
atomicAdd et ses pièges, le modèle mémoire de CUDA, les barrières, et la
question centrale : comment synchroniser entre blocs quand le modèle ne le
permet pas.
Le fil rouge¶
Trois programmes sont construits progressivement dans cette partie et réutilisés partout ensuite :
| Programme | Introduit en | Repris en |
|---|---|---|
| SAXPY (\(y \leftarrow \alpha x + y\)) | chapitre 1 | partout comme exemple minimal |
| Multiplication matricielle | chapitre 3 | IA · GEMM |
| Réduction (somme d'un tableau) | chapitre 5 | IA · FlashAttention |
Le code de cette partie n'a pas été exécuté
L'environnement de rédaction ne dispose ni de GPU ni de nvcc. Les extraits
sont écrits d'après le CUDA C++ Programming Guide et conformes aux
conventions de la documentation, mais ils n'ont été ni compilés ni mesurés.
Traitez-les comme du pseudo-code exécutable : lisez-les, puis tapez-les
vous-même sur une vraie carte
(Pratique · Obtenir un GPU).