Concetti fondamentali di CACHING • Funzionamento di base di una cache • Cache Direct-Mapped e Set-Associative • Altri aspetti del sotto-sistema di memoria primaria 1 CPU e memoria principale • Lo scambio di dati tra la CPU e la RAM è uno dei punti cruciali per le prestazioni di un computer. • Fin dai primi computer sperimentali degli anni ’40 e ‘50, lo sviluppo di un modo per memorizzare e rendere velocemente disponibili al processore le istruzioni e i dati del programma in esecuzione ha rappresentato una delicata e fondamentale sfida tecnologica. • La memoria principale è stata sempre più lenta della CPU, e il gap di prestazioni si è ampliato nel tempo. In più, il flusso di dati e istruzioni tra CPU e RAM deve passare attraverso il bus, che introduce ulteriori ritardi 2 CPU e memoria principale • Andamento dei rapporti di prestazione tra CPU e RAM negli anni, posto a 1 il rapporto di prestazioni nel 1980 (H-P3, Fig. 5.2). Miglioramento RAM: circa 7% l’anno. Miglioramento CPU: 35% l’anno fino al 1986, 55% negli anni sucessivi. 3 1 CPU e memoria principale • Qui la prestazione è misurata come differenza in tempo tra le richieste di un processore single core verso la RAM e il ritardo nelle risposte a queste richieste. É interessante osservare come questa differenza di prestazioni si sia stabilizzata dopo il 2005 (H-P5, Fig. 2.2), ma in realtà le cose siano peggiorate… 4 CPU e memoria principale • …a causa dell’introduzione dei processori multi-core, che possono produrre un enorme quantità di richieste verso la RAM. • Ad esempio, un Core i7 può generare 2 riferimenti in memoria per core per ciclo di clock. Con 4 core e un clock di 3,2 GHz, l’i7 può generare un picco di 25,6 miliardi di riferimenti a dati da 64 bit per secondo, più 12,8 miliardi di riferimenti ad istruzioni da 128 bit, per un totale di circa 409,6 Gbyte al secondo! • Per contro, con la tecnologia attuale la RAM più efficiente può fornire un massimo di circa 25 Gbyte di dati/istruzioni al secondo… 5 CPU e memoria principale • Dovrebbe essere quindi chiaro che è inutile progettare processori sempre più veloci e sofisticati, se poi non è possibile reperire in modo veloce le istruzioni che devono eseguire e i dati su cui tali istruzioni devono operare. • Nei vari datapath che abbiamo visto fin’ora, assumevano la presenza di una Instruction Memory e di una Data Memory che operavano alla stessa velocità degli altri componenti della CPU. • Questa assunzione corrisponde nella realtà all’esistenza di un sofisticato sistema di gestione delle informazioni che fluiscono tra CPU e RAM. 6 2 CPU e memoria principale • L’idea fondamentale per cercare di limitare il problema della lentezza della RAM è di utilizzare una gerarchia di memorie sempre più veloci, e quindi costose (e quindi meno capaci, anche perché occupano più spazio), in modo da portare “vicino” alla CPU i dati di cui ha più immediato bisogno. • E’ questa l’idea di base della tecnica del caching, ormai diffusa in tutte le CPU e le architetture general purpose. Tecnologia di memoria Tempo di accesso tipico Costo in dollari per Gbyte nel 2012 500 ÷ 1000 SRAM 0.5 ÷ 2.5 ns DRAM 50 ÷ 70 ns 10 ÷ 20 Memorie flash 5000 ÷ 50000 ns 0.75 ÷ 1 Dischi magnetici 5000000 ÷ 20000000 ns 0.05 ÷ 0.1 7 DRAM e SRAM • Nota: il termine DRAM (Dynamic RAM) indica la tecnologia con cui sono costruite le RAM usate nella memoria principale del computer. • Il termine SRAM (Static RAM) indica la tecnologia di base con cui sono costruite le RAM usate nei vari livelli di cache del processore. • Le SRAM usano, per memorizzare ogni singolo bit, un circuito di transistors (di solito 6), che devono essere sempre alimentati. • Le DRAM usano un condensatore (controllato da un transistor), la cui carica indica se il bit corrispondente vale 0 o 1. Ogni pochi millisecondi viene fatto il refresh della carica del condensatore, che tende a scaricarsi. • Le SRAM quindi occupano più spazio, consumano di più, sono più complesse e costano di più, ma hanno tempi di risposta più veloci. 8 Viceversa per le DRAM. DRAM e SRAM • In realtà, i diversi livelli di cache possono essere costruiti con tecnologie leggermente diverse. • Le SRAM usate per L1 sono ottimizzate rispetto alla velocità di accesso, mentre quelle usate per L2 ed L3 sono ottimizzate rispetto alla capienza di memorizzazione. • In più L2 ed L3 risultano più lente di L1 perché sono posizionate fisicamente più distanti dal punto in cui, all’interno del processore, incomincia l’elaborazione dell’istruzione o del dato. • Più raramente, L3 può essere implementata come DRAM, ma con una logica di accesso alle celle di memoria più efficiente di quella usata nella DRAM con cui viene implementata la memoria primaria. 9 3 DRAM e SRAM • A grandi linee, le SRAM hanno un tempo di accesso di qualche nanosecondo, mentre le DRAM hanno tempi di accesso dell’ordine di qualche decina di nanosecondi. • Naturalmente, diverse scelte tecnologiche e implementative possono modificare leggermente, in meglio o in peggio questi tempi di accesso. • Ma in realtà la grossa differenza tra i tempi di accesso alle informazioni contenute in una cache e alle informazioni contenute in memoria primaria sono dovute al fatto che per accedere alla memoria primaria occorre passare attraverso il bus di sistema, il che può richiedere diversi cicli di clock (vedremo in dettaglio più avanti) 10 Caching • È importante ricordare che lo sfruttamento del concetto di caching non è limitato alla relazione tra CPU e RAM, ma è fondamentale e si estende a tutto il sistema di memorie di un computer: – I registri fanno da cache per la cache hardware – la cache hardware fa da cache per la RAM – la RAM fa da cache per l’hard disk (memoria virtuale) – l’hard disk fa da cache per supporti magnetici più lenti... 11 Caching • L’idea di cache è nata insieme a quella di computer: • Ideally, one would desire an indefinitely large memory capacity such that any particular...word would be immediately available...We are forced to recognize the possibility of constructing a hierarchy of memories, each wich has greater capacity than the preceding but which is less quickly accessible A. Burks, H. Goldstine, J. von Neumann Preliminary Discussion of the logical Design of Electronic Computing Instrument (1946) 12 4 Caching • Sebbene l’idea di memoria cache sia vecchia quanto l’idea di computer secondo lo stile von Neumann, solo alla fine degli anni 60 vengono prodotte le prime CPU commerciali dotate di memoria cache vera e propria. • L’idea di base è nota: una cache è una memoria piccola ma veloce che contiene una parte delle informazioni in RAM. • Se una buona percentuale dei dati e delle istruzioni della memoria di cui ha bisogno la CPU sono nella cache, l’effetto della lentezza della RAM sulle prestazioni complessive si riduce enormemente. 13 Caching • Le CPU attuali poi, sono dotate di cache separate per dati e istruzioni. In questo modo, in un datapath pipelined, nello stesso ciclo di clock è possibile: – prelevare una istruzione dalla cache di istruzioni (quella che fino ad ora avevamo chiamato la Instruction Memory) e – leggere/scrivere dei dati (relativi ad un’altra istruzione) dalla cache di dati (quella che chiamavamo la Data Memory). • Instruction e Data memory costitiscono nell’insieme la cache di primo livello (L1) • Tutti i processori processori dispongono poi anche di una cache di secondo livello (L2), e sono ormai comuni i processori con un terzo livello di cache (L3, ovviamente) 14 Caching • Una tipica gerarchia di memorie in un normale computer (sopra) e in un dispositivo mobile (H-P5, Fig. 2.1): 15 5 Località della cache • L’uso di cache è vantaggioso perché, normalmente, valgono due tipi fondamentali di località: • Località spaziale: – Aree di memoria con indirizzi simili a quelli appena usati, saranno a loro volta usate nell’immediato futuro (ad esempio, le istruzioni vengono eseguite in sequenza, così come gli elementi di un array sono letti/scritti in sequenza) • Località temporale: – Locazioni accedute di recente verranno di nuovo accedute nell’immediato futuro (e.g. istruzioni e variabili di un ciclo). 16 Funzionamento di base di una cache • N.B. per ora ci limitiamo a descrivere operazioni di lettura in RAM. Vedremo più avanti il caso in cui il dato indirizzato vada modificato • Dal punto di vista del funzionamento di una memoria cache, la RAM viene suddivisa in blocchi di dimensione fissa detti cache lines (o semplicemente linee) o cache blocks (o semplicemente blocchi). – Una linea è formata da un numero prefissato (da 4 a 256, a seconda delle implementazioni, ma sempre una potenza di 2) di byte consecutivi della RAM. • Le linee sono numerate consecutivamente da 0, così se una linea è fatta di 32 byte avremo: – linea 0: contiene i byte della RAM da 0 a 31 – linea 1: contiene i byte della RAM da 32 a 63 – linea 2: contiene i byte della RAM da 64 a 95 17 Funzionamento di base di una cache • Ogni linea è anche identificata dal suo indirizzo in RAM: l’indirizzo in RAM del primo byte appartenente a quella linea. Supponiamo che gli indirizzi della RAM siano scritti usando m + n bit. • Se le linee sono formate da 2n byte, ciascuna linea ha un indirizzo che ha la seguente forma: xx…xx00…00 m bit n bit • Il numero di una linea non è altro che il valore rappresentato dagli m bit più significativi dell’indirizzo della linea una volta tolti gli n bit meno significativi (il concetto è identico a quello che troviamo nella paginazione della memoria primaria: infatti pagine e frame hanno 18 anch’essi una dimensione che è una potenza di 2) 6 Funzionamento di base di una cache • In ogni istante alcune delle linee della RAM sono anche nella cache (per ora assumiamo che siano presenti solo le cache di primo livello, separate per dati e istruzioni, che lavorano (più o meno) alla stessa velocità della CPU). • Quando una word (ad esempio un intero, o una istruzione scritta su 4 byte) viene indirizzata, il sottosistema hardware di indirizzamento della memoria controlla se questa word sta anche nella cache. • Se si, si verifica un cache hit tutto procede normalmente, in quanto la cache è in grado di lavorare alla stessa frequenza degli altri componenti del datapath. • Se non c’è, si verifica un cache miss: (la linea contenente) il dato mancante viene prelevata dalla RAM. Se necessario una linea della 19 cache deve essere rimossa per far spazio a quella mancante. Cache Direct-Mapped • Le cache Direct-Mapped (in italiano: ad indirizzamento diretto) sono il tipo di cache più semplice. Una cache Direct-Mapped è formata da 2k entry numerate consecutivamente. • Ogni entry memorizza una linea: 2n byte consecutivi della RAM (di solito 2n = 32 o 64). E ad ogni entry sono associate due informazioni: 1. un bit di validità che ci dice se quella entry contiene dell’informazione significativa. 2. un campo Tag che identifica univocamente la linea contenuta in quella entry della cache rispetto a tutte le linee della RAM • Ad esempio, una cache con 2048 entry da 32 byte ciascuna può contenere in tutto 2048 x 32 = 64KB di dati (o istruzioni). 20 Cache Direct-Mapped • In una cache Direct-Mapped, ogni linea della RAM viene memorizzata in una entry ben precisa della cache. • Quindi, dato l’indirizzo di una word della RAM, c’è una sola entry della cache che può contenere la linea di cui quella word fa parte. • Per stabilire in quale entry della cache cercare una linea che contiene il dato o l’istruzione indirizzati dalla CPU si usa l’operazione: (num. della linea in RAM) modulo (num. di entry della cache) • Un calcolo che è molto facile e veloce da eseguire a livello hardware se il numero di entry della cache è una potenza di 2. 21 7 Cache Direct-Mapped • Però il PC, una LOAD / STORE, specificano l’indirizzo di una word (una istruzione indirizzata dal PC, o un dato la leggere o scrivere). • Il numero della linea di RAM che contiene quella word è allora dato dagli m bit più significativi dell’indirizzo della word. • E dunque per sapere se quella linea è anche nella cache basta guardare nella entry specificata dalla formula del lucido precedente. • Ma poiché |linee in RAM| > |linee in cache|, è evidente che alla stessa entry della cache faranno capo più linee di RAM, tutte quelle per cui (num. della linea in RAM) modulo (num. di entry della cache) dà lo stesso risultato. • Come si fa a sapere se la entry della cache in cui si va a guardare contiene proprio la linea desiderata? 22 Cache Direct-Mapped • (Patterson-Henessy, fig. 5.8). Come esempio, supponiamo una RAM suddivisa in 32 linee da un byte ciascuna, e una cache con 8 entry (ovviamente da un byte). • In quale entry della cache viene inserita la linea di indirizzo 01001? • 01001 mod 1000 = 001. Ma notate che l’entry della cache 001 conterrà anche le linee di indirizzo 00001, 10001, 11001. • Cosa distingue fra loro tutte le linee che possono andare nella entry 001 della cache? I due bit più significativi del numero di ciascuna linea, che possono essere usati per distinguere fra loro tutte le linee di 23 RAM che fanno capo alla stessa entry della cache. Cache Direct-Mapped • Per cui, quando la CPU vuole leggere la linea numero 01001 dalla cache, innanzi tutto calcola 01001 modulo 1000 = 001 e scopre che quella linea, se presente in cache, si trova nella entry 001. • Se la entry 001 ha il bit di validità = invalid allora la entry è vuota, e la linea indirizzata viene prelevata dalla RAM e copiata nella entry 001 della cache. Il bit di validità viene settato a valid e dentro al campo Tag viene scritto 01. • Se invece la entry 001 ha il bit di validità = valid, l’hardware controlla se il tag della entry 001 corrisponde ai due bit più significativi della linea di numero 01001. • Se c’è corrispondenza la entry 001 della cache contiene la linea cercata, altrimenti si verifica un cache miss. La linea 01001, prelevata dalla RAM viene inserita nella entry 001 sovrascrivendo il valore precedente. Il campo Tag viene aggiornato al nuovo valore 01. 24 8 Cache Direct-Mapped • Nel caso generale, le linee hanno dimensione maggiore di un byte, e la CPU indirizza una word di dimensione inferiore alla linea che contiene quella word, ma il meccanismo è lo stesso. • Supponiamo ad esempio una RAM con indirizzi scritti su 32 bit, linee da 25 byte, word da 22 byte e una cache da 211 entry. • I 32 – 5 = 27 bit più significativi dell’indirizzo di una word costituiscono il numero della linea che contiene quella word. • Di questi 27 bit, gli 11 bit meno significativi vengono usati per indirizzare una specifica entry della cache, e i restanti 16 bit più significativi costituiscono il TAG che distingue fra loro tutte le linee di RAM che fanno capo alla stessa CACHE ENTRY. TAG (16 bit) CACHE ENTRY (11 bit) WORD (3 bit) BYTE (2 bit) 25 Cache Direct-Mapped • Ossia, i 32 bit di un indirizzo di RAM generato dalla CPU (attraverso il PC o una istruzione di LOAD/STORE) sono così suddivisi: – TAG: i 16 bit più significativi dell’indirizzo generato dalla CPU, usati per distinguere fra loro le linee che fanno capo alla stessa entry in cache. – CACHE ENTRY: gli 11 bit che indicano in quale entry della cache cercare la linea che contiene il dato/istruzione indirizzato. – WORD: i 3 bit con cui distinguiamo fra loro le 8 word contenute in una linea da 32 byte. – BYTE: i 2 bit che possono servire a individuare i singoli byte di cui è composta ciascuna word. 26 Cache Direct-Mapped • Dunque, quando la CPU genera l’indirizzo di una word scritto su 32 bit, , l’hardware estrae gli 11 bit della CACHE ENTRY e li usa per indirizzare una delle 211 entry della cache • Se la entry corrispondente è valida (come indicato dal bit di validità), vengono comparati il contenuto del campo TAG di quella entry con i 16 bit più significativi dell’indirizzo. • Se sono identici, si verifica un cache hit. Attraverso il campo WORD dell’indirizzo è possibile estrarre dalla linea contenuta in quella entry della cache la word specificata dall’indirizzo. 27 9 Cache Direct-Mapped • In caso di cache miss invece, la linea deve essere prelevata dalla RAM e copiata nella entry della cache, eventualmente sovrascrivendo la linea (e il relativo TAG) precedenti. • Notate quindi il principio di località temporale: un dato indirizzato più di recente sostituisce uno più vecchio. • Naturalmente, un cache miss produce sempre una perdità di tempo (leggermente) superiore al tempo necessario a prelevare direttamente il dato in RAM • In ogni caso, perché la cosa sia efficiente tutte le operazioni sono implementate a livello hardware, e per quanto possibile in parallelo. 28 Cache Direct-Mapped • Un esempio cache direct-mapped con 1024 entry e linee da 4 byte. I 20 bit più significativi vengono usati come tag, i 10 bit intermedi come numero della linea, e i restanti 2 bit meno significativi per indirizzare il byte all’interno di ciascuna linea (Patterson-Hennessy, fig. 5.10) • Se dovessimo indirizzare word da due byte all’interno dellle linee, quale porzione dell’indirizzo generato dalla CPU useremmo? 29 Dimensioni di una cache • Notate che la dimensione effettiva di una cache è in realtà superiore al valore dichiarato, in quanto per ogni entry occorre anche memorizzare il tag della linea memorizzata, e il bit di validità. • Consideriamo ad esempio una cache da 16 Kbyte (214 byte = 16384 byte) con 1024 (210) entry (e quindi con linee da 16 (24) byte. • Se un indirizzo è scritto su 32 bit, ciascun tag sarà composto da 32 – 10 – 4 = 18 bit, a cui va aggiunto il bit di validità, e quindi ogni entry è formata da 128 + 19 = 147 bit. • In totale la cache deve memorizzare 1024 · 147 = 150528 bit, pari a 18816 byte. 30 10 Dimensione delle linee • Le prestazioni di una cache dipendono anche dalla dimensione scelta per le linee. In generale, linee più grandi consentono di diminuire i cache miss, perché sfruttano meglio il principio di località spaziale. • Tuttavia, oltre una certa dimensione non conviene andare, perché se le linee sono troppo grandi, una cache di dimensione prefissata ne può contenere poche, e aumenta la probabilità che una linea debba essere rimossa dalla cache (perché si è verificato un cache miss) prima che molti dei dati contenuti in quella linea siano stati usati. 31 Dimensione delle linee • La figura (Patterson-Hennessy, 5.11) mostra la frequenza di cache miss per diverse dimensioni delle linee (sulle ascisse) e cache di diverse dimensioni nel caso del benchmark SPEC92. Notate come cache più grandi permettono di utilizzare linee di dimensione maggiore (oltre ovviamente a produrre un minor numero di cache miss). 32 Gestione dei cache miss • Che succede se si verifica un cache miss? La pipeline deve essere fermata, in attesa di recuperare dalla RAM il dato o l’istruzione mancante. • Nel caso di cache miss nella Instruction Memory, il PC corrente deve essere anche decrementato dello stesso valore che gli era stato aggiunto nella fase IF dell’istruzione mancante. • Quando la linea contentente il dato/istruzione mancante è stata recuperata, l’esecuzione riprende. In caso di istruzione mancante viene rieseguita la fase IF, in caso di dato mancante per una LOAD, viene rieseguita la fase MEM 33 11 Gestione delle scritture • La gestione delle scritture è più delicata, perché richiede (prima o poi) la modifica dei dati anche in RAM. • In caso di scrittura di una linea della cache, si può scegliere di propagare immediatamente la modifica anche alla RAM, in modo da garantire la coerenza della cache. • Sempre per mantenere la coerenza della cache, in caso di cache miss in scrittura il dato mancante viene prelevato dalla RAM, modificato in cache, e la modificata ripropagata alla RAM. • Questo schema di gestione delle scritture in cache prende il nome di write-through: le scritture vengono sempre eseguite sia in cache che in RAM, in modo che i dati presenti nelle due memorie siano sempre consistenti. 34 Gestione delle scritture • Lo schema write-through non offre però buone prestazioni, perché richiede, per ogni scrittura in cache, anche l’accesso alla RAM, una operazione che consuma molti cicli di clock. • Lo schema alternativo al write-through è noto come write-back, in cui un valore viene modificato solo nella cache (si usa a volte il termine write deferred). • La modifica verrà propagata alla RAM (o ai livelli inferiori di cache, nei sistemi che ne hanno più di uno) solo se il dato stesso deve essere rimpiazzato da un altro con cui condivide lo stesso tag. 35 Il supporto della RAM • Il tempo necessario a recuperare un dato in RAM quando si verifica un cache miss viene normalmente detto penalità da fallimento (miss penalty). • La durata della penalità da fallimento è dovuta alle tre operazioni fondamentali necessarie per gestire un cache miss: 1. Inviare l’indirizzo della linea mancante alla RAM 2. Accedere alla RAM per recuperare la linea 3. Inviare alla cache la linea recuperata 36 12 Il supporto della RAM • La prima e la terza operazione possono richiedere un ciclo di clock (attenzione, del bus, non del clock di CPU), mentre la seconda, richiede di solito molto più tempo, ad esempio dieci o venti cicli del clock (sempre del bus). • Inoltre, una linea della cache è di solito molto più grande della quantità di dati che un banco di RAM è in grado di fornire ad ogni accesso. • Ad esempio una linea può essere grande 16 byte, mentre con un accesso alla RAM possiamo leggere in tutto una word da 32 bit, ossia 4 byte, e abbiamo quindi bisogno di 4 accessi per recuperare l’intera linea. 37 Il supporto della RAM • Consideriamo allora un sistema a 32 bit (e quindi con un bus a 32 bit). Se supponiamo (ipotesi ragionevole) che un accesso alla RAM richieda 15 cicli di clock (del bus) per leggere una word da 32 bit, per servire un cache miss con linee da 16 byte impiegheremo: – 1 ciclo di clock per inviare l’indirizzo della linea mancante alla RAM – 4 × 15 cicli di clock per leggere l’intera linea – 4 × 1 cicli di clock per inviare l’intera linea alla cache • Per un totale di 65 cicli di clock (del bus). 38 Il supporto della RAM • Possiamo cercare di migliorare la situazione: – allargando la banda passante della RAM, ossia la quantità di dati che possiamo prelevare dalla RAM con un unico accesso (ad esempio in modo che una intera linea possa essere prelevata con un solo accesso). – Allargando il bus, in modo da poter trasportare in un unico ciclo di clock (del bus) l’intera linea prelevata dalla RAM al processore. • Però aumentare l’ampiezza del bus fino a 16×8 bit trasportati in parallelo è una soluzione tecnicamente molto costosa e difficile da realizzare. Del resto, anche il solo ampiamento della banda passante della RAM può produrre miglioramenti notevoli. 39 13 Il supporto della RAM • Per aumentare la banda banda passante della RAM occorre che questa venga organizzata in banchi in modo da poter leggere o scrivere più word (anziché una sola) per ciclo di clock. • Se una linea è formata da n word, la linea viene distribuita su n banchi di RAM, ciascuno dei quali memorizza (allo stesso indirizzo di tutti gli altri banchi) una delle n word della linea. • Gli n banchi possono quindi essere letti in parallelo, estraendo così in una sola lettura tutte le word di cui è composta una linea. • Questo schema è denominato a memoria interlacciata (interleaved memory) e permette di risparmiare sul tempo necessario a prelevare un’intera linea dalla RAM (un principio abbastanza simile alla distribuzione degli strip nei sistemi RAID) 40 Il supporto della RAM • H-P3, Fig 5.27: la memoria interlacciata (c) permette di mantenere un bus di ampiezza ragionevole e di migliorare la velocità di accesso alla RAM nella gestione dei cache miss. • Usando lo stesso esempio di prima, con la soluzione (c) avremmo: • 1 ciclo di clock per inviare l’indirizzo della linea mancante, 15 cicli di clock per prelevare le 4 word della linea (i quattro banchi vengono ora acceduti in parallelo), 4 × 1 cicli di clock per inviare l’intera linea alla 41 (a) cache, per un totale di 20 cicli di clock, contro i 65 della soluzione Cache Set-Associative • Una caratteristica fondamentale delle cache Direct-Mapped, è che una determinata linea della RAM viene memorizzata sempre nella stessa entry della cache. • Naturalmente, più linee di RAM fanno riferimento alla stessa entry della cache, dato che questa è meno capiente della RAM. • Ammettendo un posizionamento più flessibile delle linee di RAM all’interno della cache è possibile ridurre in numero di cache miss, e quindi aumentare le prestazioni del sistema. • Un tale effetto può essere ottenuto mediante le cache set-associative ad n vie, dove n è di solito pari a 2, 4, o 8. 42 14 Cache Set-Associative • Una cache set-associativa ad n vie è suddivisa in più insiemi, ciascuno dei quali è formato da n entry e può quindi contenere n linee. • Ogni linea della RAM corrisponde esattamente ad uno ed un solo insieme della cache, ma quella linea può essere memorizzata in una qualsiasi delle n entry dell’insieme. • Quindi, in una cache set-associativa l’insieme (notate, non più l’entry, come nelle cache direct-mapped) che contiene una linea è stabilito da: (numero della linea in RAM) modulo (numero di insiemi della cache) 43 Cache Set-Associative • Una cache direct mapped e una cache set-associativa a 2 vie, entrambe in grado di memorizzare 8 linee. Nella prima, la linea 12 può andare solo nella entry numero 4. Nella seconda, la stessa linea può andare nella entry 0 o nella entry 1, che fanno parte dello “zeresimo” insieme (H-P3, Fig. 5.4. Vedere anche H-P5, Fig. B.2) 44 Cache Set-Associative • Quindi, una volta individuato l’insieme che può contenere una certa linea, occorre ancora verificare se una delle entry di quell’insieme contiene la linea indirizzata (il che viene fatto con una ricerca associativa su tutti gli elementi dell’insieme). • Se una linea indirizzata manca va portata in cache, e inserita in una qualsiasi entry. Naturalmente è meglio scegliere una entry libera. • Se invece tutte le entry dell’insieme sono occupate occorre sovrascrivere una delle linee dell’insieme. Di solito si sacrifica quella indirizzata meno di recente (quindi, si applica una politica di rimpiazzamento LRU). • L’hardware necessario per implementare un tale tipo di cache è più sofisticato, ma da prestazioni migliori rispetto ad una cache Direct45 Mapped. 15 Cache Set-Associative • Come esempio, consideriamo due cache con quattro entry, la prima cache è di tipo direct-mapped, la seconda è set-associativa a 2 vie. • Supponiamo vengano generati indirizzi per le linee di RAM di indirizzo 0, 8, 0, 6, 8. • Qual è il numero di cache miss prodotti dalle due cache? 46 Cache Set-Associative • Nel caso della cache direct-mapped, le varie linee indirizzate verranno messe nelle seguenti entry della cache: Indirizzo della linea Entry nella cache 0 0 modulo 4 = 0 6 6 modulo 4 = 2 8 8 modulo 4 = 0 • I riferimenti “0, 8, 0, 6, 8” genereranno quindi 5 cache miss, in quanto le linee 0 e 8 si alternano all’interno della stessa entry della cache, e il primo riferimento a qualsiasi linea genera ovviamente un cache miss. 47 Cache Set-Associative • Nel caso della cache set-associativa a 2 vie, le 4 entry sono suddivise in 2 insiemi, di indice 0 e 1, e le linee indirizzate verranno sistemate nei seguenti insiemi: Indirizzo della linea Insieme nella cache 0 0 modulo 2 = 0 6 6 modulo 2 = 0 8 8 modulo 2 = 0 • Usando i riferimenti “0, 8, 0, 6, 8” le linee 0 e 8 vengono messe in due entry separate dello stesso insieme, per cui il secondo riferimento alla linea 0 non genera cache miss. Quando viene indirizzata la linea 6 (generando un cache miss) la linea 8 in cache viene rimossa (algoritmo LRU), e il successivo riferimento alla linea 8 genera cache miss. In totale si hanno 4 cache miss. 48 16 Cache Set-Associative • Se la cache set-associativa fosse a 4 vie, si può verificare facilmente che verrebbero generati 3 cache miss. • Più in generale, una cache associativa in cui c’è un solo unico grande insieme, e una linea può essere sistemata in una qualsiasi entry della cache, prende il nome di cache completamente associativa (fully associative cache). • Tali cache fornirebbero le prestazioni migliori in termini di cache miss, ma per cache con qualche migliaio di entry sono troppo complesse e costose da realizzare. • Tuttavia il concetto rimane valido: quanto maggiore è il numero di entry in cui possiamo sistemare una linea in cache (ossia, quanto maggiore è n, il numero di vie della cache), tanto migliori sono le prestazioni. 49 Cache Set-Associative • La frequenza di fallimenti nella cache dati per diversi tipi di cache di uguale dimensione) usando come benchmark SPEC2000 (PattersonHennessy, fig. 5.16. Vedere anche H-P5 fig. B.4) Associatività Frequenza dei fallimenti 1 via (direct mapped) 10.3% 2 vie 8.6% 4 vie 8.3% 8 vie 8.1% • I vantaggi tra diversi livelli di associatività sembrano minimi, ma se consideriamo quanto costa servire anche un solo cache miss… 50 Prestazioni: un semplice esempio • Come vengono influenzate le prestazioni di una CPU dalla presenza di un sistema di caching? Facciamo un esempio, assumendo (sono valori ragionevoli): – tempo di esecuzione di una istruzione (CPI): 1 ciclo di clock – average miss rate: 2% – numero medio di riferimenti in memoria per istruzione: 1,5 – Tempo necessario ad accedere un dato in caso di cache miss: 100 cicli di clock (della CPU) 51 17 Prestazioni: un semplice esempio • Quanti CPI ci vogliono per eseguire una istruzione, assumendo una cache perfetta? (cache miss = 0, tempo di accesso = 0). Risposta = 1 CPI • E Se non ci fosse proprio la cache? – CPI = 1 + 100 × 1,5 = 151 • E con la cache? – CPI = 1 × 0,98 + 0,02 × 100 × 1,5 = 4 (circa, assumendo una cache con tempo di accesso pari a 0). 52 Miglioramento delle Prestazioni • La presenza di una cache ha un effetto tanto più positivo sulle prestazioni di un sistema quanto più: 1. si riesce a diminuire il costo (in termini di tempo) necessario per servire un cache miss. 2. si riesce a diminuire la frequenza dei cache miss. 53 Riduzione del costo di un cache miss • Il gap di prestazioni tra CPU e RAM tende ad allargarsi nel tempo, e quindi il costo di un cache miss si fa sempre più grave. • Abbiamo già visto una tecnica, la memoria interlacciata, per ridurre il tempo necessario a recuperare una linea mancante in RAM • Un altro modo per ridurre il costo dei cache miss e di non dover andare fino in RAM per recuperare una linea mancante, mediante l’uso di più livelli di cache. • In questo modo, si riesce tra l’altro a raggiungere un accettabile tradeoff tra l’avere una cache veloce quanto la CPU (ma costosa, e quindi piccola) e una cache sufficientemente grande da contenere una buona 54 parte della RAM (più lenta, ma più economica) 18 Caching a più livelli L1-istr. 16/64K L1-dati 16/64K L2 Cache L2 Cache L3 Cache • In un sistema di cache a più livelli, le cache sono normalmente inclusive, ossia: L1 ⊆ L2 ⊆ L3 • Nei moderni multi-core, ogni core ha a disposizione L1 ed L2 private, mentre L3 è condivisa. L1 ed L2 risiedono sullo stesso chip del processore, mentre L3 può essere: sullo stesso chip; su un chip separato nello stesso package; sulla motherboard. 55 Caching a più livelli • Nel caso di un sistema con almeno due livelli di cache, è importante che: 1. le cache di primo livello abbiamo un tempo di accesso simile alla velocità della CPU, in modo da non rallentarne l’esecuzione delle istruzioni in caso di cache hit. 2. la cache di secondo livello abbia una dimensione sufficientemente maggiore della cache di primo livello, in modo da ridurre significativamente il numero di cache miss rispetto alla cache di primo livello. 3. Ragionamento analogo vale per la cache di terzo livello rispetto a quella di secondo livello. 56 Caching a più livelli • Nei processori attualmente in produzione si osservano più o meno le seguenti caratteristiche: Cache tempo di accesso dimensioni L1 1÷4 clock cycles 16÷64 Kbytes L2 8÷15 clock cycles 256÷1024 Kbytes L3 25÷50 clock cycles 2÷10 Mbytes 57 19 Riduzione del numero di cache miss • È il secondo modo per rendere l’uso di una cache il più efficace possibile. Qui si può agire in più modi. • Abbiamo già visto che l’uso di cache set-associative diminuisce la frequenza dei cache miss. • Abbiamo anche visto che una giusta dimensione delle linee rispetto alla dimensione della cache ottimizza il numero di cache miss per una data dimensione. • Infine, ovviamente, i cache miss si riducono con l’aumento delle dimensioni della cache. 58 Riduzione del numero di cache miss • Nel tempo, la dimensione delle cache (specie L2 ed L3) è costantemente aumentata: ad esempio, nel 2001 una cache di secondo livello aveva la dimensione della memoria principale di un desktop del 1991. • Addirittura, se la cache di un certo livello è troppo piccola rispetto alla quantità di dati/istruzioni di cui ha bisogno un programma, si verifica un vero e proprio fenomeno di thrashing, simile a quello che può presentarsi nel funzionamento della memoria virtuale visto nel corso di Sistemi Operativi. 59 Un caso di studio: il Core i7 • Vediamo, nel caso reale del Core i7, in quale misura 3 livelli di cache permettano di evitare di andare a prelevare i dati mancanti fino ai banchi di memoria centrale. • La tabella del prossimo lucido (H-P5, Fig. 2.23) riporta, nella colonna 2, la percentuale di data miss per L1, per diversi benchmarks. In colonna 3 vediamo invece come migliori il miss rate usando il prefetch dei dati e le load speculative (entrambe le tecniche implementate nell’i7) 60 20 Un caso di studio: il Core i7 • H-P5, Fig. 2.23: notare come migliori il miss rate usando il prefetch dei dati e le load speculative (tecniche entrambe implementate nell’i7) 61 Un caso di studio: il Core i7 Ed ecco il miss rate dei dati rispetto alle cache L2 ed L3. I miss cache di L3 sono un sottoinsieme dei miss cache di L2 che sono un sotto-insieme dei miss cache di L1 (H-P5, Fig. 2.25) 62 Prestazioni degli algoritmi e cache • Normalmente, gli algoritmi sono valutati solo a livello teorico, in base al numero di operazioni da compiere per risolvere un problema, rispetto alla “dimensione” del problema. • A livello pratico tuttavia, il modo in cui un computer funziona può influenzare enormemente le effettive prestazioni di un programma. • Pensate ad esempio a come “interferisce” il sistema operativo nell’esecuzione di un programma, cioè durante la vita del processo che esegue il codice di quel programma (context switches, page faults, system call…) 63 21 Prestazioni degli algoritmi e cache • La presenza della cache è uno degli aspetti pratici, nell’esecuzione dei programmi, che può influenzarne enormemente i tempi di esecuzione. • Così, un algoritmo che sembra più efficiente di altri a livello teorico, può in realtà fornire prestazioni peggiori se fatto girare su un sistema che usa un sistema di cache. • Un esempio è il Radix Sort, un algoritmo di ordinamento che, per array molto grandi (milioni di elementi), fornisce prestazioni migliori del Quick Sort in termini del numero di operazioni richieste per l’ordinamento. Ma cosa succede se prendiamo in considerazione la cache? 64 Prestazioni degli algoritmi e cache • Per questa ragione, sono state inventate nuove versioni di Radix Sort (e di molti altri algoritmi comunemente usati) che tengono in considerazione la presenza della gerarchia di memorie dei computer, in modo da limitare le inefficienze nascoste. (Patterson-Hennessy, Fig. 5.19) 65 DRAM, DIMM, SDRAM, DDR, DDR2, DDR3, GDRAM, FLASH… • La tecnologia per costruire la memoria principale del computer usa una serie di sigle che indicano diverse tecnologie di costruzione e funzionamento. Sappiamo già cosa vuol dire DRAM. Ecco brevemente le altre: • DIMM: Dual Inline Memory Modules. I chip di DRAM sono normalmente montati su piccole schede contenenti da 4 a 16 DRAM organizzate in modo da memorizzare i dati in blocchi di 8 bytes (+ ECC), le DIMM appunto. 66 22 DRAM, DIMM, SDRAM, DDR, DDR2, DDR3, GDRAM, FLASH… • SDRAM: Synchronous DRAM. Sono DRAM dotate di un clock, in modo da potersi sincronizzare col clock del controller della RAM, e ottimizzare le prestazioni. • DDR: Double Data Rate. Sono DRAM (in realtà, SDRAM) in cui è possibile trasferire dati sia sul fronte discendente che su quello ascendente del clock, in questo modo raddoppiando le prestazioni rispetto a normali DRAM. 67 DRAM, DIMM, SDRAM, DDR, DDR2, DDR3, GDRAM, FLASH… • DDR2, DDR3, DDR4… L’acronimo DDR indica ormai comunemente una sequenza di standard, in cui viene man mano aumentato il clock della DRAM, e quindi la quantità di dati trasferiti per secondo • In realtà viene anche diminuito il voltaggio di funzionamento, in modo da diminuire i consumi. DDR=2,5 volt; DDR2= 1,8 volt; DDR3=1,5 volts; DDR4=1,2 volts. 68 DRAM, DIMM, SDRAM, DDR, DDR2, DDR3, GDRAM, FLASH… • Prestazioni e codici delle DDR DRAM nel 2010 (H-P5, Fig. 2.14) 69 23 DRAM, DIMM, SDRAM, DDR, DDR2, DDR3, GDRAM, FLASH… • GDRAM: Graphics (Synchronous) DRAM. Sono particolari tipi di DDR (e infatti sono anche denominate GDDR) adatte a gestire le alte larghezze di banda richieste dai processori grafici. In particolare: – Trasferiscono più bit in parallelo delle DRAM – Sono collegate direttamente alla GPU mediante saldature (e non mediante normali socket come nelle DIMM) in modo da diminuire la dispersione del segnale e permettere un aumento della frequenza del clock 70 DRAM, DIMM, SDRAM, DDR, DDR2, DDR3, GDRAM, FLASH… • FLASH Memory. Sono particolari tipi di EEPROM (Electronically Erasable Programmable Read-Only Memory): possono non solo essere lette, ma anche riscritte. Tuttavia, la riscrittura avviene a livello di interi blocchi di dati, ossia anche i dati non modificati del blocco vanno riscritti. • Vengono usate al posto degli hard disk in molti dispositivi portatili, dove possono svolgere anche la funzione di memoria primaria. 71 DRAM, DIMM, SDRAM, DDR, DDR2, DDR3, GDRAM, FLASH… • Le principali caratteristiche delle memorie Flash sono: – Sono statiche, quindi mantengono i dati anche se non alimentate – Hanno un numero di cicli di riscrittura limitato a circa 100.000 per blocco. – Sono meno costose delle SDRAM e più degli Hard Disk, con un costo di circa 1$ per Gbyte memorizzato. – In lettura sono poco più lente delle SDRAM e circa mille volte più veloci degli Hard Disk. In scrittura tuttavia le prestazioni peggiorano sensibilmente (fino a 100 volte più lente delle SDRAM). 72 24