Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

CUDA (Compute Unified Device Architecture) W. Bożejko GPGPU - General-purpose computing on graphics processing units.

Podobne prezentacje


Prezentacja na temat: "CUDA (Compute Unified Device Architecture) W. Bożejko GPGPU - General-purpose computing on graphics processing units."— Zapis prezentacji:

1 CUDA (Compute Unified Device Architecture) W. Bożejko GPGPU - General-purpose computing on graphics processing units

2 Plan Wstęp Model programowania Model pamięci CUDA API Przykład – iloczyn skalarny

3 Wstęp

4 Tesla C870 ProduktTesla C870 ObudowaATX, 4.38 x Ilość GPU Tesla1 Dedykowana pamięć1.5 GB GDDR3 Szczytowa wydajnośćPonad 500 gigaflopów Precyzja obliczeń zmiennoprzecinkowych Pojedyncza precyzja w standardzie IEEE 754 Interfejs pamięci384-bit Przepustowość pamięci76.8 GBps Maksymalny pobór mocy170W Interfejs systemowyPCI Express x16 Dodatkowe źródła zasilaniaTak (2) Liczba slotów2 Chłodzeniewentylator całkowity rozmiar pamięci globalnej 1,61 GB liczba multiprocesorów 16 liczba rdzeni (procesorów) 128 całkowity rozmiar pamięci stałej KB całkowity rozmiar pamięci współdzielonej przypadającej na jeden blok KB liczba rejestrów dostępna dla każdego bloku 8192 częstotliwość zegara 1,35 GHz

5 CUDA – model programowania GPU jest widziane jako urządzenie obliczeniowe mogące wykonać część aplikacji która –musi być wykonana wielokrotnie –może być wyizolowana jako funkcja –działa niezależnie na różnych danych (model SIMD) Taka funkcja może być skompilowana o wykonana na GPU

6 CUDA – model programowania Blok wątków (Thread Block) –Wątki mogą kooperować Mają szybką pamięć współdzieloną Są zsynchronizowane można je łatwo rozróżniać (mają Thread ID) –Blok może być 1,2 lub 3-wymiarową tablicą

7 CUDA – model programowania Grid bloków wątków –Ograniczona ilość wątków w bloku –Pozwala wywołać większą liczbę wątków za pomocą jednego wywołania –Bloki są identyfikowane za pomocą block ID –Wymaga zmniejszenia kooperacji wątków –Bloki mogą być 1 lub 2-wymiarowymi tablicami

8 CUDA – model programowania

9 CUDA – model pamięci

10 Shared Memory –Wbudowana w chip Znacznie szybsza niż pamięć lokalna i globalna Tak szybka jak rejestry (jeśli nie ma konfliktów) Dzielna na równej wielkości banki –Kolejne 32-bitowe słowa są przypisane do kolejnych banków, –Każdy bank ma przepustowość (bandwidth) 32 bity na 1 cykl zegara

11 CUDA – model pamięci Shared Memory

12 CUDA API Rozszerzenie języka C –Kwalifikatory typu funkcji specyfikujące wykonanie na procesorze (host) lub na urządzeniu GPU –Kwalifikatory typu zmiennej specyfikujące rodzaj pamięci w GPU –Nowe składnia <<< mówiąca jak wykonać program na urządzeniu –Cztery wbudowane zmienne pamiętające rozmiary grida i bloku oraz numery bloku i wątku

13 CUDA API Kwalifikatory typu funkcji __device__ Wykonywane na GPU Wywoływane tylko z GPU __global__ Wykonywane na GPU Wywoływane tylko z procesora głównego (hosta) __host__ Wykonywane na hostcie, Wywoływane tylko z procesora głównego (hosta)

14 CUDA API Kwalifikatory typu zmiennych __device__ Umieszone w pamięci globalnej Widoczne przez cały czas działania programu Dostępne dla wszystkich wątków w gridzie oraz z hosta (poprzez runtime library) __constant__ (ewentulanie razem z __device__) Umieszczone w pamięci stałej (constant memory space), Widoczne przez cały czas działania programu Dostępne dla wszystkich wątków w gridzie oraz z hosta (poprzez runtime library) __shared__ (ewentulanie razem z __device__) Umieszczone w pamięci współdzielonej (shared memory) bloku danego wątku Widoczne tak długo jak istnieje blok Dostępne tylko dla wszystkich wątków w bloku

15 CUDA API Konfiguracja wykonania –Musi być sprecyzowana dla kazdego wywołania funkcji typu __global__ –Definiuje rozmiary grida i bloków –Umieszczana pomiędzy nazwą funkcji a listą argumentów: funkcja: __global__ void Func(float* parameter); musi być wywołana tak: Func >>(parameter);

16 CUDA API Konfiguracja wykonania gdzie Dg, Db, Ns są: –Dg jest typu dim3 wymiar i rozmiar grida Dg.x * Dg.y = ilość uruchamianych bloków; –Db jest typu dim3 wymiar i rozmiar bloków Db.x * Db.y * Db.z = ilość wątków na blok; –Ns jest typu size_t ilość bajtów w pamięci współdzielonej (shared memory) która jest dynamiczne alokowana dodatkowo do pamięci alokowanej statycznie Ns jest opcjonalne; domyślnie 0.

17 CUDA API Wbdowane zmienne –gridDim typu dim3 wymiary grida. –blockIdx typu uint3 number bloku w gridzie –blockDim typu dim3 wymiary bloku –threadIdx is of type uint3 numer wątku w bloku

18 Przykład – iloczyn skalarny Policzyć iloczyn skalarny –32 par wektorów –Kożdy po 4096 elementów Efektywna organizacja obliczeń: –grid składający się z 32 bloków –z 256 wątkami na blok Otrzymamy 4096/265 = 16 segmentów na wektor

19 Dane będą trzymane w GPU jako dwie tablice; wynik umieszczony zostanie w tablicy Każdy iloczyn par wektórw An, Bn będzie obliczany w segmentach, dodawanych do wyniku Vector A0Vector A1Vector AN-1 … Vector B0Vector B1Vector BN-1 … Results 0 to N-1 Vector A0 Vector B0 Results 0Results 1 Partial results 0 to S-1 segment 0segment 1segment S-1… Przykład – iloczyn skalarny

20 Program dla hosta int main(int argc, char *argv[]){ CUT_CHECK_DEVICE(); … h_A = (float *)malloc(DATA_SZ); … cudaMalloc((void **)&d_A, DATA_SZ); … cudaMemcpy(d_A, h_A, DATA_SZ, cudaMemcpyHostToDevice); … ProdGPU >>(d_C, d_A, d_B); … cudaMemcpy(h_C_GPU, d_C, RESULT_SZ, cudaMemcpyDeviceToHost); … CUDA_SAFE_CALL( cudaFree(d_A) ); free(h_A); … CUT_EXIT(argc, argv); } Przykład – iloczyn skalarny

21 Funkcja dla GPU (Kernel Function) Parametry: –d_C: wskaźnik do wyniku (tj. tablicy) –d_A, d_B wskaźniki do danych (tablic) Tablice lokalne: –t[]: wynkki8 pojedynczego wątku –r[]: używane do dodawania wyników segmentów I: numer (Id) wątku w bloku __global__ void ProdGPU(float *d_C, float *d_A, float *d_B){ __shared__ float t[THREAD_N]; __shared__ float r[SLICE_N]; const int I = threadIdx.x; for(int vec_n=blockIdx.x; vec_n 0; stride /= 2){ if(I < stride) t[I] += t[stride + I]; __syncthreads(); } if(I == 0) r[slice] = t[0]; } for(int stride = SLICE_N / 2; stride > 0; stride /= 2){ if(I < stride) r[I] += r[stride + I]; __syncthreads(); } if(I == 0) d_C[vec_n] = r[0]; } Przykład – iloczyn skalarny

22 Funkcja dla GPU Uruchamiane dla każdej pary wektorów wejściowych Zostanie uruchomione tylko raz, ponieważ: Grid dimension == number of vectors vector number = block Id __global__ void ProdGPU(float *d_C, float *d_A, float *d_B){ __shared__ float t[THREAD_N]; __shared__ float r[SLICE_N]; const int I = threadIdx.x; for(int vec_n=blockIdx.x; vec_n 0; stride /= 2){ if(I < stride) t[I] += t[stride + I]; __syncthreads(); } if(I == 0) r[slice] = t[0]; } for(int stride = SLICE_N / 2; stride > 0; stride /= 2){ if(I < stride) r[I] += r[stride + I]; __syncthreads(); } if(I == 0) d_C[vec_n] = r[0]; } Przykład – iloczyn skalarny

23 Funkcja dla GPU Uruchamiane dla każdego segmentu wektorów wejściowych Każdy wątek wylicza jeden iloczyn i zapamiętuje go __global__ void ProdGPU(float *d_C, float *d_A, float *d_B){ __shared__ float t[THREAD_N]; __shared__ float r[SLICE_N]; const int I = threadIdx.x; for(int vec_n=blockIdx.x; vec_n 0; stride /= 2){ if(I < stride) t[I] += t[stride + I]; __syncthreads(); } if(I == 0) r[slice] = t[0]; } for(int stride = SLICE_N / 2; stride > 0; stride /= 2){ if(I < stride) r[I] += r[stride + I]; __syncthreads(); } if(I == 0) d_C[vec_n] = r[0]; } Przykład – iloczyn skalarny

24 Funkcja dla GPU Wyliczenie wyniku częściowego dla segmentu Zapamiętanie wyniku częsciowego __global__ void ProdGPU(float *d_C, float *d_A, float *d_B){ __shared__ float t[THREAD_N]; __shared__ float r[SLICE_N]; const int I = threadIdx.x; for(int vec_n=blockIdx.x; vec_n 0; stride /= 2){ if(I < stride) t[I] += t[stride + I]; __syncthreads(); } if(I == 0) r[slice] = t[0]; } for(int stride = SLICE_N / 2; stride > 0; stride /= 2){ if(I < stride) r[I] += r[stride + I]; __syncthreads(); } if(I == 0) d_C[vec_n] = r[0]; } t[0] += t[128] t[1] += t[129] t[0] += t[64] t[2] += t[130] t[1] += t[65] … t[0] += t[1] … … t[64]+= t[127] t[127]+= t[255] Przykład – iloczyn skalarny

25 Funkcja dla GPU Dodanie wyników dla wszystkich segmentów Zapisanie wyniku w pamięci __global__ void ProdGPU(float *d_C, float *d_A, float *d_B){ __shared__ float t[THREAD_N]; __shared__ float r[SLICE_N]; const int I = threadIdx.x; for(int vec_n=blockIdx.x; vec_n 0; stride /= 2){ if(I < stride) t[I] += t[stride + I]; __syncthreads(); } if(I == 0) r[slice] = t[0]; } for(int stride = SLICE_N / 2; stride > 0; stride /= 2){ if(I < stride) r[I] += r[stride + I]; __syncthreads(); } if(I == 0) d_C[vec_n] = r[0]; } Przykład – iloczyn skalarny


Pobierz ppt "CUDA (Compute Unified Device Architecture) W. Bożejko GPGPU - General-purpose computing on graphics processing units."

Podobne prezentacje


Reklamy Google