PGI Accelerator Model Philip Höhlein, Nils Werner Supervision: R. Membarth, P. Kutzer, F. Hannig Hardware-Software-Co-Design Universität Erlangen-Nürnberg Philip Höhlein, Nils Werner 1
Übersicht Motivation Das PGI Accelerator Modell Eigenschaften einer NVIDIA GPU Funktionsweise Fazit Philip Höhlein, Nils Werner 2
Übersicht Motivation Das PGI Accelerator Modell Eigenschaften einer NVIDIA GPU Funktionsweise Fazit Philip Höhlein, Nils Werner 3
Motivation GPUs bieten hohen Performancegewinn bei parallelisierbaren Schleifen Fehlende Portabilität existierender Lösungen (CUDA, OpenCL,...) Umständliche Erzeugung der Schnittstellen und manuelle Allozierung des GPU-Speichers Daher wurde PGI Accelerator entworfen... Philip Höhlein, Nils Werner 4
Motivation Unterstützung für NVIDIA Familie (weitere in Entwicklung) Zusatz für Hochsprachen C und Fortran Programmieren der GPU alleine mit Pragmas Code zum Speicher Allozieren u. Kopieren wird vom Compiler automatisch generiert Schleifen werden automatisch in Kernels umgewandelt und zur GPU übertragen Spezielle Compiler PGCC und PGFortran Philip Höhlein, Nils Werner 5
Übersicht Motivation Das PGI Accelerator Modell Eigenschaften einer NVIDIA GPU Funktionsweise Fazit Philip Höhlein, Nils Werner 6
Das PGI Accelerator Modell OpenMP-Ähnliche Syntax #pragma in C #pragma acc region { } [...] Sentinals in Fortran!$acc region [...]!$acc end region Philip Höhlein, Nils Werner 7
Das PGI Accelerator Modell Regionen: (compute) region: Auswahl der Schleifen und zu kopierenden Daten data region (optional): Manuelle Kopieranweisungen - copy: Kopiere Variable zur GPU und anschließend zurück - local: Erzeuge lokale Variablen auf GPU - copyin: Kopiere Variable zur GPU und nicht zurück loop (optional): Optionen für die direkt folgende Schleife Philip Höhlein, Nils Werner 8
Das PGI Accelerator Modell Beispiel:!$acc data region copy(a(1:n,1:m)) &!$acc& local(b(2:n 1,2:m 1)) copyin(w(2:n 1)) do while(resid.gt.tol) resid = 0.0!$acc region do i = 2, n 1 do j = 2, m 1 b(i,j) = 0.25*w(i)*(a(i 1,j)+a(i+1,j)+a(i,j 1)+a(i,j+1)) enddo enddo do i = 2, n 1 do j = 2, m 1 resid = resid + (b(i,k) a(i,j))**2 a(i,j) = b(i,j) enddo enddo!$acc end region enddo!$acc end data region Philip Höhlein, Nils Werner 9
Übersicht Motivation Das PGI Accelerator Modell Eigenschaften einer NVIDIA GPU Funktionsweise Fazit Philip Höhlein, Nils Werner 10
Eigenschaften einer NVIDIA GPU... Multiprozessor Multiprozessor Multiprozessor Shared Memory Shared Memory Shared Memory GPU Speicher Host Speicher PCI Express Philip Höhlein, Nils Werner 11
Eigenschaften einer NVIDIA GPU Kernel Grid Block Block Block Threads Warp Threads Threads Block Block Block Threads Threads Threads Philip Höhlein, Nils Werner 12
Übersicht Motivation Das PGI Accelerator Modell Eigenschaften einer NVIDIA GPU Funktionsweise Fazit Philip Höhlein, Nils Werner 13
Funktionsweise 1. Finden von Parallelisierungsmöglichkeiten Suchregionen werden z.b. mittels #pragma acc vom Programmierer festgelegt Feedback wird zu Kompilierungszeit gegeben Philip Höhlein, Nils Werner 14
Funktionsweise 2. Abbilden der parallelen Schleifen auf die Hardware Jede Schleife wird auf 2 oder mehr verschachtelte Schleifen abgebildet Zwischenliegende Schleifen werden umsortiert um Stride-1 Speicherzugriffe zu ermöglichen Ggf. wird innerste Schleife abgerollt Anzahl Threads pro Block wird so angepasst um sämtliche MPs (min. ein Block pro MP!) auszulasten Daten für den Shared Memory werden auswählt Philip Höhlein, Nils Werner 15
Funktionsweise Unter Beachtung der User Direktiven: Äußerste Schleifen werden auf Blockindexraum abgebildet Gleichzeitig auf mehreren MPs MIMD-Parallelisierung Innerste Schleifen werden auf Threadindexraum abgebildet Gleichzeitig in einem Multiprozessor SIMT/Vektor-Parallelisierung Philip Höhlein, Nils Werner 16
Funktionsweise 3. Generierung und Optimierung des Kernel-Codes Maximale Anzahl der Threads pro Block festgelegt durch deren Resourcenbedarf (Shared Memory + Register) Compiler probiert 1-, 2- und 3-dimensionale Blockformen Maximal 512 Threads pro Block möglich: Sämtliche möglichen Blockformen innerhalb der Limits finden Philip Höhlein, Nils Werner 17
Funktionsweise Blockform wird gewählt nach 1 Plan mit den wenigsten Speicherzugriffen 2 Falls gleich, Plan mit den wenigsten zufälligen Speicherzugriffen 3 Falls gleich, Plan mit der größten Blockgröße 4 Falls gleich, Plan mit der größten Verschachtelungstiefe 5 Falls gleich, Plan mit kleinstem Speicherbedarf 6 (weitere kleinere, Unentschieden abwendende Regeln) Philip Höhlein, Nils Werner 18
Funktionsweise Beispiel do i = 2, n 1 do j = 2, m 1 b(i,j) = enddo enddo do i0 = 2, n 1, bi0!blockindex x do j0 = 2, m 1, bj0!blockindex y do i1 = i0, min(n 1, i0+bi0 1), bi1!sequentiell do j1 = j0, min(m 1, j0+bj0 1), bj1!sequentiell do i = i1, min(n 1, i1+bi1 1)!Threadindex x do j = j1, min(m 1, j1+bj1 1)!Threadindex y b(i,j) = enddo enddo enddo enddo enddo enddo Philip Höhlein, Nils Werner 19
Funktionsweise do i = 2, n-1 do j = 2, m-1 Philip Höhlein, Nils Werner 20
Funktionsweise do i0 =... do j0 =... do i1 =... do j1 =... do i =... do j =... Zum Beispiel: i0, j0 in 100er- Schritten i1,j1 in 10er- Schritten i, j in 1er-Schritten Philip Höhlein, Nils Werner 21
Funktionsweise Ausschnitt aus Aufteilung der Daten in x- und y-indizes Philip Höhlein, Nils Werner 22
Funktionsweise Feedback zu Kompilierzeiten smooth: 3, PGI Unified Binary version for tp=k8 64e ta=host 10, Loop interchange produces reordered loop nest: 11,10... smooth: 3, PGI Unified Binary version for tp=k8 64e ta=nvidia 8, Generating copyout(a(2:n 1,2:m 1)) Generating copyin(b(1:n,1:m)) Generating copyout(b(2:n 1,2:m 1))... Philip Höhlein, Nils Werner 23
Funktionsweise Feedback zu Kompilierzeiten for( i = 0; i < n 1; ++i ){ y = a[i+1]; b[i] = x + y; x = y; } >> 48, Loop carried scalar dependence for 'x' for( i = 0; i < n 1; ++i ){ b[i] = a[i] + a[i+1]; } Philip Höhlein, Nils Werner 24
Funktionsweise Feedback zu Kompilierzeiten for( i = 0; i < n; ++i ){ for( j = 0; j < n; ++i ){ a[j] = b[i][j] * w + c[i]*d[j]; if( a[j] > 0 ) p[i] = a[j]; } } >> Parallelization would require privatization of array 'a[0:n 1]' #pragma acc for private(a[0:n 1]) Philip Höhlein, Nils Werner 25
Funktionsweise Feedback zu Kompilierzeiten Accelerator Kernel Timing data c5.c test 32: region entered 1 time time(us): total=1411909 init=1408006 region=3903 kernels=44 data=3859 w/o init: total=3903 max=3903 min=3903 avg=3903 35: kernel launched 1 times grid: [7x7] block: [16x16] time(us): total=28 max=28 min=28 avg=28 39: kernel launched 1 times grid: [7x7] block: [16x16] time(us): total=16 max=16 min=16 avg=16 Philip Höhlein, Nils Werner 26
Übersicht Motivation Das PGI Accelerator Modell Eigenschaften einer NVIDIA GPU Funktionsweise Fazit Philip Höhlein, Nils Werner 27
Fazit PGI Accelerator versucht Auf existierenden Sprachen aufzubauen Den Anwender mit Feedback zu unterstützen Nicht Stride-1 Zugriffe zu vermeiden Portabel zu sein Noch nicht portabel z.b. zu ATI oder Intel Larrabee Planungen: Abbildung auf OpenMP, Standard Multicore funktioniert nur mit Fortran und C, kein C++, keine Structs Fehlt die feingranulare manuelle Optimierbarkeit z.b. von CUDA, Code ist meist langsamer Philip Höhlein, Nils Werner 28
Quellen [1] WOLFE, M. Implementing the PGI Accelerator Model (2010) [2] LEBACK, B., NAKAMOTO S., WOLFE, M. An Accelerator Programming Model for Multicore (2009) [3] WOLFE, M. et al. The PGI Accelerator Programming Model on NVIDIA GPUs (2009) http://www.pgroup.com/accelerate [4] BRADLEY, T. Advanced Cuda Optimization (2010) http://www.gris.informatik.tu-darmstadt.de/cuda-workshop/slides.html Philip Höhlein, Nils Werner 29
Vielen Dank für die Aufmerksamkeit! Noch Fragen? Philip Höhlein, Nils Werner 30