Você está na página 1de 5

SIMD

Single instruction, multiple data (abreviat SIMD; din engleză) reprezintă una dintre
arhitecturile de calculatoare paralele menționate în Taxonomia lui Flynn. Acest tip de calculatoare
dispune de elemente multiple de procesare (în imaginea din dreapta: PU) care toate efectuează în
paralel aceeași operație sau instrucțiune, dar pe date diferite. Astfel, aceste mașini exploatează
paralelismul datelor (pe măsura în care acesta e prezent).

Introducere
Majoritatea procesoarelor moderne conțin elemente hardware speciale care permit ca o singură
instrucțiune să genereze operații multiple care să fie executate în paralel. Această tehnică se numește
SIMD (o singură instrucțiune, date multiple). Spre exemplu, generațiile recente de procesoare Intel și
AMD au instrucțiuni care realizează adunarea a patru perechi de numere reale în simplă precizie (tipul
de date float din C) în paralel. Aceste instrucțiuni au fost create pentru a imbunătăți viteza aplicațiilor
pentru procesare de imagine, sunet și video. Deși unele compilatoare incearcă să extragă automat
acest tip de paralelism din programele scrise în C, o metodă mai fiabilă este scrierea programelor
folosind tipuri speciale de date (vectorizate) în compilatoare precum GCC. Intel a introdus în 1999
instrucțiunile SSE – acronim pentru Streaming SIMD Extensions. SSE este o clasă de instrucțiuni
pentru a manipula vectori de întregi sau de date în virgulă mobilă. Fiecare bloc de date poate avea
dimensiuni de 1, 2 sau 4 octeți, împachetate în vectori de 128 de biți. Versiunile ulterioare ale acestui
chip au depășit 24M de tranzistori, datorită înglobării memoriei cache de nivel 2 (L2). Ideea din spatele
modelului SIMD este aceea că fiecare registru XMM de 16 octeți poate reține valori multiple.
Instrucțiunile SSE pot apoi să efectueze operații pe acești regiștri precum adunarea sau înmulțirea a
două sau patru seturi de valori în paralel. Compilatorul GCC suporta extensii ale limbajului C care
permit programatorilor să scrie cod folosind operații vectorizate ce pot fi compilate în instrucțiunile SIMD
ale SSE. Acest stil de programare este preferabil celui de a scrie cod direct în limbaj de asamblare
fiindcă GCC poate genera cod pentru instrucțiunile SIMD de pe alte procesoare. Scrierea codului în C
are de asemenea avantajul că GCC va genera cod scalar pentru sistemele care nu oferă suport pentru
instrucțiuni vectorizate.[1]

Avantaje
O aplicație care poate beneficia de SIMD este una în care aceeași valoare se adaugă (sau se
scade) la un număr mare de date, o operațiune comună în multiple aplicații multimedia. Un exemplu ar
fi schimbarea luminozității unei imagini. Fiecare pixel al unei imagini este format din trei valori pentru
luminozitate: roșu (R), verde (G) și albastru (B). Pentru a modifica luminozitatea, valorile R, G și B sunt
citite din memorie, valoarea se adaugă (sau se scade) acestora și rezultatele valorilor sunt scrise înapoi
în memorie.
Cu un procesor SIMD există două îmbunătățiri pentru acest proces. Pentru unul dintre ele,
datele trebuie să fie în blocuri, și un număr de valori poate fi încărcat dintr-o dată. În loc de o serie de
instrucțiuni ce spun „obtine acest pixel, acum obține următorul pixel”, un procesor de SIMD va avea o
singură instrucțiune care va spune într-un mod eficient „obtine loturi de pixeli” („loturi” reprezintă un
număr care variază de la design la design). Din diverse motive, acest lucru poate dura mult mai puțin
decât „obtinerea” fiecărui pixel individualizat, așa cum se întâmplă la un design CPU tradițional.
Un alt avantaj îl reprezintă acela că sistemele SIMD includ de obicei doar acele instrucțiuni care
pot fi aplicate la toate datele într-o singură operațiune. Cu alte cuvinte, în cazul în care sistemul SIMD
lucrează până la opt puncte de date o dată, se adaugă operația ce va lucra cu toate cele opt valori în
același timp. Deși același lucru este valabil pentru orice model de procesor super-scalar, nivelul de
paralelism într-un sistem SIMD este de obicei mult mai mare.

Dezavantaje
Nu toți algoritmii pot fi vectorizați. De exemplu, o sarcină cu prioritate de control al fluxului, cum ar fi
analiza codului, nu ar beneficia de SIMD;

 Acesta are, de asemenea, registre cu fișiere de mari dimensiuni care conduc la creșterea
consumului de energie și zona chip;
 În prezent, punerea în aplicare a unui algoritm de instructiuni SIMD, implică de obicei forță de
muncă umană, deoarece cele mai multe compilatoare nu generează instrucțiuni SIMD dintr-un
program C. Vectorizarea în compilatoare este un domeniu activ de cercetare în informatică.
(Compararea prelucrarii vectorului);
 Programarea cu seturi speciale de instructiuni SIMD poate implica numeroase provocări low-
level.
 SSE (Streaming SIMD Extension) are restricții privind alinierea datelor, programatorii
familiarizați cu arhitectura x86 nu se pot aștepta la acest lucru.
 Colectarea datelor în registrele SIMD împrăștie destinația corectă a locațiilor ceea ce
este dificil și ineficient.
 Instructiunile specifice cum ar fi rotatiile sau three-operand addition nu există în seturile
de instrucțiuni SIMD.
 Seturile de instrucțiuni au o arhitectură specifică: procesoarele vechi și procesoarele ce
nu utilizează arhitectura x86 le lipsește în intregime SSE-ul, de exemplu, programatorii trebuie
să furnizeze implementări non-vectorizate.
 În trecut, setul de instrucțiuni MMX partaja fișierul registru cu stiva floating-point,lucru
care a provocat ineficiență, atunci când s-a folosit în același timp floating-point și codul MMX.
Cu toate acestea SSE2 corectează acest lucru.

Cronologie[
Prima utilizare a instrucțiunilor SIMD a fost în supercomputerele vector la începutul anilor 1970, cum ar
fi Star CDC-100 și Texas Instruments ASC. Vectorul de prelucrare a fost popularizat în special de Cray
în anii 1070 și 1980.
Mai târziu, mașinile încep să utilizeze un numar mult mai mare de procesoare relativ simpe, cu o
configurație tip procesare masivă. Câteva exemple de acest tip de mașină:

 ILLIAC IV, 1974;


 ICL Distributed Array Processor (DAP), 1974;
 Burroughs Scientific Processor, 1976;
 Geometric-Arithmetic Parallel Processor, de Martin Marietta, începând în anul 1981, continuat
de Lockheed Martin, apoi de Teranex și Silicon Optix;
 Massively Parallel Processor (MPP), de NASA/Goddard Space Flight Center, 1983-1991 ;
 Connection Machine, modelul 1 si 2 (CM -1 si CM-2), de Thinking Machines Corporation, 1985;
 MasPar MP-1 and MP-2, 1987-1996;
 Zephyr DC computer de Wavetracer, 1991;
 Xplor, de Pyxsys, Inc., 2001.

Multe alte exemple de acest tip de mașină existau în acea eră.

Hardware[
SIMD-urile la scară mică (64 sau 128 biți) au devenit populare pe procesoarele de uz general la
începutul anilor 1990, a continuat până în 1997 și mai târziu cu Motion Video Instructions (MVI) pentru
Alpha. Instrucțiunile SIMD pot fi găsite, la un grad sau altul, pe cele mai multe procesoare, inclusiv
produsul AltiVec al IBM-ului și SPE pentru PowerPC, PA-RISC Multimedia Acceleration eXtensions
(MAX) al HP-ului, Intel MMX, SSE, SSE2, SSE3 și SSS3, AMD 3DNow!, ARC Video subsystem,
SPARC VIS si VIS2, Sun MAJC, ARM NEON, MIPS' MDMX (MaDMaX) și MIPS-3D. IBM, Sony, Toshiba
au co-dezvoltat setul de instructiuni SPU al procesorului Cell și se bazează puternic pe setul de
instrucțiuni SIMD. NXP fondată de Philips a dezvoltat mai multe procesoare SIMD numite Xetal. Xetal
are 320 de elemente procesare pe 16 biti concepute special pentru sarcici de vizualizare.
Unitățile moderne de procesare grafică(GPU-urile) sunt deseori largi implementari ale SIMD, capabile
de a încarca sau de a memora pe 128 și 256 biți la un moment dat.
Viitoarele procesoare promit o capacitate mai mare de SIMD: instructiunile Intel's AVX vor procesa pe
256 biti, si microarhitectura grafică Intel Larrabee promite două registre SIMD pe 512 biți pe fiecare din
nucleele sale (VPU - Wide Vector Processing Units) [ deși, la începutul anului 2010, proiectul Larrabee
a fost anulat la Intel].[necesită citare]

Software
Instrucțiunile SIMD sunt utilizate pe scară largă pentru procesarea de grafică 3D, deși plăcile
grafice moderne, cu SIMD integrat au preluat în mare parte această sarcină de la procesor(CPU).
Unele sisteme includ, de asemenea, funcții de permutare in interiorul vectorilor, ceea ce le face
deosebit de utile pentru prelucrarea datelor de compresie. Acestea sunt, de asemenea, folosite în
criptografie.[2][3][4] Tendința de calcul de uz general pe GPU (GPGPU) poate duce la folosirea pe scară
mai larga a SIMD-ului în viitor. Adoptarea de sisteme SIMD în software-ul de pe calculatoarele
personale a fost la început lentă, datorita numărului de probleme. Una a fost că multe dintre
instrucțiunile SIMD au tendița de a încetini performanța generală a sistemului datorită reutilizării
regiștrilor existenți în floating point. Alte sisteme, cum ar fi MMX și 3DNow!, oferă suport pentru tipurile
de date care nu au fost interesate pentru publicul larg si au avut contexte costisitoare de schimbare a
instrucțiuniilor pentru comutarea între utilizarea regiștrilor FPU și MMX. Compilatoarele, de asemenea,
de multe ori nu ajutau programatorii. Astfel încât aceștia trebuiau să recurga la limbajul de
asamblare de codificare.
SIMD pe x86 biți a avut un start lent. Introducerea de 3Dnow! de AMD și Intel Sse au provocat
probleme confuze, dar astăzi sistemul pare a fi stabilit ( dupa ce AMD a adoptat SSE) și compilatoarele
noi ar trebui să conțină software pentru SIMD. Intel și AMD, furnizau biblioteci matematice optimizate ce
folosesc instrucțiunile SIMD și alternativele open source ca libSIMD și SIMDx86.
Computerele Apple au avut un succes mai mare, chiar dacă au intrat în piața SIMD mai târziu
decât restul. AltiVec oferea un sistem bogat și poate fi programat să foloseasca compilatoare din ce în
ce mai sofisticate de la Motorola, IBM, GNU, prin urmare, un limbaj de programare de asamblare fiind
necesar foarte rar. În plus, multe dintre sistemele, care ar beneficia de SIMD au fost furnizate de către
Apple, de exemplu: iTunes și QuickTime. Cu toate acestea, în anul 2006, computerele Apple s-au mutat
pe procesoarele Intel x86. APl-urile Apple și instrumentele de dezvoltare (XCode) au fost rescrise
pentru a utiliza SSE2 si SSE3 în loc de AltiVec. Apple a fost cumpărătorul dominant de cipurile
PowerPC de la IBM și Freescale Semiconductor și chiar dacă ei au abandonat platforma, dezvoltarea
AltiVec continuă.
SIMD într-un registru, sau SWAR reprezintă o gamă de tehnici și trucuri folosite pentru
efectuarea SIMD în registrele de uz general pe hardware, care nu oferă nici un spijin direct pe
instrucțiunile SIMD. Acest lucru poate fi folosit pentru a exploata paralelismul în anumiți algoritmi chiar și
pe hardware care nu suportă SIMD direct.

Exemplu de implementare
Se poate folosi compilatorul GCC ca suport pentru a scrie cod ce utilizează operații cu
vectorizare. Strategia fundamentală este de a defini un tip de dată vec_t care reține patru valori pe 4
octeți sau două valori pe 8 octeți. Primul pas este de a declara un tip de dată vectorizat. Având în
vedere faptul că se dorește ca același cod să poată funcționa și pentur tipuri primitive de date precum
int, float și double, se folosește typedef pentru declarații și definiri de constante pentru a generaliza
codul. Se definiște VBYTES pentru a reprezenta numărul de octeți din vector. Pentru SSE, acesta este
definit ca fiind 16, dar se va parametriza aceasă valoare pentru a garanta adaptarea pe alte sisteme.
Un alt considerent este definirea VSIZE, numărul de elemente în fiecare vector.

/* Numărul de octeți dintr-un vector */


#define VBYTES 16

/* Numărul de elemente dintr-un vector */


#define VSIZE VBYTES/sizeof(data_t) //data_t este tipul de bază

/* Definirea unui nou tip de vector */


typedef data_t vec_t __attribute__ ((vector_size(VBYTES)));

Această declarare sugerează faptul că tipul de dată vec_t este vector, cu elementele de tipul
data_t și având dimensiunea VBYTES în octeți. Pentru a accesa elementele vectorului, o soluție este
folosirea unui union:

typedef union {
vec_t v;
data_t d[VSIZE];
} pack_t;
Un exemplu simplu ce calculează produsul scalar pentru doi vectori SIMD:

data_t produs_scalar(vec_t av, vec_t bv){


pack_t xfer;
int i;
vec_t pv = av * bv; // se înmulțesc elementele din av si bv
data_t result = 0;
xfer.v = pv;
for (i = 0; i < VSIZE; i++)
rez += xfer.d[i];
return result;
}

Multe din instrucțiunile SSE impun cerințe stricte pentru alinierea operanzilor în memorie.
Trebuie ca orice date citite din memorie într-un registru XMM sau scrise din XMM în memorie să
satisfacă un aliniament de 16 octeți. O instrucțiune care încearcă să citească sau să scrie date
nealiniate va cauza o eroare de tip segmentation fault care indică încercarea de a se accesa o locație
invalidă de memorie. Începând de la SSE2 există instrucțiuni care pot accesa date nealiniate, însă
datorită lipsei de eficiență a implementărilor de început, GCC nu generează cod care să le folosească.
Ideea generală a următorului cod este de a defini o variabilă de tip vec_t (accum) care să acumuleze
patru (date de tip int sau float) sau două (date de tip double) valori în paralel. Mai intâi se inițializează
acumulatorii cu elementul identitate (IDENT), folosind tipul de dată pack_t pentru a seta elementele
individuale dintr-un vector. Pentru a satisface cerința de aliniament se vor acumula câteva elemente din
vector folosind operații scalare până când variabila dată va conține o adresă care este multiplu de
VBYTES. E necesară o conversie explicită asupra pointerului data pentru a-l transforma într-un long.
Astfel se poate testa dacă este un multiplu de VBYTES. De asemenea, e necesar să se cunoască
numărul de elemente rămase cnt, luând în considerare cazul în care cnt este mai mic decât numărul de
elemente rămase dintr-un singur vector.

void simd_combine(vec_ptr v, data_t* dest){


long int i;
pack_t xfer;
vec_t accum;
data_t* data = get_vec_start(v);
int cnt = vec_length(v);
data_t result = IDENT;

/* Se inițializează accum la valoarea IDENT */


for (i = 0; I < VSIZE; i++0)
xfer.d[i] = IDENT;
accum = xfer.d;

while ( ((long) data) % VBYTES && cnt ){


result = result OP *data++; //aliniere în memorie
cnt--;
}

while (cnt >= VSIZE){


vec_t chunk = *((vec_t *) data);
accum = accum OP chunk;
data += VSIZE;
cnt -= VSIZE;
}
/* iterare prin elementele rămase */
while (cnt){
result = result OP *data++;
cnt--;
}
/*combinarea elementelor în vectorul acumulator */
xfer.v = accum;
for (i = 0; i < VSIZE; i++)
result = result OP xfer.d[i];
/* memorarea rezultatului */
*dest = result;
}

Operațille vectorizate efectuate mai sus fac ca valori multiple (2 sau 4) să fie acumulate în paralel în
variabila accum.

while (cnd >= VSIZE){


vec_chunk = *((vec_t *)data);
accum = accum OP chunk;
data += VSIZE;
cnt -= VSIZE;
}

În blocul de cod de mai sus se observă folosirea conversiei explicite pentru a crea un pointer la
un vector având aceeași adresă cu a pointerului la data. Dereferențierea acestui pointer duce la
obținerea unui întreg vector de date din memorie, definit aici prin variabila vectorizată chunk.
Instrucțiunea accum = accum OP chunk combină valorile vectorizate citite din memorie cu valorile din
acumulatorii paraleli. În cazul în care bucla de mai sus se termină înainte ca toate valorile să fie
acumulate, bucla imediat următoare va itera prin toate elementele rămase. Apoi referențiem
acumulatorii printr-un union și le combinăm pentru a acumula rezultatul final. [5]

Aplicații comerciale
Deși s-a dovedit, în general, dificil de a găsi aplicații comerciale durabile pentru procesoarele
SIMD, doar unul care a avut o anumită masură de succes este GAPP, care a dost dezvoltat
de Lockheed Martin. Încercări recente ale GAPP au devenit un instrument puternic în aplicațiile în timp
real de procesare video cum ar fi conversia între diferite standarde video și viteze de cadre (NTSC la/de
la PAL, NTCD la/de la formatele HDTV). O cerere mai des întâlnită pentru SIMD se regăsește în jocurile
video: aproape fiecare joc video modern tip consolă, începând cu anul 1998, are încorporat un procesor
SIMD undeva în arhitectura sa. Playstation 2 a fost neobișnuit în sensul că unitățile sale vector-float ar
putea funcționa ca DSP-uri autonome, care execută propriile fluxuri de instrucțiuni, sau că
coprocesoare conduse de instrucțiuni CPU obișnuite. Aplicații grafice 3D au tendința de a se potrivi bine
la procesarea SIMD, deoarece acestea se bazează foarte mult pe operațiile cu vectori de 4
dimensiuni. Direct3D 9.0 de la Microsoft își alege în momentul rulării procesorului implementării
specifice, cu propriile sale operații matematice, inclusiv SIMD-uri pentru instrucțiuni. Printre ultimele
procesoare care folosește procesarea vectorizata este ăăCell (procesor)|Procesorul Cell]] dezvoltat
de IBM, în colaborare cu Toshiba și Sony. Se folosește un număr de procesoare SIMD (fiecare
cu RAM independent și controlate de un procesor de uz general) și este proiectat pentru seturile de
instrucțiuni uriașe cerute de către 3D și aplicațiile de procesare video. Un progres recent al Ziilabs a fost
producerea de un procesor tip SIMD, care poate fi utilizat pe dispozitive mobile, cum ar fi playere
multimedia și telefoane mobile. [6] Procesoare SIMD pentru o scară comercială mai largă sunt disponibile
de la ClearSpeed Technology, Ltd. și de la Stream Processors. ClearSpeed CSX600 (2004) are 96
nuclee fiecare cu două unități dublă-precizie în virgulă mobilă, în timp ce CSX700 (2008) are 192 de
nuclee.

Você também pode gostar