Professional Documents
Culture Documents
tomislav.hrkac@fer.hr
7. lipnja 2018.
1/64
Hrkać Arhitktura grafičkih procesora
Suvremeni višejezgreni procesor
2/64
Hrkać Arhitktura grafičkih procesora
Suvremeni višejezgreni procesor
3/64
Hrkać Arhitktura grafičkih procesora
Suvremeni višejezgreni procesor
4/64
Hrkać Arhitktura grafičkih procesora
Suvremeni višejezgreni procesor
5/64
Hrkać Arhitktura grafičkih procesora
Prikrivanje memorijskih zastoja
Memorijski zastoj
Vrijeme pristupa memoriji – oko 100 ciklusa takta
Procesor za to vrijeme mora čekati i ne može nastaviti s izvodenjem daljnjih instrukcija koje
ovise o traženom podatku
Ublažavanje problema: korištenje priručnih memorija (cache)
6/64
Hrkać Arhitktura grafičkih procesora
Prikrivanje memorijskih zastoja
7/64
Hrkać Arhitktura grafičkih procesora
Suvremeni višejezgreni procesor
8/64
Hrkać Arhitktura grafičkih procesora
Primjeri višejezgrenih procesora
9/64
Hrkać Arhitktura grafičkih procesora
Suvremeni višejezgreni procesor
10/64
Hrkać Arhitktura grafičkih procesora
Suvremeni višejezgreni procesor
11/64
Hrkać Arhitktura grafičkih procesora
Suvremeni višejezgreni procesor
12/64
Hrkać Arhitktura grafičkih procesora
Tipičan procesor prijenosnog računala (pojednostavljeni prikaz)
13/64
Hrkać Arhitktura grafičkih procesora
GPU
14/64
Hrkać Arhitktura grafičkih procesora
Memorijski sustav CPU / GPU
17/64
Hrkać Arhitktura grafičkih procesora
Opis sustava
18/64
Hrkać Arhitktura grafičkih procesora
Opis sustava
Operacije
Svaki program strukturiran
na sljedeći način:
ulaz – lista vrhova
GPU računa gdje se taj vrh
projicira na ekran (vertex
processing)
grupira vrhove u primitive
(trokute)
za svaki trokut, računa
piksele koje prekriva
za svaki piksel prekriven
primitivom, računa boju tog
piksela
19/64
Hrkać Arhitktura grafičkih procesora
Kratki povijesni pregled programiranja grafičkih jedinica 1/4
Raniji sustavi
nema ISA arhitekture
dajemo GPU-u samo listu vrhova, dalje sve računa sam
problem: modeliranje različitih materijala
20/64
Hrkać Arhitktura grafičkih procesora
Kratki povijesni pregled programiranja grafičkih jedinica 2/4
Rezultat:
Učinimo neke od koraka grafičke protočne strukture programirljivima
koraci za koje su se stalno povećavali zahtjevi: vertex processing, primitive
processing, fragment processing
Programeri sada mogu sami specificirati minijaturne programe – ”shadere”
koji definiraju ”logiku” pojedinih dijelova protočne strukture
21/64
Hrkać Arhitktura grafičkih procesora
Kratki povijesni pregled programiranja grafičkih jedinica 3/4
22/64
Hrkać Arhitktura grafičkih procesora
Kratki povijesni pregled programiranja grafičkih jedinica 4/4
”GPGPU” 2002-2003
23/64
Hrkać Arhitktura grafičkih procesora
Jezik Brook (2004)
24/64
Hrkać Arhitktura grafičkih procesora
NVIDIA Tesla arhitektura (2007)
25/64
Hrkać Arhitktura grafičkih procesora
Programski jezik CUDA
Plan
CUDA programske apstrakcije
CUDA implementacija na modernim GPU
Detalji GPU arhitekture
// kernel definition
__global__ void matrixAdd(float A[Nx][Ny], float B[Nx][Ny],
float C[Nx][Ny])
{
int i = blockIdx.x * blockDim.x + ThreadIdx.x;
int j = blockIdx.y * blockDim.y + ThreadIdx.y;
///////////////////////////////////////////////////////
dim3 threadsPerBlock(4,3,1);
dim3 numBlocks(Nx/threadsPerBlock.x, Ny/threadsPerBlock.y, 1);
// kernel definition
__global__ void matrixAdd(float A[Nx][Ny], float B[Nx][Ny],
float C[Nx][Ny])
{
int i = blockIdx.x * blockDim.x + ThreadIdx.x;
int j = blockIdx.y * blockDim.y + ThreadIdx.y;
///////////////////////////////////////////////////////
dim3 threadsPerBlock(4,3,1);
dim3 numBlocks(Nx/threadsPerBlock.x, Ny/threadsPerBlock.y, 1);
29/64
Hrkać Arhitktura grafičkih procesora
Broj SPMD dretvi – eksplicitan u programu
broj poziva jezgre nije odreden veličinom skupa podataka
const int Nx=11;
const int Ny=5;
// kernel definition
__global__ void matrixAdd(float A[Nx][Ny], float B[Nx][Ny],
float C[Nx][Ny])
{
int i = blockIdx.x * blockDim.x + ThreadIdx.x;
int j = blockIdx.y * blockDim.y + ThreadIdx.y;
if (i < Nx && j < Ny) // guard against out of bounds array access
C[j][i] = A[j][i] + B[j][i];
}
///////////////////////////////////////////////////////
dim3 threadsPerBlock(4,3,1);
dim3 numBlocks(Nx/threadsPerBlock.x, Ny/threadsPerBlock.y, 1);
31/64
Hrkać Arhitktura grafičkih procesora
Memorijski model
// populate deviceA
cudaMemcpy(deviceA, A, bytes, cudaMemcpyHostToDevice);
Memorijska hijerarhija
Ne samo da postoje odvojene
memorije računala domaćina i
vanjskog uredaja, nego na vanjskom
uredaju postoji memorijska hijerarhija
Tri ”općenamjenska” tipa
memorije vidljiva GPU kodu
privatna memorija dostupna
samo tekućoj dretvi
dijeljena memorija dostupna
svim dretvama u bloku
globalna memorija dostupna
svim dretvama
(+2 dodatna, specifična za
grafiku – ”constant memory” i
”texture memory” – ne
razmatramo)
33/64
Hrkać Arhitktura grafičkih procesora
CUDA sinkronizacijski konstrukti
34/64
Hrkać Arhitktura grafičkih procesora
Primjer: 1D konvolucija
35/64
Hrkać Arhitktura grafičkih procesora
Primjer: 1D konvolucija
support[threadIdx.x] = input[index];
if (threadIdx.x <2) {
support[THREADS_PER_BLOCK + threadIdx.x] = input[index + THREADS_PER_BLOCK];
}
__syncthreads();
36/64
Hrkać Arhitktura grafičkih procesora
CUDA program za 1D konvoluciju
128 dretvi po bloku – tako smo naprosto odlučili
zadnji redak – pokretanje velikog broja dretvi – po jedne za svaki izlazni
element
koristimo dijeljenu memoriju bloka (polje support)
reduciramo broj pristupa globalnoj memoriji za faktor 3
(svaka dretva treba 3 podatka →) svakom podatku pristupa se 3 puta
dijeljena memorija bitno brža
kooperativno učitavanje odgovarajućeg dijela globalne memorije u dijeljenu
memoriju bloka
barijera ( syncthreads()): svi podatci moraju biti u dijeljenoj memoriji
prije početka računanja
svaka dretva računa jedan element rezultata
upis rezultata u globalnu memoriju (polje output)
37/64
Hrkać Arhitktura grafičkih procesora
Rezime – CUDA apstrakcije
38/64
Hrkać Arhitktura grafičkih procesora
CUDA semantika
Pthreads:
#define THREADS_PER_BLOCK 128
40/64
Hrkać Arhitktura grafičkih procesora
Prevodenje CUDA programa
Bitna pretpostavka
CUDA-e: izvodenje
blokova dretvi može biti
proizvoljnim redoslijednom
(nema meduovisnosti)
Implementacija dodjeljuje
blokove dretvi (”posao”)
jezgrama korištenjem
dinamičke politike
rasporedivanja koja poštuje
zahtjeve za resursima
42/64
Hrkać Arhitktura grafičkih procesora
Nvidia GeForce GTX 1080
43/64
Hrkać Arhitktura grafičkih procesora
NVIDIA GTX 680 (2012)
44/64
Hrkać Arhitktura grafičkih procesora
Nvidia GeForce GTX 285
45/64
Hrkać Arhitktura grafičkih procesora
NVIDIA GTX 680 (2012)
46/64
Hrkać Arhitktura grafičkih procesora
NVIDIA GTX 680 (2012)
47/64
Hrkać Arhitktura grafičkih procesora
Dodjela CUDA dretvi izvršnim resursima jezgre
support[threadIdx.x] = input[index];
if (threadIdx.x <2) {
support[THREADS_PER_BLOCK + threadIdx.x] =
input[index] + THREADS_PER_BLOCK];
}
__syncthreads();
↑
CUDA blok dretvi dodijeljen jezgri
Kako izvršavamo logiku bloka?
48/64
Hrkać Arhitktura grafičkih procesora
Warp: grupa dretvi sa zajedničkim instrukcijskim tokom
support[threadIdx.x] = input[index];
if (threadIdx.x <2) {
support[THREADS_PER_BLOCK + threadIdx.x] =
input[index] + THREADS_PER_BLOCK];
}
__syncthreads();
50/64
Hrkać Arhitktura grafičkih procesora
Divergencija grananja
– smanjena učinkovitost
51/64
Hrkać Arhitktura grafičkih procesora
Rasporedivanje CUDA programa
Primjer: 1000 blokova; 128 CUDA dretvi po bloku
- Svaka dretva zahtijeva 130*sizeof(float) = 520B dijeljene memorije
Jednostavna GPU sa samo 2 jezgre i podrškom za 12 warpova po jezgri
Korak 1: CPU šalje CUDA napravi (GPU) naredbu ”izvrši ovu jezgru”
52/64
Hrkać Arhitktura grafičkih procesora
Rasporedivanje CUDA programa
53/64
Hrkać Arhitktura grafičkih procesora
Rasporedivanje CUDA programa
54/64
Hrkać Arhitktura grafičkih procesora
Rasporedivanje CUDA programa
55/64
Hrkać Arhitktura grafičkih procesora
Rasporedivanje CUDA programa
Primjer: 1000 blokova; 128 CUDA dretvi po bloku
- Svaka dretva zahtijeva 130*sizeof(float) = 520B dijeljene memorije
Korak 3: Rasporedivač nastavlja mapirati blokove na dostupne izvršne
kontekste (prikazano isprepleteno mapiranje) Samo dva bloka mogu stati na
jezgru – treći blok ne stane zbog nedovoljnog prostora u dijeljenoj memoriji
(3 ∗ 520B > 1.5KB)
56/64
Hrkać Arhitktura grafičkih procesora
Rasporedivanje CUDA programa
57/64
Hrkać Arhitktura grafičkih procesora
Rasporedivanje CUDA programa
58/64
Hrkać Arhitktura grafičkih procesora
Rasporedivanje CUDA programa
59/64
Hrkać Arhitktura grafičkih procesora
Rasporedivanje CUDA programa
60/64
Hrkać Arhitktura grafičkih procesora
Implikacije CUDA atomičkih operacija
62/64
Hrkać Arhitktura grafičkih procesora
Tehnika ”perzistentnih dretvi”
Izvršna semantika:
Particioniranje problema u blokove dretvi u duhu podatkovno paralelnog
modela (ciljano da bude neovisno o sklopovlju: sustav rasporeduje blokove
na proizvoljan broj jezgara)
Dretve u bloku izvršavaju se konkurentno (moraju, jer su kooperativne)
Unutar bloka: SPMD programiranje s dijeljenim adresnim prostorom
Postoji suptilna ali uočljiva razlika izmedu ovih modela izvodenja. Bitno
razumjeti!
Semantika memorije:
Raspodijeljeni adresni prostor: memorije računala domaćina i vanjskog
uredaja
Unutar memorije vanjskog uredaja: lokalne varijable dretve, dijeljene
varijable bloka, globalne varijable
Premiještanje varijabli izmedu različitih memorija putem load/store funkcija
→ ispravno je lokalni/dijeljeni/globalni prostor smatrati različitim adresnim
prostorima
Ključni implementacijski detalji:
Dretve u bloku rasporeduju se na istu jezgru GPU kako bi se omogućila brza
komunikaciji preko dijeljene memorije
Dretve u bloku grupirane u warpove za SIMD izvodenje na sklopovlju GPU
64/64
Hrkać Arhitktura grafičkih procesora