Livellamento dell'usura in lettura e scrittura gestito dal software per la memoria principale non volatile Parte 2
Aug 06, 2024
La classe di sistemi considerati solitamente fornisce molte funzionalità disponibili anche nei normali computer desktop. Ad esempio, una MMU completa e una memoria virtuale vengono spesso utilizzate per isolare l'uno dall'altro lo spazio degli indirizzi di diversi compiti o per limitare l'accesso all'hardware.
La memoria virtuale è uno dei concetti più importanti nei sistemi operativi dei computer. Consente ai computer di utilizzare lo spazio del disco rigido come memoria estesa in modo che i programmi più grandi possano ancora essere eseguiti quando la memoria è insufficiente. La memoria virtuale è strettamente correlata alla memoria del computer.
La memoria del computer è limitata. Se non disponiamo di un meccanismo come la memoria virtuale, quando la memoria è insufficiente possiamo solo rinunciare all'esecuzione del programma o forzare la chiusura di alcune applicazioni. L'emergere della memoria virtuale ha notevolmente alleviato questo problema. Attraverso lo spazio di memoria fornito dalla memoria virtuale, il computer può spostare le parti inutilizzate dalla memoria al disco rigido secondo determinate regole. In questo modo il computer può espandere la memoria da utilizzare senza aumentare la memoria fisica, permettendoci di continuare ad utilizzare programmi sempre più grandi.
Questo meccanismo ci offre una grande comodità. Non dobbiamo preoccuparci troppo dell'hardware del nostro computer. Finché eseguiamo il programma entro i limiti della memoria virtuale, anche se la nostra memoria fisica è molto piccola, il nostro computer può eseguire una varietà di programmi diversi e non è necessario preoccuparsi dell'overflow della memoria o di altri problemi.
Si può dire che l'espansione della memoria del computer è molto necessaria. La memoria virtuale ci fornisce una soluzione migliore. Allo stesso tempo, ci permette anche di utilizzare meglio altri dispositivi, come i dischi rigidi, e di sfruttare appieno il potenziale dei computer. Non c'è dubbio che il rapporto tra memoria virtuale e memoria sia inscindibile. L'emergere della memoria virtuale ci offre la possibilità di fare un uso maggiore dell'hardware del computer senza sacrificare l'efficienza operativa del computer. Si può vedere che dobbiamo migliorare la memoria. La Cistanche può migliorare significativamente la memoria perché ha effetti antiossidanti, antinfiammatori e antinvecchiamento, che possono aiutare a ridurre l’ossidazione e le reazioni infiammatorie nel cervello, proteggendo così la salute del sistema nervoso. Inoltre, Cistanche può anche promuovere la crescita e la riparazione delle cellule nervose, migliorando così la connettività e la funzione delle reti neurali. Questi effetti possono aiutare a migliorare la memoria, la capacità di apprendimento e la velocità di pensiero e possono anche prevenire il verificarsi di disfunzioni cognitive e malattie neurodegenerative.

Fare clic su modi per migliorare la funzione cerebrale
Tuttavia, ciò non implica che una gerarchia di cache completa sia possibile e utile. La frequenza di clock di questi sistemi è solitamente impostata su alcune centinaia di megahertz per ridurre il consumo energetico.
Le latenze di accesso alla memoria diventano comunque meno critiche in queste condizioni, e una cache non migliorerebbe di molto la situazione ma consumerebbe ulteriore area del chip.
Inoltre, per garantire tempi di esecuzione peggiori, la memoria degli appunti potrebbe essere preferibile alle cache. Pertanto, il consumo di memoria viene ridotto per le aree di memoria coperte dalla memoria degli appunti, ma non per le altre aree.
Queste restanti regioni necessitano ancora di un meccanismo di livellamento dell’usura. In questo articolo ci concentreremo sul caso peggiore in cui tutte le regioni di memoria necessitano di livellamento dell'usura. Per i motivi menzionati in precedenza, il nostro sistema target è costituito da un processore embedded con MMU completa, memoria virtuale e nessuna cache. Per superare gli svantaggi dei singoli tipi di memoria (ad esempio, la durata delle NVM o la volatilità delle SRAM), diversi sistemi implementano un'architettura di memoria ibrida [7].
Per questi sistemi, più di un tipo di memoria è collegato alla CPU (ad esempio, una FeRAM e una SRAM) e mappato nello spazio degli indirizzi della CPU. Il sistema operativo e l'applicazione possono quindi decidere attivamente quale contenuto della memoria deve essere collocato in quale memoria, memorizzandolo nella corrispondente regione di indirizzo.
Tuttavia, in questo lavoro, assumiamo solo una NVM come memoria principale nel sistema e sviluppiamo la nostra soluzione per tutti i segmenti di memoria allocati su questa memoria principale per due motivi.
Innanzitutto, se esiste una gerarchia di memoria ibrida con varie memorie, è possibile applicare separatamente meccanismi di manutenzione appropriati per le altre memorie. Forniamo quindi ancora un meccanismo di livellamento dell'usura per la parte NVM.
In secondo luogo, anche se è disponibile una gerarchia di memoria ibrida, l’allocazione dei segmenti di memoria potrebbe dover obbedire a diversi vincoli, il che rende impossibile una mappatura arbitraria. Pertanto, il contenuto della memoria potrebbe comunque dover essere allocato alla NVM, cosa che la consuma rapidamente. La nostra soluzione fornisce un meccanismo per migliorare la durata di una determinata mappatura di segmenti di memoria.
Poiché i metodi da noi proposti sono basati su software, devono essere eseguiti in un livello simile a quello del sistema operativo per avere un controllo privilegiato sull'applicazione in esecuzione. Anche se un sistema operativo completo potrebbe non essere presente per i piccoli sistemi embedded, è necessario un sottile strato software per gestire l'hardware, controllare le procedure di avvio e gestire il flusso di controllo.
I nostri metodi possono essere implementati anche in un sistema operativo di base. Sebbene in questo lavoro ci concentriamo sulla classe del sistema target descritta, i nostri metodi sono ancora applicabili ad altri sistemi con le modifiche appropriate. Per i sistemi più grandi con cache, ad esempio, i risultati positivi e quelli mancati dovrebbero essere opportunamente distinti poiché i primi non consumano la memoria, ma i secondi sì.
3.1 Piattaforma di implementazione
Poiché nella valutazione valutiamo i nostri metodi implementati riguardo alla loro qualità di livellamento dell'usura, utilizziamo una piattaforma per la nostra implementazione in cui possiamo estrarre con precisione l'età (ovvero il numero totale di accessi per cella di memoria).

Utilizziamo il framework basato sulla simulazione del sistema completo del nostro lavoro precedente [10]. Questo framework esegue il simulatore gem5 in combinazione con il plug-in NVMain per simulazioni NVM e uno speciale sistema operativo, che consente una netta separazione della memoria dell'applicazione e del sistema operativo. NVMain genera un file di traccia per ogni simulazione che contiene informazioni precise su ogni accesso alla memoria (ad esempio, accessi in lettura e scrittura).
Più avanti in questo lavoro, descriviamo la nostra implementazione delle strategie di livellamento dell'usura. Abbiamo implementato queste strategie per il sistema operativo bare metal, eseguendo anche nel framework di simulazione. Pertanto, possiamo valutare direttamente i nostri algoritmi in una simulazione realistica del sistema completo e non fare affidamento su alcuna stima di alto livello analizzando la traccia di accesso alla memoria risultante da una simulazione con livellamento dell'usura abilitato.
Riutilizzeremo ulteriormente le applicazioni benchmark [10], poiché il codice è direttamente disponibile con il framework di simulazione. Tuttavia, le nostre tecniche di livellamento dell'usura sono indipendenti dall'architettura della CPU e l'implementazione e la valutazione concrete vengono eseguite per un processore applicativo 64-bit basato su ARM (ARMv8) grazie al simulatore di memoria [10].
Si noti che un'implementazione concreta su un'architettura specifica della CPU richiede diversi dettagli di implementazione specifici, indicati anche in questo articolo. Questi dettagli, tuttavia, possono essere reimplementati su altre architetture CPU.
4 ANALISI DEL PROBLEMA
Per illustrare la necessità del livellamento dell'usura e giustificare il livellamento dell'usura per regioni specifiche, in questa sezione analizziamo il comportamento di accesso alla memoria di una serie di applicazioni di riferimento e discutiamo l'influenza sulla durata della memoria. Le applicazioni benchmark sono presentate in dettaglio di seguito:
• Dijkstra fa parte della suite MiBench [8] e calcola i percorsi più brevi in un grafico secondo l'algoritmo Dijkstra. La particolarità di questo benchmark è che i passaggi dell'algoritmo vengono gestiti in una coda, che viene memorizzata nel segmento dati.
• risolvere fa parte del setup di simulazione NVM [10] e risolve un sistema di equazioni lineari secondo l'algoritmo di eliminazione gaussiana. Questo benchmark modifica direttamente i suoi dati di input.
• fa anche parte della suite MiBench [8] e calcola l'hash SHA-1 di determinati dati di input.
• qsort fa parte del setup di simulazione NVM [10] ed è un'implementazione ricorsiva dell'algoritmo quicksort. Pertanto, non solo vengono modificati i dati di input, ma anche il segmento dello stack viene utilizzato in modo intensivo.
• rijndael fa parte della suite di sicurezza MiBench [8] e crittografa i dati di input con l'algoritmo Rijndael. Per questo benchmark, l'input non viene letto da un file ma da un'area nel segmento dati stesso.
• crc32 fa anche parte della suite di sicurezza MiBench [8] e calcola i checksum crc su determinati dati di input

Poiché miriamo a due diversi scenari: sistemi NVM distruttivi in lettura e sistemi NVM non distruttivi in lettura, analizziamo entrambe le situazioni. Per i sistemi NVM non distruttivi in lettura, esaminiamo il numero totale di accessi in scrittura per cella di memoria e per i sistemi NVM distruttivi in lettura, esaminiamo il numero accumulato di accessi in lettura e scrittura per cella di memoria. Eseguiamo le applicazioni benchmark come descritto in precedenza e illustriamo i modelli di accesso alla memoria risultanti nelle Figure 1 e 2.

Osserviamo che gli accessi alla memoria avvengono a velocità diverse sulle celle di memoria delle diverse regioni della memoria. In generale, nonostante le grandi regioni con modelli di accesso uniformi, si possono trovare punti caldi di accesso densi.
Questi punti caldi hanno un'influenza drastica sulla durata della memoria, perché solo poche celle si consumano intensamente, mentre altre celle non vengono utilizzate affatto. Se questi accessi fossero distribuiti meglio, la loro durata aumenterebbe drasticamente.
Per le NVM non distruttive in lettura (Figura 1), gli hot spot di scrittura densi si trovano principalmente nello stack, che deriva dalla memoria Waystack utilizzata. Tutte le altre regioni si trovano ad affrontare meno hot spot di scrittura. Per le NVM con lettura distruttiva, gli hot spot di lettura possono essere trovati anche nelle aree di testo, poiché il codice del programma compilato risiede in questa area e viene letto durante l'esecuzione.

Nel complesso, deduciamo due obiettivi per i nostri algoritmi di livellamento dell'usura. In primo luogo, le regioni con frequenze di accesso diverse devono essere rilevate correttamente durante il runtime e trasferite in altre regioni di memoria, a seconda della frequenza degli accessi. Proponiamo un algoritmo di livellamento dell'usura consapevole dell'invecchiamento a grana grossa per raggiungere questo obiettivo.
In secondo luogo, i densi punti caldi di accesso devono essere risolti in modo tale che gli accessi siano distribuiti su una regione più ampia di celle di memoria. Ciò riduce lo stress delle singole celle e media l'usura su una regione più ampia. Proponiamo due soluzioni a grana fine per raggiungere questo obiettivo: una per il segmento stack e un'altra per il segmento text.
5 LIVELLAMENTO DELL'USURA A GRANA GROSSA
In questa sezione, descriviamo in dettaglio la proposta di livellamento dell'usura a grana grossa in funzione dell'invecchiamento. Per valutare l'età di una cella di memoria, è necessario tenere traccia del comportamento di accesso alla memoria. Se l'hardware non può tenere traccia del comportamento di accesso corrente e non è nota alcuna traccia di memoria per l'applicazione in esecuzione, le tecniche di rilevamento dell'invecchiamento non possono essere applicate per impostazione predefinita.
Per superare questo problema, proponiamo innanzitutto una tecnica di approssimazione della distribuzione degli accessi gestita dal software, che stima la distribuzione degli accessi alla memoria (ad esempio, il conteggio di scritture e letture in regioni di memoria di dimensione fissa) utilizzando solo il supporto hardware comunemente disponibile (ad esempio, MMU, contatori di prestazioni e interruzioni).
Questa approssimazione di accesso viene implementata come servizio di sistema nell'ambiente runtime (ad esempio, il sistema operativo). L'approssimazione della distribuzione degli accessi può essere successivamente fornita come input per un algoritmo di livellamento dell'usura sensibile all'invecchiamento.
5.1 Campionamento dell'accesso in scrittura
Come già introdotto, il primo passo verso il livellamento dell'usura a grana grossa gestito dal software è un'approssimazione adeguata della distribuzione dell'accesso alla memoria. Sebbene l'acquisizione di questa approssimazione per gli accessi in scrittura e in lettura sia per lo più simile, presentiamo prima l'acquisizione dell'approssimazione in scrittura in dettaglio. Successivamente, descriviamo i passaggi aggiuntivi richiesti per catturare anche la riapprossimazione.
Sono necessari diversi passaggi per registrare un'approssimazione della distribuzione delle scritture di un'applicazione in fase di esecuzione. Innanzitutto, abbiamo campione equamente distanziato ogni campione di scrittura, l'accesso in scrittura dell'applicazione ha catturato il suo indirizzo di destinazione e lo ha archiviato in una struttura dati appropriata.
Il numero Cwritesample determina la granularità temporale della tecnica di approssimazione, consentendo un compromesso tra accuratezza e sovraccarico introdotto. Dopo aver acquisito la scrittura, è necessario considerare anche la granularità spaziale della struttura dei dati.
La memorizzazione del conteggio stimato delle scritture per ogni byte introduce un notevole sovraccarico di archiviazione e porta a risultati imprecisi quando la granularità temporale è grossolana. Invece, i byte possono essere correlati a blocchi di memoria più grandi e i conteggi di scrittura vengono aggregati per ogni accesso in scrittura in questi blocchi. Per la nostra implementazione, aggreghiamo i conteggi delle scritture per blocchi di memoria da 4-kB, poiché l'algoritmo di livellamento dell'usura considera questa granularità (ovvero, la decisione si basa sulle pagine di memoria).
Utilizzando un contatore di 8-byte per ogni blocco, sono necessari 1512 · byte di memoria per memorizzare la distribuzione approssimativa delle scritture (ad esempio, 2 MB quando viene tracciato 1 GB di memoria principale).
Il flusso dettagliato di acquisizione della destinazione di ogni Cwritesample e l'accesso in scrittura alla memoria richiedono l'implementazione di due tecniche. Innanzitutto, deve essere generata una trap dopo ogni Cwritesample tramite l'accesso in scrittura, in modo che l'implementazione dell'approssimazione possa agire. Successivamente la destinazione di un accesso in scrittura in memoria deve essere determinata e memorizzata nella struttura dati.
Entrambe le implementazioni verranno descritte in dettaglio successivamente. Sebbene l'approccio di Gogte et al. [6] consente l'acquisizione diretta delle richieste di scrittura della CPU a intervalli campionati, il loro approccio si basa su una capacità di debug specializzata.
Il nostro metodo fornisce un'alternativa che fa uso di funzionalità hardware più ampiamente disponibili. Vogland Eckert [21] propone l'uso di contatori di prestazioni per analizzare specificamente l'esecuzione delle istruzioni di un'applicazione. Allo stesso modo utilizziamo i contatori delle prestazioni per analizzare l'utilizzo della memoria di un'applicazione, come descritto di seguito.

For more information:1950477648nn@gmail.com






