Mecanisme avansate de folosire a transferurilor DMA. Liste DMA

In prima parte a laboratorului am studiat modalitatea de baza de folosire a DMA pentru transfer de date intre memoria locala a SPU si spatiul principal de stocare. Din cauza ca memoria locala este limitata, multe aplicatii vor avea nevoie sa transfere, pe rand, mai multe secvente de date catre SPE, spre procesare.
Pentru acest scenariu se pot folosi mai multe metode: liste DMA sau double-buffering (studiat in laboratorul urmator).


Liste DMA

O lista DMA este o secventa de elemente de transferat, ce specifica o serie de transferuri DMA intre o singura zona din memoria locala si mai multe zone (posibil discontinue) din spatiul principal de stocare. Se pot construi astfel functii de tip scatter-gather intre memoria locala si spatiul principal de stocare. Toate transferurile initiate pe baza aceleiasi liste au acelasi tag id si folosesc comenzi de acelasi tip (getl, putl etc.). Lista DMA se stocheaza in memoria locala a aceluiasi SPE.

Crearea unei liste DMA

Fiecare element dintr-o lista DMA contine 3 parametri:

  • 'notify:' flag care, daca este setat, suspenda secventa de transferuri dupa transferul acestui element
  • 'size:' marimea transferului in octeti
  • 'eal:' adresa efectiva in spatiul principal de stocare (lower 32-bits)
typedef struct mfc_list_element {
    uint64_t notify : 1; // optional stall-and-notify flag
    uint64_t reserved : 16; // the name speaks for itself
    uint64_t size : 15; // transfer size in bytes
    uint64_t eal : 32; // lower 32-bits of an EA in main storage
} mfc_list_element_t;

Initierea transferurilor din lista DMA

Dupa ce lista este stocata in memoria locala a SPE, se apeleaza comenzi de transfer specifice (cele cu sufix “l”):

  • mfc_getl implementeaza comanda getl
  • mfc_putl implementeaza comanda putl.

Aceste functii sunt non-blocante, iar SPU poate continua executarea programului, economisind timp pretios. Insa, desigur, daca ele nu au loc in MFC SPU command queue, vor avea caracter blocant pana la obtinerea unui slot.

Comenzile de transfer de tip lista folosesc parametri similari comenzilor de transfer obisnuite, cu mici mentiuni (vezi exemplul de mai jos):

  • parametrul LS specifica adresa zonei de memorie continue din Local Store
  • parametrul EA specifica adresa zonei de memorie din Main Storage (util doar in cazul in care codul de PPU e compilat pe 64 de biti)
  • parametrul list specifica adresa listei in memoria locala (adresele individuale din Main Storage, precum si dimensiunile transferurilor sunt precizate folosind membri din structura listei)
  • parametrul marime a transferului (size) specifica spatiul in octeti ocupat de lista DMA in memoria locala, mai exact, numarul de elemente din lista inmultit cu sizeof(struct mfc_list_element).

mfc_getl este implementat astfel (mfc_putl e implementat similar):

spu_mfcdma64(ls,mfc_ea2h(ea),(unsigned int)(list), list_size, tag, ((tid<<24)|(rid<<16)|MFC_GETL_CMD)) 

Exemplu transfer lista DMA

mfc_list_element_t list[16] __attribute__((aligned(8)));
 
// Transfer possibly more than 16 KB with one transfer
 
void large_transfer( void *LS, unsigned long long EA, unsigned int nbytes ) {
	unsigned int i = 0;
	unsigned int tagid = 0;
	unsigned int listsize;
	unsigned int sz;
	unsigned int ealow = mfc_ea2l(EA);
	while( nbytes > 0 ) {
		sz = (nbytes < 16384) ? nbytes : 16384;
		list[i].size = sz;
		list[i].eal = ealow;
		nbytes -= sz;
		ealow += sz;
		i++;
	}
	listsize = i * sizeof(mfc_list_item_t);
	mfc_getl(LS, EA, list, listsize, tagid, 0, 0);
	mfc_write_tag_mask(1 << tagid);
	mfc_read_tag_status_any();
}


  1. (Bonus - 2p) Realizati transferurile de date (transferul vectorilor A si B din Main Storage in Local Store si transferul vectorului C din Local Store in Main Storage) folosind liste DMA.
asc/cellcookbook/dmalists.txt · Last modified: 2016/02/01 11:21 by vlad.spoiala
CC Attribution-Share Alike 4.0 International
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