7. Vorlesung GPU Programmierung Thorsten GroschThorsten … · Grid 2 die von allen Threads...

Preview:

Citation preview

CUDA7. Vorlesung GPU ProgrammierungThorsten GroschThorsten GroschDanke an Hendrik Lensch

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

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

M i P ll l B hMassiv Parallele Berechnungen

PCIe

CPU (4 cores) GPU (480 cores)

4GPU Programmierung

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.

W P ll l PWarum Parallele Prozessoren

Speicherbandbreite 40 GB/Sek. 170 GB/Sek.

6GPU Programmierung

Speicherbandbreite 40 GB/Sek. 170 GB/Sek.

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

CUDA P i d llCUDA Programmiermodell

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

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

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

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

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

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)

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)

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)

Bl k d Th dBlocks und Threads

17GPU Programmierung

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

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

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

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

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

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

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

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)

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)

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

}

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

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

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

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

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

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

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

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

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

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

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

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);

}

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

W i d ?Wer ist das ?

siehe Übung…

41GPU Programmierung

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

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(…)

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

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

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

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

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

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

Z fZusammenfassung

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

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

50GPU Programmierung

Recommended