TD — Séance 2 — Cohérence de cache et protocoles
Appliquer chaque notion du cours sur des données nouvelles : politiques d’écriture, traces des protocoles MSI et MESI avec leurs latences, false sharing et disposition des données en mémoire, cohérence séquentielle, modèle TSO et barrières mémoire. Durée : une séance de TD.
Protocoles à espionnage de bus, write-back et write-allocate. Transactions : BusRd, BusRdX (y compris pour écrire depuis S), BusWB. Latences du cours : succès \(1\) cycle ; BusRd ou BusRdX \(100\) cycles ; BusWB \(100\) cycles de plus quand un autre cache détient la ligne en M ; E\(\to\)M en MESI : \(1\) cycle. Colonne « Fournie par » : « Mémoire », le cache qui détenait la ligne en M (après son BusWB), ou « – » quand le demandeur avait déjà une copie valide. Ligne de cache de \(64\) octets ; int de \(4\) octets, long de \(8\) octets (x86-64). Toutes les variables valent \(0\) au départ.
Exercice 1 : politiques d’écriture
Un programme effectue la séquence suivante sur une variable y non présente en cache, puis la ligne de y est évincée :
- Write y = 3 ; (2) Read y ; (3) Write y = 8 ; (4) Write y = 6 ; (5) Read y ; (6) éviction.
Compléter le tableau pour les trois configurations : pour chaque accès, succès (S) ou défaut (D) et nombre de transferts mémoire.
accès WT + no-allocate WB + allocate WT + allocate S / D transferts S / D transferts S / D transferts (1) Write y = 3 (2) Read y (3) Write y = 8 (4) Write y = 6 (5) Read y (6) éviction total Donner le total de chaque configuration. Laquelle limite le trafic ? Pourquoi write-through + write-allocate ne gagne-t-il rien ici sur write-through + no-allocate ?
Avec write-back + allocate, à quel moment la mémoire contient-elle la valeur \(6\) ? Que lirait un autre processeur qui irait chercher
yen mémoire juste après l’accès (4), en l’absence de protocole de cohérence ?
Exercice 2 : trace MSI à trois processeurs
Trois processeurs P1, P2, P3 et leurs caches C1, C2, C3 utilisent le protocole MSI ; tous les caches sont initialement invalides. Séquence :
- P2 : Read x
- P1 : Write x = 7
- P3 : Read x
- P2 : Read x
- P3 : Write x = 3
- P1 : Read x
Compléter le tableau (transaction sur le bus, origine de la donnée, état de chaque cache, sous la forme I\(\to\)S quand l’état change).
# Action Bus Fournie par C1 C2 C3 0 Initial – – I I I À quelles étapes y a-t-il une invalidation ? Quels caches sont invalidés ?
Après quelles étapes la mémoire est-elle périmée ? À quelles étapes redevient-elle à jour, et par quelle transaction ?
Quelle est la latence totale de la séquence (latences du cours) ?
Exercice 3 : trace MESI et latences
Mêmes trois processeurs, protocole MESI, caches initialement invalides. Séquence :
- P3 : Read x
- P3 : Write x = 8
- P1 : Read x
- P2 : Read x
- P2 : Write x = 4
- P2 : Write x = 6
- P1 : Write x = 2
Compléter le tableau : transaction, origine de la donnée, états, latence de l’étape et latence cumulée.
# Action Bus Fournie par C1 C2 C3 Latence Cumul 0 Initial – – I I I – 0 Refaire le calcul de la latence de chaque étape avec MSI. Quel est le gain de MESI ? À quelle étape est-il obtenu ?
Pourquoi l’écriture (5) coûte-t-elle \(100\) cycles dans les deux protocoles, et l’écriture (6) seulement \(1\) cycle ?
Même travail, sans tableau détaillé, pour la séquence : P1 : Read x ; P2 : Read x ; P3 : Write x = 5 ; P3 : Read x ; P1 : Read x ; P2 : Write x = 1. Donner les états après chaque étape et les deux latences totales. Pourquoi MESI ne gagne-t-il rien ici ? Quelle étape utilise le signal de partage ?
Exercice 4 : false sharing
Le service des statistiques compte les ventes de huit régions (Dakar, Thiès, Kaolack, Saint-Louis, Ziguinchor, Kolda, Matam, Tambacounda) avec huit fils sur huit cœurs ; le fil i incrémente ventes[i] \(500\,000\) fois.
long ventes[8];
/* le fil i execute : */
for (int j = 0; j < 500000; j++) {
ventes[i]++;
}- Combien d’octets occupe
ventes? Dans combien de lignes de cache, si le tableau commence au début d’une ligne ? Et sinon ? - Donner une borne haute du nombre de transferts de la ligne entre caches. Pourquoi le nombre réel est-il plus petit ?
- Écrire une structure rembourrée
struct vente_pqui place chaque compteur à \(64\) octets du suivant. Quelle est la taille du rembourrage ? Que vautsizeof(struct vente_p)? - La déclaration
alignas(64) long ventes[8];corrige-t-elle le problème ? Proposer une déclaration qui aligne chaque compteur sur une ligne. - Réécrire la boucle avec une variable locale. Combien d’écritures chaque fil fait-il alors dans le tableau partagé ?
- Compilée avec
gcc -O2, la boucle d’origine devientaddq $500000, (%rdx,%rax,8). Que devient le false sharing ? Comment le rendre mesurable dans une expérience ?
Exercice 5 : cohérence séquentielle
Deux fils partagent X et Y, qui valent \(0\) au départ ; r1 et r2 sont des registres du second fil.
| Fil 1 | Fil 2 |
|---|---|
(1) X = 1 |
(3) r1 = Y |
(2) Y = 1 |
(4) r2 = X |
Combien d’ordres globaux respectent l’ordre de chaque programme ? Les écrire tous et compléter le tableau.
n° ordre global r1r21 2 3 4 5 6 Quelles sorties \((r1, r2)\) sont possibles en cohérence séquentielle ? La sortie \((1, 0)\) est-elle possible ? Justifier par un cycle d’ordre.
Ce code sert à « publier » une donnée :
Xest la donnée,Yun drapeau. Que garantit la réponse de (b) au fil qui litY = 1?Sous TSO (x86), la sortie \((1, 0)\) devient-elle possible ? Justifier avec les règles de TSO.
Exercice 6 : vrai ou faux
Dire si chaque affirmation est vraie ou fausse et justifier en une phrase.
- En MSI, une ligne en S peut se trouver dans plusieurs caches à la fois.
- Une lecture qui trouve sa ligne en M dans son propre cache émet un BusRd.
- En MESI, une lecture qui part de I donne toujours l’état E.
- Avec write-through et write-no-allocate, une écriture sur une ligne absente ne charge pas la ligne.
- Un cache en E qui observe un BusRdX passe en I sans BusWB.
- Déclarer deux compteurs voisins
volatilesupprime le false sharing. - Sous TSO, deux écritures d’un même fil peuvent être vues dans l’ordre inverse par un autre fil.
- Une barrière StoreLoad empêche une lecture de dépasser une écriture précédente du même fil.
Exercice 7 (approfondissement) : TSO et barrières
| Fil 1 | Fil 2 |
|---|---|
(1) X = 1 |
(4) Z = 1 |
(2) Y = 1 |
(5) r2 = X |
(3) r1 = Z |
- Combien d’ordres globaux respectent l’ordre de chaque programme ? En cohérence séquentielle, la sortie \(r1 = r2 = 0\) est-elle possible ? Justifier sans énumérer tous les ordres.
- Sous TSO, décrire une exécution, avec le contenu des tampons d’écriture et de la mémoire à chaque étape, qui donne \(r1 = r2 = 0\).
- On place une barrière StoreLoad entre (2) et (3), dans le fil 1 seulement. La sortie \(r1 = r2 = 0\) reste-t-elle possible ? Justifier.
- Où faut-il placer des barrières pour interdire cette sortie ? Pourquoi une barrière StoreStore entre (1) et (2) ne sert-elle à rien sous TSO ?
Pour cette séance
Le cours
Les slides
À lire en ligne
À télécharger
- Notebooks des labs de la séance 2 (ZIP, 36 Ko)