Cinq postes, un colis par minute
Dans un entrepôt, une seule personne prend l’article, l’emballe, pèse le colis, colle l’étiquette et le charge. Chaque commande demande cinq minutes.
L’entrepôt installe cinq postes, un par geste. Chaque colis demande toujours cinq minutes. Pourtant, un colis prêt sort maintenant chaque minute. Un processeur fait la même chose avec les instructions.
À la fin de cette leçon
Remarque
Je peux dire comment un pipeline accélère un processeur et ce qui le ralentit.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Pipeline | les étapes de plusieurs instructions menées en même temps, chacune dans un étage | |
| Étage | une étape du pipeline, qui dure un cycle d’horloge | EX |
| Aléa | ce qui empêche l’instruction suivante de partir à temps | |
| Bulle | un cycle où un étage attend sans rien faire d’utile | |
| Transmission anticipée | le passage d’un résultat à l’instruction suivante avant son écriture | |
| Prédiction de branchement | deviner le sens d’un branchement avant de le connaître |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Cinq étages, cinq instructions à la fois
Un pipeline RISC-V classique a cinq étages. IF lit l’instruction, ID la décode et lit les registres, EX calcule. MEM lit ou écrit la mémoire, et WB écrit le résultat dans un registre.
Chaque étage dure un cycle d’horloge. Pendant qu’une instruction est en EX, la suivante est en ID et celle d’après en IF. Jusqu’à cinq instructions sont donc dans le processeur en même temps.
Exemple travaillé : trois instructions, aucun aléa
| Instruction | Cycle 1 | Cycle 2 | Cycle 3 | Cycle 4 | Cycle 5 | Cycle 6 | Cycle 7 |
|---|---|---|---|---|---|---|---|
| addi t0, zero, 4 | IF | ID | EX | MEM | WB | ||
| addi t1, zero, 6 | IF | ID | EX | MEM | WB | ||
| addi t2, zero, 8 | IF | ID | EX | MEM | WB |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Aller dans le dossier d’architecture
cd ~/archAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Plus rapide sans instruction plus rapide
Une par une, 200 instructions de 5 cycles prennent 1000 cycles. Dans un pipeline, la première finit au bout de 5 cycles, puis une autre finit à chaque cycle. Les 200 instructions prennent donc 5 + 199, soit 204 cycles.
Chaque instruction met toujours 5 cycles du début à la fin. Ce qui augmente, c’est le nombre d’instructions finies par cycle. Cela ne tient que si rien ne fait attendre une instruction.
Un résultat qui n’est pas encore prêt
Un aléa empêche l’instruction suivante de partir à temps. Le plus courant est l’aléa de données : une instruction a besoin d’un registre qu’une instruction plus ancienne n’a pas fini.
Sans aide, le pipeline insère des bulles jusqu’à l’écriture de la valeur. La transmission anticipée supprime presque toute l’attente : le résultat de EX passe directement à l’instruction suivante. Un chargement est différent. Sa valeur n’existe qu’après MEM : l’instruction qui suit attend encore un cycle.
Exemple travaillé : les bulles de notre modèle
| Instruction plus ancienne | Distance avant l’utilisatrice | Bulles sans transmission | Bulles avec transmission |
|---|---|---|---|
| add, sub ou addi | 1 instruction | 2 | 0 |
| add, sub ou addi | 2 instructions | 1 | 0 |
| lw | 1 instruction | 2 | 1 |
| lw | 2 instructions | 1 | 0 |
| Toute instruction | 3 ou plus | 0 | 0 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Écrire un programme avec un aléa de chargement
printf '.globl _start\n_start:\n addi sp, sp, -16\n li t0, 20\n sw t0, 8(sp)\n lw a0, 8(sp)\n add a0, a0, a0\n li a7, 93\n ecall\n' > attente.sAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
L’assembler
riscv64-linux-gnu-as attente.s -o attente.oAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Faire l’édition de liens
riscv64-linux-gnu-ld attente.o -o attenteAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le lancer dans l’émulateur
qemu-riscv64 ./attenteAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lire le code de sortie
echo $?Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lire le code machine
riscv64-linux-gnu-objdump -d attenteAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Erreur fréquente
Attention
Beaucoup pensent qu’un pipeline rend chaque instruction plus rapide. C’est faux : chaque instruction passe toujours par les cinq étages. Le pipeline termine plus d’instructions par cycle. Une bulle gaspille une part de ce gain : c’est pourquoi l’ordre des instructions compte.
Le compilateur bouche le trou
Un compilateur connaît les règles des bulles. Quand un chargement est suivi d’une instruction qui en a besoin, il cherche une autre instruction indépendante et la place entre les deux.
Les commandes suivantes compilent le loop.c du labo pour RISC-V. Regardez la boucle ligne par ligne, .L6, et trouvez ce qui sépare le chargement de son addition.
Compiler loop.c en assembleur RISC-V simple
riscv64-linux-gnu-gcc -O2 -march=rv64gc -S loop.cAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
La boucle ligne par ligne
grep -A 4 'L6:' loop.sAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Deviner le sens d’un branchement
Un branchement crée un aléa de contrôle : tant que EX n’a pas fait le test, le pipeline ne sait pas quoi lire ensuite. Attendre coûterait des cycles à chaque branchement.
Le processeur pratique donc la prédiction de branchement : il devine et continue. Une bonne prédiction ne coûte rien ; une mauvaise jette le travail lu depuis et repart. Le bne en bas d’une boucle revient en arrière presque à chaque fois : il est facile à deviner.
Pour aller plus loin : supprimer les bulles
Prenez ce programme : lw t0, 0(a0), add t1, t0, t0, lw t2, 4(a0), sub t3, t2, t1. Comptez ses bulles avec transmission, grâce à votre fonction.
Réordonnez ensuite les quatre lignes pour garder le même résultat avec 0 bulle. Dites quelle règle vous a permis de juger qu’un déplacement était sans danger.