[JUG] JCuda

87
JCuda Czy Java i CUDA mogą się polubić? Konrad Szałkowski

Transcript of [JUG] JCuda

JCudaCzy Java i CUDA mogą się polubić?

Konrad Szałkowski

• GPU

• Dlaczego warto używać GPU

• Budowa GPU

• CUDA

• JCuda

• Przykładowa implementacja

Agenda

GPU

Co to jest?

Graphical

GPU

Graphical

Processing

GPU

Graphical

Processing

Unit

GPU

GPU

Graphical

Processing

Unit

Procesor graficzny.

Krótka historia GPU

• Terminale znakowe

Krótka historia GPU

• Terminale znakowe

• Renderowanie obrazu składającego się z pixeli

Krótka historia GPU

• Terminale znakowe

• Renderowanie obrazu składającego się z pixeli

• Akceleracja 2D, rysowanie kształtów, Z-bufory, sprite'y.

Krótka historia GPU

• Wejście w świat 3D - obliczenia na wektorach macierzach liczb zmiennoprzecinkowych

Krótka historia GPU

• Wejście w świat 3D - obliczenia na wektorach macierzach liczb zmiennoprzecinkowych

• Pojawienie się pierwszego GPU - NV10. Karta graficzna przejęła obliczenia T&L.

Krótka historia GPU

• Wejście w świat 3D - obliczenia na wektorach macierzach liczb zmiennoprzecinkowych

• Pojawienie się pierwszego GPU - NV10. Karta graficzna przejęła obliczenia T&L.

• Pojawienie się shaderów. Krótkich programów operujących na danych wewnątrz karty graficznej. (NV30)

Krótka historia GPU

• Wejście w świat 3D - obliczenia na wektorach macierzach liczb zmiennoprzecinkowych

• Pojawienie się pierwszego GPU - NV10. Karta graficzna przejęła obliczenia T&L.

• Pojawienie się shaderów. Krótkich programów operujących na danych wewnątrz karty graficznej. (NV30)

• Pojawienie się CUDA - dowolne programowanie na GPU (G80).

Dlaczego warto używać GPU

Architektura procesora graficznego jest zoptymalizowana pod kątem obliczeń zmiennoprzecinkowych.

Dlaczego warto używać GPU

Architektura procesora graficznego jest zoptymalizowana pod kątem obliczeń zmiennoprzecinkowych.

Wydajność tego typu obliczeń jest aż do 5 razy większa niż CPU, w przypadku obliczeń podwójnej skali precyzji.

Dlaczego warto używać GPU

Architektura procesora graficznego jest zoptymalizowana pod kątem obliczeń zmiennoprzecinkowych.

Wydajność tego typu obliczeń jest aż do 5 razy większa niż CPU, w przypadku obliczeń podwójnej skali precyzji.

I aż do 10 razy w przypadku pojedynczej skali precyzji.

Dlaczego warto używać GPU

Prędkość pamięci

DDR3-19200 ~ 19,2 GB/s

Dlaczego warto używać GPU

Prędkość pamięci

DDR3-19200 ~ 19,2 GB/s

GDDR5 ~ 224 GB/s

Dlaczego warto używać GPU

Prędkość pamięci

DDR3-19200 ~ 19,2 GB/s

GDDR5 ~ 224 GB/s

Wydajność mocy

Intel i7 Core 980XE: 220 GFLOPS / 130W = 1,7 GFLOPS/W

Dlaczego warto używać GPU

Prędkość pamięci

DDR3-19200 ~ 19,2 GB/s

GDDR5 ~ 224 GB/s

Wydajność mocy

Intel i7 Core 980XE: 220 GFLOPS / 130W = 1,7 GFLOPS/W

NVIDIA GTX 580: 1580 GFLOPS / 244 W = 6,5 GFLOPS/W

Dlaczego warto używać GPU

Źródło:http://www.hardwareinsight.com/

Dlaczego warto używać GPU

CPU GPUCore 2 Duo Quad Q6600 2,4GHz

4GB DDR2-800NVidia GeForce GTX470

1296 MB GDDR5

Dlaczego warto używać GPU

CPU GPUCore 2 Duo Quad Q6600 2,4GHz

4GB DDR2-800NVidia GeForce GTX470

1296 MB GDDR5

Raytracer 4-8 FPS 80 FPS

Dlaczego warto używać GPU

CPU GPUCore 2 Duo Quad Q6600 2,4GHz

4GB DDR2-800NVidia GeForce GTX470

1296 MB GDDR5

Raytracer 4-8 FPS 80 FPS

SGEMM 1000x1000 5924 ms 528 ms

Dlaczego warto używać GPU

CPU GPUCore 2 Duo Quad Q6600 2,4GHz

4GB DDR2-800NVidia GeForce GTX470

1296 MB GDDR5

Raytracer 4-8 FPS 80 FPS

SGEMM 5924 ms 528 ms

Sort 10^6 43 ms 547 ms

Sort 10^8 1000 ms 800 ms

Do czego użyto GPU

• Symulacje objętościowe cieczy i gazów

Do czego użyto GPU

• Symulacje objętościowe cieczy i gazów

• Optymalizacja wydajności aerodynamicznej pojazdów

Do czego użyto GPU

• Symulacje objętościowe cieczy i gazów

• Optymalizacja wydajności aerodynamicznej pojazdów

• Analiza pogody

Do czego użyto GPU

• Symulacje objętościowe cieczy i gazów

• Optymalizacja wydajności aerodynamicznej pojazdów

• Analiza pogody

• Wizualizacje

Do czego użyto GPU

• Symulacje objętościowe cieczy i gazów

• Optymalizacja wydajności aerodynamicznej pojazdów

• Analiza pogody

• Wizualizacje

• Symulacja detonacji atomowej bomby plecakowej

Do czego użyto GPU

• Symulacje objętościowe cieczy i gazów

• Optymalizacja wydajności aerodynamicznej pojazdów

• Analiza pogody

• Wizualizacje

• Symulacja detonacji atomowej bomby plecakowej

• Problem n ciał

• … i wiele innych.

Gdzie GPU, będzie skuteczne

• Algorytmy przetwarzania równoległego

Gdzie GPU, będzie skuteczne

• Algorytmy przetwarzania równoległego

• Mało komunikacji między wątkowej

Gdzie GPU, będzie skuteczne

• Algorytmy przetwarzania równoległego

• Mało komunikacji między wątkowej

• Masowe obliczenia zmienno przecinkowe SP

Zapraszam

http://www.nvidia.pl/object/cuda_apps_flash_pl.html

GPU

Piękne liczby, powodują dreszcze, ale gdzie jest haczyk?

GPU

Piękne liczby, powodują dreszcze, ale gdzie jest haczyk?

• Wątki.

GPU

Piękne liczby, powodują dreszcze, ale gdzie jest haczyk?

• Wątki. Dużo wątków.

GPU

Piękne liczby, powodują dreszcze, ale gdzie jest haczyk?

• Wątki. Dużo wątków. Nawet 2^9 * 2^32 wątków.

CPU

DRAM

CPU

DRAM

Cache

CPU

CONTROL

DRAM

Cache

CPU

CONTROL

DRAM

Cache

ALU

ALU

ALU

ALU

ALU

ALU

GPU

DRAM

GPU

DRAM

GPU

DRAM

GPU

DRAM

Cache

CONTROL

Cache

CONTROL

Cache

CONTROL

Cache

CONTROL

GPU

DRAM

Cache

CONTROL ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU

ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU

Cache

CONTROL ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU

ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU

Cache

CONTROL ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU

ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU

Cache

CONTROL ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU

ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU ALU

GPU

Piękne liczby, powodują dreszcze, ale gdzie jest haczyk?

• Wątki. Dużo wątków. Ok. 2^24 * 2^32 wątków.

• Pamięć. Zarządzanie. Transfer. Optymalne wykorzystanie.

GPU

DRAM

GPU

DRAM

Pamięć tekstur Pamięć stałych

GPU

DRAM

Cache stałychCache tekstur

Pamięć tekstur Pamięć stałych

GPU

DRAM

Pamięćinstrukcji

Cache stałychCache tekstur

Procesor Procesor Procesor Procesor

Pamięć tekstur Pamięć stałych

GPU

DRAM

Pamięćinstrukcji

Cache stałychCache tekstur

Procesor Procesor Procesor Procesor

Rejestry Rejestry Rejestry RejestryRejestry

Pamięć tekstur Pamięć stałych

GPU

DRAM

Pamięćinstrukcji

Cache stałychCache tekstur

Procesor Procesor Procesor Procesor

Rejestry Rejestry Rejestry Rejestry

Pamięć współdzielona

Rejestry

Pamięć tekstur Pamięć stałych

CUDA

Compute

Unified

Device

Architecture

CUDA

Cytując stronę NVidii:

CUDA jest opracowaną przez firmę NVIDIA, równoległą architekturą obliczeniową, która zapewnia radykalny wzrost wydajności obliczeń dzięki wykorzystaniu mocy układów GPU (graphics processing unit – jednostka przetwarzania graficznego).

CUDA

Jest to również synonim rozszerzenia standardowego języka C o składnię i biblioteki potrzebne do wygodnego przeprowadzania obliczeń na kartach graficznych.

JCuda

Zestaw bibliotek opakowywujących natywne biblioteki CUDY z wykorzystaniem interfejsu JNI.

Niestety, zależne od systemu operacyjnego/architektury procesora.

JCuda

CUDA DRIVER API

CUDA RUNTIME API

libJCudaDriver.so

libJCudaRuntime.so

JCuda

CUDA DRIVER API

CUDA RUNTIME API

libJCudaDriver.so

libJCudaRuntime.so

JCuda

CUDA DRIVER API

CUDA RUNTIME API

JCudaRuntime.jar JCudaDriver.jar

Jęk zawodu na sali

Niestety, zależne od systemu operacyjnego/architektury procesora.

Jęk zawodu na sali

Niestety, zależne od systemu operacyjnego/architektury procesora.

Należy jednak pamiętać, że API CUDY plus biblioteki to ok. 2500 różnych funkcji zmieniających się z każdym wydaniem.

Co to jest kernel?

Funkcja ładowana do pamięci instrukcji multiprocesora.

Co to jest kernel?

Funkcja ładowana do pamięci instrukcji multiprocesora.

Przykład JCudaVectorAdd.cu:

extern "C"__global__ void add(int n, float *a, float *b, float *sum){ int i = blockIdx.x * blockDim.x + threadIdx.x; if (i<n) { sum[i] = a[i] + b[i]; }}

Organizacja przetwarzania

struct dim3 {

int x, y, z;

}

dim3 gridDim, blockDim;

dim3 blockIdx, threadIdx;

Organizacja przetwarzania

Blok

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

WątekWątek

Wątek Wątek

Organizacja przetwarzania

Każdy blok może zostać przydzielony do dowolnego multiprocesora.

To w jaki sposób zostanie on przydzielony zależy od jego wymagań co do pamięci współdzielonej oraz rejestrów.

Organizacja przetwarzania

Grid

BlokBlok

Blok Blok

BlokBlok

Blok Blok

BlokBlok

Blok Blok

Ograniczenia przetwarzania

Ograniczenia:• Maksymalna ilość wątków w bloku: 512 (256).• Maksymalny wymiar grida 2^16 x 2^16 x 1.• Do niedawna brak rekurencji.• Do niedawna brak printf.

Ograniczenia przetwarzania

Wątki w bloku formowane są w tzw. warpy po 32 wątki każdy i następnie są ładowane do multiprocesora.

W ramach jednego warpa równolegle przez wątki może być wykonywana tylko jedna instrukcja.

Jeśli nastąpi rozgałęzienie (if) zasada ta nadal obowiązuje i instrukcje gałęzi się przeplatają.

Typowy przebieg przetwarzania

1. Przygotowanie środowiska i kerneli

2. Alokacja pamięci na urządzeniu.

3. Ładowanie danych (wąskie gardło)

4. Wykonaniu obliczeń

a. wykonywanie obliczeń GPU

b. wykonywanie obliczeń CPU

5. Synchronizacja z kartą

6. Pobranie wyników obliczeń (wąskie gardło)

7. Dealokacja pamięci

Typowy przebieg przetwarzania

1. Przygotowanie środowiska i kerneli

import static jcuda.driver.JCudaDriver.*;// Enable exceptions and omit all subsequent error checkssetExceptionsEnabled(true);

// Initialize the driver and // create a context for the first device.cuInit(0);CUdevice device = new CUdevice();cuDeviceGet(device, 0);CUcontext context = new CUcontext();cuCtxCreate(context, 0, device);

Typowy przebieg przetwarzania

1. Przygotowanie środowiska i kerneli

// Load the ptx file.// Create the PTX file by calling the NVCCString ptxFileName =

preparePtxFile("JCudaVectorAddKernel.cu");CUmodule module = new CUmodule();cuModuleLoad(module, ptxFileName);

// Obtain a function pointer to the "add" function.CUfunction function = new CUfunction();cuModuleGetFunction(function, module, "add");

Typowy przebieg przetwarzania

2. Alokacja pamięci i ładowanie danych// Allocate the device input data, and copy the// host input data to the deviceCUdeviceptr deviceInputA = new CUdeviceptr();cuMemAlloc(deviceInputA, numElements * Sizeof.FLOAT);cuMemcpyHtoD(deviceInputA, Pointer.to(hostInputA),

numElements * Sizeof.FLOAT);

CUdeviceptr deviceInputB = new CUdeviceptr();cuMemAlloc(deviceInputB, numElements *

Sizeof.FLOAT);cuMemcpyHtoD(deviceInputB,

Pointer.to(hostInputB), numElements * Sizeof.FLOAT);

Typowy przebieg przetwarzania

2. Alokacja pamięci wyjściowej

// Allocate device output memoryCUdeviceptr deviceOutput = new CUdeviceptr();cuMemAlloc(deviceOutput, numElements * Sizeof.FLOAT);

Typowy przebieg przetwarzania

3. Wykonanie obliczeń

// Set up the kernel parameters: A pointer to an array// of pointers which point to the actual values.Pointer kernelParameters = Pointer.to( Pointer.to(new int[]{numElements}), Pointer.to(deviceInputA), Pointer.to(deviceInputB), Pointer.to(deviceOutput));

Typowy przebieg przetwarzania

3. Wykonanie obliczeń// Call the kernel function.int blockSizeX = 256;int gridSizeX = (int)

Math.ceil((double)numElements / blockSizeX);cuLaunchKernel(function, gridSizeX, 1, 1, // Grid dimension blockSizeX, 1, 1, // Block dimension 0, null, // Shared memory size

and stream kernelParameters, null // Kernel- and extra

parameters);cuCtxSynchronize();

Typowy przebieg przetwarzania

4. Pobranie wyników obliczeń

// Allocate host output memory and copy the device output// to the host.float hostOutput[] = new float[numElements];cuMemcpyDtoH(Pointer.to(hostOutput), deviceOutput, numElements * Sizeof.FLOAT);

Typowy przebieg przetwarzania

5. Dealokacja pamięci

// Clean up.cuMemFree(deviceInputA);cuMemFree(deviceInputB);cuMemFree(deviceOutput);

JCuda – zmapowane biblioteki

Biblioteki:• Core – mapowanie podstawowych funkcji zarówno

Cuda Driver API jak i Cuda Runtime API

• JcuFFT – biblioteka FFT

• JcuBLAS – biblioteka operacji na macierzach

• JcuRAND – biblioteka liczb losowych

• JcuDPP – biblioteka operacji równoległych (scan, suma, redukcja)

• JcuSPARSE – biblioteka operacji na macierzach rzadkich

Maven challenge

Obecnie pracuję nad integracją biblioteki z mavenem.

Niestety biblioteki będą zależne od architektury – co psuje jedną z idei maven'a.

CMake... ?

Pytania

?

Materiały

JCUDAhttp://jcuda.org

CUDAhttp://www.nvidia.com/object/cuda_home_new.html

-> NVIDIA CUDA Programming Guide

Materiały

Repozytorium

svn://smijran.is-a-geek.org/jcuda

login: visitor

pass: access#52832

Godz. 8-24