La cohérence des caches en 3 leçons:
Broadcasting: CPU1 a besoin d'une ligne qui n'est pas dans sa cache (un ligne de mémoire, pas de coke, quoique, le pentium original en FDIV, il avait bien sniffé),on envoie un message à tout le monde pour savoir si un autre CPU a déjà la ligne en cache qqe part. En fonction de la réponse, on avise. Evidemment, le nombre de message croît exponentiellement avec le nombre de CPU.
Directory: l'entité qui se charge de la mémoire garde une trace de quel CPU a quoi. C'est évidemment nettement plus complexe à mettre en oeuvre mais les performances ne se dégradent pas lorsque l'on ajoute des CPU.
L'opteron utilise le broadcasting, l'EV7 des directories distribués, c'est-à-dire que chaque controlleur mémoire sur chaque CPU est chargé de mémoiriser qui a quoi (du moins c'ezst ce que l'on peut supposer, le système de cohérence de l'EV7 n'a jamais fait l'objet d'une publication, c'est un secret très bien guardé).
write-update: protocole où en cas de modification d'une ligne de cache, le CPU responsable va envoyer à tous les CPUs ayant une copie de la ligne la dernière valeur
write-invalidate: c'est comme le write-update sauf que le CPU n'envoie pas la valeur, il signale juste aux autres que leur valeur n'est plus à jour (plus valide)
MESI, MOESI: acronymes désignant deux protocoles possibles pour gérer la cohérence des caches. Ces lettres désignent les états par lesquels passent les lignes d'une cache.
MESI, protocole utilisé par les CPUs intel
M: modified: toute ligne de cache sur laquelle le CPU écrit passe en modified
E: exclusive: le CPU est le seul a avoir cette ligne en cache, la donnée n'a pas encore été modifiée. Si un autre CPU va chercher cette ligne en mémoire, elle passe en Shared
S: Shared: plusieurs CPU ont cette ligne en cache (mais elle n'a pas encore été modifiée)
I: invalid: la ligne de cache n'est plus valide (elle est en M ailleurs)
Question classique: pq un état E et S? parce que tant que la ligne est en E, pas besoin de générer un message d'invalidation si on la modifie. La seul modment où on génère un broadcast c'est lors d'une transition S->M ou I->M
MOESI, protocole utilisé sur le K7, K8, EV6, EV7
C'est la même chose sauf que l'on a aussi un nouvel état, le O
O: Owned: La ligne a été modifiée et elle était partagée entre plusieurs CPU. Un CPU qui veut écrire sur un ligne S doit donc d'abord devenir le propriétaire de cette ligne et passer en O. Avantage: les autres CPUs peuvent aller demander cette ligne directement au propritaire sans passer par la mémoire.
Concrètement, un conflit mémoire sur le P4 et le K8, ça se passe comment?
1° il faut lire qqc en mémoire.
Le P4 envoie l'adresse sur le bus commun, personne ne réagit et le controlleur mémoire envoie la donnée qui est inscrite comme ligne E dans la cache.
Le K8 envoie une demande mémoire qui est acheminée au bon controlleur mémoire (ben oui, la mémoire est partagée entre les CPUs) ainsi qu'une série de messages aux autres CPUs pour leur demander si ils ont déjà une copie de la ligne. Comme il n'y a que des réponses négatives, il utilise la valeur que lui renvoie le controlleur mémoire.
2° Un deuxième CPU lit la même donnée. Même scénario, on envoie les requêtes sur le bus commun/les liens HT.
Pour le P4, la seule différence c'est que le premier CPU va signaler qu'il a une copie chez lui et les deux CPU vont faire passer la ligne en S. Néanmoins il n'y a aucun transfert de donnée CPU à CPU, le deuxième CPU va attendre que le controlleur mémoire aille à nouveau lire la DRAM pour envoyer la donnée.
Pour le K8, un des CPUs va dire qu'il a déjà la ligne, donner l'ordre d'arrêter la lecture en mémoire et va envoyer la ligne directement de CPU à CPU. La ligne va être en S chez les deux CPUs.
3° Le premier CPU modifie cette ligne.
Pour le P4, on broadcaste sur le bus commun un message d'invalidation de la ligne qui passe de S à I sur le deuxième CPU.
Pour le K8, on broadcaste une demande de prise de possession de la ligne qui passe de S à O pour le premier CPU.
4° Le deuxième CPU aimerait à nouveau accéder à cette ligne.
Pour le P4, une demande classique est envoyée sur le bus commun comme en 1° mais cette fois-ci le deuxième CPU se réveille et dit No Yuo!, interrompant la transaction. Il va ensuite réécrire en mémoire la ligne (qui passe en S) puis le controlleur mémoire va aller relire la valeur en mémoire pour l'envoyer au deuxième CPU (je sais, c'est pas très efficace mais c'est comme ça que ça marche sur le P3/P4). L'étape de lecture peut éventuellement être évitée si le chipset a une petite cache MAIS on ne peut éviter l'écriture qui est vitale pour maintenir la cohérence.
Pour le K8, il y a simplement un transfert de propriété entre les deux CPUs comme en 2°. On ne repasse donc pas par une phase d'écriture en mémoire.
Et qu'est-ce qui se passe si deux CPUs tentent d'écrire sur la même ligne (qu'ils ont en S) au même moment? Ben, c'est comme dans Ghostbuster quand on croise les flux, c'est mal. (le soft est censé empêcher ça)