Innanzitutto se sei preoccupato per i recenti (ultimi 5-10 anni, da Nahalem?) Intel x86, allora il tuo architetto è un po 'fuori. Ogni core ha il proprio split di cache L1 da 128K (codice 64K / codice 64K). Oltre a ciò, ogni core ha una propria cache L2 che funge fondamentalmente da buffer tra la cache L1 e L3. Ogni socket ha la sua cache L3 (fino a 20 MB, penso). Le cache L1 e L2 sono piccole, semplici e veloci. La cache L3 è molto più grande e complessa (è suddivisa in piccoli segmenti che si trovano tutti su un anello con altre cose come il controller di memoria e il bridge QPI ad altri socket). (Si prega di ignorare le cose come il carico e memorizzare i buffer che renderà questo ancora più complesso.)
Inoltre, le linee della cache sono 64-byte.
Così sembra (ad esempio una macchina dual socket, con 4 core per CPU):
Core 0 (socket 0) -> L1-0 -> L2-0 -> L3-0 -> QPI link to socket 1
Core 1 (socket 0) -> L1-1 -> L2-1 -> ^
Core 2 (socket 0) -> L1-2 -> L2-2 -> |
Core 3 (socket 0) -> L1-3 -> L2-3 -> +
Core 4 (socket 1) -> L1-4 -> L2-4 -> L3-1 -> QPI link to socket 0
Core 5 (socket 1) -> L1-5 -> L2-5 -> ^
Core 6 (socket 1) -> L1-6 -> L2-6 -> |
Core 7 (socket 1) -> L1-7 -> L2-7 -> +
Pre Nahalem, le cache L2 sono state condivise tra coppie di core. Non ho dovuto fare un sacco di lavoro sulle prestazioni su questo in un attimo, quindi non sono davvero sicuro delle sottigliezze lì.
La cache L3 è completamente inclusiva della cache L1 e L2 sotto di essa. La cache contiene i valori "corretti" per tutti gli indirizzi di memoria. Più corretto della memoria principale, poiché le scritture possono rimanere in L3 per un po 'di tempo prima di andare in memoria (memorizzazione nella cache di write-back). Tutte le cache sono coerenti. Cioè, non avrai mai avuto due valori diversi per la stessa posizione di memoria. Questa coerenza è garantita da una versione del protocollo MESI, chiamata MESIF (per Intel, AMD ha una diversa strategia di caching e usa MEOSI e ha organizzato il loro caching in modo diverso).
Dato che L1 e L2 sono privati del core, la coerenza deve essere gestita solo al livello L3 (penso, non sono stato in grado di ottenere una risposta definitiva su questo). Le interconnessioni della cache hanno quattro corsie: dati, richiesta, conferma e ficcanaso (per tenerti aggiornato su altre operazioni di memoria).
Ora possiamo rispondere alle tue domande.
Se un thread su Core 0 sta leggendo un indirizzo, l'indirizzo risiederà in L1-0 e L3-0 nello stato Exclusive, Shared o Forward (tutti e tre mostrano che l'indirizzo non è modificato e memorizzato nella cache). Ora, Core-4 vuole scrivere su di esso. Una Request / Read-For-Ownership invierà la linea cache dall'altra cache L3 (L3-0) e farà in modo che le altre cache contrassegnino le loro copie come non valide. Ora sarà in L1-4 e L3-1 (contrassegnato come esclusivo).
(Qui è dove l'ignorare i buffer del negozio è stato semplificato molto.)
Core-4 scriverà da un registro nella cache L1-4. Causando il passaggio della linea allo stato Modificato. Questo viene propagato alla cache L3-1 (poiché è completamente inclusivo).
Ora, Core-0 vuole leggere di nuovo. La cache L1-0 non è valida a quell'indirizzo, quindi invia una richiesta di lettura che perde la cache L3-0 e fa in modo che l'L3-1 invii la linea cache indietro. L'L3-1 ora afferma che l'indirizzo è condiviso, e L3-0 mantiene la linea come Forward (il richiedente più recente ottiene la responsabilità di inoltro).
Chiaro come fango? Potrebbero esserci alcune modifiche a questo per ripulire parte del linguaggio su cui potrei essere troppo vago.