Von Neumann Bottleneck
Gerarchia di memoria
Struttura della Gerarchia Al livello 1 poniamo la memoria più veloce (piccola e costosa) Al livello n poniamo la memoria più lenta (grande ed economica) Scopo gerarchia e delle politiche di gestione delle memorie è dare l illusione di avere a disposizione una memoria grande (come al livello n) e veloce (come al livello 1)
Esempio a 2 livelli
Gerarchia di memoria All inizio i nostri dati e i nostri programmi sono memorizzati nel livello n (memoria più capiente e lenta) I blocchi (linee) di memoria man mano riferiti vengono fatti fluire verso i livelli più alti (memorie più piccole e veloci), più vicini alla CPU Se il blocco richiesto è presente nel livello più alto Hit: l accesso soddisfatto dal livello più alto Hit rate: n. hit / n. accessi Se il blocco richiesto è assente nel livello più alto Miss: il blocco è copiato dal livello più basso Miss rate: n. miss / n. accessi = 1 hit ratio Miss penalty: tempo necessario per trasferire i dati e fornirli al processore Poi l accesso è garantito dal livello più alto
Problemi Problema 1: Cosa succede se un blocco riferito è già presente nel livello 1 (più alto)? La CPU può accedervi direttamente (hit), ma abbiamo bisogno di un meccanismo per individuare e indirizzare il blocco all interno del livello più alto! Problema 2: Cosa succede se il livello più alto è pieno? Dobbiamo implementare una politica di rimpiazzo dei blocchi!
Cache Cache: posto sicuro [nascosto] dove riporre le cose Nascosta perché il programmatore non la vede direttamente L uso gli è interamente trasparente L uso della cache fu sperimentato per la prima volta negli anni 70 e da allora è divenuto assolutamente prevalente in tutti i calcolatori
Cache
Esempio Partiamo da un semplice esempio in cui la i blocchi di cache siano costituiti da una sola word. Supponiamo che a un certo punto il processore richieda la parola X n che non e in cache Cache miss
Domande Come facciamo a capire se un dato richiesto è nella cache? Dove andiamo a cercare per sapere se c è? Cache ad accesso diretto: a ogni indirizzo in della memoria corrisponde una precisa locazione della cache Possibilità: indirizzo locazione dove un indirizzo è mappato = indirizzo blocco modulo numero di blocchi in cache Se il numero di elementi nella cache è potenza di 2, ci è sufficiente prendere i bit meno significativi dell indirizzo in numero pari al logaritmo in base 2 della dimensione della cache
Cache ad accesso diretto Ogni locazione di memoria è mappata direttamente in esattamente una locazione di cache (direct mapped cache) Soluzione più semplice cache block index memory block address block index = (block address) mod (block num)
Cache ad accesso diretto Un blocco di cache può contenere una copia dei dati di diverse locazioni di memoria. Come distinguerle? I bit più significativi dell indirizzo di memoria sono salvati in un campo tag tag bits tag blocco = (indirizzo blocco) modulo (numero di blocchi) un bit valid è usato per indicare che i dati del blocco sono validi
Esempio Accesso a 10110 (miss) Accesso a 11010 (miss) Accesso a 11010 (hit)
Esempio MIPS 32 bit Indirizzo su 32 byte Cache ad accesso diretto Dimensioni della cache 2 n blocchi, di cui n bit usati per l indice dimensione del blocco di cache 2 m parole ossia 2 m+2 byte In questo caso la dimensione del tag è data da 32 (n + m + 2) Numero totale bit nella cache: 2 n x (dim. blocco + dim. tag + valid bit) Per convenzione si considera solo la dimensione del blocco.
4KB Cache
Esercizio Si consideri una cache con 64 blocchi di 16 byte ciascuno. A quale numero di blocco corrisponde l indirizzo 1200 espresso in byte? Blocco identificato da: (indirizzo blocco) modulo (numero blocchi in cache) (indirizzo blocco) = (indirizzo dato in byte) / (byte per blocco) Quindi l indirizzo del blocco è 1200/16 = 75 Blocco contente il dato è 75 modulo 64 = 11
Dimensione del blocco Dimensioni di linea di cache molto grandi esaltano la località spaziale e da questo punto di vista diminuiscono le probabilità di miss Tuttavia avere pochi blocchi diminuisce l efficacia nello sfruttamento della località temporale Inoltre avere dei miss con blocchi grandi porta a un costo di gestione alto (bisogna spostare molti byte) Quindi abbiamo un tradeoff
Tradeoff
Gestione delle miss La Parte di Controllo deve rilevare le miss e portare in cache i dati contenuti nella memoria indirizzata Hit in lettura (conseguenza di i-fetch e load) accesso alla memoria con il massimo della velocità Miss in lettura (conseguenza di i-fetch e load) La Parte di Controllo mette in stallo la CPU (cicli di attesa, con registri interni immutati), finché la lettura del blocco (dalla memoria in cache) viene completata Instruction cache miss: si ripete il fetch dell istruzione Data cache miss: si completa l accesso al dato dell istruzione (load)
Gestione delle miss Hit in scrittura (solo conseguenza di store) write-through: scrive sulla cache e in memoria (con buffer di scrittura) write-back: scrive solo sulla cache, e segnala che il blocco è stato modificato (setting del bit di Dirty) Miss in scrittura (solo conseguenza di store) con politica write-back, stallo della CPU (cicli di attesa), lettura del blocco dalla memoria in cache (write allocate), completamento dell istruzione di store in cache con politica write-through, solitamente non si ricopia il blocco in cache prima di effettuare la scrittura (no write allocate) che avviene in memoria
Esempio FastMATH Intrinsity Split cache 256 blocchi 16 word per blocco write-through e writeback I miss rate: 0.4 % D miss rate: 11.4 % Total miss rate: 3.2 %