Wykład 9 - Politechnika Warszawska

Transkrypt

Wykład 9 - Politechnika Warszawska
Maciej Sypniewski
lato 2014, Politechnika Warszawska,
Wydział Elektroniki i Technik Informacyjnych
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL,
 C++ AMP
 Wybrane algorytmy obliczeniowe 2D
 Transpozycja macierzy
 Iloczyn macierzy
 Optymalizacja obliczeń GPU
 Elementy architektury
 Narzędzia optymalizacji
lato 2014
SMOR
2
Maciej Sypniewski
Politechnika Warszawska
[email protected]
OpenCL
źródło – Kronos OpenCL specification
lato 2014
SMOR
3
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – architektura




Model platformy
Model pamięci
Model wykonania
Model programowy
źródło – Kronos OpenCL specification
lato 2014
SMOR
4
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – model platformy
źródło – Kronos OpenCL specification
lato 2014
SMOR
5
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – model platformy – przykład
 ICD – installable client driver
Dwie platformy
lato 2014
SMOR
6
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – model platformy – przykład cd.
Jedno urządzenie dla każdej platformy
lato 2014
SMOR
7
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – model pamięci




Globalna
Stała
Lokalna
Prywatna
źródło – Kronos OpenCL specification
lato 2014
SMOR
8
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – model wykonania
 Kontekst – kontener urządzeń, obiektów pamięci i kolejek
komend – ma szczególne znaczenie dla skomplikowanych
scenariuszy zarządzania zasobami (wiele
wielordzeniowych CPU, GPU itd. )
 Kolejka komend – dla kolejki wykonujemy program
„kernel” na urządzeniu
▪ Komendy kernela
▪ Komendy zarządzania pamięcią
▪ Komendy synchronizacji
lato 2014
SMOR
9
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – model wykonania
 Kontekst + kolejki
kontekst
dev1
dev2
q1
q2
……….
devn
qn
Komunikacja w ramach kontekstu odbywa się poprzez
współdzielone bufory, komunikacja międzykontekstowa nie jest wspierana
lato 2014
SMOR
10
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – model wykonania
GPU’s
CPU’s
kontekst
Programy
kompilacja
lato 2014
Kernele
Obiekty pamięci
Ustawianie danych i argumentów
SMOR
Kolejki
wykonanie
11
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – model wykonania - przykład
cl.hpp – opakowanie C++ dla cl.h
lato 2014
SMOR
12
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – cl.hpp – podstawowe struktury
cl::Platform
cl::Device
cl::Context
cl::Program
cl::Program::Sources
cl::Kernel
cl::CommandQueue
cl::Buffer
cl::NDRange
lato 2014
SMOR
cl::Event
cl::Error
13
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – cl.hpp – podstawowe metody
Konstruktory struktur
get, get”WHAT”, getInfo<„WHAT”>()
program.build({ dev });
queue.enqueue{Read,Write}Buffer
kernel.setArg (nrArg,Arg)
queue.enqueueNDRangeKernel
lato 2014
SMOR
14
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – cl.hpp – obsługa błędów
catch ( cl::Error &err ) {
std::cerr << „CL ERROR: "
<< err.what()
<< "(" << err.err() << ")"
<< std::endl;
}
lato 2014
SMOR
15
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – kernel
 CUDA saxpy
__global__ void saxpy (const int n, const float *const xt, const float a, float *const yt) {
for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < n; i += blockDim.x * gridDim.x)
yt[i] += a*xt[i]; }
 OpenCL saxpy
__kernel void saxpy(const int n,__global const float *const xt, const float a,__global float *const yt
{
const int gid=get_global_id(0);
const int gis=get_global_size(0);
for (int i = gid; i < n; i += gis)
yt[i] += a*xt[i]; }
 C++AMP saxpy
concurrency::parallel_for_each( concurrency::extent<1>(N), [&d_vx, &d_vy, a]
(concurrency::index<1> idx) restrict(amp) {
d_vy[idx] += a*d_vx[idx];}
lato 2014
SMOR
16
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – CUDA kernel indeksowanie
CUDA
OPENCL
blockIdx.x
blockDim.x
threadIdx.x
blockIdx.x * blockDim.x + threadIdx.x
gridDim.x
gridDim.x * blockDim.x
get_group_id(0)
get_local_size(0)
get_local_id(0)
get_global_id(0)
get_num_groups(0)
get_global_size(0)
lato 2014
SMOR
17
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – transpozycja macierzy
macierze MxN umieszczone liniowo w std::vector
Kernel 2D
Rozwiązanie 1 – pamięć globalna
Rozwiązanie 2 – pamięć dzielona
Rozwiązanie 3 – pamięć dzielona z eliminacja
konfliktów pamięci dzielonej
lato 2014
SMOR
18
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – transpozycja macierzy
macierze MxN umieszczone liniowo w std::vector
Kernel 2D
Rozwiązanie 1 – pamięć globalna
Rozwiązanie 2 – pamięć dzielona
Rozwiązanie 3 – pamięć dzielona z eliminacja
konfliktów pamięci dzielonej
lato 2014
SMOR
19
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – Windows, Nvidia, MS VC++
Konfiguracja OpenCL W7 CUDA 5.5/6.0 x64 Visual C++
1. C++ -> General -> Additional Include Directories $(CUDA_INC_PATH)
przykladowy wynik
/I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include"
2. Linker -> General -> Additional Library Directories $(CUDA_LIB_PATH)
3. Linker -> Input -> Additional Dependencies OpenCL.lib
lato 2014
SMOR
20
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL/CUDA – transpozycja macierzy
 Rozwiązanie 1 – pamięć globalna
Cuda
Przykladowo M=N=8096, TILE_DIM=32, BLOCK 32x8=256
__global__ void transpose1(const int m, const int n, const float *const xt, const float a, float *const yt) {
const int ix = blockIdx.x * TILE_DIM + threadIdx.x;
const int iy = blockIdx.y * TILE_DIM + threadIdx.y;
for (int j = 0; j < TILE_DIM; j += blockDim.y) {
yt[ix*n + (iy+j)] = xt[ix + (iy+j)*m]; } }
dim3 grids(M/TILE_DIM,N/TILE_DIM,1);
dim3 blocks(TILE_DIM,8,1);
transpose1<<<grids, blocks>>>(M, N, dev_x, a, dev_y);
lato 2014
SMOR
21
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL/CUDA – transpozycja macierzy
 Rozwiązanie 1 – pamięć globalna
OpenCL
Przykladowo M=N=8096, TILE_DIM=32, BLOCK 32x8=256
__kernel void transpose1(const int m, const int n, const int TILE_DIM,
__global const float *const xt, __global float *const yt) {
const int ix = get_group_id(0) * TILE_DIM + get_local_id(0);
const int iy = get_group_id(1) * TILE_DIM + get_local_id(1);
for (int j = 0; j < TILE_DIM; j += get_local_size(1)) {
yt[ix*n + (iy + j)] = xt[ix + (iy + j)*m]; } }
cl::NDRange global(M , N/4 , 1);
cl::NDRange local(TILE_DIM, TILE_DIM/4);
queue.enqueueNDRangeKernel(kernel, cl::NullRange, global, local, NULL, &event);
lato 2014
SMOR
22
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL/CUDA – transpozycja macierzy
 Rozwiązanie 1 – pamięć globalna
Różnica w indeksowaniu – te sam schemat
obliczeniowy 2D (MxN), BLOCK(32x8)
OpenCL
cl::NDRange global(M , N/4 , 1);
cl::NDRange local(TILE_DIM, TILE_DIM/4);
CUDA
dim3 grids(M/TILE_DIM,N/TILE_DIM,1);
dim3 blocks(TILE_DIM, TILE_DIM/4,1);
lato 2014
SMOR
23
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL/CUDA – transpozycja macierzy
 Rozwiązanie 2 – pamięć dzielona aby uniknąć
niełączonego zapisu lub odczytu
lato 2014
SMOR
24
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL/CUDA – transpozycja macierzy
 Rozwiązanie 2 – pamięć dzielona
OpenCL
__kernel void transpose2(const int m, const int n, const int TILE_DIM,
__global const float *const xt, __global float *const yt) {
__local float tile[32][32];
int ix = get_group_id(0) * TILE_DIM + get_local_id(0);
int iy = get_group_id(1) * TILE_DIM + get_local_id(1);
for (int j = 0; j < TILE_DIM; j += get_local_size(1))
tile[get_local_id(1) + j][get_local_id(0)] = xt[(iy + j)*m + ix];
barrier(CLK_LOCAL_MEM_FENCE);
ix = get_group_id(1) * TILE_DIM + get_local_id(0); // transpose block offset
iy = get_group_id(0) * TILE_DIM + get_local_id(1);
for (int j = 0; j < TILE_DIM; j += get_local_size(1))
yt[(iy + j)*m + ix] = tile[get_local_id(0)][get_local_id(1) + j]; }
lato 2014
SMOR
25
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL/CUDA – transpozycja macierzy
 Rozwiązanie 3 – eliminacja konfliktów dostępu do
pamięci dzielonej
OpenCL
__kernel void transpose3(const int m, const int n, const int TILE_DIM,
__global const float *const xt, __global float *const yt) {
__local float tile[32][33];
int ix = get_group_id(0) * TILE_DIM + get_local_id(0);
int iy = get_group_id(1) * TILE_DIM + get_local_id(1);
for (int j = 0; j < TILE_DIM; j += get_local_size(1))
tile[get_local_id(1) + j][get_local_id(0)] = xt[(iy + j)*m + ix];
barrier(CLK_LOCAL_MEM_FENCE);
ix = get_group_id(1) * TILE_DIM + get_local_id(0); // transpose block offset
iy = get_group_id(0) * TILE_DIM + get_local_id(1);
for (int j = 0; j < TILE_DIM; j += get_local_size(1))
yt[(iy + j)*m + ix] = tile[get_local_id(0)][get_local_id(1) + j]; }
lato 2014
SMOR
26
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL/CUDA – transpozycja macierzy
 Rozwiązanie 3 – eliminacja konfliktów dostępu do
pamięci dzielonej
Przykład - 4 banki pamięci pamięć dzielona 4x4/5
Konflikt pamięci dla
odczytu kolumn
Brak konfliktu pamięci dla
odczytu kolumn
0/0
1/1
2/2
3/3
0/0
1/1
2/2
3/3
*/0
4/0
5/1
6/2
7/3
4/1
5/2
6/3
7/0
*/1
8/0
9/1
10/2
11/3
8/2
9/3
10/0
11/1
*/2
12/0
13/1 14/2
15/3
12/3
13/0
14/1
15/2
*/3
lato 2014
SMOR
27
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL/CUDA – transpozycja macierzy
 Wyniki CUDA
1
OpenCL
2
3
lato 2014
SMOR
28
Maciej Sypniewski
Politechnika Warszawska
[email protected]
 OpenCL – kompilacja kernela - clcc
lato 2014
SMOR
29

Podobne dokumenty