L'École Gray Scott

Jour 1 — Fondations

Le vocabulaire et les principes. Optimiser suppose de comprendre le fonctionnement du matériel et de localiser les pertes de temps.

1. Le CPU

Un processeur est composé de plusieurs cœurs indépendants. La fréquence d'horloge stagne depuis ~2005 (limite thermique) ; la performance vient désormais du nombre de cœurs, ce qui rend le parallelisme incontournable.

La performance provient du nombre de cœurs, non de la fréquence brute.

CPU (socket)cœur 1registres · ALUSIMDL1 · L2cœur 2registres · ALUSIMDL1 · L2cœur 3registres · ALUSIMDL1 · L2cœur 4registres · ALUSIMDL1 · L2cache L3 partagébus mémoire (lent)RAM
Un processeur : des cœurs indépendants, chacun avec ses registres, son ALU, son unité vectorielle et ses caches

2. La compilation

La compilation traduit le C++ en code machine avant l'exécution, avec optimisation. Ses quatre étapes : préprocesseur, compilation (assembleur + optimisation), assemblage, édition de liens. L'optimisation et la vectorisation naissent à la compilation.

source.cpppréprocesseur#include, macroscompilationOPTIMISATIONassemblage.oliens+ libs → exécutable-O3 -march=native
Les quatre étapes de la compilation — l’optimisation et la vectorisation naissent à l’étape de compilation

Options recommandées : -O3 -march=native. Sans optimisation (-O0), le code peut être un ordre de grandeur plus lent.

3. La vectorisation (SIMD)

Single Instruction, Multiple Data : une instruction traite plusieurs valeurs à la fois. Le compilateur la génère automatiquement quand la boucle est régulière (accès contigus, sans dépendances).

Scalaire — 8 instructions, l’une après l’autre++++++++t₁ → t₂ → t₃ → … → t₈Vectorisé (AVX2) — 1 instruction sur 8 flottants++++++++registre 256 bits · t₁ seulement
Le même calcul : 8 additions séquentielles, ou une seule instruction vectorielle

Gain typique : ×4 à ×16 selon la largeur des registres (SSE 128 bits, AVX2 256 bits, AVX-512 512 bits).

4. Concurrence et parallélisme

ConcurrenceParallélisme
Objectifmasquer l'attente (E/S, réseau)accélérer le calcul
Matérielpossible sur un seul cœurexige plusieurs cœurs
Domaineserveurs, E/S asynchronescalcul intensif
Concurrence — 1 cœurles tâches se relaient (masquer l’attente)cœurtemps →ABParallélisme — 4 cœursles calculs s’exécutent en même tempscœur 1cœur 2cœur 3cœur 4temps →×4
Concurrence : structurer l’attente sur un seul cœur. Parallélisme : calculer réellement en même temps sur plusieurs cœurs

La concurrence est un outil de structuration ; le parallélisme en est le résultat lorsque le matériel le permet.

5. Memory-bound et compute-bound

  • Compute-bound — limité par les unités de calcul → ajouter des cœurs aide.
  • Memory-bound — limité par la bande passante ; les cœurs attendent les données → l'ajout de cœurs n'apporte qu'un gain marginal.

L'intensité arithmétique (opérations par octet chargé) détermine le régime. Les stencils ont une faible intensité arithmétique et sont généralement memory-bound. Outil d'analyse de référence : le roofline model.

performance (Gflop/s, log)intensité arithmétique (flops / octet, log)memory-boundcompute-boundtoit mémoire — bande passantetoit calcul — pic Gflop/spoint d’équilibrestencil Gray-Scott
Le roofline : sous le toit incliné, on attend la mémoire ; sous le toit plat, on attend le calcul. Le stencil vit à gauche — memory-bound
Le mur mémoire : coût d'un accès selon le niveau
Registre
0,3 ns
L1
1 ns
L2
4 ns
L3
15 ns
RAM
100 ns

Ordres de grandeur typiques — un accès RAM coûte ~100× un hit L1.

6. La pureté

Une fonction est pure lorsque sa sortie ne dépend que de ses entrées, sans effet de bord. Un calcul pur n'a pas de dépendance cachée : il est parallélisable sans data race. Un schéma à double tampon (lecture d'un tableau, écriture d'un autre) est pur et trivialement parallèle.

Pur — double tamponU0 (lecture)U1 (écriture)✓ parallélisable sans risqueEn place — impurU (lecture + écriture)⚠ data race possible
Lire un tableau, écrire dans un autre : aucune dépendance cachée. Lire et écrire le même : les threads se marchent dessus

La pureté est ce qui autorise la parallélisation sans bug.

7. Tests unitaires en calcul scientifique

Les arrondis flottants interdisent la comparaison exacte. Trois règles guident la validation :

1.  Comparaison avec tolérance    |a − b| < ε   (jamais d'égalité stricte)
2.  Vérification d'invariants      énergie, symétrie, absence de NaN, cas analytique
3.  Équivalence séq. / parallèle   une divergence révèle une data race
Copyright © 2026