Aller au contenu

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.

  1. 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.
  2. 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.
  3. 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).