Upload
others
View
5
Download
0
Embed Size (px)
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