cuda c/ c ++ programozás
DESCRIPTION
CUDA C/ C ++ programozás. Atomikus műveletek. A segédanyag készítése a TÁMOP 4.2.4.A/2-11-1-2012-0001 Nemzeti Kiválóság Program című kiemelt projekt keretében zajlott. A projekt az Európai Unió támogatásával, az Európai Szociális Alap társfinanszírozásával valósul meg. - PowerPoint PPT PresentationTRANSCRIPT
CUDA C/C++ programozás
Atomikus műveletek
A segédanyag készítése a TÁMOP 4.2.4.A/2-11-1-2012-0001 Nemzeti Kiválóság Program című kiemelt projekt keretében zajlott. A projekt az Európai Unió támogatásával, az Európai Szociális Alap társfinanszírozásával valósul meg.
GPU számítási képességek
Számítási képesség ismétlés: Minden GPU-hoz tartozik egy adott számítási képesság.
Pl.: 1.2, 2.0, 3.0
Leírja: Az architektúra főbb jellemzőit.
A GPU által adott lehetőségeket, és szolgáltatásokat.
Inkrementális szolgáltatáslista. A magasabb számítási képességű GPU több
szolgáltatást ad.
Régi elemek nem vesznek el.
Visszafelé kompatibilitás.
Fordítás adott számítási képességre
A kód fordításakor jelezni lehet, a fordító számára, hogy:
Mi a minimális szolgáltatáskészlet (számítási képesség) amire fordítani szeretnénk a programot.
Milyen GPU-ra optimalizáljon.
Megadás az nvcc parancssori argumentumával: nvcc –arch=sm_11
A program minimum 1.1-es képességű GPU-n fut.
Miért érdekes ez nekünk? Mert a mai óra anyaga, az atomikus műveletek a 2.0-s
képességtől jönnek be a GPU-ba.
Meg különben sem árt tudni.
Konkurens futtatás
A párhuzamos programok futásakor előfordulhatnak versenyhelyzetek:
Két vagy több utasítás ugyanazt az adatot próbálja elérni/módosítani.
Például:__global__ void kernel(int* x) {
(*x)++; // x növelése (nem pixelenként)
return;}
Int main(...) { int* dev_x;
// ...
kernel<<<2, 2>>>(dev_x); // melyik szál növeli x-et?
// ...}
Probléma konkurens adatelérésnél
(*x)++;
3 lépésben
X értékének kiolvasása a memóriából,
Az érték növelése,
Eredmény visszaírása a memóriába
Ha párhuzamosan megy (pl.: x):
1. szál
Olvasás:• reg = *x;
// 4 beolvasva
Növelés:• reg++;
// növelt érték: 5
Visszaírás:• *x = reg; // *x=5;
2. szál
Olvasás:• reg = *x;
// 4 beolvasva
Növelés:• reg++;
// növelt érték: 5
Visszaírás:• *x = reg; // *x=5;
3. szál
Olvasás:• reg = *x;
// 4 beolvasva
Növelés:• reg++;
// növelt érték: 5
Visszaírás:• *x = reg; // *x=5;
idő
Ugyanaz szekvenciálisan
(*x)++;
3 lépésben
X értékének kiolvasása a memóriából,
Az érték növelése,
Eredmény visszaírása a memóriába
Ha párhuzamosan megy (pl.: x):
1. futás
Olvasás:• reg = *x;
// 4 beolvasva
Növelés:• reg++;
// növelt érték: 5
Visszaírás:• *x = reg; //
*x=5;
2. futás
Olvasás:• reg = *x;
// 5 beolvasva
Növelés:• reg++;
// növelt érték: 6
Visszaírás:• *x = reg; // *x=6;
3. futás
Olvasás:• reg = *x;
// 6 beolvasva
Növelés:• reg++;
// növelt érték: 7
Visszaírás:• *x = reg; // *x=7;
idő
Konkurens változónövelés a gyakorlatban
14_RaceCondition.cu
Egy változó érték növelése adott számszor.
Párhuzamosan a GPU-n.
És szekvenciálisan a GPU-n.
Atomikus műveletek
Feloldják a konfliktusokat. Biztosított, hogy egyszerre csak egy szál férhessen hozzá egy
adatelemhez.
Műveletek: int atomicAdd(int* address, int val);
int atomicSub(int* address, int val);
int atomicExch(int* address, int val);
int atomicMin(int* address, int val);
int atomicMax(int* address, int val);
unsigned int atomicInc(unsigned int* address, unsigned int val);
unsigned int atomicDec(unsigned int* address, unsigned int val);
int atomicCAS(int* address, int compare, int val);
int atomicAnd(int* address, int val);
int atomicOr(int* address, int val);
int atomicXor(int* address, int val);
Valós példa:Hisztogram
Hisztogram számítása a GPU-n.
Adott egy adatsor (diszkrét elemekből).
Pl.: kép egész pixelintenzitásokkal 0 és 255 között.
Megoldása CPU-n.
15_HistCPU.cu
Sima ügy.
unsigned char* adat; int* hiszt[256];
for(int i=0; i<256; i++) hiszt[i] = 0;
for(int i=0; i<adat_meret; i++) hiszt[adat[i]]++;
Hisztogram a GPU-n
Bonyolult művelet.
A szálak konkurens módon párhuzamosan dolgozzák fel az adatot.
Konfliktus léphet fel, ha két szál ugyanazt a hisztogram számlálót akarja növelni.
Magoldás: atomikus műveletek
A számláló növeléseket atomikus műveletekkel végezzük a kernelben.
Ez automatikusan feloldja a konfliktusokat.
Hátrányok:
Lassítja a kódot
A szálak sorban várhatnak egy számláló növelésére.
16_Hist_GPU.cu
További lehetőségek
Mire lehetne még használni az atomikus műveleteket?