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.

Multi-GPU-Computing: Eins, zwei, drei, ganz viele

1,463 views

Published on

Slides of my talk at the parallel 2015 conference in Karlsruhe.

Published in: Education
  • Be the first to comment

  • Be the first to like this

Multi-GPU-Computing: Eins, zwei, drei, ganz viele

  1. 1. Multi-GPU-Computing: Eins, zwei, drei, ganz viele Jörn Dinkla para//el 2015 Karlsruhe, 22. 4. 2015 Version 0.1
  2. 2.  Tablet, PC, Großrechner, Cloud, Spielkonsole, Autos … GPU-Computing ist überall
  3. 3.  Schnelle erste Erfolge  2x – 5x Speedup  Dann wird es schwieriger …  Oft sind 10x drin Speedup 2 3 4 5 6 7 8 9 10 11 … „Enabler“
  4. 4.  Bis zu 16 GPU pro Knoten  Abhängig von  Mainboard, CPU, Chipsatz, PCIe-Controller Multi-GPU
  5. 5.  2 GPUs  3 GPUs  …  Erreichbar? Amdahl‘s Gesetz? X-facher Speedup? 4 6 8 10 12 14 16 18 20 6 9 12 15 18 21 24 27 30
  6. 6. Frameworks im Überblick C ++ 11 C ++ C Device Framework CUDA C++ AMP DirectX AMDTreiber TDD WDDM Thrust C++- Wrapper Library OpenCL Bolt Intel AMD
  7. 7.  CUDA ⊕ Am meisten verbreitet ⊕ C++ 11 ⊖ nur NVIDIA-Hardware  C++ AMP ⊕ C++ 11 ⊖ Einschränkungen wegen DirectX (bisher) ⊖ geringe Verbreitung  OpenCL ⊕ Apple, Intel, AMD ⊖ Geringer Abstraktionsgrad, C99 ⊖ Nicht so viele Libraries wie bei CUDA Vor- und Nachteile
  8. 8. 1. Partitioning 2. Communication 3. Agglomeration 4. Mapping  Siehe http://www.mcs.anl.gov/~itf/dbpp/ PCAM-Methodik
  9. 9.  … und parallele Datenstrukturen  … und partitionierte Datenstrukturen  Aufgabenstellung ähnlich  Egal ob Multi-  -CPU,  -Core  oder -GPU Parallele Algorithmen
  10. 10. Speicher und Synchronisation
  11. 11. 1 GPU, Daten passen
  12. 12.  Partionierung u. „Swapping“ erforderlich 1 GPU, Daten passen nicht
  13. 13.  Partionierung erforderlich 2 GPUs, Daten passen Szenario für den Vortrag
  14. 14.  Partionierung u. „Swapping“ erforderlich 2 GPUs, Daten passen nicht
  15. 15.  Listen, Arrays  2D: Ebenen, Bilder  3D: Volumen  Ganz  Als Vektor/Liste von Ebenen  Grids, Gitter  Einfach zu partitionieren Regelmäßige Datenstrukturen
  16. 16. Regelmäßige Datenstrukturen Teilung nach Anzahl Elemente x y*z x/2 * y y z x*y/2 z 2 x*y*z/2 Kopie
  17. 17.  Bäume  Teilbäume als Partitionen  Graphen  Zusammenhangskomponenten  Klein genug? Gleich groß? Unregelmäßige Datenstrukturen
  18. 18.  Graph Partitioning / Clustering  Aufteilung gemäß Kostenfunktion  Im allg. NP vollständig  Minimale „cuts“  Social Networks und Big Data  Apache Spark und GraphX  Kernighan-Lin, 𝑂(𝑛3 )  Buluc et. al. „Recent Advances in GP“ 2013 Unregelmäßige Datenstrukturen
  19. 19.  Homogen (Gleiche GPUs)  Gleiche Arbeit  Inhomogen (Unterschiedliche GPUs)  Messen und gewichten  Wie bei CPUs  Work-Balancing / Job-Stealing  Scheduling-Theory  Divisible Load Theory Scheduling
  20. 20.  Nicht das Rad neu erfinden!  „best practices“  „think parallel“  Tip  McCool et. al.  „Structured Parallel Programming“  Intel-lastig, Cilk Plus, TBB Parallele Patterns
  21. 21. Parallele Patterns Siehe http://www.parallelbook.com/
  22. 22.  P: Elemente  C: Keine  „embarassingly parallel“  A: Granularität  CPU vs. GPU  Großer Unterschied!  M:  TBB, OpenMP, CUDA, etc. Map mit PCAM
  23. 23.  Beispiele  Durchschnitt, Smoothing  PDEs  P, A, M wie Map  C: Nachbarschaft  Optimierung  Speicherzugriffe und Cache  Berechnungen speichern Stencil mit PCAM
  24. 24.  Wärmeleitungsgleichung in 2D  Stencil o[x,y] += c* ( i[x-1,y] + i[x+1,y] + i[x,y-1] + i[x, y+1] - 4 * i[x,y] ) Beispiel: Heat-Simulation
  25. 25.  Initialisiere Wärmequelle heat  prev := 0  Für alle Iterationen  Addiere Wärmequellen prev += heat  current := stencil(prev)  Tausche prev und current Ablauf
  26. 26.  Daten  Buffer(float) für Wärmequelle  Buffer(float) für prev und current  Kernel  add_heat() bzw. mask()  stencil()  Optional  Buffer(uchar4)  Kernel für Umwandlung Zu implementieren …
  27. 27. Obfuscation Aus Wilt „The CUDA Handbook“, S. 218 „Index- Schlacht“ OptimiertNachteil: Speicherorganisation fest verdrahtet
  28. 28.  Größe / Extension  width, height  index(x,y)  in_bounds(x,y)  in_bounds_strict(x,y) Extent2 0 1 2 3 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3
  29. 29. Stencil-Kernel (CUDA 7.0)
  30. 30.  Vor Kernel-Aufruf  Wechsel der Abstraktionsebene  Host zu Device  Von C++-Datenstrukturen zu Device-Pointern Aufruf des Kernels Kernel-Aufruf
  31. 31.  Basis BaseBuffer  HostBuffer  Unpinned (C++)  Pinned (CUDA, nicht swapbar)  Lokaler Speicher (NUMA)  DeviceBuffer (CUDA)  ManagedBuffer (CUDA) Buffer
  32. 32.  GPU besteht aus mehreren SM/CU  Thread-Block wird festen SM zugewiesen  Warp / Wavefront  Kleinste Scheduling-Einheit  32 bei NVIDIA, 64 bei AMD  Occupancy Warps und Wavefronts W0SM* W1 W2 W3 W4 -- -- --
  33. 33.  Thread-Block (Work group, tile)  Performance, abhängig von Hardware  Grid (NDRange)  Beispiel  Daten 8x8  Grid 2x2  Block 4x4 Grid = Data/Block 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
  34. 34.  kernel<<<g, tb, sm, s>>>(params)  Kernel-Konfiguration  dim3 Grid g  dim3 Thread-Block tb  Größe des Shared-Memory sm  cudaStream_t s  Oft abhängig vom Extent2  CudaExecConfig(Extent2& e) CudaExecConfig
  35. 35. mask() / add_heat()
  36. 36.  Single Instruction Multiple Threads!  Mask-Bit für jeden Thread im Warp SIMT - Divergenz 0 1 2 3 int tid = treadIdx.x; if (tid < 2) { call_expensive_function() } else { call_expensive_function2() } Warps Code
  37. 37.  CUDA  Nsight (Visual Studio, Eclipse)  nvvp, Visual Profiler (Eclipse)  Kommandozeile nvprof  OpenCL  Intel Vtune (*)  AMD CodeXL  C++ AMP  Visual Studio 2013  Concurrency Visualizer Profiling
  38. 38.  Computation Bound  Alle Prozessoren 100% ausgelastet  Memory Bound  Bandbreite zum Speicher voll ausgelastet  Latency Bound  Warten auf die Daten Arten der Auslastung
  39. 39. NVVP sagt zu stencil() Arithmetische Intensität 1/5
  40. 40.  Nicht optimal  Arithmetische Intensität niedrig  #Berechnungen / #Speichertransfers  Möglichkeiten  Mask()  Textur-Speicher ausprobieren  Stencil()  Zwischenspeichern im Shared-Memory Fazit Single GPU
  41. 41.  Partitionierte Map Map mit Multi-GPU
  42. 42.  „Overlap“ Stencil mit Multi-GPU
  43. 43.  Halo  Ghost Cells  „Overlap“ Iterierter Stencil
  44. 44.  Initialisiere Wärmequelle heat  Für jede GPU  Initialisiere Buffer prev und current  Kopiere Teil von heat auf‘s Device  prev := 0  Für alle Iterationen  Für jede GPU  Addiere Wärmequellen prev += heat  current := stencil(prev)  Tausche prev und current  Kopiere Halo/Ghost Cells zu Nachbarn  Kopiere Ergebnisse aller GPUs auf Host Ablauf (Multi)
  45. 45.  Host (wie bisher)  Wärmequellen  Endergebnis  Benötigt pro GPU  Buffer für prev und current  Heat-Buffer (Ausschnitt) Datenstrukturen (Multi)
  46. 46.  cudaGetDeviceCount(int* count)  Ermittelt Anzahl der Devices  cudaGetDeviceProperties(cudaDevice Prop* prop, int device)  Eigenschaften des Devices  cudaSetDevice(int device)  Setzt Device für aktuellen Thread  Betrifft alle folgenden cuda*-Funktionen Multi-GPU mit CUDA
  47. 47.  Jeder Thread hat CUDA-Kontext  Dieser speichert aktuelle GPU  Kernel  Nur Speicher auf gleichem Device!  Vorsicht bei Bibliotheken  Z. B. Thrust Multi-GPU mit CUDA
  48. 48. Partition, CudaPartition
  49. 49. GPU
  50. 50.  Explizit einschalten  cudaDeviceCanAccessPeer(&i,d,e)  cudaDeviceEnablePeerAccess(e,0)  Einschränkungen  Nicht Windows u. WDDM Peer-to-Peer-Kopien D2D
  51. 51. 2D-Partition
  52. 52. 2D-Partition auf Device
  53. 53.  mask()-Kernel  Verschiedene Extents für Quelle und Ziel mask()
  54. 54. Erinnerung: mask()
  55. 55. mask() mit Offset
  56. 56. Pos2
  57. 57.  Mit_overlap zu mit_overlap  Kernel nur für inneren Bereich aufrufen stencil()
  58. 58. Erinnerung: stencil()
  59. 59. stencil() mit Offset
  60. 60. Multi-GPU in CUDA
  61. 61. Halo vergessen?
  62. 62. Kopieren der Halos
  63. 63. XExtent2
  64. 64. Region2
  65. 65. Init in CUDA
  66. 66. Update in CUDA #1
  67. 67. Update in CUDA #2 Async!
  68. 68.  Wichtig: cudaDeviceSynchronize() parallel Analyse mit NVVP / Nsight Orange seq. Orange par.
  69. 69.  Aktuelle Hardware  Intel i7-5930K, 4,0 Ghz  16 GB DDR4 RAM, 2,4 Ghz  2x NVIDIA GTX 970, Standard-Clocks  2x 16x PCIe 3.0  OS  Windows 7 bzw. Ubuntu 14.10 Benchmark Testsystem
  70. 70. Speedups 10x
  71. 71. Speedups Multi-GPU 1,955x
  72. 72.  1,955 Speedup bei 2 GPUs  Und was bei 3, 4 oder mehr Karten?  Problem:  PCIe-Bus skaliert nur begrenzt  Bandbreite ist begrenzt  Anzahl der Geräte ist begrenzt Und bei mehr GPUs?
  73. 73.  Lane ist 1 bit, full duplex  Punkt-zu-Punkt Verbindung  1,2,4,8,12 oder 16 Lanes  Geschwindigkeiten  2.0: pro Lane 500MB/s, max. 8 GB/s  3.0: pro Lane 1GB/s, max. 16 GB/s (*)  Controller  Hat max. Anzahl Lanes PCIe
  74. 74.  Grafikkarte x16  CPU hat 40 Lanes  => max. 2 x16 + 1x8  bis zu 4 x8 PCIe D2D
  75. 75.  Anzahl PCIe-Slots auf Mainboard  Anzahl Lanes des PCIe-Controller  Anzahl der Switches / IOHs  4, 8 oder 16 GPUs  Wichtig ist die Bandbreite nicht zu überladen  Praxiserfahrung:  3 GPUs waren bei vielen Kopien schneller als 4 GPUs Anzahl der GPUs
  76. 76. PCIe Switch D2D D2DD2D
  77. 77.  Kein D2D über QPI NUMA D2D D2D
  78. 78.  Rechts-Links  „Rechts“ Erst Kopie von g zu g+1  „Links“ Dann von g zu g -1 Kopieren der Halos
  79. 79. PCIe-Bus
  80. 80.  …  Für alle Iterationen  Für jede GPU  Addiere Wärmequellen prev += heat  current := stencil(prev)  Tausche prev und current  Kopiere Halo/Ghost Cells zu Nachbarn  … Ablauf (Multi)
  81. 81. Kopieren der Halo‘s #2
  82. 82.  Aktuelle GPUs können gleichzeitig  Kernel, 1 Kopie hin u. 1 Kopie zurück Streaming
  83. 83.  …  Für alle Iterationen  Für jede GPU  Berechne nur den Halo („Spezialkernel“)  Kopiere Asynchron zu Nachbarn  Berechne Teil ohne Halo  … Modifizierter Ablauf (Multi)
  84. 84. Kopieren der Halo‘s #2 Code-Komplexität vs. Performance
  85. 85.  Abhängig von Implementierung und Hardware  Wie groß sind die Halos?  Lässt sich die Kopie hinter dem Kernel verstecken?  Ab wie vielen GPUs ist der Bus ausgelastet?  Gibt es Stau („contention“) auf dem Bus? Lohnt sich das?
  86. 86.  Viele melden Erfolge … Linearer Speedup http://on-demand.gputechconf.com/gtc/2015/posters/GTC_2015_Computational_Physics_03_P5122_WEB.pdf http://on-demand.gputechconf.com/gtc/2015/presentation/S5585-Wei-Xia.pdf
  87. 87.  2016 Pascal  4 „Connections“ per GPU  Jede 20GB/s peak, 16GB/s praktisch  US DoE, Summit 2017 150-300 PetaFLOPS NVLINK
  88. 88. C++ AMP  Daten: array, array_view  Kernel: parallel_for_each
  89. 89. Single GPU mit AMP
  90. 90. DoubleBuffer<T>
  91. 91. Single GPU mit AMP #2
  92. 92.  restrict(amp)  Extent2 hat schon __device__ Extent2AMP
  93. 93. Single GPU mit AMP #3 x, y: andere Reihenfolge!
  94. 94.  GPU heißt „accelerator“  accelerator_view ist logische Sicht  Argument zu parallel_for_each Multi-GPU mit C++ AMP #1 view
  95. 95.  array_view logische Sicht auf ein array  array<float> name(size, view) Multi-GPU mit C++ AMP #2
  96. 96.  „D2D“-Kopien  Aber:  Über Host  Nicht parallel zu parallel_for_each Multi-GPU mit C++ AMP #3
  97. 97. OpenCL-stencil() Kein Extent2 Kein C++ 11
  98. 98. OpenCL und C++Bindings
  99. 99.  Platform  Device  Context  Program  Kernel  Buffer, Image  CommandQueue  Event Übersicht OpenCL Platform Device
  100. 100.  Context wird mit vector<> angelegt  Für jedes Device eine Queue Single-Context, Multi-Device
  101. 101.  OpenCL-Objekte „shared“  MemObjects, Programs, Kernels  MemObjects brauchen explizite Kopie  Kein D2D  Support für Partitions / Multi-GPU  Offsets für Kernel und Kopien  SubBuffer Single-Context, Multi-Device
  102. 102.  Pro Device einen Context  Alles separat und redundant  Evtl. einfacher zu programmieren  Scatter/Gather/Broadcast statt SubBuffer  Aufpassen bei der Datenhaltung  Einfache Erweiterung  Multi-Node oder heterogenes System Multi-Context & Multi-Device
  103. 103.  Von Single- zu Multi-GPU 1. Partionierung einführen 2. Vervielfachung der Datenstrukturen 3. Kernel erweitern  Mit Offsets und weiteren Extents Zusammenfassung
  104. 104.  Parallele Algorithmen  … und partitionierte Datenstrukturen  Hardware  PCIe-Problematik  Kompetenter PC-Hersteller notwendig  Fazit  Gute Speedups möglich  Wenn Halo-Kopien klein  und/oder hinter Kernel versteckt  Skaliert wegen PCIe nur begrenzt Fazit
  105. 105. Multi-Node
  106. 106.  Das gleiche Partitionierungsproblem  Kommunikation zwischen Nodes  Kein Shared-Host-Memory mehr  MPI_Send()  MPI_Recv()  GPU-spezifische Erweiterungen  OpenMPI, MVAPICH2 Multi-Node mit MPI
  107. 107.  Titan  18688 Opterons und 18688 Tesla K20X  Nr. 2 in Top 500 Multi-Node Nur am Rande …
  108. 108.  Folien http://dinkla.net/parallel2015  Sourcecode https://github.com/jdinkla/parallel2015_gpuco mputing Organisatorisch
  109. 109.  Schwerpunkte  Parallele Systeme  C++ und Java/JVM  GPU-Computing  CUDA, OpenCL, C++ AMP  Big Data, BI, Data Science  http://www.dinkla.com Last but not least Fragen? Sprechen Sie mich an oder joern@dinkla.com

×