Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

GPU-Computing mit CUDA und OpenCL

533 views

Published on

Mit GPUs sind oft große Performanceverbesserungen möglich. Um diese erreichen zu können, sind allerdings Kenntnisse der GPU-Architektur notwendig und wie man diese bei der Programmierung zu berücksichtigen hat. Die Programmierung von GPUs ist also immer noch "hardware-nah".

In diesem Vortrag werden deshalb die Unterschiede zwischen der GPU- und der CPU-Architektur erläutert. Die Frameworks CUDA und OpenCL werden vorgestellt. Es wird gezeigt, wie man die üblichen Patterns für Parallelität mit diesen Frameworks implementiert.

Schließlich werden die wichtigsten Optimierungstechniken und nützliche Tipps & Tricks aus der Praxis vorgestellt.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

GPU-Computing mit CUDA und OpenCL

  1. 1. GPU-COMPUTING MIT CUDA UND OPENCL Jörn Dinkla, para//el 2017, 31. März 2017, Heidelberg
  2. 2. GPU COMPUTING IST ÜBERALL
  3. 3. EINSATZ VON GPU-COMPUTING Es locken große Speedups: 2 3 4 5 6 7 8 9 10 11 … ProfiFortgeschrittenAnfänger „Enabler“
  4. 4. ABER GPU-COMPUTING IST NICHT TRIVIAL Entwickler Kenntnisse, Lernbereitschaft, Zeit Code Reorganisation, Anpassung Management Time is Money
  5. 5. ZIEL: GRUNDLAGEN FÜR ERFOLGREICHEN EINSATZ Grundlagen der Parallelisierung Architektur CPU und GPU Programmierung mit CUDA und OpenCL Optimierung 2 3 4 5 6 7 8 9 10 11 … Fortgeschritten
  6. 6. JÖRN DINKLA Software-Developer und Berater TechEd von OpenCL in Action Konferenzen & Artikel Auch: JVM, C++, JavaScript jdinkla@thoughtworks.com
  7. 7. A community of passionate individuals whose purpose is to revolutionize software design, creation and delivery, while advocating for positive social change.
  8. 8. LINKS Source-Code https://github.com/jdinkla/parallel2017_gpucomputing Weitere Vorträge und Schulungen https://www.slideshare.net/dinkla
  9. 9. VOM MODELL ZUM BILD Bilder aus Tomas Akenine-Mőller © 2002, Quelle: http://www.realtimerendering.com/ Vertex Pixel
  10. 10. PROGRAMMIERBARE SHADER Ab 2002 HLSL, Cg, GLSL
  11. 11. GPGPU UND GPU-COMPUTING GPGPU Generall Purpose computing on GPUs 2003 – 2008 ein „hack“ GPU-Computing 2007 erste Version von CUDA 2008 von OpenCL 2012 C++ AMP
  12. 12. FRAMEWORKS IM ÜBERBLICK Device Driver C ++ 11 C ++ C CUDA Runtime C++ AMP MS DirectX AMDNVIDIA Thrust C++- Wrapper OpenCL Boost Compute Intel AMD CUDA Driver OpenACC
  13. 13. VOR- UND NACHTEILE CUDA + Verbreitung + C++ 11 - nur NVIDIA OpenCL + Offen - C99 - Nicht so viele Libraries C++ AMP + C++ 11 - DirectX - geringe Verbreitung
  14. 14. VERSIONEN DES APIS CUDA 8.0 Pascal, Unified Memory 7.5 Lambdas, 7.0 C++ OpenCL 2.2 C++ Kernel (Zukunft) 2.1 SPIR-V, Dynamic Parallelism
  15. 15. VERSIONEN DER HARDWARE Unterschiede zwischen Karten-Generationen z. B. NVIDIA Pascal: Unified Memory incl. Management Maxwell: Dynamic Parallelism für alle Kepler: Unified Memory
  16. 16. VERSIONEN VON OPENCL HARDWARE Beispiel Intel®SDK 2016 R3 Siehe https://software.intel.com/file/529975/download
  17. 17. FÜR WELCHE API UND HARDWARE SCHREIBT MAN? Am einfachsten: Für jeweils die Neueste Neue Hardware preiswerter als Entwickler Aber Kunden mit älteren Karten? Maintenance-Probleme später berücksichtigen
  18. 18. PARALLELE PATTERNS Siehe http://www.parallelbook.com/
  19. 19. SPMD - SINGLE PROGRAM MULTIPLE DATA 1. Übergebe ID als Parameter 2. Hole Daten anhand ID 3. Verarbeitung 4. Speichere Daten anhand ID
  20. 20. MAP: UNABHÄNGIGE ELEMENTE for i = 0 to n-1 d[i] = f(s[i]); CPUGPU Granularität Daten-parallel
  21. 21. REDUKTION: ABHÄNGIGE ELEMENTE Sequentiell Zeit O(n), Arbeit O(n) Parallel Zeit O(log(n)), Arbeit O(n) sum = 0 for i = 0 to n-1 sum += s[i];
  22. 22. ANMERKUNG: MAPREDUCE Verteilte Systeme, Cluster Siehe http://www.drdobbs.com/database/hadoop-the-lay-of-the-land/240150854
  23. 23. FORK-JOIN-PATTERN Eingabe 2 3 Ausgabe1 Eingabe 2a 2b 3 AusgabeFork Join1
  24. 24. AMDAHL‘S GESETZ 1 32 1 3 2a 2b Siehe https://en.wikipedia.org/wiki/Amdahl's_law#/media/File:AmdahlsLaw.svg 1 3 2a 2b
  25. 25. 2D-MAP https://uploads5.wikiart.org/images/vincent-van-gogh/rest-work-after-millet-1890.jpg
  26. 26. 2D-MAP for y = 0 to n-1 for x = 0 to n-1 int i = y*width+x d[i] = f(s[i]); 0 1 2 3 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 y*width+x
  27. 27. OPENMP Präprozessor-Direktive Runtime im Hintergrund
  28. 28. ARITHMETISCHE INTENSITÄT for y = 0 to n-1 for x = 0 to n-1 int i = y*w+x d[i] = f(s[i]); 𝑎𝑖 = 𝑅𝑒𝑐ℎ𝑒𝑛𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛𝑒𝑛 𝑆𝑝𝑒𝑖𝑐ℎ𝑒𝑟𝑧𝑢𝑔𝑟𝑖𝑓𝑓𝑒
  29. 29. ARTEN DER AUSLASTUNG Computation Bound Alle Prozessoren 100% ausgelastet Memory Bound Bandbreite zum Speicher voll ausgelastet Latency Bound Warten auf die Daten
  30. 30. AUFBAU EINES COMPUTERS CPU 1 Core L1 / L2 Core L1 / L2 L3 Cache Memory Controller PCIe Global Memory Devices CPU 2 Core L1 / L2 Core L1 / L2 L3 Cache QPI Memory ControllerPCIe Global MemoryDevices ≈25 ≈14 ≈26 Bus ist „von-Neumann-Flaschenhals“ ≈50 ≈100 Transparent für Programmierer
  31. 31. OPTIMIERUNG DER CPU Clock Frequency Memory Hierarchy / Cache Parallelizing ALU Pipelining Very-long Instruction Words (VLIW) Instruction-Level parallelism (ILP) Superscalar processors Vector data types (SIMD) Multithreaded Multicore / Manycore
  32. 32. AMD RYZEN UND NVIDIA PASCAL Mehr Platz für Kerne
  33. 33. NVIDIA PASCAL 60 SMs á 64 Kerne á 32 Bit 3840 Kerne 4 MB L2 Cache 1080: 2560 Kerne 1080 Ti: 3584 Kerne https://devblogs.nvidia.com/parallelforall/wp-content/uploads/2016/04/gp100_block_diagram-1-624x368.png
  34. 34. AMD FIJI  64 CUs á 64 Kerne á 32 Bit  4096 Kerne  2 MB L2 Cache Siehe http://www.anandtech.com/show/9390/the-amd-radeon-r9-fury-x-review/4
  35. 35. AUFBAU DER GPU CPU 1 Core L1 / L2 Core L1 / L2 L3 Cache Memory Controller PCIe Global Memory Devices ≈25 ≈ 14 ≈50 ≈100 ≈ 14 GPU Global Memory Constant Texture Prozessor (SM, CU) Shared / L1 Registers C L2 Cache C C C C C C C C C C C C C SM SM SM SM SM SM SM SM SM SM ≈ 8000 ≈ 1600 ≈ 320 - 700 Schneller Device-Speicher Daten-Lokalität
  36. 36. DIE UNTERSCHIEDE 1. Daten-Lokalität wegen Flaschenhals
  37. 37. GPU-IFIZIERUNG Host Algorithmu s Buffer Buffer ‘ Host Buffer Buffer ‘ Device KernelBuffer Buffer‘
  38. 38. HOST UND DEVICE Host  Der „Kopf“ des Ganzen  Management, Synchronisation  Speicher, Queues, Events  Aufruf von Kerneln Device  Traditionell „reine Arbeitspferde“, Ausnahme: Dynamic Parallelism
  39. 39. SPEICHER ALLOKIEREN C/C++ CUDA OpenCL
  40. 40. MAP-2D FÜR CUDA Alloc Free __host_ _ __device__
  41. 41. KERNEL-KONFIGURATION UND -AUFRUF Aufruf Synchronisation Block & Grid
  42. 42. 2D-MAP-KERNEL Kernel Template ID berechnen Wo ist die for-Schleife?
  43. 43. KERNEL-SCHEDULING Abbildung von Berechnungen/Daten auf SMs unter Berücksichtigung der Hardware-Constraints 4000 x 3000 Pixel 4000 Kerne
  44. 44. BLOCKGRÖßE DURCH HARDWARE DEFINIERT Pascal-SM: 64 Kerne (128 Kepler, 192 Maxwell) Fiji-CU: 64 Kerne Kleinste Schedulingeinheit: NVIDIA: Warp 32 Threads AMD: Wavefront 64 Threads
  45. 45. SIMT - SINGLE INSTRUCTION MULTIPLE THREADS Nur ein PC für Warp if (threadIdx.x < 2) { expensive_function1(); } else { expensive_function2(); } 0 1 2 3 Divergenz
  46. 46. SIMT - SINGLE INSTRUCTION MULTIPLE THREADS Bei sequentiellen Programmen (Single-Thread) 𝑇 = max(𝑇𝑖𝑓, 𝑇𝑒𝑙𝑠𝑒) Laufzeit bei SIMT 𝑇 = 𝑇𝑖𝑓 + 𝑇𝑒𝑙𝑠𝑒
  47. 47. AUSWIRKUNG VON DIVERGENZ Wenn divergente Threads vorhanden sind Kerne sind idle SM wird nicht ausgelastet Berechnung dauert länger als notwendig Daher Divergenz vermeiden
  48. 48. DIE UNTERSCHIEDE 1. Daten-Lokalität wegen Flaschenhals 2. Divergenz
  49. 49. GRID = DATEN/BLOCK Grid: Einteilung der Daten in Blöcke Beispiel Daten 8x8 Block 4x4 → Grid 2x2 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 Daten, Pixel, Voxel Grid
  50. 50. BESTIMMUNG DER ID threadIdx innerhalb Block blockIdx innerhalb Grid blockDim Größe eines Blocks 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 Daten, Pixel, Voxel Grid
  51. 51. OCCUPANCY Pascal-SM kann „gleichzeitig“ 32 Blöcke, 64 Warps bzw. 2048 Threads ausführbereit halten („in flight“, „resident“) W0SM W1 W2 W3 W4 -- -- --
  52. 52. LATENCY HIDING Speicherzugriffe sind langsam Durch Berechnungen „überdecken“ Immer genügend Warps „in flight“ haben DER Grund für gute Performance der GPU Memory- Flaschenhals überwunden W0SM W1 W2 W3 W4 -- -- -- Occupancy 5/8
  53. 53. WARUM NICHT IMMER 100% OCCUPANCY? Platz auf SM beschränkt Warps auf SM teilen sich Shared-Memory L1-Cache Register-Speicher GPU Global Memory Constant Texture Prozessor (SM) Shared / L1 Registers C L2 Cache C C C C C C C C C C C C C SM SM SM SM SM SM SM SM SM SM
  54. 54. OCCUPANCY-CALCULATOR
  55. 55. DIE UNTERSCHIEDE 1. Daten-Lokalität wegen Flaschenhals 2. Divergenz 3. Occupancy – Latency Hiding
  56. 56. 2D-KERNEL Unterschiedliche Layouts 8x1 4x2 2x4 1x8 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
  57. 57. 8X1 ZUGRIFFE AUF DEN SPEICHER 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 1 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 2 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 3 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 4 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 5 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 6 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 7
  58. 58. 4X2 ZUGRIFFE AUF DEN SPEICHER 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 1 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 2 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 3 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 4 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 5 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 6 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 7
  59. 59. 2X4 ZUGRIFFE AUF DEN SPEICHER 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 1 4 5 4 5 4 5 4 5 4 5 4 5 4 5 4 5 4 5 2 6 7 6 7 6 7 6 7 6 7 6 7 6 7 6 7 6 7 3 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 4 2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 5 4 5 4 5 4 5 4 5 4 5 4 5 4 5 4 5 6 6 7 6 7 6 7 6 7 6 7 6 7 6 7 6 7 7
  60. 60. 1X8 ZUGRIFFE AUF DEN SPEICHER 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
  61. 61. COALESCING Zugriffe innerhalb eines Warps können in 32, 64 und 128 Byte „zusammengefasst“ werden 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 1 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 2 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 3 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 4 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 5 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 6 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 4 5 6 7 7 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 5 4 5 4 5 4 5 4 5 4 5 4 5 4 5 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 6 7 6 7 6 7 6 7 6 7 6 7 6 7 6 7 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 4 5 4 5 4 5 4 5 4 5 4 5 4 5 4 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 6 7 6 7 6 7 6 7 6 7 6 7 6 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 1 pro Warp insg. 16 2 pro Warp insg. 32 4 pro Warp insg. 64 8 pro Warp insg. 128
  62. 62. X-Y- STATT Y-X- ZUGRIFF CPU „hintereinander“: for y … for x … GPU „nebeneinander“: for x .. for y … Gut für CPU Gut für GPU
  63. 63. ARRAY OF STRUCTURES VS. STRUCTURE OF ARRAYS Siehe Stroustrup, „C++ Prog. Language“, 4th ed., p. 207 mem 0 1 2 3 4 5 AoS value 1 2 3 4 5 6 SoA value 1 3 5 2 4 6
  64. 64. AOS - ARRAY OF STRUCTURES mem 0 1 2 3 4 5 AoS value 1 2 3 4 5 6 SoA value 1 3 5 2 4 6 0 1 20 1 2 Verschwenden Bandbreite
  65. 65. SOA - STRUCTURE OF ARRAYS mem 0 1 2 3 4 5 AoS value 1 2 3 4 5 6 SoA value 1 3 5 2 4 6 0 1 2 0 1 2 Nebeneinander gut
  66. 66. ALIGNMENT IST AUCH WICHTIG 31 63 95 127 159 191 223 255 287 319 351 383 31 63 95 127 159 191 223 255 287 319 351 383
  67. 67. ALIGNMENT ERZWINGEN sizeof(SoA) == 24 sizeof(SoA2) == 32
  68. 68. DIE UNTERSCHIEDE 1. Daten-Lokalität wegen Flaschenhals 2. Divergenz 3. Occupancy – Latency Hiding 4. Coalescing von Speicherzugriffen
  69. 69. 2D-MAP IN OPENCL C++ BINDING Programm bauen Context & Queue
  70. 70. 2D-MAP IN OPENCL C++ BINDING Device- Speicher Argumente
  71. 71. 2D-MAP IN OPENCL C++ BINDING Sync H2D Kernel- Konfiguration D2H
  72. 72. 2D-MAP IN OPENCL - KERNEL __kerne l __global ID no C++ no templates
  73. 73. SMOOTHING
  74. 74. STENCIL-PATTERN Durchschnitt, Smoothing, PDEs Nachbarschaften von-Neumann, Moore Optimierung Speicherzugriffe und Cache Berechnungen speichern
  75. 75. SMOOTHING-ALGORITHMUS for all pixel at x,y in image sum = 0, c = 0 for all dx,dy in neighborhood sum += e[x+dx, y+dy] c += 1 a[x,y] = sum / c 𝑎𝑖 = 𝑅𝑒𝑐ℎ𝑒𝑛𝑜𝑝𝑒𝑟𝑎𝑡𝑖𝑜𝑛𝑒𝑛 𝑆𝑝𝑒𝑖𝑐ℎ𝑒𝑟𝑧𝑢𝑔𝑟𝑖𝑓𝑓𝑒
  76. 76. OPTIMIERUNG Ermittle das Bottleneck mit Profiler Verwende Amdahls Gesetz für Abschätzung Siehe https://devblogs.nvidia.com/parallelforall/cuda-8-features-revealed/
  77. 77. TOOLS z. B. NVVP‘s „Guided Analysis“ Viele nützliche Infos und Analysen
  78. 78. MAXIMALE RECHENLEISTUNG TFLOPS = Anzahl Kerne * Takt * 2 / (1000^2) Beispiel GTX 1080 Ti: 3584 * 1480 * 2 ≈ 10.61 TFLOPS Beispiel GTX 1080: 2560 * 1607 * 2 ≈ 8.23 TFLOPS FMA: fused multiply add Basistakt
  79. 79. IN DER PRAXIS WENIGER 1080: 4,5 TFLOPS
  80. 80. OPTIMIERUNG (AUS DER CUDA-DOKU) Maximiere … 1. Parallelität 2. Speicherdurchsatz 3. Berechnungsdurchsatz
  81. 81. MÖGLICHKEITEN FÜR PARALLELITÄT CPU 1 Core L1 / L2 Core L1 / L2 L3 Cache Memory Controller PCIe Global Memory Devices GPU Global Memory Constant Texture Prozessor (SM) Shared / L1 Registers C L2 Cache C C C C C C C C C C C C C SM SM SM SM SM SM SM SM SM SM CPU || GPU Cores Calc || Mem SMs Cores HT Kernel || Copy
  82. 82. MAXIMIERE PARALLELITÄT Auslastung der GPU Parallele Kernel, Streams Auslastung der SMs Thread-Block, Occupancy Auslastung der Kerne „Instruction level parallelism“ (ILP)
  83. 83. AUSLASTUNG BEI SCHLEIFE DeviceHost I KI O O I KI O O I KI O O Last Nicht ausgelastet Bus ausgelastet
  84. 84. STREAMS & OVERLAP Schritt Ein Stream Stream 1 Stream 2 Stream 1 Stream 2 1 H2D H2D H2D 2 Kernel 1 Kernel 1 H2D Kernel 1 H2D 3 D2H D2H Kernel 2 D2H Kernel 2 4 H2D D2H H2D D2H 5 Kernel 2 H2D Kernel 3 6 D2H Kernel 3 D2H 7 H2D D2H 8 Kernel 3 9 D2H Kernel + Kopie überlappend Kernel + Kopie und H2D und D2H
  85. 85. MAXIMIERE SPEICHERDURCHSATZ Daten-Lokalität Minimiere Kopien On-Chip-Speicher: Register, Shared-Memory Coalesced Zugriffe Pinned-Host-Speicher
  86. 86. MAXIMIERE BERECHNUNGSDURCHSATZ Minimiere Divergenz Berechnen statt Speichern Loop-Unrolling Fast-Math Float statt Double Fusion von Kerneln
  87. 87. NOCHMAL: DIE UNTERSCHIEDE 1. Daten-Lokalität 2. Divergenz 3. Occupancy – Latency Hiding 4. Coalescing von Speicherzugriffen
  88. 88. METHODIK Entwickle 1. „Golden Code“ sequentiell und korrekt 2. Parallelisiere auf CPU 3. Parallelisiere und transformiere zu GPU-Code Unit-Tests stellen Korrektheit sicher
  89. 89. FAZIT Happy GPU-Computing ! 2 3 4 5 6 7 8 9 10 11 … Fortgeschritten

×