Loading AI tools
Particolare tipo di memoria molto veloce e interamente gestita dall'hardware Da Wikipedia, l'enciclopedia libera
La memoria cache (in inglese cache memory, memory cache o CPU cache), in informatica, è una memoria veloce (rispetto alla memoria principale), relativamente piccola, non visibile al software e completamente gestita dall'hardware, che memorizza i dati più recentemente usati della memoria principale (MM - Main Memory) o memoria di lavoro del sistema.
La funzione della memoria cache è di velocizzare gli accessi alla memoria principale aumentando le prestazioni del sistema. Nei sistemi multiprocessori con memoria condivisa permette inoltre di ridurre il traffico del bus di sistema e della memoria principale, che rappresenta uno dei maggiori colli di bottiglia di questi sistemi. La memoria cache fa uso della tecnologia veloce SRAM, contro una più lenta DRAM della memoria principale, connessa direttamente al processore.
"CPU cache" è un termine non comune ed è raramente o per niente usato sia in letteratura che negli ambienti industriali tra gli esperti del settore. Per esempio, nei documenti relativi ai brevetti (USA), il termine "CPU cache" è usato meno del 2% dei casi[1] rispetto al termine "Cache Memory" (83%)[2] e "Memory Cache" (15%)[3]. La Cache Memory è una funzione associata ad una memoria e non ad uno specifico utente di questa funzione. Questa funzione può essere usata da una CPU, o in Shared Cache da un gruppo di CPU o Core o Nodi, o anche associata a un gruppo di memorie remote nei sistemi NUMA, o in generale da qualsiasi device che può accedere a una memoria principale. Il termine "CPU cache" è perciò troppo restrittivo e quindi inappropriato (vedi per es. Cache remota - cache delle memorie remote).
La cache è una memoria che memorizza dati temporanei "in modo silenzioso" al più alto livello di utilizzazione per un veloce riuso.[4][5][6]
Il termine cache deriva dal francese e significa "nascosto".
Il termine cache memory o memory cache o brevemente cache senza nessun'altra specificazione, generalmente si riferisce a una memoria nascosta che memorizza un sottoinsieme del contenuto della memoria principale e più precisamente le istruzioni di un programma e i relativi dati su cui operare.
La logica funzionale della memoria cache è la seguente:
Il funzionamento della cache si basa principalmente su due principi di località, la località temporale e la località spaziale.
L'efficienza della cache è misurata in termini di "Hit Rate". L'Hit Rate rappresenta la percentuale di Hit, ovvero il numero di riferimenti alla memoria che può essere soddisfatto dalla cache rispetto al numero degli accessi totali. Per esempio, ipotizzando che su un totale di 10 riferimenti alla memoria 8 vengono soddisfatti dalla cache l'hit rate è 0,8 ovvero l'80%.
Per "Miss" si intende invece il numero di riferimenti non soddisfatti dalla cache rispetto al numero totale degli accessi alla memoria. Nel caso precedente il miss rate è 0,2 quindi il 20%, questo significa che su 10 richieste è stato necessario accedere 2 volte alla memoria principale per trovare il dato (o l'istruzione). L'efficienza della cache dipende da diversi elementi quali la dimensione della cache, la dimensione della linea di cache, il tipo, l'architettura e dalle applicazioni. Una buona figura di rendimento, per applicazioni commerciali, può essere compresa nel range di 80-95 % di hit[8].
Ci sono tre strutture di base per le cache:
Ogni blocco di memoria può essere memorizzato in qualsiasi posizione della cache. È chiamata "fully associative" (completamente associativa) perché ogni dato memorizzato in cache è associato al suo indirizzo completo di memoria. La cache è divisa in due banchi: la directory (indice guida) e il banco data (dati). La directory è divisa a sua volta in due campi, data attribute bit (bit di attributo dati) o State (stato), e indirizzo dati ADD (indirizzo del blocco di memoria). I bit di attributo dati include il Valid bit (bit di validità) e può includere anche diversi altri bit di stato come il Modified bit (M) (bit di modifica), Shared bit (S) (bit di condivisione) e altri (vedi sotto Stati della Cache). Oltre a questi bit possono essere inclusi anche i "bit di protezione" come Supervisor/User (Supervisore/Utente) e Write protection - "protezione di scrittura". Nella cache Fully Associative viene memorizzato in cache l'indirizzo completo del blocco di memoria. Quando un dato è letto dalla cache, tutti gli indirizzi memorizzati nella "Directory" sono contemporaneamente confrontati con l'indirizzo del blocco di memoria del dato richiesto. Se un indirizzo viene trovato con dato "valido" (hit) il dato corrispondente viene letto dalla cache. In caso di miss il blocco del dato viene letto dalla MM. Il dato letto dalla MM viene anche poi memorizzato in cache che rimpiazzerà (sovrascriverà) una linea di cache scelta in accordo con la politica di rimpiazzo (Replacement policy). La cache Fully Associative ha un'alta efficienza. Come detto prima, il principale vantaggio di questa tecnologia è che il dato può essere memorizzato in qualsiasi posizione della cache, ma purtroppo è costosa in termini di hardware. Necessita di vie di accesso simultanee indipendenti ed un comparatore per ogni entry (entrata) di cache. Perciò le dimensioni di questa cache sono in genere molto piccole ed è usata solamente per casi specifici (per es. nel TLB). Normalmente non è mai usata come Cache Memory, ma vengono invece usate le Direct-Mapped e le Set-Associative cache.
Nella cache Direct Mapped - Mappata Direttamente ogni blocco di memoria può essere memorizzato in una sola entry di cache. La entry (cioè la posizione di cache) dove memorizzare il blocco è direttamente derivata dall'indirizzo di memoria (da cui il nome "Direct-Mapped" - mappata direttamente). La dimensione della cache è più piccola della MM, perciò l'indirizzo di memoria deve essere ridotto per adattarsi allo spazio di cache. Tutti i dati di memoria devono poter essere memorizzati in uno spazio più piccolo, ma ovviamente non tutti contemporaneamente. Molti algoritmi, chiamati hash coding (o hashing), sono usati per far questo. La soluzione comune[9] per ottenere l'indirizzo di cache è di usare direttamente una parte dell'indirizzo di memoria, e precisamente il campo chiamato index (indice), cioè, escludendo l'offset, i bit meno significativi dell'indirizzo (Least significant bit - LSB), vedi fig. Cache addressing. L'offset (offset della linea) è invece il campo dell'indirizzo usato per l'indirizzamento interno della linea di cache a livello di byte. Per esempio avendo un indirizzamento di memoria a 32 bit (4 GB di spazio), e una dimensione di cache di 4 MB con una linea di cache di 256 B, i bit meno significativi (8-21), l'index, sono usati per selezionare l'indirizzo della linea di cache. Questa soluzione di indirizzamento lineare, nella Demand-Paging Virtual memory (Memoria virtuale), (vedi anche sotto Indirizzamento Virtuale), permette la memorizzazione di una pagina completa di memoria (Memory page) nella cache. Tutti i dati aventi lo stesso Index, chiamati sinonimi vengono memorizzati nella stessa entry, perciò solo un sinonimo alla volta può essere memorizzato nella cache (conflitto di sinonimi). I sinonimi differiscono tra loro per l'MSB (Most Significant Bits - bit più significativi dell'indirizzo). Per distinguere i vari sinonimi l'MSB denominato tag dell'indirizzo (targhetta dell'indirizzo) è memorizzato nella directory della cache (nell'esempio precedente i bit (22-31)). Quando un dato viene letto dalla cache, l'MSB della directory della cache è confrontato con l'MSB dell'indirizzo di memoria del dato da leggere. Come per la cache Fully Associative, in caso di hit, il dato è letto dalla cache, altrimenti in caso di miss, dalla memoria. La distanza tra due sinonimi, in termini di indirizzo, è un multiplo della dimensione della cache. Il conflitto di sinonimi diminuisce con l'aumentare della dimensione della cache perché la distanza tra sinonimi aumenta. In questo tipo di cache una sola linea di cache alla volta viene selezionata, di conseguenza è necessario un solo comparatore. Per minimizzare il problema dei sinonimi viene utilizzata la Set Associative cache.
La cache Set Associative (o multi-via-direct-mapped ) è una combinazione dei due approcci precedenti ed è usata per ridurre il conflitto tra sinonimi. Questa cache è composta da un set di identiche cache Direct Mapped, indirizzate nello stesso identico modo, cosicché per ciascuna entry è disponibile un "set" (gruppo, way-vie) di alternative linee di cache per memorizzare più di un sinonimo. I sinonimi possono essere memorizzati in qualsiasi set delle entry selezionate, in funzione dell'algoritmo di politica di rimpiazzo utilizzata, generalmente LRU. Normalmente il numero di set è nel range di 2-8/16 o più, sino a 48 (AMD Athlon[10]) e 128 (POWER3[11]), in funzione del tipo di cache (Istruzioni/Dati - vedi sotto "Tipi di cache"). Nella cache Set Associative viene usato un comparatore di indirizzi per ogni set. Una cache Direct Mapped può essere vista come una cache Set Associative con un solo set e una cache Fully Associative con n-linee come una cache Set Associative a n-vie (set) con una sola entry. In dipendenza dalla politica di rimpiazzo "Replacement policy" adottata, la Directory può o no contenere anche i replacement bits (bit di rimpiazzo) per selezionare la linea di cache candidata per il rimpiazzo.
Quando è disponibile più di una entry per memorizzare un dato, come nel caso di cache Fully Associative e Set Associative, la entry che dovrà essere rimpiazzata è selezionata in base alla "Replacement policy" adottata. Ci sono differenti politiche[12].
Le principali sono:
In un sistema può essere usata più di una cache. Le cache sono organizzate in livelli gerarchici. Sono possibili sino a quattro livelli, L1-L4 o più[13]. Una cache più grande ha un hit-rate migliore ma un tempo di latenza maggiore. Una cache multi-livello garantisce un accesso veloce con un alto hit-rate. Generalmente la cache multi-livello opera verificando prima la cache più piccola di più basso livello, il Livello 1 (L1). Se si ha hit il processore procede velocemente. Se la cache più piccola dà miss, viene controllata la successiva cache più grande (L2), e così via fino al più alto livello. Il miglioramento della tecnologia permette sufficiente spazio per implementare una piccola cache L1 all'interno del chip del processore. Una cache interna è più veloce di una esterna, ma ha un più basso hit rate dovuto alla sua minore dimensione, tipicamente nel range tra 8KB a 64KB. Per aumentare la dimensione globale della cache e così l'hit rate, si usa una cache L2 maggiore strettamente accoppiata al processore. Una dimensione tipica della cache L2 è nel range da 64KB a 8MB. La cache L2 può essere esterna o interna al chip o al package del processore. In questo ultimo caso perciò può essere usata un'ulteriore cache L3 esterna ancora maggiore (4-256MB). Nei sistemi multi-core la L3 può essere implementata in un MCM (Multi-chip module) (vedi per es. POWER5 IBM, AMD Bulldozer). Normalmente la L1 è una cache Set Associative separata Istruzioni e Dati (vedi sotto Tipi di cache). La cache L2 può essere unificata o separata, come pure essere una cache Direct Mapped o Set Associative. Lo stesso per la cache L3.
Ci sono due tipi di cache:
Nella memoria principale vengono memorizzate due tipi di informazioni, le istruzioni (anche chiamate codice) e i dati (come operandi o di stack - vedi Stack cache). Le cache possono essere suddivise in cache unificate e cache separate, le cache unificate memorizzano sia le istruzioni che i dati mentre nelle cache separate istruzioni e dati sono memorizzati in cache dedicate.
La cache istruzioni viene abbeviata in "I-Cache" mentre la cache dati in "D-Cache", l'utilizzo di cache separate presenta principalmente tre vantaggi:
La maggior parte delle cache possono trattare solo una richiesta alla volta. Se una richiesta è fatta e c'è miss, la cache deve aspettare il dato dalla memoria, e in attesa di questo, la cache rimane "bloccata". Una cache non-blocking (o lock-free) ha la possibilità di lavorare su altre richieste mentre è in attesa dei dati "miss" dalla memoria.
La cache può essere inclusiva o esclusiva:
Inclusività vs Esclusività: L'inclusività è preferibile nei sistemi multiprocessori/multi-core bus-based, cioè basati sul bus per la coerenza dei dati, altrimenti il controllo di coerenza deve essere fatto in tutte le cache (vedi sotto Interferenze tra Snoopy e attività del processore). L'inclusività semplifica la coerenza delle cache. L'aspetto negativo della cache inclusiva è che la cache L2 contiene dati ridondanti, questo significa una riduzione della dimensione della cache globale. Questo è vero solo se le dimensioni delle cache L1 e L2 sono comparabili. Spesso la dimensione di L2 è un ordine di grandezza rispetto a L1, perciò la riduzione del hit-rate dovuto alla riduzione della dimensione globale può essere molto bassa (qualche percento), considerando anche che nel range di 80-95 % di hit-rate, aumentando la dimensione, il guadagno del hit-rate tende rapidamente ad essere piatto[8]. Le stesse considerazioni possono essere fatte per la cache L3 rispetto a L2 (vedi per esempio Shanghai (AMD) vs Nehalem-EP (Intel)[14]).
La write policy - o politica di scrittura - determina come vanno gestite le scritture in memoria di dati memorizzati in cache. Generalmente solo la D-Cache è interessata, perché normalmente le istruzioni non sono auto-modificanti, e in caso di auto-modifica, il software forza la scrittura di questo codice (Istruzioni) solo in memoria senza coinvolgere la cache (vedi ad esempio AMD64 Self-Modifying Code[15])
Ci sono due tipi di politiche:
Il dato viene scritto contemporaneamente sia in cache che in memoria o in cache e poi in memoria (da cui il nome)
Il dato è aggiornato solamente nella cache. Viene riscritto in memoria solo quando è necessario, per esempio in casi di "rimpiazzo" (sovrascrittura) della linea di cache o quando richiesto da altre cache. Questo riduce il traffico di memoria e di bus perché il successivo aggiornamento della linea di cache viene fatto solo nella cache senza coinvolgere la memoria. Nella Directory della cache, in questi casi viene attivato (settato) il bit "D" o "M" (Dirty = sporco o Modificato) - (vedi sotto Stati della Cache).
In caso di miss in scrittura si hanno due differenti soluzioni:
Write allocate on miss (allocazione in scrittura su miss) detta anche Fetch-on-write (acquisire per scrivere) o RWITM (Read With Intent To Modify - lettura con intenzione di modifica) o Read for Write - lettura per scrittura
In caso di miss in scrittura, la linea di cache è letta prima dalla memoria principale o da una cache in caso di Cache Intervention (intervento di cache), poi è aggiornata (modificata) in cache con il nuovo dato (scrittura parziale della linea: byte, halfword, word o doubleword - 8, 16, 32 o 64 bit, dipendente dal parallelismo operativo intrinseco del processore)
Il dato è scritto direttamente in MM "by-passando" la cache
Write allocate è normalmente associata al write-back. Write no-allocate può essere o non associata al write-through.
Le architetture Superscalar processor (processori superscalari = multi unità operative) sono in grado di eseguire simultaneamente istruzioni in parallelo (sfruttando il parallelismo intrinseco delle istruzioni stream / multithread - flusso continuo/multi ramificazioni). In questo genere di processori ci sono diversi unità funzionali dello stesso tipo con dei circuiti addizionali per il "dispaccio" delle istruzioni alle varie unità. Nella maggior parte di questi sistemi "superscalar" includono più di un'unità aritmetica-logica (unità per operazioni aritmetiche e logiche). Per esempio in IBM POWER3[16] sino a otto istruzioni, due floating point (virgola mobile), due load/store (lettura/scrittura = spostamento dati - in inglese "move"), tre fixed point - (virgola fissa), due singolo ciclo, un multi-ciclo e un "branch" (istruzione di salto - le istruzioni vengono eseguite in modo sequenziali sino a trovare un'istruzione di "salto" che salta d una nuova sequenza) che possono essere eseguite nello stesso ciclo. Le istruzioni disponibili sono inviate fuori ordine (out of order) dalle code di uscita, consentendo a queste istruzioni di essere eseguite fuori ordine per mezzo dell'uso della tecnica dei Register renaming (sostituzione di un registro già in uso con un registro diverso - cambio del nome) per la sincronizzazione e il riordino dei risultati.
L'esecuzione parallela delle istruzioni richiede accessi simultanei alla D-cache L1. Conflitti avvengono quando due o più richieste accedono simultaneamente allo stesso banco di cache. Questi conflitti possono parzialmente essere eliminati tramite l'uso di cache multi-banco e/o di multi-porte[17][18][19]
Ci sono diverse soluzioni[20][21]:
La D-cache L1 è divisa in banchi multipli con indirizzi indipendenti.
Ci sono due approcci:
I banchi sono indirizzati in parallelo tramite un crossbar (connessioni dirette incrociate). L'indirizzo è lineare, cioè il successivo indirizzo dell'ultimo indirizzo di un banco è il primo indirizzo del banco successivo. I banchi sono selezionati in sequenza tramite l'uso dei bit più significativi (MSB) dell' "Index" dell'indirizzo (per esempio, con 8 banchi, i tre bit 21-19 dell'esempio in Cache addressing). I banchi multipli possono supportare multiple richieste per ciclo quando queste non indirizzano lo stesso banco. L'approccio multi-banco può essere efficiente per applicazioni che hanno una scarsa località spaziale dei dati (dati statisticamente indipendenti), ma per applicazioni con una buona località spaziale, come negli accessi consecutivi, accessi simultanei multipli non sono permessi causa "conflitti di banco" (bank collision - collisioni di banchi)
Linee di cache consecutive sono memorizzate su banchi consecutivi. L'indirizzamento delle linee di cache è "interlacciato" (distribuito orizzontalmente) tra i banchi come mostrato nella fig. a lato. I banchi sono selezionati tramite i bit più o meno significativi dell' "Index" dell'indirizzo (per esempio, con una 8-way interleaving (interlacciamento a 8 vie), i bit 10-8 dell'esempio sopra in Cache addressing). Comunemente il numero di banchi varia da due, quattro od otto (vedi ad es. IBM POWER3[22]), chiamati two-way, four-way o eight-way interleaving rispettivamente. La cache interleaving dà vantaggi specialmente nelle operazioni su stringhe di dati multipli. Per esempio, avendo una cache two-way interleaving (indirizzo pari nel Banco 0 e dispari nel Banco 1) e due programmi (threads) che operano su due stringhe indipendenti, il primo programma può accedere al Banco 0 mentre il secondo al Banco 1. Nel successivo accesso, il primo programma può accedere al Banco 1 mentre il secondo al Banco 0, e così via alternativamente. In caso di "conflitto di banchi" (bank collision), cioè accesso simultaneo allo stesso banco, un programma all'inizio deve aspettare un ciclo, poi può iniziare. Anche negli accessi casuali simultanei multipli questo sistema offre vantaggi, dipendente dal numero di banchi. La probabilità di conflitto diminuiscono all'aumentare del numero di banchi. Esempio di interleaving: la cache L1 di POWER3[23] con interleaving a 8-vie è in grado di servire due "load" (letture), una "store" (scrittura) e una rilettura (reload) di una linea di cache per ciclo.
Porte multiple permettono di fare accessi paralleli multipli alla cache nello stesso ciclo di clock, che operano in modo indipendente fra loro[7][24].
Le cache multi-porte permettono di ottenere la più alta frequenza di accesso per ciclo, ma sono complesse e perciò lente e costose. Inoltre comporta l'uso di strutture di celle non standard. Mentre una singola celle di memoria statiche richiede 6 transistor a effetto di campo (field-effect), per aver una porta doppia sono necessari 2 transistor in più. Perciò questa soluzione può essere usata per solo poche porte, normalmente due per le letture e una per le scritture (es. POWER4 IBM).
Cache con "n" identiche copie (cloni) con indirizzamento simultaneo indipendente. Limitazioni: copie replicate senza benefici di spazio di memorizzazione. Inoltre le richieste di scrittura devono essere fatte simultaneamente su tutte le copie, cosicché nessun'altra richiesta può essere inviata in parallelo. Poiché circa il 30% di accessi alla memoria sono scritture[25], questa soluzione ha dei severi limiti.
La "time division multiplexing" è una tecnica che può essere anche riferita come "cache over-clocking" cioè clock con frequenza maggiorata. Funzionamento della cache con frequenza 2x (3x, 4x) della frequenza del processore in modo che la cache può essere acceduta due (tre, quattro) volte per ciclo (clock).
Combinazione della soluzione cache interleaving con multi-porte. I banchi multipli interleaving permettono accessi paralleli a basso costo mentre le porte multiple riducono i conflitti di banco.
I processori possono condividere una cache comune. Le cache condivise generalmente sono usate per la coerenza dei dati nei sistemi multi-core (Multi-chip) e per la riduzione dei costi. Nei sistemi come il multiprocessore simmetrico (SMP), il multi core e il cc-NUMA, dove viene usata una cache dedicata per ogni processore, core o nodo, si può verificare un problema di coerenza, o coerenza, dei dati quando uno stesso dato è memorizzato in più di una cache e si verifica che un dato viene modificato in una cache.
Può essere risolto in due modi:
In entrambi i casi la memoria può essere aggiornata (write through) o non aggiornata (write-back); la coerenza dai dati generalmente riguarda solo i dati (come operandi) e non le istruzioni (vedi Self-Modifying Code).
Gli schemi si possono classificare in base a:
Tre approcci sono adottati per mantenere la coerenza dei dati:
Protocollo usato nei sistemi con bus, come ad esempio nei sistemi SMP. Sistema operante sotto un unico sistema operativo con due o più processori omogenei e con una memoria principale centralizzata condivisa. Ciascun processore ha una propria cache che agisce come ponte tra il processore e la memoria principale. La connessione è fatta usando un bus di sistema (system bus) o un crossbar (xbar, connessioni incrociate)[26] o un mix dei due precedenti sistemi, bus per gli indirizzi e crossbar per i dati (data crossbar)[27][28][29].
Il limite maggiore di questi sistemi è il traffico e la larghezza di banda di memoria (quantità di dati al sec.). La banda può essere aumentata usando un largo canale dati, un crossbar dati, la memory interleaving e la transazioni di dati fuori ordine (out of order data transaction). Il traffico può essere ridotto usando una cache che agisce da filtro verso la memoria condivisa. La cache è quindi un elemento essenziale nei sistemi SMP con memoria condivisa (shared-memory). Nei sistemi multiprocessori con cache separate che condividono una memoria comune, uno stesso dato può essere memorizzato in più di una cache. Un problema di coerenza nei dati nasce quando un dato è modificato in una sola cache. I protocolli per mantenere la coerenza fra processori multipli sono chiamati cache-coherency protocols (protocolli di coerenza delle cache). Generalmente nei sistemi SMP la coerenza si basa sull'approccio chiamato Bus watching (sorveglianza del bus) o Snoopy. In un sistema basato sullo snoopy, tutte le cache controllano le transazioni del bus per intercettare i dati e verificare se ha una copia nella propria cache. Vari protocolli di coerenza sono usati per mantenere la coerenza dei dati tra cache[30]. Questi protocolli sono generalmente classificati solo in base agli stati della cache (da 3 a 5 e 7 o più) e le transazioni tra questi, ma questo potrebbe creare qualche confusione in quanto la definizione di un protocollo così fatta è incompleta perché mancante di importanti ed essenziali informazioni come le azioni che questi producono; queste azioni possono essere indotte dal processore o dal bus (esempio "intervention", "invalidation", "broadcasting", "updating", ecc.). Il tipo di azioni sono dipendenti dalle implementazioni adottate. Protocolli aventi gli stessi stati e le stesse regole di transazioni possono essere differenti, per es. il protocollo MESI con "shared intervention" (intervento su dati condivisi puliti (clean)) e MESI senza "intervention". Protocolli con stati differenti possono essere praticamente lo stesso protocollo, per esempio i protocolli 4-stati MESI Illinois e 5-stati MERSI (IBM) / MESIF-Intel sono solo un'implementazione diversa delle stesse funzionalità. I più comuni protocolli sono il protocollo 4-stati conosciuto con l'acronimo MESI e il 5-stati MOESI. Altri protocolli usano gli stessi stati - o un sottoinsieme di questi - ma con differenti implementazioni e spesso con una differente ma equivalente terminologia. Con il termine MESI o MOESI, o un sottoinsieme di questi, generalmente si fa riferimento a una classe di protocolli piuttosto che a uno specifico protocollo.
Stati speciali:
L'attività dello Snoopy richiede l'accesso alla Directory della cache e può essere in conflitto con gli accessi concorrenti del processore. Questa interferenza fa aumentare la latenza della cache.
Per ridurre o eliminare questa interferenze possono essere usate tre soluzioni:
L'attività dello Snoopy richiede l'accesso alla Directory della cache e può essere in conflitto con gli accessi concorrenti del processore. Questa interferenza fa aumentare la latenza della cache.
Per ridurre o eliminare questa interferenze possono essere usate tre soluzioni:
Si distinguono tre operazioni: transazioni di bus, caratteristiche dei dati e operazioni di cache:
Protocolli:
Terminologia usata:
È noto che i sistemi SMP hanno una limitata scalabilità. La memoria multi-banco e il crossbar dati[27] permettono accessi paralleli alla memoria. L'uso di grandi cache riduce il traffico sul bus di sistema ma non le write invalidate (scrittura con invalidazione) o write-broadcast (scrittura con distribuzione). La maggiore limitazione è che l'indirizzo di memoria deve essere monitorato (snoopy) usando un unico bus. Per superare questa limitazione, viene adottata una nuova architettura chiamata cc-NUMA.
Il sistema cc-NUMA è un insieme di sistemi SMP chiamati nodi connessi via una rete di connessione che può essere un link (collegamento) formato da un singolo o doppio anello bidirezionale o multi-anello, connessioni punto-punto[26][33] o un mix di queste (vedi ad es. sistemi IBM Power Systems[24][54]), intercessione via bus (es. NUMAq[55]), crossbar, segmented bus (bus segmentato - NUMA Bull HN ISI ex Honeywell[56]), Mesh router, ecc..
Esempi di interconnessione:
La caratteristica principale del sistema cc-NUMA è di avere un'unica memoria globale condivisa e distribuita in ciascun nodo direttamente acceduta da tutti i processori di tutti i nodi
In un sistema NUMA l'accesso di un processore a una memoria remota di un nodo remoto è più lento rispetto all'accesso alla propria memoria locale. Per questa ragione questo sistema è chiamato NUMA (Non Uniform Memory Access - accesso della memoria non uniforme).
L'architettura NUMA è anche chiamata Distributed Shared Memory (DSM) - memoria condivisa distribuita[57].
Normalmente ciascun nodo è un sistema SMP, dove un processore può essere un singolo processore o un multi-core, o un mix dei due, o qualsiasi altro tipo di architettura. La fig. a lato è solo un esempio.
La differenza del tempo di accesso fra una memoria locale e una remota può anche essere di un ordine di grandezza, in dipendenza del tipo di connessione (più veloce nel segmented bus, crossbar e interconnessione punto-punto, più lenta con la connessione ad anelli seriali).
Terminologia: (da un punto di vista di un nodo)
Per ridurre le differenze di accesso tra dati locali e remoti, viene utilizzata una cache remota (Remote cache). Questa cache memorizza i dati letti dalle altre memorie remote. Normalmente questa cache è inclusiva-condivisa (shared inclusive) con protocollo MESI. Le cache L1-L3 possono essere tipo MESI esteso (es. R-MESI, RT-MESI, ecc.). Ogni dato remoto memorizzato nelle cache L1-L3 è anche memorizzato in questa cache (per l'inclusività). Questa cache è il 4º livello di cache del nodo per i soli dati remoti (cache delle memorie remote), mentre le cache L1-L3 memorizzano sia dati locali che remoti (cache del nodo relativo alla memoria globale). Da un punto di vista interno di un nodo la remote cache può essere vista come un'estensione della memoria locale (dati remoti memorizzati localmente).
Poiché la funzione di questa cache è di ridurre il tempo di accesso remoto almeno come il tempo di accesso della propria memoria locale, può essere usata una tecnologia ibrida - SRAM per la directory, DRAM per la cache dei dati[58]. Questa soluzione permette di implementare cache sufficientemente grandi come richiesto da questi sistemi.
La cache remota può memorizzare sia le istruzioni (codice) che i dati (come operandi), ma normalmente solo i dati sono memorizzati. L'accesso ai dati privati, come il codice e i dati di stack, spesso possono essere elaborati localmente copiando il codice (replicazione del codice) da un altro nodo (aumento dell'efficienza).[59]
La coerenza delle cache nei sistemi cc-NUMA (Cache Coherency-NUMA) è ottenuta usando il protocollo noto col nome di Directory-based - Message-passing. Questo approccio è stato proposto per la prima volta da Censier e Feaultrier[60] e descritto anche in "The Directory-Based Cache Coherency Protocol for DASH Multiprocessor"[61].
Poiché normalmente non tutti i nodi accedono nello stesso tempo agli stessi dati, il controllo di coerenza può essere molto più efficiente se fatto in modo selettivo sui soli nodi interessati.
Nei sistemi cc-NUMA la coerenza della cache a livello di sistema (inter-nodo) è perciò fatta mediante un protocollo directory-based (basato su una directory), usando una directory associata a ciascuna memoria locale (local memory directory) che tiene traccia dello stato globale di tutti i blocchi della propria memoria locale e un indicatore (indicator bit) per indicare quale nodo ha il blocco memorizzato nella propria cache remota. La coerenza all'interno del nodo invece è basata sullo schema bus-snoopy.
Ciascuna entry (linea di ingresso) della directory ha N-1 bit indicatori di nodo e tre stati globali associati a ciascun blocco di memoria che sono una copia degli stati di tutte le cache remote.
Ci sono quattro possibili situazioni per un nodo:
Tipicamente usato nei sistemi Multi-core per la coerenza e per riduzione dei costi (in termini di spazio).
Il multi-core ("multipli processori integrati"), denominato anche chip multiprocessors, multicore chips, e many-core chips, è uno speciale genere di multiprocessore dove tutti i processori sono sullo stesso chip MCM (Multi-Chip Module)[64][65]
I processori Multi-core sono dei sistemi MIMD: core differenti eseguono differenti threads (Multithread/Multiple Istruzioni - esecuzione parallela sullo stesso contesto di piccole sequenze di istruzioni programmate), operando su differenti parti di memoria (Multiple Data).
Una soluzione comune di implementazione dei sistemi Multi-core è l'uso di cache multi-livello condivise e inclusive (multi-level inclusive shared cache) per mantenere la coerenza dei dati.
L'inclusività forza i dati ad essere coerenti. Dati memorizzati in L1 sono memorizzati anche in L2 (e in L3 se usata). Qualsiasi cambiamento in L1 deve essere riportato anche nella cache L2 e così anche in L3. Se L2 è aggiornata o invalidata anche tutte le cache L1 devono essere invalidate o aggiornate (stessa relazione tra L2-L3).
La coerenza delle cache è mantenuta mediante l'uso di un controllore centralizzato della cache condivisa. La cache condivisa può essere la L2, o L3 se L2 è una cache privata.
Il protocollo di coerenza si basa protocollo tipo point-to-point message-passing simile a quello descritto nel sistema cc-NUMA. La differenza sta solamente nella directory, che nel sistema cc-NUMA è relativo alla memoria e non alla cache condivisa.
Ci sono due generi di implementazione. Messaggio distribuito (message broadcasting) a tutte le cache L1 oppure solo alle specifiche cache L1 che hanno il dato memorizzato. Nel primo caso il protocollo di coerenza è di tipo snoopy. La cache condivisa agisce come ponte in sostituzione del bus di sistema, rinviando le transazioni a tutte le cache L1 per lo snooping, solo però quando è necessario, cioè quando un dato non è esclusivo nella cache condivisa. Nel secondo caso, nella directory della cache condivisa c'è un "indicator bit" per ciascuna cache L1 per indicare quale L1 può avere il dato (Intel Nehalem[44]).
Sistemi Multi-core possono essere connessi assieme per formare un sistema NUMA. La coerenza è garantita tramite message-passing tra le L3 shared-cache dei vari nodi (vedi ad es.Intel Nehalem[44], AMD Opteron[26][33][66], MCM Interconnections POWER5 IBM[7][54][67], ecc.)
L'MMU (Memory Management Unit) è l'unità di gestione degli accessi di MM. Le funzioni principali sono:
La memoria virtuale è lo spazio visto da un processo. Generalmente questo spazio è molto più grande della memoria fisica. Questo spazio è segmentato in pagine di dimensione prefissata. La page table (tabella delle pagine), generalmente caricata in memoria, tiene traccia di dove le pagine virtuali vengono caricate nella memoria fisica. Il TLB (Translation Lookaside Buffer - memoria di traduzione a lato) o Page Table cache o page-translation caches - cache di traduzione delle pagine) è una cache della Page Table, cioè solamente un sottoinsieme del suo contenuto è memorizzato nel TLB. Il TLB, come per la cache di memoria può essere "separato" Istruzioni (ITLB) e Dati (DTLB) o "unificato", come pure essere Direct Mapped o Set Associative o Fully Associative. Generalmente l'organizzazione segue l'organizzazione della cache associata, ma può essere organizzata in modo indipendente da questa (vedi TLB). Come per la cache, per aumentarne l'efficienza può essere usato anche un secondo livello di TLB aggiungendo un L2 TLB (es. Intel Nehalem[44]).
La cache può essere indirizzata in modo fisico o virtuale. Ci sono pro e contro per entrambe le implementazioni, ma generalmente l'indirizzamento fisico è quello normalmente usato.
In fig. sotto un esempio di indirizzo virtuale con 4 GB di spazio virtuale, 4 MB cache, 4 KB di dimensione di pagina e 256 B di dimensione della linea di cache.
Lo spazio virtuale o logico è diviso in pagine. L'MSB + PA formano l'indirizzo di pagina dello spazio virtuale VPA (Virtual Page Address). Anche la cache è divisa in pagine.
La cache memorizza un sottoinsieme delle pagine dello spazio virtuale. È indirizzata dall'Index che è formato da PA + PA Offset dove il PA (Page Address) è l'indirizzo di pagina della cache e il PA Offset è l'indirizzo della linea di cache all'interno della pagina, mentre l'offset è l'indirizzo interno, a livello di byte, della linea di cache.
Nel indirizzamento virtuale o logico una cache è direttamente indirizzata dall'indirizzo virtuale Index senza dover prima convertire l'indirizzo virtuale in fisico. Anche i TAG sono virtuali (logical MSB). Questo tipo di indirizzamento è denominato anche Virtual Index - Virtual TAG (VIVT).
In un ambiente multiprocessing differenti indirizzi logici di contesti (context) o processi diversi possono riferirsi ad uno stesso indirizzo fisico, e lo stesso indirizzo logico di un processo può mappare differenti indirizzi fisici causando un problema di coerenza, mentre al contrario all'interno dello stesso contesto, lo stesso indirizzo logico è sempre relativo allo stesso indirizzo fisico.
Ci sono tre possibili soluzioni:
Poiché differenti indirizzi logici di differenti contesti possono riferisci allo stesso indirizzo fisico (dati condivisi), più di una posizione di memoria potrebbe memorizzare lo stesso dato, causando un problema di coerenza in caso di scrittura. Solamente una posizione di memoria sarebbe aggiornata.
Ci sono due soluzioni principali[69]
In ogni caso la cache deve sempre essere invalidata quando la mappatura virtuale-fisica viene cambiata, per es. nel caso di rimpiazzo della pagina - page replacement.
Nell'indirizzamento fisico, per prima cosa viene indirizzato il TLB (*) usando l'indirizzo virtuale L-MSB + LPA, poi l'indirizzo fisico (PPA) ottenuto dal TLB più PPA Offset è usato per indirizzare la cache. Solamente la parte dell'indirizzo virtuale che differisce dall'indirizzo fisico è convertita, cioè "L.MSB" e "LPA".
Il TLB è una cache della Page Table cache ed è gestita come una normale cache con in aggiunta che il CTX associato all'indirizzo logico è confrontato con il CTX memorizzato nel TLB perché cambiando contesto cambia l'associazione LPA-PPA (vedi indirizzamento virtuale).
Questa soluzione (indirizzamento Physical Index - Physical TAG - PIPT) è molto più semplice ed evita qualsiasi problema di ambiguità, ma è più lenta perché prima è richiesto l'accesso al TLB.
(*) - All'inizio la dimensione della cache era piccola ed uguale alla dimensione della pagina, perciò "index" (l'indice) virtuale e fisico erano coincidenti e il TLB era acceduto in parallelo (a lato - look aside, da cui il nome) solamente per verificare gli MSB, come nell'indirizzamento virtuale.
Questo approccio si basa sul principio della località spaziale
Facendo riferimento alla fig. Virtual Space Address Structure, l'indirizzo virtuale/logico "Index" è diviso in due parti: Logical Page Address (LPA - indirizzo di pagina logica o numero di pagina) e LPA offset (l'indirizzo della linea di cache all'interno della pagina). L'offset è l'indirizzo interno (a livello di byte) della linea di cache.
Il virtual e il physical page offset coincidono (come pure, ovviamente, l'offset). L'indirizzo virtuale e l'indirizzo fisico differiscono per l' L.MSB e per l' LPA. Il TLB converte l'L.MSB logico e la Logical Page Address (LPA), rispettivamente in P.MSB fisico e in Physical Page Address (PPA = indirizzo fisico di pagina). Nell'indirizzamento fisico, il PPA + LPA Offset formano l'index fisico che è usato per indirizzare la cache.
Località spaziale significa che se un accesso è fatto in una pagina ci sono moltissime probabilità che il prossimo accesso (relativo allo stesso tipo) sia fatto nella stessa pagina.
Separatamente per le Istruzioni e per i Dati e i dati di Stack (se la cache Stack è usata), la probabilità che il successivo accesso sia fatto nella stessa pagina del precedente accesso è molto alta dovuta a una località spaziale molto ampia (4 KB o più rispetto, per esempio, a una molto più piccola dimensione di una linea di cache).
Il precedente indirizzo logico/virtuale di pagina (LPA) con il suo Context Number (CTX) e il corrispondente indirizzo fisico di pagina (PPA) sono memorizzati in un dedicato registro.
Nel successivo accesso, il nuovo indirizzo logico di pagina e confrontato (assieme al CTX) con l'indirizzo memorizzato precedentemente nel registro LPA. Se coincidono (hit), viene usato il corrispondente registro dell'indirizzo fisico di pagina PPA per indirizzare direttamente la cache, senza la necessità di accedere al TLB così come avviene nel caso di indirizzamento virtuale (da cui il nome Pseudo Virtual addressing- indirizzo Pseudo Virtuale).
In caso di miss, il PPA è fornito dal TLB, come nel caso di indirizzamento fisico senza alcuna penalità rispetto a quest'ultimo.
Questo approccio è efficiente se un set di registri "LPA-PPA" è riservato ciascun per tipo di funzione: uno per la istruzione, due per gli operandi (le istruzioni possono avere sino a due indirizzi di operandi) ed eventualmente uno per i dati di stack. In aggiunta per aumentare l'efficienza nei sistemi multithreading, possono essere usati un gruppo di dedicati registri "LPA-PPA" per ogni thread.
Nota - Questi registri possono essere visti come una cache L1 del TLB con una sola entry, separata per ogni tipo di dato (istruzioni, dato1, dato2, stack) e per ogni thread, cioè una cache L1 TLB fatta a registri e perciò velocissima.
Con questa soluzione, praticamente senza costi aggiuntivi, nella quasi totalità dei casi, e in particolare per le istruzioni e per stringhe di dati sequenziali, l'indirizzamento è fatto in modo fisico senza però la necessità di aspettare la traslazione dell'indirizzo da virtuale a fisico, esattamente come avviene nel caso dell'indirizzamento virtuale, e senza anche la necessita, rispetto a quest'ultimo, di invalidare (flush) la cache in caso page replacement (sostituzione della pagina), eliminando qualsiasi problema di coerenza.
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.