genere | Dispositivo di memorizzazione delle informazioni , componente software , hardware del computer |
---|
Una cache o memoria cache è, in informatica , una memoria che memorizza temporaneamente copie di dati da una sorgente, al fine di diminuire il tempo di un successivo accesso (in lettura) di un hardware di computer (in generale, un processore).) questi dati. Il principio della cache può essere utilizzato anche in scrittura, e quindi esiste in tre possibili modalità: write-through , write-back e write-around .
La memoria cache, più veloce e più vicina all'apparecchiatura informatica che richiede i dati, è più piccola - per le sue prestazioni e quindi per il suo costo - della memoria per la quale funge da intermediario. Commercialmente, la nozione di cache è apparsa sul mainframe IBM 360/85 nel 1968.
I meccanismi di memoria cache possono essere posizionati tra tutti i produttori e consumatori di dati che operano in modo asincrono, ad esempio processore e memoria ad accesso casuale , spazio di rete e applicazione, disco rigido e memoria ad accesso casuale, ecc.
Tecnicamente è vantaggioso gestire separatamente i dati non modificabili (illustrazioni di un sito remoto, sezione di codice programma) e quelli modificabili (modulo, sezioni dati, ecc.). Ad esempio, i processori molto spesso hanno cache separate per codice e dati.
La sua velocità necessaria rende la memoria cache costosa e per questo limitata. Nel caso dei microprocessori , le dimensioni e le prestazioni di queste cache, esterne o interne, possono influenzare notevolmente la velocità di elaborazione del programma. È possibile misurarlo mediante inibizione totale o parziale della cache, oppure modificandone le dimensioni se esterno.
Nel caso delle cache interne, lo spazio utilizzato dai transistor cache nel wafer determina il suo costo di produzione. La memoria cache è tanto più utile in quanto l'algoritmo da eseguire richiede accessi ripetitivi a piccole aree di memoria:
Quando il processore è in grado di prevedere approssimativamente le sue esigenze di dati future, può popolare la cache in anticipo, operazione chiamata prefetch .
La memoria cache è la stessa espressione usata in inglese , ovvero memoria cache , che ha sostituito "slave-memory", data dal suo inventore Maurice Vincent Wilkes nel 1965. L' Accademia francese propone invece il termine cache memory .
La differenza tra memoria cache e memoria buffer è che la memoria cache duplica le informazioni, mentre il buffer può esprimere l'idea di una sala d'attesa, senza necessariamente implicare la duplicazione. Il buffer cache (buffer cache) del disco o il disk cover (disk cache) è sia un buffer che gestisce le informazioni sia una memoria cache che copia elettronicamente i dati memorizzati nel disco in forma magnetica.
La principale differenza tra il disco e la cache di memoria è che nel secondo caso hai pochissimo tempo per capire dove mettere ciò che stai nascondendo. Quando si nasconde un disco, è possibile scegliere con attenzione dove posizionare ogni informazione in base alle caratteristiche delle pagine. La cache IBM 370 , consentita solo a un ciclo minore per prendere la sua decisione, utilizza arbitrariamente i bit meno significativi dell'indirizzo di memoria come indirizzo del frame di pagina associato. Spetta quindi al compilatore evitare potenziali collisioni nel miglior modo possibile.
Vedi Algoritmo LRU .
La cache contiene una copia dei dati originali quando è costoso (in termini di tempo di accesso) recuperare o calcolare il tempo di accesso alla cache. Una volta che i dati sono stati memorizzati nella cache, vi si accede direttamente tramite la cache anziché recuperarli o ricalcolarli, il che riduce il tempo medio di accesso.
Il processo funziona come segue:
Se le memorie cache consentono di aumentare le prestazioni è in parte grazie a due principi che sono stati scoperti a seguito di studi sul comportamento dei programmi per computer:
Per quanto riguarda il calcolo di matrici , la cache presenta invece forti asimmetrie a seconda che si acceda alla matrice per righe o per colonne, dissimmetrie tanto più importanti quanto la matrice è grande. Un rapporto CNUCE menziona una differenza di prestazioni di un fattore da 8 a 10 per gli stampi con la dimensione più piccola di 50.
C'è un'area cache:
Nei microprocessori vengono differenziati diversi livelli di cache, spesso tre:
Questi ultimi coperchi possono essere posizionati all'interno o all'esterno del microprocessore.
È molto veloce, ma anche molto costoso. Spesso questo è SRAM .
La presenza della memoria cache permette di velocizzare l'esecuzione di un programma. Pertanto, maggiore è la dimensione della memoria cache, maggiore può essere la dimensione dei programmi accelerati. Tuttavia, esiste un limite oltre il quale aumentare la dimensione della cache non è più utile. Infatti, nei codici, ci sono connessioni che non possono essere previste dai processori. Ad ogni connessione, la parte del codice può richiamare una diversa area di memoria. Ecco perché l '“orizzonte” oltre il quale il microprocessore non può vedere se avrà bisogno di determinati dati limita l'efficacia della cache. La dimensione della cache è un elemento spesso utilizzato dai produttori per variare le prestazioni di un prodotto senza modificare altro hardware. Ad esempio, per i microprocessori, esistono serie limitate (con una dimensione della memoria cache deliberatamente ridotta), come Duron presso AMD o Celeron presso Intel , e serie di fascia alta con una grande memoria cache come i processori Opteron presso AMD, o Pentium 4EE di Intel. In altre parole, la dimensione della memoria cache risulta da un compromesso tra costi e prestazioni.
In programmazione, per sfruttare l'accelerazione fornita da questa velocissima memoria, le parti del programma devono stare il più possibile in questa memoria cache. Poiché varia a seconda dei processori, questo ruolo di ottimizzazione è spesso dedicato al compilatore. Detto questo, un programmatore esperto può scrivere il proprio codice in modo da ottimizzare l'utilizzo della cache.
Questo è il caso di cicli molto brevi che si adattano interamente a cache di dati e istruzioni, ad esempio il seguente calcolo (scritto in linguaggio C ):
long i; double s; s = 0.0; for (i = 1; i < 50000000; i++) s += 1.0 / i;Esistono tre tipi di errori della cache nei sistemi a processore singolo e quattro in ambienti multiprocessore. È :
Poiché la memoria cache non può contenere tutta la memoria principale, è necessario definire un metodo che indichi a quale indirizzo della memoria cache deve essere scritta una riga della memoria principale. Questo metodo è chiamato mappatura. Esistono tre tipi di mappatura comuni nelle cache oggi:
Ogni riga nella memoria di primo livello può essere scritta in qualsiasi indirizzo nella cache. Questo metodo richiede molta logica perché dà accesso a molte possibilità. Questo spiega perché la piena associatività viene utilizzata solo in piccole cache (tipicamente dell'ordine di pochi kibibyte ). Ciò fornisce la seguente ripartizione dell'indirizzo:
Corrispondenza preimpostata nella cache ( cache mappata direttamente )Ogni riga della memoria principale può essere registrata solo su un singolo indirizzo della memoria cache, ad esempio associato al modulo del suo indirizzo. Ciò crea molti errori di cache se il programma accede a dati in conflitto sugli stessi indirizzi di cache. La selezione della riga in cui verranno registrati i dati si ottiene solitamente da: Riga = Mod address Numero di righe .
Una riga della cache è condivisa da molti indirizzi nella memoria di primo livello. Quindi abbiamo bisogno di un modo per sapere quali dati sono attualmente nella cache. Queste informazioni sono fornite dal tag , che è un'informazione aggiuntiva memorizzata nella cache. L'indice corrisponde alla riga in cui vengono registrati i dati. Inoltre, il controller della cache deve sapere se un determinato indirizzo contiene dati o meno. Un bit aggiuntivo (chiamato bit di validità) viene caricato con queste informazioni.
Ad esempio, si consideri un indirizzo a 32 bit che fornisce l'accesso alla memoria indirizzabile in byte, una dimensione di riga a 256 bit e una cache kibibyte di 2 s . La memoria cache contiene quindi 2 s + 13 bit (1 kiB = 2 10 byte e 1 byte = 2 3 bit). Sapendo che una riga è di 256 bit o 2 8 bit, deduciamo che ci sono 2 s + 5 righe memorizzabili nella memoria cache. Pertanto, l'indice è s + 5 bit.
L'indirizzo a 32 bit consente l'accesso a una memoria di 232 byte o 235 bit. Essendo l'indice di s + 5 bit, è necessario distinguere 2 elementi da 22 s della memoria principale per linea di cache. Il tag è quindi di 22 bit.
Inoltre, una riga ha una dimensione di 256 bit o 32 byte. Essendo la memoria indirizzabile per byte, ciò implica un offset di 5 bit. L'offset è l'offset all'interno di una riga per accedere a un particolare byte. Questi calcoli forniscono la seguente suddivisione degli indirizzi per una cache mappata direttamente:
La mappatura diretta è una strategia semplice ma inefficiente perché crea molti errori di cache in conflitto. Una soluzione è consentire la memorizzazione di un indirizzo di memoria principale in un numero limitato di indirizzi di memoria cache. Questa soluzione è presentata nella sezione successiva.
Cache associativa degli insiemi a n vieÈ un compromesso tra "mappatura" diretta e completamente associativa cercando di coniugare la semplicità dell'una e l'efficacia dell'altra.
La cache è divisa in insiemi ( insiemi ) di N linee di cache. Un insieme è rappresentato nella figura allegata dall'unione dei rettangoli rossi. Una riga della memoria di livello superiore è assegnata ad un set, di conseguenza può essere scritta in uno qualsiasi dei canali, cioè delle N righe del set. Questo per evitare molti errori di cache in conflitto. All'interno di un set, la mappatura è Direct Mapped, mentre la mappatura di N Sets è Full Associative. In generale, la selezione del set viene effettuata da: Set = Mod memory address ( Numero di set ).
Prendiamo l'esempio della sezione precedente (memoria cache kibibyte ) ma composta da canali. Il numero di canali infatti è sempre una potenza di 2 per ottenere una semplice divisione dell'indirizzo di memoria. La memoria cache contiene quindi bit per canale. Sapendo che una linea rappresenta 256 bit, ci sono quindi voci per set. L'indice è quindi s-n + 5 bit.
Le memorie qui considerate sono indirizzabili per byte. Pertanto, gli indirizzi a 32 bit forniscono l'accesso alla memoria di bit, che è l'equivalente delle righe della memoria cache. Pertanto, ogni set della cache contiene righe separate. Il tag è quindi di 22-s + n bit. La ripartizione dell'indirizzo è quindi:
Per funzionare, un processore necessita di dati e istruzioni. Esistono quindi due soluzioni per implementare le memorie cache:
La separazione di dati e istruzioni consente in particolare di aumentare la frequenza di funzionamento del processore, che può così accedere contemporaneamente a un dato e ad un'istruzione. Questa situazione è particolarmente comune per Load / Store. Questo spiega perché la cache unificata è spesso l'anello debole del sistema. Inoltre, in una cache unificata, deve essere introdotta una logica aggiuntiva che assegna la priorità ai dati o alle istruzioni, il che non è il caso delle cache separate.
Laddove sappiamo che le istruzioni non possono essere modificate dal programma (che fa parte di una buona pratica), potremmo in teoria fare a meno dello sporco . Tuttavia, i programmi che richiedono prestazioni elevate (driver di dispositivo veloci, ad esempio) a volte si prendono delle libertà al riguardo, il che richiede cautela. Al massimo sappiamo che le istruzioni - a differenza dei dati - verranno modificate raramente o molto raramente , e possiamo ottimizzare i circuiti di conseguenza.
Se le istruzioni vengono modificate dal programma, le cache separate introducono un problema di consistenza della cache delle istruzioni: il programma dovrebbe invalidare le voci corrispondenti nella cache delle istruzioni per farle aggiornare in avanti per eseguire le istruzioni modificate, altrimenti potrebbe essere disponibile una versione precedente di quelle istruzioni rilevato ed eseguito dal processore (o un mix imprevedibile di nuove e vecchie istruzioni).
Nel 2011, la soluzione più comune è la separazione delle cache, perché consente, tra l'altro, di applicare ottimizzazioni specifiche a ciascuna cache in base al suo tipo di accesso.
Quando un dato è nella cache, il sistema ne ha due copie: una nella memoria di primo livello (ad esempio, la memoria principale) e una nella memoria cache. Quando i dati vengono modificati localmente, esistono diversi criteri di aggiornamento:
Write Through ( write-through ) i dati vengono scritti sia nella cache che nella memoria principale. La memoria principale e la cache hanno sempre lo stesso valore, semplificando così molti protocolli di consistenza; Writeback ( write-back ) le informazioni vengono scritte nella memoria principale solo quando la riga scompare dalla cache (invalidata da altri processori, rimossa per scrivere un'altra riga ...). Questa tecnica è la più diffusa perché consente di evitare molte scritture inutili della memoria. Per non dover scrivere informazioni che non sono state modificate (e quindi per evitare inutili ingombri del bus), ogni riga della memoria cache è dotata di un bit indicante la modifica ( dirty bit ). Quando la riga viene modificata nella cache, questo bit viene impostato a 1, a indicare che i dati dovranno essere riscritti nella memoria principale. Il write-back richiede naturalmente precauzioni speciali quando viene utilizzato per supporti rimovibili ("Rimozione sicura del volume" con lo svuotamento della cache).Algoritmo di scrittura
Algoritmo di write-back
Le cache associative e completamente associative a canale N implicano la mappatura di righe diverse di memoria di primo livello sullo stesso set. Quindi, quando il set di righe della cache, in cui è possibile mappare una riga di memoria superiore, viene riempito, designare la riga che verrà cancellata a favore della riga appena scritta. L'obiettivo dell'algoritmo di sostituzione della riga della cache è scegliere quella riga in modo ottimale. Questi algoritmi devono essere implementati nell'hardware per cache di basso livello per essere il più veloci possibile e non rallentare il processore. Tuttavia, possono essere implementati nel software per cache di livello superiore.
La maggior parte degli algoritmi si basa sul principio della località per cercare di prevedere il futuro dal passato. Alcuni degli algoritmi di sostituzione delle righe della cache più popolari sono:
Oltre a questi sistemi hardware per la gestione di una cache, il termine memoria cache viene utilizzato anche da abuso di linguaggio per designare qualsiasi meccanismo implementato nel software al fine di consentire un rapido riutilizzo dei dati già trasferiti in precedenza.
Ad esempio, qualsiasi sistema operativo moderno ha, all'interfaccia tra i file system ei driver responsabili dell'archiviazione di massa, una sottoentità il cui scopo è conservare nella RAM i dati letti o scritti di recente; questo aiuta a evitare I / O non necessari con l'archiviazione di massa, poiché questi sono generalmente più lenti di quelli con RAM.
Il principio è il seguente:
La coerenza è garantita se qualsiasi trasferimento è associato a una marcatura dei dati in memoria. Un algoritmo che utilizza criteri di età e riutilizzo dei dati sceglie quale sarà la priorità per rimanere nella cache quando si avvicina alla saturazione. Per l'uso casuale, che è sempre almeno il caso delle directory , questo algoritmo considera che ciò che è stato utilizzato molto di recente è più probabile che venga utilizzato nel prossimo futuro (vedi: Legge 80/20 ).