Chiaroveggenza nel caching: strategie ottimali?

2

Questa domanda si riferisce alla domanda qui , ma generalizzerò in modo che tu possa rispondere in modo efficace senza leggere tutto ciò.

Contesto:

Immagina di avere un grande set di dati più grande della RAM disponibile che è stata partizionata in blocchi.

(Ridimensionato in modo tale che l'accesso sia stato elaborato in modo efficiente dai gestori di memoria virtuale ecc.) .

Un'applicazione con una GUI richiede a un utente di registrare un processo sequenziale che richiederà l'accesso a sezioni di questi dati nel tempo.

In tempo reale questo sarebbe gestito da una sorta di cache LRU per l'utente in modo da ottenere un feedback (forse con una risoluzione inferiore per tenere conto della latenza). I dati richiesti, ma non nella RAM, verrebbero caricati sostituendo i dati meno recenti contrassegnati come "utilizzati meno di recente" ...

But now instead, imagine that I know the sequence in advance - i.e. I effectively have look-ahead/clairvoyance of future memory access requirements.

Si presume che la dimensione (in GB / qualunque) dei dati unici richiesti integrati nell'intera sequenza sia superiore alla quantità di RAM disponibile (almeno il doppio).

Domande:

Quali algoritmi / strategie ottimale sono lì per gestirlo nel caso di:

  1. È necessario "riprodurre" la sequenza in una sorta di modalità psuedo-realtime (sequenziale) per un utente.
  2. Hai bisogno di elaborarlo il più velocemente possibile in modo "non in linea" non sequenziale.

Immagina il caso peggiore in cui i dati fossero richiesti "on e off", ma spesso in tutta la sequenza - ovvero il periodo di requisiti è appena trascorso il periodo in cui una strategia LRU, LFU imporrebbe "no" -necessario'. Ma con la maggior parte delle definizioni di ottimali preferiamo semplicemente tenerlo nella RAM, giusto?

Aggiornamento: dovrebbe notare, sto memorizzando nella cache i dati input - gli output della funzione effettiva dell'applicazione non hanno alcuna (utile) relazione tra le iterazioni.

    
posta Lamar Latrell 18.04.2016 - 22:31
fonte

1 risposta

1

Tutto quello che puoi veramente fare è un profilo: qualsiasi consiglio generale sarà molto, molto, generale. Dovresti cercare di mantenere il tuo working set di dimensioni ridotte in modo che si adatti ai primi livelli di cache ed evitare accessi di memoria ridondanti. Se è costoso calcolare un valore intermedio, precalcalo e memorizza il risultato. Se sai che avrai bisogno di dati, precaricalo dalla RAM.

Per il controllo della cache, puoi utilizzare le intrinseche del compilatore come __builtin_prefetch di GCC :

void __builtin_prefetch (const void *addr, ...)

This function is used to minimize cache-miss latency by moving data into a cache before it is accessed. You can insert calls to __builtin_prefetch into code for which you know addresses of data in memory that is likely to be accessed soon. If the target supports them, data prefetch instructions will be generated. If the prefetch is done early enough before the access then the data will be in the cache by the time it is accessed.

Ti permette di specificare se ti aspetti di leggere o scrivere e quale grado di localizzazione temporale ti aspetti che gli accessi abbiano.

Per il controllo della memoria virtuale, puoi caricare i dati usando mmap e dire al gestore della memoria virtuale come ti aspetti di accedere alle pagine mappate usando madvise , ad esempio:

MADV_SEQUENTIAL

Expect page references in sequential order. (Hence, pages in the given range can be aggressively read ahead, and may be freed soon after they are accessed.)

MADV_WILLNEED

Expect access in the near future. (Hence, it might be a good idea to read some pages ahead.)

Dovrai eseguire un benchmark e un profilo per determinare dove utilizzare effettivamente tali strategie. Intel VTune può darti utili statistiche su come la tua applicazione sta facendo uso della cache e conduttura.

    
risposta data 18.04.2016 - 23:20
fonte

Leggi altre domande sui tag