50
CUDA 7. Vorlesung GPU Programmierung Thorsten Grosch Thorsten Grosch Danke an Hendrik Lensch

7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

CUDA7. Vorlesung GPU ProgrammierungThorsten GroschThorsten GroschDanke an Hendrik Lensch

Page 2: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

P ll l P i i d GPUParallele Programmierung mit der GPU

• Bisher: GPU = OpenGL Pipeline mit Shadernp p• Alles orientiert sich am Rendering• Programme für Eckpunkte und Pixel• Oft muß man um die Ecke denken

J t t Di GPU i t i h ll P ll l h fü b li bi “• Jetzt: Die GPU ist ein schneller Parallelrechner für „beliebige“ Aufgaben

• Verteile die Aufgabe in Form von parallelen Threads an die GPUVerteile die Aufgabe in Form von parallelen Threads an die GPU

• Die Programmierung ist dabei ähnlich zur Programmierung g g g gder CPU

• CUDAO CL

2GPU Programmierung

• OpenCL

Page 3: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

LiLiteratur

• Die Vorlesung ist an folgendem Buch orientiert:g g• J. Sanders, E. Kandrot: CUDA by Example, NVIDIA

• Mehrfach vorhanden in Bibliothek• Beispielprogramme verfügbar• Gut zum Einstieg

F h i P i• Fortgeschrittene Programmierung• D. Kirk: CUDA Programming Guide

• Programmierung mit OpenCL ist ähnlich

3GPU Programmierung

Page 4: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

M i P ll l B hMassiv Parallele Berechnungen

PCIe

CPU (4 cores) GPU (480 cores)

4GPU Programmierung

Page 5: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

W P ll l PWarum Parallele Prozessoren

GPU = günstiger Parallelrechner in jedem handelsüblichen PC200 GFLOPS/Sek 1300 GFLOPS/Sek

5GPU Programmierung

200 GFLOPS/Sek. 1300 GFLOPS/Sek.

Page 6: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

W P ll l PWarum Parallele Prozessoren

Speicherbandbreite 40 GB/Sek. 170 GB/Sek.

6GPU Programmierung

Speicherbandbreite 40 GB/Sek. 170 GB/Sek.

Page 7: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

A d hl GAmdahls Gesetz

• Serieller Teil α des Algorithmus, paralleler Anteil 1-αg , p

• Erwarteter Speedup (Beschleunigung) S bei P Prozessoren• falls α=0 perfekt parallelisierbar Smax = P• falls α=1 S = 1

S 1P

S/)1( αα −+

=

7GPU Programmierung

Page 8: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

CUDA P i d llCUDA Programmiermodell

Page 9: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

G F 8800GeForce 8800

16 highly threaded SM’s, >128 FPU’s, Host 367 GFLOPS, 768 MB DRAM, 86.4 GB/S

Mem BW, 4GB/S BW to CPU

Thread Execution Manager

Input Assembler

Host

Thread Execution Manager

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Texture Texture Texture Texture Texture Texture Texture TextureTexture

Load/store

Global Memory

Load/store Load/store Load/store Load/store Load/store

9GPU Programmierung

Global Memory

Page 10: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

AbküAbkürzungen

SPA (Device)Streaming Processor Array (variable across GeForce 8-series)

SMSt i M lti (8 SP f 8800 15 SP f GTX480)Streaming Multiprocessor (8 SP for 8800, 15 SP for GTX480)Multi-threaded processor coreFundamental processing unit for CUDA thread block

SPStreaming ProcessorScalar ALU for a single CUDA threadScalar ALU for a single CUDA thread

10GPU Programmierung

Page 11: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

S i P AStreaming Processor Array

Host

Thread Execution Manager

Input Assembler

Host

Thread Execution Manager

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

SPATexture Texture Texture Texture Texture Texture Texture TextureTexture

Load/store

Global Memory

Load/store Load/store Load/store Load/store Load/store

11GPU Programmierung

Global Memory

Page 12: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

S i M l iStreaming Multiprocessor

Host

Thread Execution Manager

Input Assembler

Host

Thread Execution Manager

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

SMTexture Texture Texture Texture Texture Texture Texture TextureTexture

Load/store

Global Memory

Load/store Load/store Load/store Load/store Load/store

12GPU Programmierung

Global Memory

Page 13: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

S i PStreaming Processor

Host

Thread Execution Manager

Input Assembler

Host

SP Thread Execution ManagerSP

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Parallel DataCache

Texture Texture Texture Texture Texture Texture Texture TextureTexture

Load/store

Global Memory

Load/store Load/store Load/store Load/store Load/store

13GPU Programmierung

Global Memory

Page 14: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

P i d llProgrammiermodell

Der Programmierer schreibt

Host Device

Grid 1geine Kernel Funktion (in C) für die durchzuführendeAufgabe

Kernel 1

Block(0, 0)

Block(1, 0)

Block(2, 0)

Block Block BlockAufgabe

Kernel = (kleine) Funktion,

(0, 1) (1, 1) (2, 1)

Grid 2

die von allen Threads parallel ausgeführt wird

Kernel 2

Host = CPUDevice = GPU

Block (1, 1)

Thread(0, 0)

Thread(1, 0)

Thread(2, 0)

Thread(3, 0)

Thread(4, 0)

Thread(0, 1)

Thread(1, 1)

Thread(2, 1)

Thread(3, 1)

Thread(4, 1)

Thread(0 2)

Thread(1 2)

Thread(2 2)

Thread(3 2)

Thread(4 2)

14GPU Programmierung

(0, 2) (1, 2) (2, 2) (3, 2) (4, 2)

Page 15: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

P i d llProgrammiermodell

Aufteilung der Threads in

Host Device

Grid 1geinem 2-Level Gitter

A f j d Th d i h lb

Kernel 1

Block(0, 0)

Block(1, 0)

Block(2, 0)

Block Block BlockAuf jedem Thread innerhalbdes Gitters läuft die gleicheKernel Funktion

(0, 1) (1, 1) (2, 1)

Grid 2

Grid• Gitter aufgeteilt in Blöcke

Kernel 2

• Gitter, aufgeteilt in BlöckeBlock

• Aufgeteilt in Threads

Block (1, 1)

Thread(0, 0)

Thread(1, 0)

Thread(2, 0)

Thread(3, 0)

Thread(4, 0)

Viele Probleme haben einenatürliche Blockstruktur

Thread(0, 1)

Thread(1, 1)

Thread(2, 1)

Thread(3, 1)

Thread(4, 1)

Thread(0 2)

Thread(1 2)

Thread(2 2)

Thread(3 2)

Thread(4 2)

15GPU Programmierung

natürliche Blockstruktur (0, 2) (1, 2) (2, 2) (3, 2) (4, 2)

Page 16: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

G id d Bl kGrid und Blocks

• Die Kernel Funktion wird in

Host Device

Grid 1

einem Gitter (grid) von thread blocks ausgeführt

Alle threads teilen sich dabei

Kernel 1

Block(0, 0)

Block(1, 0)

Block(2, 0)

Block Block Blockden gleichen Adressraum

• Threads innerhalb eines

(0, 1) (1, 1) (2, 1)

Grid 2

Blocks können kooperieren:Synchronisation ist möglichBenutzung von sehr

Kernel 2

Benutzung von sehrschnellem, gemeinsamemSpeicher ist möglich

Block (1, 1)

Thread(0, 0)

Thread(1, 0)

Thread(2, 0)

Thread(3, 0)

Thread(4, 0)

• Zwei Threads ausverschiedenen Blöckenkönnen nicht kooperieren (!)

Thread(0, 1)

Thread(1, 1)

Thread(2, 1)

Thread(3, 1)

Thread(4, 1)

Thread(0 2)

Thread(1 2)

Thread(2 2)

Thread(3 2)

Thread(4 2)

16GPU Programmierung

können nicht kooperieren (!) (0, 2) (1, 2) (2, 2) (3, 2) (4, 2)

Page 17: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Bl k d Th dBlocks und Threads

17GPU Programmierung

Page 18: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Bl k d Th d IdBlock und Thread Id

• Threads und Blocks haben IDsJeder Thread kennt seine Position auf welche Datenmuss ich zugreifen

Device

Grid 1

Block Block BlockgBlock ID: 1D oder 2DThread ID: 1D, 2D, oder 3D

Block(0, 0)

Block(1, 0)

Block(2, 0)

Block(0, 1)

Block(1, 1)

Block(2, 1)

• Vereinfachter Speicherzugriffauf mehrdimensionale Daten,

( ) ( ) ( )

Block (1, 1),z.B.

BildverarbeitungLösen von Thread Thread Thread Thread Thread

Thread(0, 0)

Thread(1, 0)

Thread(2, 0)

Thread(3, 0)

Thread(4, 0)

Lösen von Differentialgleichungen…

(0, 1) (1, 1) (2, 1) (3, 1) (4, 1)

Thread(0, 2)

Thread(1, 2)

Thread(2, 2)

Thread(3, 2)

Thread(4, 2)

18GPU Programmierung

Page 19: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

S i hSpeichertypen

• Auf der GPU gibt esGrid

Block (0 0) Block (1 0)gverschiedene Arten von Speicher die sichunterscheiden in

Block (0, 0)

Shared Memory

Block (1, 0)

Shared Memory

unterscheiden in• Grösse und• Geschwindigkeit

Thread (0, 0)

Registers

Thread (1, 0)

Registers

Thread (0, 0)

Registers

Thread (1, 0)

Registers

• Bei der Implementierungsollten häufig benötigte

LocalMemory

LocalMemory

LocalMemory

LocalMemoryg g

Daten immer im schnellstenSpeicher liegen

C t t

GlobalMemory

Host

• Die Geschwindigkeit einerGPU Implementierung hängt

ConstantMemory

TextureMemory

19GPU Programmierung

oft vom Speicherlayout ab

Page 20: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

S i hSpeichertypen

Global Memory Shared! MemoryyRead-write per-gridMehrere Hundert MBSehr langsam (600 clocks)

yRead-write per-block16 KB per blockSehr schnell (4 clocks)g ( )

Texture MemoryRead-only per-gridMehrere Hundert MB

Se sc e ( c oc s)Local Memory

Read-write per threadSehr langsam (ähnlich zu GlobalMehrere Hundert MB

Langsamer ersterSpeicherzugriff, aber mit Cachefiltering clamping

Sehr langsam (ähnlich zu Global Memory)

RegistersR d i h dfiltering, clamping

Constant MemoryRead-only per-grid

Read-write per threadSehr schnell (1 clock)

Die CPU kann lesen/schreiben in64 KBLangsamer ersterSpeicherzugriff, aber mit CacheK h ll l Gl b l

•Global Memory•Texture Memory•Constant Memory

20GPU Programmierung

Kann schneller als Global Memory sein

y

Page 21: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

CUDA P i d llCUDA Programmiermodell

• Die GPU wird als “Berechnungseinheit” betrachtet:gCoprozessor für die CPU (Host)Eigener Speicher (DRAM, device memory)Bearbeitet viele Threads parallelBearbeitet viele Threads parallel

• Alle (Daten-) parallelen Anteile der Anwendung werden auf ( ) p gder GPU ausgeführt in Form von Kernels auf vielen, parallelen Threads

• Unterschiede zwischen GPU und CPU Threads GPU threads sind extrem “leichtgewichtig”g g• Können schnell erzeugt werden

GPU braucht 100-1000e von Threads, um effizient zu arbeiten• Multi-core CPU braucht nur wenige Threads

21GPU Programmierung

Multi core CPU braucht nur wenige Threads

Page 22: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Di GPU i füDie GPU ist gut für…

… datenparallele Berechnungenp g• Die gleiche Berechnung wird auf vielen Datenelementen

parallel ausgeführt

…viel Floating-Point ArithmetikViele Berechnungen pro Speicherzugriff• Viele Berechnungen pro Speicherzugriff

• Speicherzugriff immer noch der Flaschenhals

22GPU Programmierung

Page 23: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

CUDACUDA

Compute Unified Device Architecturep

Hardware und Software Spezifikation für parallele Berechnungen

Einfache Erweiterung für C Möglichkeit, Code auf der GPU auszuführen

NVIDIA (seit GeForce 8800 Serie)

23GPU Programmierung

Page 24: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

CUDA A li i P i I fCUDA Application Programming Interface

• Die CUDA API ist eine Erweiterung zu C/C++ g /

• Eigener Compiler: nvcc

• Compiliervorgang in zwei Schritten• z.B. nvcc in Kombination mit gcc

CUDA Fil h l hl GPU l h CPU F k i• CUDA Files enthalten sowohl GPU als auch CPU Funktionen

24GPU Programmierung

Page 25: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Z ä fü F k i d V i blZusätze für Funktionen und Variablen

• Funktionen__device__ Funktion läuft auf GPU und wird von GPU aufgerufen

__global__ Funktion läuft auf GPU und wird von CPU aufgerufen

Kernel Funktion, Rückgabetyp void__host__ Funktion läuft auf CPU und wird von CPU aufgerufen

• Einschränkungen für GPU Funktionen• keine Rekursion keine statischen Variablenkeine Rekursion, keine statischen Variablen

• Variablen__device__ Global Memory (per grid, GPU)__constant__ Constant Memory (per Grid, GPU)

25GPU Programmierung

__shared__ Shared Memory (per Block, GPU)

Page 26: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Ei b V i bl H tEingebaute Variablen

gridDim : Größe des Gitters

Host

Kernel

Device

Grid 1

Block Block Block(in Blocks)• gridDim.x = Breite, gridDim.y = Höhe

1Block(0, 0)

Block(1, 0)

Block(2, 0)

Block(0, 1)

Block(1, 1)

Block(2, 1)

blockDim : Größe eines Blocks• blockDim.x = Breite, blockDim.y = Höhe Kernel

( , ) ( , ) ( , )

Grid 2

blockIdx : Index des Blocks (vom aktuellen Thread)

• blockIdx.x = x-Position,

Kernel 2

Block (1, 1)blockIdx.y = y-Position

threadIdx : Thread Index (Position des Threads innerhalb

Thread Thread Thread Thread Thread

Thread(0, 0)

Thread(1, 0)

Thread(2, 0)

Thread(3, 0)

Thread(4, 0)

des Blocks)• threadIdx.x = x-Position, threadIdx.y = y-Position

Thread(0, 1)

Thread(1, 1)

Thread(2, 1)

Thread(3, 1)

Thread(4, 1)

Thread(0, 2)

Thread(1, 2)

Thread(2, 2)

Thread(3, 2)

Thread(4, 2)

26GPU Programmierung

gridDim = (3,2) blockDim = (5,3) blockIdx = (1,1) threadIdx = (2,0)

Page 27: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Ei f h CUDA B i i l Addi i f d GPUEinfaches CUDA Beispiel: Addition auf der GPU

{ __global__ void add( int a, int b, int *c ) {

U Kernel = kleines Programmauf der GPU (pro Thread){ *c = a + b;

}GP

U

int main( void ) {int c;int *dev_c; Speicher auf GPU_cudaMalloc( (void**)&dev_c, sizeof(int) );

add<<<1,1>>>( 2, 7, dev c );

Speicher auf GPU reservieren (global)

Kernel aufrufenU

_

cudaMemcpy( &c, dev_c, sizeof(int), cudaMemcpyDeviceToHost ) ); Ergebnis zur CPU kopieren

CP

U

printf( "2 + 7 = %d\n", c );cudaFree( dev_c ) ;return 0;

27GPU Programmierung

}

Page 28: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

GPU S i h iGPU Speicher reservieren

cudaMalloc( (void**)&devPtr, size );cudaMalloc( (void )&devPtr, size );

• size Bytes werden auf der GPU reserviert (Globalsize Bytes werden auf der GPU reserviert (Global Memory)

• Die Anfangsadresse steht in devPtrg• Vorsicht, das ist eine GPU Adresse (!)

cudaFree( devPtr ) ;

• Speicher auf der GPU wieder freigeben

28GPU Programmierung

Page 29: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

G C bGPU CPU Datenübertragung

cudaMemcpy( ptr, devPtr, size,cudaMemcpy( ptr, devPtr, size, cudaMemcpyDeviceToHost ) );

• Kopieren von size Bytes von der GPU (Device) zur CPU (Host)• CPU Adresse: ptr• GPU Adresse: devPtr

cudaMemcpy( devPtr, ptr, size, cudaMemcpyHostToDevice ) );cudaMemcpyHostToDevice ) );

• Kopieren von size Bytes von der CPU (Host) zur GPU (Device)• CPU Adresse: ptr• GPU Adresse: devPtr• Achtung: Parameterreihenfolge vertauscht !

29GPU Programmierung

Es gibt auch cudaMemcpyDeviceToDevice

Page 30: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

K l A f fKernel Aufruf

global void kernel( … ) __g __ ( ){…

}kernel<<<gridSize,blockSize>>>( … );

• Die Kernel-Funktion kernel wird in einem 1D Grid derGröße gridSize mit blockSize Threads pro BlockGröße gridSize mit blockSize Threads pro Blockaufgerufen

• insgesamt werden gridSize * blockSize Threads gestartetg g g• Der Kernel läuft auf der GPU und wird von der CPU aufgerufen__global__

30GPU Programmierung

Page 31: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

K l A f f B i i lKernel Aufruf Beispiel

add<<<1,1>>>( 2, 7, dev c );add<<<1,1>>>( 2, 7, dev_c );

• Die Kernel-Funktion add wird mit den Parametern ( 2,Die Kernel Funktion add wird mit den Parametern ( 2, 7, dev_c ) aufgerufen

• Die Größe von Grid/Block wird durch die Werte innerhalbvon <<< … >>> angegeben

• <<<M,N>>> entspricht einem 1D Grid mit M Blöcken mitje N Threads pro Blockje N Threads pro Block

• Im Beispiel wird also nur 1 Thread (in einem Block) gestartet

31GPU Programmierung

Page 32: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

1 Si ll B i i l1. Sinnvolles Beispiel

• Parallelität ausnutzen, viele Threads gleichzeitig, g g

• z.B. 2 Arrays gegeben Komponentenweise Addition• c[i] = a[i] + b[i]

• Jeder Thread (i=1..N) berechnet eine Addition

I P ä d i h f l d• Im Programm ändert sich folgendes• Der Kernel Aufruf erfolgt jetzt mit einem größeren Grid (N, 1)• Der Speicher für die Arrays wird auf der GPU reserviert• Der Speicher für die Arrays wird auf der GPU reserviert• Der Kernel ermittelt über den Index den richtigen Wert

32GPU Programmierung

Page 33: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Addi i i A f d GPUAddition von zwei Arrays auf der GPUint main( void ) {

int a[N] b[N] c[N];int a[N], b[N], c[N];int *dev_a, *dev_b, *dev_c;

// allocate the memor on the GPU// allocate the memory on the GPUcudaMalloc( (void**)&dev_a, N * sizeof(int) );cudaMalloc( (void**)&dev_b, N * sizeof(int) );d M ll ( ( id**)&d N * i f(i t) )cudaMalloc( (void**)&dev_c, N * sizeof(int) );

// fill the arrays 'a' and 'b' on the CPU

CP

U

// copy the arrays 'a' and 'b' to the GPUcudaMemcpy( dev_a, a, N * sizeof(int), cudaMemcpyHostToDevice ) );cudaMemcpy( dev_b, b, N * sizeof(int), cudaMemcpyHostToDevice ) );

add<<<N,1>>>( dev_a, dev_b, dev_c );

33GPU Programmierung

Page 34: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Addi i i A f d GPUAddition von zwei Arrays auf der GPU

// copy the array 'c' back from the GPU to the CPU// copy the array 'c' back from the GPU to the CPUcudaMemcpy( c, dev_c, N * sizeof(int), cudaMemcpyDeviceToHost ) );

// free the memor allocated on the GPU// free the memory allocated on the GPUcudaFree( dev_a );cudaFree( dev_b );d F ( d )cudaFree( dev_c );

return 0;

CP

U

}

34GPU Programmierung

Page 35: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Addi i i A f d GPU K lAddition von zwei Arrays auf der GPU: Kernel

global void add( int *a, int *b, int *c ) __g __ ( , , ){

int tid = blockIdx.x;

PU

c[tid] = a[tid] + b[tid];}

GP

D h d A f f i d i G id i N 1• Durch den Aufruf add<<<N,1>>> wird ein Grid mit N x 1 Blöcken angelegt (1 Thread pro Block)

• Daher wird über den Blockindex auf das Array zugegriffen

35GPU Programmierung

Page 36: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Addi i i A f d GPU K lAddition von zwei Arrays auf der GPU: Kernel

• Was würde sich ändern wenn der Kernel mit dd<<<1 N>>>• Was würde sich ändern, wenn der Kernel mit add<<<1,N>>> aufgerufen wird ?

• Es wird ein Grid mit einem Block angelegt, in dem einen Block laufen N Threads

• Im Kernel muß daher mit int tid = threadIdx.x

auf das Array zugegriffen werden

• An der Laufzeit ändert sich in diesem Fall nichts

36GPU Programmierung

Page 37: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

G id d Bl k öß fü 2D F ll f lGrid- und Blockgröße für 2D-Fall festlegen

• Eigener Typ dim3g yp• Beschreibt praktisch Integer Vektor mit 3 Komponenten

• Bei einem 2D Grid/Block wird hier die 3. Komponente automatisch auf 1 gesetzt

di 3 idSi ( idWidth idH i ht)dim3 gridSize(gridWidth, gridHeight)dim3 blockSize(blockWidth, blockHeight)

kernel<<<gridSize, blockSize>>>

• Das 2D Grid besteht aus gridWidth x gridHeight Blöcken• jeder Block besteht aus blockWidth x blockHeight

37GPU Programmierung

j gThreads

Page 38: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

2D G id2D-Grid

• Aufteilung Grid in Blocksg• An welcher xy-Position befindet sich der aktuelle Thread ?

int x = threadIdx.x + blockIdx.x * blockDim.x;int y = threadIdx.y + blockIdx.y * blockDim.y;

38GPU Programmierung

Page 39: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

B K l fü F k lBsp. Kernel für Fraktal__global__ void fractalKernel( float *imagePtr, int ticks ) {

int pixelX = threadIdx.x + blockIdx.x * blockDim.x;int pixelY = threadIdx.y + blockIdx.y * blockDim.y;int offset = pixelX + pixelY * blockDim.x * gridDim.x;

float cx = 0.41 * sin(0.001 * float(ticks)); float cy = 0.77 * cos(0.0011 * float(ticks));

float x = 2.0f * (pixelX / (float)DIM) - 1.0f;float y = 2.0f * (pixelY / (float)DIM) - 1.0f;int i = 0;int max = 256;float dist = x*x + y*y;while ((i < max) && (dist < 4.0)) {

float newX = x*x - y*y + cx;y = 2*x*y + cy;x = newX;dist = x*x + y*y;i++;

}

39GPU Programmierung

}imagePtr[offset] = pow(float(i) / float(max) , 0.25f);

}

Page 40: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Bild iBildanzeige

• Für die Anzeige von einem Bild verwenden wir zunächst gfolgendes

kernel<<<gridSize, blockSize>>>(devPtr…);…cudaMemcpy( pixels, devPtr, size, cudaMemcpyDeviceToHost );cudaMemcpy( pixels, devPtr, size, cudaMemcpyDeviceToHost );glDrawPixels( width, height, …, pixels );

• Da sich die Pixeldaten bereits auf der GPU befinden sind dies zwei unnötige Kopiervorgänge

• Effizientere Lösung später• Effizientere Lösung später…

40GPU Programmierung

Page 41: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

W i d ?Wer ist das ?

siehe Übung…

41GPU Programmierung

Page 42: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

A h K dAsynchrone Kommandos

• Viele CUDA Kommandos arbeiten asynchrony• d.h. das CPU Programm läuft weiter

• Dies sind z.B.• Kernel Aufrufe

K d K i S i h di f A () d• Kommandos zum Kopieren von Speicher, die auf …Async() enden• Device – Device Speicherkopie• …

42GPU Programmierung

Page 43: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

F hl bfFehlerabfrage

static void HandleError( cudaError_t err,const char *file,int line ) {

if (err != cudaSuccess) {printf( "%s in %s at line %d\n", cudaGetErrorString( err ),

file, line );exit( EXIT FAILURE );_

}}#define HANDLE ERROR( err ) (HandleError( err, FILE , LINE ))# _ ( ) ( ( , __ __, __ __ ))

• Mit HANDLE_ERROR(function) wird ein vorkommender Fehler direkt angezeigt und abgebrochendirekt angezeigt und abgebrochen

• Ist evtl. eine Bremse, aber sicherer…• Alternative: cutilSafeCall(…)

43GPU Programmierung

Alternative: cutilSafeCall(…)

Page 44: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Z iZeitmessung

cudaEvent_t start, stop;cudaEventCreate( &start );cudaEventCreate( &stop );cudaEventRecord( start, 0 );

….

cudaEventRecord( stop, 0 );cudaEventSynchronize( stop );float elapsedTime;p ;cudaEventElapsedTime( &elapsedTime, start, stop );printf( "Time to generate: %3.1f ms\n", elapsedTime );

cudaEventDestroy( start );cudaEventDestroy( stop );

44GPU Programmierung

Page 45: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

GPU Ei h f bfGPU Eigenschaften abfragen

cudaDeviceProp prop;int count;HANDLE_ERROR( cudaGetDeviceCount( &count ) );for (int i=0; i< count; i++) {

HANDLE_ERROR( cudaGetDeviceProperties( &prop, i ) );printf( " --- General Information for device %d ---\n", i );printf( "Name: %s\n", prop.name );p p pprintf( "Compute capability: %d.%d\n", prop.major, prop.minor );printf( "Clock rate: %d\n", prop.clockRate );…

}

• Wieviele CUDA-fähige Grafikkarten sind in meinem Rechner und was können die ?

45GPU Programmierung

Page 46: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

CUDA C ilCUDA Compiler

• Der CUDA Compiler nvcc benötigt einen C-Compilerp g p

• Aufruf z.B.:

nvcc –ccbin „CompilerDirectory“ –L „LibraryDirectory“ myCudaProgram.cu –o myCudaProgram.exe

C il Di t ist z B bei Visual Studio (cl exe) :CompilerDirectory ist z.B. bei Visual Studio (cl.exe) : C:\Program Files\Microsoft Visual Studio 9.0\VC\bin

46GPU Programmierung

Page 47: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

D i P i LDevice Properties von Laptop…

--- General Information for device 0 ---

Name: GeForce 9600M GTCompute capability: 1.1Clock rate: 1250000

CUDA Version

Device copy overlap: EnabledKernel execution timeout : Enabled

--- Memory Information for device 0 ---T t l l b l 521732096

Gleichzeitig MemCopy und Kernel ausführenMax. Zeit für Kernel

Total global mem: 521732096Total constant Mem: 65536Max mem pitch: 2147483647Texture Alignment: 256Texture Alignment: 256

--- MP Information for device 0 ---Multiprocessor count: 4Shared mem per mp: 16384

Anzahl Streaming Multiprocessors (SMP)Shared Memory pro SMP

Registers per mp: 8192Threads in warp: 32Max threads per block: 512M th d di i (512 512 64)

Anzahl Register pro SMPThreads im GleichschrittMax. Gesamtanzahl (!) Threads pro BlockMax Größe der Achsen von einem Block

47GPU Programmierung

Max thread dimensions: (512, 512, 64)Max grid dimensions: (65535, 65535, 1)

Max. Größe der Achsen von einem Block

Page 48: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

I ll i CUDAInstallation von CUDA

1. CUDA Toolkit installieren1. CUDA Toolkit installierenWir nutzen CUDA 3.2 (Download)

2 Treiber aktualisieren2. Treiber aktualisierenTreiber muss zur CUDA Version passen (Download)

3. CUDA in Visual Studio 2008 integrierenBuild Rules (*.rules) von „…\ NVIDIA GPU Computing Toolkit\CUDA\v3 2\extras\visual studio integration\rules“Toolkit\CUDA\v3.2\extras\visual_studio_integration\rulesnach „…\Microsoft Visual Studio 9.0\VC\VCProjectDefaults“ kopieren fertig

CUDA in Visual Studio 2010 integrierenWir haben es nicht getestet, aber hier schon mal ein Anfang…

48GPU Programmierung

g , g

Page 49: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

CUDA D b iCUDA Debugging

• Device Emulation• CUDA Kernel läuft auf CPU (langsam)• Dafür z.B. printf() im Kernel möglich

• nvcc -G -g -deviceemu file.cu

49GPU Programmierung

Page 50: 7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads parallel ausgeführt wird Kernel 2 Host = CPU Device = GPU Block (1, 1) Thread (0, 0) Thread

Z fZusammenfassung

• CUDA• Erste Schritte• Programmiermodell, Grids und Blocks• Kernel Funktionen

Nä h t M l• Nächstes Mal• Speichertypen• SynchronisationSynchronisation

50GPU Programmierung