Documente Academic
Documente Profesional
Documente Cultură
Primele dou instruc iuni ini ializeaz parametrii configura iei de execu ie. Deoarece grid-ul i blocurile
sunt tablouri unidimensionale, numai prima dimensiune a variabilelor predefinite dimBlock i dimGrid
este folosit . Celelalte dimensiuni sunt setate la valoarea 1. A treia instruc iune realizeaz lansarea efectiv a
kernel-ului. Parametrii configura iei de execu ie se specific între <<< i >>>. Se pot de asemenea utiliza i
valori scalare dac un grid-ul sau blocurile au o singur dimensiune, de exemplu:
Valorile variabilelor gridDim.x i gridDim.y pot fi între 1 i 65.535 i pot fi calculate înainte de
lansarea kernel-ului pe baza altor variabile din cadrul programului. Odat ce kernel-ul este lansat
dimensiunile nu mai pot fi îns schimbate. Toate firele dintr-un bloc au aceea i valoare a variabilei
blockIdx. Variabila blockIdx.x ia valori între 0 i gridDim.x-1 iar variabila blockIdx.y ia
valori între 0 i gridDim.y-1. Fig 2.2 ilustreaz un grid 2D mic care este lansat cu urm torul cod host:
Grid-ul const din patru blocuri organizate într-un tablou 2x2. Fiecare bloc din fig. 2.2 este etichetat cu
valoarea (blockIdx.x, blockIdx.y).
În general blocurile con in structuri 3D de fire. Toate blocurile dintr-un grid au acelea i dimensiuni. Fiecare
variabil threadIdx const din trei componente: coordonata x threadIdx.x, coordonata y
threadIdx.y i coordonata z threadIdx.z. Num rul de fire ale fiec rei dimensiune a unui bloc este
specificat de cel de-al doilea parametru al configura iei de execu ie utilizate la lansarea kernel-ului.
Dimensiunea maxim a unui bloc este limitat la 512 fire de execu ie, care pot fi îns organizate în
nenum rate moduri în cadrul blocului atât timpul cât num rul lor total nu dep te 512: (512,1,1), (8,16,2)
i (16,16,2) sunt permise, dar (32,32,1) nu este permis deoarece num rul total de fire ar fi 1024.
Fig. 2.2. Exemplu de organizare multidimensional a unui grid CUDA.
Fig. 2.2 ilustreaz de asemenea un exemplu de organizare a firelor în cadrul unui bloc. În cazul de fa
fiecare bloc con ine 4x2x2 fire. Deoarece toate blocurile dintr-un grid au acelea i dimensiuni, este suficient
se prezinte un singur bloc. În cazul de fa este prezentat blocul (1,1) împreun cu cele 16 fire ale sale. În
total sunt 4 blocuri de câte 16 fire, deci în total 64 de fire în întreg grid-ul (s-au folosit numere mici pentru a
permite o ilustrare clar – în realitate se folosesc mii de fire de execu ie).
Fig. 2.3. Înmul irea matricelor prin utilizarea mai multor blocuri.
Fig. 2.4 ilustreaz un mic exemplu de utilizare a mai multor blocuri pentru a calcula matricea Pd. Pentru
simplitate se folose te o valoare mic pentru variabila LATIME_PORTIUNE (2). Matricea Pd este împ it
în 4 por iuni, fiecare dimensiune a lui Pd fiind împ it în dou p i. Fiecare bloc trebuie s calculeze 4
elemente din matricea Pd. Acest lucru poate fi realizat prin crearea unor blocuri care sunt organizate în
tablouri de 2x2 fire, fiecare fir calculând un element Pd. În exemplu, firul (0,0) al blocului (0,0) calculeaz
elementul Pd0,0, iar firul (0,0) din blocul (1,0) calculeaz elementul Pd2,0. Elementul Pd calculat de firul
(0,0) din blocul (1,0) poate fi determinat astfel: Pd[bx* LATIME_PORTIUNE + tx][by*
LATIME_PORTIUNE + ty] = Pd[1*2 + 0][0*2 + 0]=Pd[2][0].
Odat ce au fost identifica i indicii elementului Pd care trebuie calculat de c tre un fir, s-a identificat i
rândul (y) din Md i coloana (x) din Nd de unde se preiau valorile de intrare. Dup cum este ilustrat în fig.
2.3., indicele rândului matricei Md utilizat de firul (tx, ty) din blocul (bx, by) este (by*
LATIME_PORTIUNE + ty). Indicele coloanei matricei Nd utilizate de acela i este (bx*
LATIME_PORTIUNE + tx). Se poate acum prezenta versiunea revizuit a kernel-ului din fig. 1.14, care
folose te mai multe blocuri pentru a calcula Pd.
Fig. 2.4. Exemplu simplificat de utilizare a mai multor blocuri pentru calculul matricei Pd.
Fig. 2.5 prezint ac iunile de înmul ire ale fiec rui bloc. Firele din blocul (0,0) realizeaz patru produse
scalare. Firul (0,0) îl determin pe Pd0,0 prin calculul produsului scalar al rândului 0 al matricei Md i al
coloanei 0 a matricei Nd. S ge ile de la Pd0,0, Pd1,0, Pd0,1 i Pd1,1 indic rândurile i coloanele utilizate
pentru calculul valorii rezultante.
global__ void InmultMatrKernel (float* Md, float* Nd, float* Pd, int
latime)
{
// Calculul indexului de rand al elementelor din matricele Pd si Md
int Row = blockIdx.y * blockDim.y + threadIdx.y;
// Calculul indexului de coloana al elementelor din matricele Pd si Nd
int Col = blockIdx.x * blockDim.x + threadIdx.x;
float Pval = 0;
// fiecare fir calculeaza un element din portiunea matricei
for (int k = 0; k < latime; ++k)
Pval += Md[Row*latime+k] * Nd[k*latime+Col];
Pd[Row*latime + Col] = Pval;
}
Fig. 2.6. Kernel revizuit utilizat pentru înmul irea matricelor, bazat pe mai multe blocuri de fire.
Fig. 2.7 prezint codul host revizuit utilizat pentru lansarea kernel-ului revizuit de înmul ire a matricelor. Se
remarc faptul c dimGrid ia valoarea latime/LATIME_PORTIUNE atât pentru dimensiunea x cât i
pentru dimensiunea y. Codul revizuit lanseaz kernel-ul cu mai multe blocuri.
Fig. 2.8. Scalabilitate transparent a programelor CUDA asigurat de lipsa sincroniz rii între blocurile de
fire.
Se poate calcula num rul de warp-uri care se afl simultan pe un multiprocesor folosind dimensiunea unui
bloc i num rul de blocuri asociate fiec rui multiprocesor. Dac de exemplu fiecare bloc are 256 de fire,
adic 8 warp-uri, i trei blocuri sunt asociate simultan unui multiprocesor, atunci în total exist 24 de warp-
uri pe un multiprocesor la un moment dat. Num rul maxim de warp-uri pentru multiprocesoarele
dispozitivului GT200 este de 32 deoarece sunt permise maxim 1024 pe un multiprocesor.
Întrebarea este de ce este nevoie de atâtea warp-uri, dac nu sunt decât 8 unit i de procesare într-un
multiprocesor? R spunsul este c acesta modul în care procesoarele CUDA execut eficient opera iile cu
laten mare, precum acces rile memoriei globale. Când o instruc iune executat de firele unui warp trebuie
a tepte rezultatul unei opera ii ini iate anterior, i care are o laten mare, atunci warp-ul respectiv nu este
selectat pentru execu ie. Un alt warp, care nu trebuie s a tepte rezultatul unei opera ii este atunci selectat
pentru execu ie. Dac mai mult de un warp este preg tit de execu ie, un mecanism de prioritate este folosit
pentru a selecta un warp în vederea execu iei sale. Acest mecanism de contracarare a laten ei opera iilor prin
executarea altor fire se nume te mascare a laten ei.
Planificarea warp-urilor este utilizat i pentru tolerarea altor tipuri de opera ii cu laten mare, precum
opera ii în virgul mobil sau opera ii de ramificare. Dac exist suficiente warp-uri, este probabil ca
hardware-ul s g seasc un warp pe care s -l poat executa la un moment dat i s se foloseasc în acest fel
la maxim hardware-ul în ciuda prezen ei opera iilor de laten mare. Selec ia warp-urilor preg tite de
execu ie nu introduce timpi de pauz de-a lungul execu iei. Prin planificarea warp-urilor, timpii de a teptare
lungi ai instruc iunilor warp-urilor sunt ascun i prin executarea instruc iunilor altor warp-uri. Aceast
capacitate de tolerare a opera iilor de laten mare este unul din motivele principale pentru care GPU-urile
nu aloc nici pe de parte la fel de multe resurse pentru memorii cache i mecanisme de predic ie a
comportamentului de ramificare precum procesoarele clasice CPU. Prin urmare, GPU-urile dedic o mai
mare parte a chip-ului resurselor necesare pentru efectuarea calculelor în virgul mobil .
Se analizeaz în continuare un exemplu simplu. Care dintre urm toarele dimensiuni de blocuri, 8x8, 16x16
sau 32x32, trebuie folosite pentru dispozitivul GT200. Dac s-ar alege op iunea 8x8, fiecare bloc ar avea
doar 64 de fire i ar fi nevoie de 1024/64=12 blocuri pentru a ocupa pe deplin un multiprocesor (s-ar folosi
doar 512 fire pentru fiecare multiprocesor datorit limitei de 8 blocuri). E probabil astfel ca resursele
multiprocesorului s nu fie utilizate la maxim, deoarece mai pu ine warp-uri sunt disponibile pentru mascare
opera iilor cu laten mare. Cu 16x16 fire pe bloc se ob in 256 de fire pe bloc, ceea ce înseamn 1024/256=4
blocuri, adic sub limita de 8 blocuri. Aceasta este o configura ie bun deoarece s-ar ob ine num rul maxim
de warp-uri. Trebuie îns re inut faptul c acesta este un exemplu simplificat i sunt i alte aspecte care
trebuie luate în considerare atunci când se determin num rul de blocuri care pot fi asociate simultan unui
multiprocesor.