16
Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf 1 Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian Graf [email protected], [email protected] Betreuung: Matthias Hartl, Hritam Dutta, Frank Hannig Hardware-Software-Co-Design Universität Erlangen-Nürnberg

1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Embed Size (px)

Citation preview

Page 1: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 1

Hauptseminar MAP08

Random Heightmap on GPUHannes Stadler, Sebastian Graf

[email protected], [email protected]

Betreuung: Matthias Hartl, Hritam Dutta, Frank Hannig

Hardware-Software-Co-Design

Universität Erlangen-Nürnberg

Page 2: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 2

Gliederung

Was ist eine Heightmap? Fault Algorithmus Parallelisierung des Fault Algorithmus Umsetzung in Cuda Benchmarks Probleme Zusammenfassung

Page 3: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 3

Was ist eine Heightmap? dt. Höhenfeld Zwei-dimensionales Skalarfeld Beschreibung eines Höhenreliefs Jedem Punkt ist ein Wert zugeordnet, der dessen Höhe

angibt

Page 4: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 4

Fault Algorithmus

Erzeuge ein ebenes 2-dimensionales Grid

Algorithmus:

Wähle zwei zufällige Punkte im R² Lege Gerade durch diese zwei Punkte Erhöhe alle Punkte auf der eine Seite der Gerade,

erniedrige die auf der anderen um einen konstanten Wert Wiederhole diese Schritte für eine vorher festgelegt Anzahl

von Iterationen

Page 5: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 5

Fault Algorithmus Pseudo-Code:

foreach(Iteration){

CreateRandomLine();foreach( RowOfImage){

foreach(PixelOfRow){

processNewValue();}

}}

Page 6: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 6

Fault Algorithmus

Page 7: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 7

Variationen des Fault Algorithmus

Multiplikation der Geraden mit Sinus/Cosinus um weiche Übergänge an den Kanten zu bekommen

Page 8: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 8

Parallelisierung Fault Algorithmus

Algorithmus besteht aus drei for-Schleifen Parallelisierung der Schleifen:

1.for-Schleife durchläuft Anzahl der Iterationen mehrere Iterationen parallel möglich, da unabhängig

2.for-Schleife führt Berechung für jede Zeile im Bild ausParallelisierbar, da Zeilen unabhängig

3.for-Schleife arbeitet auf genau einer ZeilePro Zeile eine Grenze ( Schnittpunkt mit der Geraden), Aufteilung in Teil der erhöht und der erniedrigt wird

Page 9: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 9

Umsetzung in CUDA Naiver Ansatz:

Laden des Grids in Global Memory Threads arbeiten auf Daten im Global Memory Probleme mit Nebenläufigkeit, Performance etc.

Optimierter Ansatz: Aufteilung des Grids in Blöcke Block in Shared Memory laden Berechnung aller Iterationen für jeweiligen Block Danach wieder zurück in Global Memory speichern

Weitere Optimierungen: Coalesced Speicherzugriff der Threads Zugriff auf Zufallzahlen über Constant Memory

- Oder: Zufallszahlen auf der GPU erzeugen

Page 10: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 10

Quellcode – Kernelaufrufint CreateHeightMap(){ CUT_DEVICE_INIT(); dim3 threads(TPL,ZPB);// 16 x 16 dim3 grid(WIDTH/BLOCKWIDTH,HEIGHT/ZPB); // 1k x 1k -> 64 x 8, bei 2k x 2k -> 128 x 16 int rand[ITERATIONS*4];

for(i=0;i<ITERATIONS*4;i++){ // rand[ ] mit Zufallszahlen füllen } CUDA_SAFE_CALL(cudaMemcpyToSymbol(rand_d, rand ,ITERATIONS*4*sizeof(int),0) );

GLfloat* HeightMap_d; CUDA_SAFE_CALL(cudaMalloc((void**) &HeightMap_d, WIDTH*HEIGHT*sizeof(float))); splitpicture<<<grid, threads>>>(HeightMap_d);

CUDA_SAFE_CALL(cudaMemcpy(HeightMap, HeightMap_d , WIDTH*HEIGHT*sizeof(float),cudaMemcpyDeviceToHost) );

}

Page 11: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 11

Quellcode – Kernelextern __constant__ int rand_d[];__global__ void splitpicture(GLfloat *HeightMap_d){ __shared__ float aRow[ZPB][SMB/ZPB]; // Init. mit default-Wert weggelassen for(int i = 0; i < ITERATIONS; i++){ // Variableninitialisierung, random-Werte, „Wendestelle“ bestimmen for(int a=0;a<((SMB/ZPB)/TPL);a++){ int rel_pos=threadIdx.x*(BLOCKWIDTH/TPL) + a; aRow[threadIdx.y][rel_pos] +=4*faktor*((float)value)*(1-__sinf(phi)/WAVEWIDTH); } }

for(int j = 0; j < ((SMB/ZPB)/TPL); j++){ HeightMap_d[offset+threadIdx.y*WIDTH+threadIdx.x*(BW/TPL)+j] = aRow[threadIdx.y][threadIdx.x*(BLOCKWIDTH/TPL)+j];

}}

Page 12: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 12

Probleme CUDA-Kernel kann unter X-Linux leider nur max. 5sek

laufen, bevor er terminiert wird der Komplexität der Aufgabe ist ein Ende gesetzt ;-) Komischerweise klappts manchmal doch ab und an stürzt auch die GPU ab

Bildgrößen müssen vielfache von Zweierpotenzen sein Im Idealfall: sind Zweiterpotenzen

Ursprüngliche (naive) Implementierung hatte (im Vergleich zur Finalen Version) nur mäßige Performanz Man muss schon manchmal etwas genauer nachdenken

Dokumentation von CUDA teilweise ungenau z.B. Shared Memory kann nicht voll ausgenutzt werden

Page 13: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 13

Benchmarks - CPU• CPU-Implementierung ( P4 – 3,0GHz )

Bildgröße

Iterationen

Laufzeit MPixel/s

512x512 256 7,2s 9,32

1024x1024

256 28,7s 9,35

1024x1024

512 59,4s 9,04

1024x1024

1024 120,7s 8,90

1024x1024

2048 229s 9,38

1024x1024

4096 457,35s 9,39

2048x2048

4096 1834s 9,37

4096x4096

2048 ~3700s ~9,37

Page 14: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 14

Benchmarks - CUDA• CUDA-Implementierung (GF 8800 GTX )

Bildgröße

Iterationen

Laufzeit MPixel/s

SpeedUp

512x512

256 0,015s 4473,92 480

1024x1024

256 0,059s 4549,75 486,44

1024x1024

512 0,118s 4549,75 503,39

1024x1024

1024 0,235s 4569,11 513,62

1024x1024

2048 0,47s 4569,11 487,23

1024x1024

4096 0,94s 4569,11 486,54

2048x2048

1024 0,92s 4668,44 497,83

2048x2048

2048 1,84s 4668,44 498,37

2048x2048

4096 3,68s 4668,44 498,37

4096x4096

1024 3,60s 4772,19 509,72

4096x4096

2048 7,20s 4768,21 513,46

3072x4096

2048 7,40s 3484,76 372,55

Page 15: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 15

Zusammenfassung Auf der CPU teilweise nicht zumutbare Ausführungszeiten

Allerdings noch größere Problemgrößen lösbar als mit CUDA, da kein Timeout

Primitive CUDA-Implementierung Relativ schnell lauffähig Speedup bereits zwischen 10 und 40

Endversion: Enormer Speedup von ~ 500 Bereits bei kleinen Eingabedaten Sehr gut skalierend Allerdings auch nur durch viel Arbeit erreichbar

Page 16: 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Hannes Stadler, Sebastian Graf Hauptseminar MAP08 Random Heightmap on GPU Hannes Stadler, Sebastian

Friedrich-Alexander-Universität Erlangen-NürnbergHannes Stadler, Sebastian Graf 16

Demo

Genug geredet, jetzt wird’s gezeigt!

Oder gibt’s bisher schon

Fragen?