Software Managed Cache

Concepte de baza despre cache

Cache-ul este o zona de stocare temporara care permite un acces rapid la date frecvent/recent accesate. Componentele si caracteristicile unui cache sunt:

  • din motive de performanta, cache-ul este impartit in blocuri de dimensiune fixa denumite 'linii de cache'
  • fiecare linie de cache poate contine 'o copie a unor date din memoria principala'
  • fiecare unitate de date din memoria principala poate fi pusa doar intr-un 'set redus si bine determinat de linii de cache'
  • fiecare linie de cache are un 'tag' care identifica (in cadrul unui set de linii de cache) zona din memoria principala ale carei date sunt stocate pe acea linie.

Cand se fac accese la memoria principala, se cauta mai intai datele (sau codul) in cache. Din motive de performanta, cautarea se face doar in submultimea bine specificata unde ar putea fi stocata acea unitate de memorie, si anume in setul coresponzator de linii de cache. Daca vreunul din tag-urile din acea zona corespund adresei referite spunem ca avem un cache-hit; altfel avem un cache-miss.

Tipuri de cache-uri

Din punct de vedere al asociativitatii, cache-urile se impart in trei categorii:

  • 'mapate direct', pentru care oricare bloc de memorie poate fi pozitionat pe o singura linie de cache (un set este compus dintr-o singura linie de cache).
  • 'mapate complet asociativ', in cadrul carora oricare bloc de memorie poate fi pozitionat pe oricare linie de cache (un set este compus din toate liniile din cache - exista un singur set)
  • 'mapate set asociativ', pentru care fiecare bloc de memorie poate fi pozitionat pe oricare linie dintr-un set de N linii de cache. Cache-urile set asociative reprezinta un compromis intre cache-urile mapate direct si cache-urile complet asociative.

Cache implementat software pentru un SPE

SPE-urile pot accesa direct, atat pentru cod cat si pentru date, doar memoria locala (LS), care are o capacitate de 256 KB. Toate accesele la memoria principala (sau alte zone de memorie mapate in spatiul de adresa curent, cum ar fi memoria video) se fac prin cereri DMA, fapt ce impune un efort suplimentar din partea programatorului, marind complexitatea programului. Implementarea unui cache in software poate:

  • simplifica modelul de programare
  • micsora timpul de portare a unui algoritm pe SPE
  • fi optimizata pentru diferite tipuri de acces (secvential, random, in ordine inversa, etc.)
  • fi integrata cu algoritmi sofisticati de inlocuire (dezvoltati pentru subsistemele de paginare pentru memorie virtuala).

Utilizare

Un program care utilizeaza sofware cache-ul oferit de SDK-ul Cell/BE trebuie sa includa fisierul header “cache-api.h” si o serie de defintii plasate inainte de directiva '#include' care declara cache-ul. Definitiile disponibile (nu toate sunt obligatorii) sunt:

  • 'CACHE_NAME' - un nume unic ce va identifica cache-ul.
  • 'CACHED_TYPE' - tipul elementelor stocate in cadrul cache-ului. Poate fi orice tip de date valid in limbajul C.
  • 'CACHELINE_LOG2SIZE' - log2(dimensiunea_unei_linii_de_cache).
  • 'CACHE_LOG2NWAY' - specifica asociativitatea cache-ului. Exista 2 valori posibile: 0 si 2 (2 fiind valoarea implicita).
  • 'CACHE_LOG2NSETS' - log2(numarul_de_seturi_din_cache). Valorile posibile sunt cuprinse intre 0 si 12. Valoarea implicita este 6 (2^6 = 64 seturi).
  • 'CACHE_TYPE' - tipul de acces la cache: read-only (0) sau read-write (1 - implicit)
  • 'CACHE_SET_TAGID(set)' - specifica tag-ID-ul unui anumit set. Valorile posibile sunt cuprinse intre 0 si 31. Implicit se defineste ca set % 32.
declarare_cache.c
/* definitii obligatorii */
#define CACHE_NAME               my_cache
#define CACHED_TYPE              my_type_t
 
/* definitii optionale; daca o definitie lipseste se foloseste o valoare implicita */
#define CACHE_LOG2NWAY     2     /* 4-way */
#define CACHE_LOG2NSETS    3     /* 8 set-uri */
#define CACHE_TYPE         1     /* RW */
#define CACHELINE_LOG2SIZE 9     /* 512b */
#define CACHE_STATS              /* activare statistici */
 
/* in mod obligatoriu <cache-api.h> trebuie inclus dupa definirea variabilelor CACHE_* */
/* "cache-api.h" foloseste aceste definitii pentru a crea tipuri de date noi care implementeaza cache-ul */
#include <cache-api.h>

Pentru a defini mai multe cache-uri se redefinesc variabilele CACHE_* si se include din nou “cache-api.h”.

In tabelul de mai jos gasiti functiile care pot fi folosite pentru a interactiona cu sistemul de cache implementat software de SDK-ul Cell/BE ('name' reprezinta numele cache-ului cu care se lucreaza):

Instructiune Descriere
cache_rd(name, eaddr) Copiaza valoarea stocata la adresa eaddr in cache. Returneaza valoarea.
cache_wr(name, eaddr, val) Scrie in cache valoarea val. In memoria principala valoarea va fi stocata la adresa eaddr.
cache_flush(name) Forteaza scrierea tuturor datelor modificate (dirty) in cache inapoi in memoria principala.
cache_rd_x4(name, eaddr) Citeste un vector care contine 4 valori unsigned int de la adresa eaddr.
e_pr_stats(name) Afiseaza statistici despre cache.

Software cache-ul poate fi operat in mod sincron (folosind API-ul prezentat anterior) sau asincron (folosit un API diferit, bazat pe adresele din LS care aparțin cache-ului). In modul sincron, accesul la datele din cache se face doar prin adrese din spatiul de adrese al PPE-ului (adica din memoria principala sau eventual memoria video). Desi datele din memoria principala sunt aduse in LS-ul SPE-ului, folosind cache-ul implementat software, programatorul nu va folosi adresele locale pentru a accesa datele.

cache_sincron.c
#define CACHE_NAME         MY_CACHE      /* numele cache-ului */
#define CACHED_TYPE        int           /* tipul elementului de baza al cache-ului */
 
/* atribute optionale */
#define CACHE_TYPE         CACHE_TYPE_RW /* acces de scriere si citire */
#define CACHELINE_LOG2SIZE 11            /* 2^11 = lungimea unei linii de cache de 2048 bytes */
#define CACHE_LOG2NWAY     2             /* 2^2 = 4-way cache */
#define CACHE_LOG2NSETS    4             /* 2^4 = 16 seturi */
 
#include <cache-api.h>
 
int main(unsigned long long spu_id, unsigned long long parm){
        int a, b;
        unsigned eaddr_a, eaddr_b;
 
        /* initializeaza adresele efective cu o adresa din memoria principala */
        eaddr_a = parm;
        eaddr_b = parm + sizeof(int);
 
        /* citeste a si b din memoria principala (folosind adresa efectiva) */
        a = cache_rd(MY_CACHE, eaddr_a);
        b = cache_rd(MY_CACHE, eaddr_b);
 
        /* modifica valorile locale */
        a++;
        b++;
 
        /* scrie valorile modificate in cache. */
        /* nu se face imediat scriere in memoria principala (nu e un cache write-through) */
        /* se actualizeaza doar copiile din LS si se marcheaza ca "dirty" liniile corespunzatoare */
        cache_wr(MY_CACHE, eaddr_a, a);
        cache_wr(MY_CACHE, eaddr_b, b);
 
        /* scrie toate liniile modificate (dirty) inapoi in memoria principala */
        cache_flush(MY_CACHE);
        return 0;
}

# (3p) In memoria principala este definita o matrice ce descrie calea de la intrarea într-un labirint pana la o comoara. Drumul spre comoara este encodat în matrice ca un set de salturi de la niste coordonate (rand, coloana) la altele (un nod din drum contine ca informatie urmatorul nod la care trebuie sa se sara). Cautarea va incepe din celula (0, 0). Stim ca am ajuns la comoara cand trebuie sa sarim inapoi in celula (0, 0). Scheletul contine un program PPU care genereaza un labirint si trimite SPU-ului adresa catre începutul matricii precum si dimensiunea unei linii a labirintului. SPU-ul va trebui sa gaseasca coordonatele comorii si sa le scrie în prima celula a labirintului (0, 0). Programul PPU va verifica apoi daca in celula (0, 0) se gasesc coordonatele comorii.

asc/cellcookbook/smc.txt · Last modified: 2020/02/04 14:44 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0