Prezentacja z ćwiczeń - Programowanie Współbieżne 2016/2017

Transkrypt

Prezentacja z ćwiczeń - Programowanie Współbieżne 2016/2017
Programowanie Współbieżne
Agnieszka Łupińska
5 października 2016
Hello World!
helloWorld.cu:
#include <cstdio>
__global__
void helloWorld(){
int thid = (blockIdx.x * blockDim.x) + threadIdx.x;
printf("Hello World! thread #%d\n", thid);
}
int main(){
int NUM_BLOCKS = 4;
int NUM_THREADS = 5;
helloWorld<<<NUM_BLOCKS, NUM_THREADS>>>();
cudaDeviceSynchronize();
return 0;
}
aga@ubuntu$ nvcc -arch=sm 20 helloWorld.cu
Hello World! - Output
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
Hello
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
World!
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
thread
#5
#6
#7
#8
#9
#0
#1
#2
#3
#4
#15
#16
#17
#18
#19
#10
#11
#12
#13
#14
Model programowania CUDA
Host
- działa na CPU
- wątek główny programu
- obsługuje Device
Device
- działa na GPU
- jest koprocesorem Hosta
- fizycznie oddzielony od Hosta
- obsługuje CUDA wątki
- wykonuje funkcje zwane
kernelami
Host i Device mają
odzielną, niezależną pamięć.
Deklaracja CUDA funkcji
device int DeviceFunc() - wykonywana na Device, wywoływana z
Device (przez CUDA wątki)
global void KernelFunc() - wykonywana na Device, wywoływana z
Hosta, zawsze jest ”void”
host int HostFunc() - wykonywana na Hoscie, wywoływana z Hosta,
można pominąć ” host ”, chyba, że jest używana razem z ” device ”
Zmienne wbudowane
gridDim.x
gridDim.y
gridDim.z
blockDim.x
blockDim.y
blockDim.z
blockIdx.x
blockIdx.y
blockIdx.z
threadIdx.x
threadIdx.y
threadIdx.z
int thid = (blockIdx.x * blockDim.x) + threadIdx.x;
Zarządzanie pamięcią
Host - tak jak w C/C++
Device:
local memory - każdy wątek ma swoją własną prywatną pamięć,
niewidoczną dla pozostałych wątków
shared memory - pamięć współdzielona przez wszystkie wątki w bloku,
nietrwała - czas życia taki jak bloku
global memory - pamięć globalna, współdzielona przez wszystkie wątki
działające w programie, trwała.
cache - pamięć podręczna, dwa poziomy: L1 - jeden dla każdego
multiprocesora, L2 - współdzielony między wszystkie multiprocesory.
Keszują dostęp do pamięci lokalnej i globalnej.
Cache i shared memory używają pamięci ”on-chip”, więc dostęp tam jest
bardzo szybki.
Local memory jest pamięcią ”off-chip” i dostęp kosztuje tyle samo co
dostęp do pamięci globalnej.
Synchronizacja
Wątki wewnątrz bloku można synchronizować za pomocą funkcji:
syncthreads()
Nie powinno się synchronizować wątków w obrębie gridu, ale można to
zrobić za pomocą zmiennych globalnych.
Poza tym kod, który wymaga synchronizacji wszystkich wątków w gridzie
można podzielić w miejscu synchronizacji na dwa osobne kernele i
wykonać najpierw jeden, potem drugi.
Compute Capability
Compute Capability karty graficznej jest zadany przez dwie liczby:
znaczący i mniej znaczący numer wersji.
Urządzenia o tym samym znaczącym numerze mają tą samą architekturę
rdzeni. Na przykład, cc dla kart z architekturą Fermi to 2.x (znaczący
wynosi 2). Karty z architekturą Maxwell mają cc 5.x.
cc sprzętu na Satori: 2.x.
cc sprzętu na Miracle: 5.x.
Jak sprawdzić architekturę sprzętu?
Najlepiej skorzystać z SDK Nvidii i uruchomić deviceQuery:
./NVIDIA GPU Computing SDK/C/bin/linux/release/deviceQuery
Przykłady z SDK
/usr/local/cuda/samples/
deviceQuery
Device 0: ”GeForce GTX 560 Ti”
CUDA Driver Version / Runtime Version
CUDA Capability Major/Minor version number
Total amount of global memory:
( 8) Multiprocessors x ( 48) CUDA Cores/MP:
GPU Clock rate:
Memory Clock rate:
Memory Bus Width:
L2 Cache Size:
Max Texture Dimension Size (x,y,z)
Max Layered Texture Size (dim) x layers
Total amount of constant memory:
Total amount of shared memory per block:
Total number of registers available per block:
Warp size:
Maximum number of threads per multiprocessor:
Maximum number of threads per block:
Maximum sizes of each dimension of a block:
Maximum sizes of each dimension of a grid:
5.0 / 4.2
2.1
1023 MBytes (1072889856
384 CUDA Cores
1800 MHz (1.80 GHz)
2004 Mhz
256-bit
524288 bytes
1D=(65536), 2D=(65536,6
1D=(16384) x 2048, 2D=(
65536 bytes
49152 bytes
32768
32
1536
1024
1024 x 1024 x 64
65535 x 65535 x 65535
Maximum memory pitch:
Texture alignment:
Concurrent copy and execution:
Run time limit on kernels:
Integrated GPU sharing Host Memory:
Support host page-locked memory mapping:
Concurrent kernel execution:
Alignment requirement for Surfaces:
2147483647 bytes
512 bytes
Yes with 1 copy engine(s)
Yes
No
Yes
Yes
Yes
Specyfikacja według Compute Capability
Specyfikacja według Compute Capability
Interfejsy programowania w CUDA
CUDA Driver API - niskopoziomowe
CUDA Runtime - zaimplementowane powyżej CUDA Driver API