Prinzipieller Aufbau der Architektur eines Multikern- Prozessors. Programmierung Standard-Mulitkern-Prozessoren mit OpenMP

Ähnliche Dokumente
Eine kurze Geschichte der Grafikkarten

Einführung. GPU-Versuch. Andreas Schäfer Friedrich-Alexander-Universität Erlangen-Nürnberg

MESIF- (links) vs. MESI-Protokoll (rechts)

GPGPU-Architekturen CUDA Programmiermodell Beispielprogramm. Einführung CUDA. Ralf Seidler. Friedrich-Alexander-Universität Erlangen-Nürnberg

CUDA. Moritz Wild, Jan-Hugo Lupp. Seminar Multi-Core Architectures and Programming. Friedrich-Alexander-Universität Erlangen-Nürnberg

Viele Rechenaufgaben können auf verschiedene CPUs und/oder Maschinen aufgeteilt und verteilt werden, um die Leistung zu steigern

Intels Tick-Tock-Prinzip

Praxiseinheit: Realisierung einer hardwarebeschleunigten Disparitätenberechnung zur automatischen Auswertung von Stereobildern

GPGPU-Architekturen CUDA Programmiermodell Beispielprogramm Organiosatorisches. Tutorial CUDA. Ralf Seidler

Compute Unified Device Architecture CUDA

Grundlagen von CUDA, Sprachtypische Elemente

General Purpose Computation on GPUs

Masterpraktikum Scientific Computing

Programmierbeispiele und Implementierung. Name: Michel Steuwer

Grafikkarten-Architektur

OpenCL. Programmiersprachen im Multicore-Zeitalter. Tim Wiersdörfer

CUDA. Axel Jena, Jürgen Pröll. Multi-Core Architectures and Programming. Friedrich-Alexander-Universität Erlangen-Nürnberg Axel Jena, Jürgen Pröll 1

RST-Labor WS06/07 GPGPU. General Purpose Computation On Graphics Processing Units. (Grafikkarten-Programmierung) Von: Marc Blunck

2 Rechnerarchitekturen

Software Engineering für moderne parallele Plattformen 9. GPGPUs: Grafikkarten als Parallelrechner

OpenMP. Viktor Styrbul

Ferienakademie Erik Muttersbach

Yilmaz, Tolga MatNr: Mesaud, Elias MatNr:

CUDA. Jürgen Pröll. Multi-Core Architectures and Programming. Friedrich-Alexander-Universität Erlangen-Nürnberg Jürgen Pröll 1

Programmierung von Graphikkarten

2 Homogene und Heterogene Multi-/Vielkernprozessoren

Parallele Programmiermodelle

Konzepte der parallelen Programmierung

Beispielvortrag: HPCG auf Intel Haswell-EP

Einige Grundlagen zu OpenMP

Multicore-Architekturen

Gliederung. Was ist CUDA? CPU GPU/GPGPU CUDA Anwendungsbereiche Wirtschaftlichkeit Beispielvideo

Multi- und Many-Core

Seminar Multicore-Programmierung

GPGPU-Programming. Constantin Timm Informatik 12 TU Dortmund 2012/04/09. technische universität dortmund. fakultät für informatik informatik 12

nutzt heute Diese Prinzipien werden wir im Kapitel 4 behandelt Lehrstuhl für Informatik 3 - D. Fey Vorlesung GRa - SS

LEISTUNGSVERGLEICH VON FPGA, GPU UND CPU FÜR ALGORITHMEN ZUR BILDBEARBEITUNG PROSEMINAR INF-B-610

Parallele Programmierung mit GPUs

2 Homogene und Heterogene Multi-/Vielkernprozessoren

Praktikum: Paralleles Programmieren für Geowissenschaftler

ANALYSE DER LATENZEN IM KOMMUNIKATIONSSTACK EINES PCIE-GEKOPPELTEN FPGA-BESCHLEUNIGERS. Sascha Kath

PGI Accelerator Model

Motivation (GP)GPU CUDA Zusammenfassung. CUDA und Python. Christian Wilms. Integriertes Seminar Projekt Bildverarbeitung

Grundlagen der Spieleprogrammierung

Untersuchung und Vorstellung moderner Grafikchiparchitekturen

High Performance Embedded Processors

OpenCL. OpenCL. Boris Totev, Cornelius Knap

Automatische Parallelisierung

In heutigen Computern findet man schnellen/teuren als auch langsamen/billigen Speicher

Stream Processing und High- Level GPGPU Sprachen

Parallel Computing. Einsatzmöglichkeiten und Grenzen. Prof. Dr. Nikolaus Wulff

Technische Informatik 1 Übung 8 Instruktionsparallelität (Rechenübung) Andreas Tretter 8./9. Dezember Bitte immer eine Reihe freilassen

Multicore Architektur vs. Amdahl`s Gesetz

Vertiefungsrichtung Rechnerarchitektur

Multicore Herausforderungen an das Software-Engineering. Prof. Dr.-Ing. Michael Uelschen Hochschule Osnabrück

Mehrprozessorarchitekturen

Universität Karlsruhe (TH)

Software Engineering für moderne, parallele Plattformen. 9. GPGPUs: Grafikkarten als Parallelrechner. Dr. Victor Pankratius

Games with Cellular Automata auf Parallelen Rechnerarchitekturen

Projektseminar Parallele Programmierung

Architektur von Parallelrechnern 50

Computeranwendung in der Chemie Informatik für Chemiker(innen) 3. Software

Einleitung Die Pins alphabetisch Kapitel 1 Programmierung des ATmega8 und des ATmega

Vorstellung der SUN Rock-Architektur

1. Einführung in OpenMP

Grundlagen der Rechnerarchitektur

Intels Tick-Tock-Prinzip

Quiz. Gegeben sei ein 16KB Cache mit 32 Byte Blockgröße. Wie verteilen sich die Bits einer 32 Bit Adresse auf: Tag Index Byte Offset.

Inhalt. Prozessoren. Curriculum Manfred Wilfling. 28. November HTBLA Kaindorf. M. Wilfling (HTBLA Kaindorf) CPUs 28. November / 9

SS08, LS12, Friedrich-Alexander-Universität Erlangen Florian Hänel, Frederic Pollmann HS Multicore Architectures and Programming GPU EVOLUTION

> High-Level Programmierung heterogener paralleler Systeme

GPU-Programmierung: OpenCL

CPU, GPU und FPGA. CPU, GPU und FPGA Maximilian Bandle, Bianca Forkel 21. November 2017

Cell Broadband Engine & CellSs: ein Programmiermodel für den Cell Prozessor

Multi-threaded Programming with Cilk

PRIP-Preis. Effizientes Object Tracking durch Programmierung von Mehrkernprozessoren und Grafikkarten

Evaluation. Einleitung. Implementierung Integration. Zusammenfassung Ausblick

Grundlagen der Parallelisierung

Shared-Memory Programmiermodelle

Numerik und Rechnen. Martin Heide & Dominik Holler. 12. Juni 2006

OpenCL Implementierung von OpenCV Funktionen

OpenMP - Threading- Spracherweiterung für C/C++ Matthias Klein, Michael Pötz Systemprogrammierung 15. Juni 2009

Parallele Programmierung mit OpenMP

Parallele und verteilte Programmierung

GPGPU mit NVIDIA CUDA

Systeme 1: Architektur

Technische Grundlagen der Informatik 2 SS Einleitung. R. Hoffmann FG Rechnerarchitektur Technische Universität Darmstadt E-1

Ein kleiner Einblick in die Welt der Supercomputer. Christian Krohn

Datenbanken Implementierungstechniken SS2015

Architektur moderner GPUs. W. Sczygiol - M. Lötsch

Vorlesung Rechnerarchitektur. Einführung

Physikalische Berechnungen mit General Purpose Graphics Processing Units (GPGPUs)

Computational Biology: Bioelektromagnetismus und Biomechanik

Multi-Port-Speichermanager für die Java-Plattform SHAP

OpenMP am Beispiel der Matrizenmultiplikation


Systeme I: Betriebssysteme Kapitel 4 Prozesse. Wolfram Burgard

Eine Einführung in die Architektur moderner Graphikprozessoren

Arithmetische und Logische Einheit (ALU)

Beispiel Parallelisierung 2D Laplace. Lagrange Formulierung/Hyperelastisches Material. Finite Differenzen Diskretisierung

Transkript:

3.1 Einführung Multi-Core-Architekturen Motivation Multikern-Prozessoren Prinzipieller Aufbau der Architektur eines Multikern- Prozessors Programmierung Standard-Mulitkern-Prozessoren mit OpenMP Programmierung von Grafikkern-Prozessoren unter CUDA WS 2013/14, 9.12.-16.12.2012 Folie 1

3.1 Einführung Multi-Core-Architekturen Sprunghafter Anstieg der Leistung von Mikroprozessoren Verbesserte Organisation, verbesserte Architektur Erhöhte Taktfrequenz Mehr Parallelität Pipelining Superskalare Architekturen Simultanes Multithreading (SMT) Preis der höheren Parallelität Höhere Komplexität erfordert mehr Logik Ansteigende Chipfläche für die Organisation und Bedarf an Logik für Signalübertragung Schwieriger zu entwerfen, herzustellen und Fehler zu suchen (debugging) WS 2013/14, 9.12.-16.12.2012 Folie 2

3.1 Einführung Multi-Core-Architekturen Grobe Skizzierung des Aufbaus der Architekturen Superskalar Simultanes Multithreading Multikern-Prozessor WS 2013/14, 9.12.-16.12.2012 Folie 3

3.1 Einführung Multi-Core-Architekturen Anstieg Leistung Relativ zu Leistung einer Architektur von 1985 In Relation zur Taktfrequenz WS 2013/14, 9.12.-16.12.2012 Folie 4

3.1 Einführung Multi-Core-Architekturen Anforderung: elektrische Leistung wächst exponentiell mit Schaltungsdichte auf Chip und Taktfrequenz WS 2013/14, 9.12.-16.12.2012 Folie 5

3.1 Einführung Multi-Core-Architekturen Gegensteuern durch Verwendung Chipfläche für Cache Höhere Dichte möglich durch regulären Aufbau SRAM-Speicher Eine Größenordnung weniger Leistungsbedarf vs. Logik WS 2013/14, 9.12.-16.12.2012 Folie 6

3.1 Einführung Multi-Core-Architekturen Schätzung bis 2015 (ca. 8 Jahre alt) 100 Milliarden Transistoren auf 300 mm² Chip-Die (Chip-Inneres) Cache der Größe 100 MB 1 Milliarde Transistoren für Logik WS 2013/14, 9.12.-16.12.2012 Folie 7

3.1 Einführung Multi-Core-Architekturen Regel von Pollack Leistung ungefähr proportional zur Quadratwurzel des Anstiegs an Komplexität Doppelte Komplexität, d.h. doppelt so großer Einzelprozessor schafft nur 40% mehr Leistung Multikern-Technik hat prinzipielles Potential für nahezu lineare Verbesserung Unwahrscheinlich, dass ein einziger Thread den gesamten Cache effektiv nutzt Mehrere Threads nutzen mehrere Caches als einen einzigen riesig großen Cache besser aus WS 2013/14, 9.12.-16.12.2012 Folie 8

3.1 Einführung Multi-Core-Architekturen Vorteile bei Leistung hängen effektiv von der Ausnutzung der parallelen Ressourcen ab Bereits geringe Anteile an seriellem Kode beeinflussen die Leistung 10% inhärenter serieller Anteil führt auf 8 Prozessorsystem nur zu 4,7-fachen Leistungsanstieg (Details s. später Kapitel 5) Weiterhin: Zusatzaufwand durch Parallelisierung Kommunikation Lastverteilung Einhalten der Cachekohärenz Bestimmte Anwendungen können Potential von Multikernprozessoren effektiv ausnutzen WS 2013/14, 9.12.-16.12.2012 Folie 9

3.1 Einführung Multi-Core-Architekturen Beispiele: allgemein Serverrechner, die unabhängige Anfragen beantworten Datenbanken Native Multi-Thread und Multi-Prozess Applikationen Z.B. Lotus Domino, Siebel CRM, Oracle, SAP, PeopleSoft Java VM ist Multi-Thread-Lösung mit Ablaufplanung und Speichermanagement Sun s Java Application Server, BEA s Weblogic, IBM Websphere, Tomcat Mehrfache Instanziierungen einer Applikation Eine Applikation, die mehrfach läuft Single Program Multiple Data (SPMD) Inhärente Parallelität, z.b. Parameterstudien Details s. Kap. 5, Parallelisierungsstrategien WS 2013/14, 9.12.-16.12.2012 Folie 10

3.1 Einführung Multi-Core-Architekturen Erreichbare Beschleunigung (Speedup) gegenüber einem Prozessor Für verschiedene Anzahl an Prozessoren Verschieden hohe serielle Anteile Ohne Berücksichtigung Overhead WS 2013/14, 9.12.-16.12.2012 Folie 11

3.1 Einführung Multi-Core-Architekturen Mit Berücksichtigug Overhead WS 2013/14, 9.12.-16.12.2012 Folie 12

3.1 Einführung Multi-Core-Architekturen Merkmale für Multikern-Architekturen Anzahl Prozessorkerne auf dem Chip Anzahl Cacheebenen auf dem Chip Anteil gemeinsamer Speicher Auf den nächsten Folien Beispiele: Intel Core Duo Intel Core i7 WS 2013/14, 9.12.-16.12.2012 Folie 13

3.1 Einführung Multi-Core-Architekturen Verschiedene Varianten der Core-Cache-Anbindung Dedizierter vs. gemeinsamer Cache WS 2013/14, 9.12.-16.12.2012 Folie 14

3.1 Einführung Multi-Core-Architekturen Intel Core Duo verwendete superskalare Kerne WS 2013/14, 9.12.-16.12.2012 Folie 15

3.1 Einführung Multi-Core-Architekturen Stand 2006 2 superskalare x86 - Architekturen, gemeinsamer L2 Cache Dedizierter L1-Cache pro Kern 32 KB für Befehle und 32 KB für Daten Thermische Steuereinheit pro Kern Behandelt Hitzedissipation des Prozessorchips Maximiert Leistung unter Beachtung von Randbedingungen Verbesserte Ergonomie Advanced Programmable Interrupt Controller (APIC) Interprozess Unterbrechungen zwischen Kernen Verteilt Unterbrechung zu entsprechenden Kern Beinhaltet Timer-Komponente, so dass Betriebssystem den Kern unterbrechen kann WS 2013/14, 9.12.-16.12.2012 Folie 16

3.1 Einführung Multi-Core-Architekturen Power Management Logic Zeigt thermische Bedingungen und CPU Aktivität an Regelt Spannung und damit Leistungsverbrauch Kann individuell logische Subsysteme zu- und abschalten Gemeinsamer 2 MB großer L2 Cache Dynamische Zuweisung MESI (ist ein Cache-Kohärenz-Protokoll, s. 4.5.2) Unterstützung für L1 Cache Wurde gegenüber früheren Lösungen erweitert um mehrere Duo- Kern-Architekturen beim Aufbau von symmetrischen Multiprozessoren (SMP) zu unterstützen gemeinsame L2 Daten zwischen lokalen Kernen oder externen Kernen geteilt WS 2013/14, 9.12.-16.12.2012 Folie 17

3.1 Einführung Multi-Core-Architekturen Intel Core i7 verwendet simultanes Multi-Threading (SMT) Skaliert bis zur Anzahl unterstützter Threads 4 SMT Kerne, jeder unterstützt 2 Threads somit 8 logische Kerne WS 2013/14, 9.12.-16.12.2012 Folie 18

3.1 Einführung Multi-Core-Architekturen November 2008 Vier x86 SMT Prozessorkerne Dedizierter L2, gemeinsamer L3 Cache Spekulative vorausschauendes Holen (pre-fetch) für Caches On chip DDR3 Speicherkontroller Drei 8 Byte Kanäle (192 Bits) mit insgesamt 32 GB/s Bandbreite Keinen Front Side Bus mehr QuickPath Verbindung Cache-kohärente Punkt-zu-Punkt-Verbindung Hochgeschwindigkeits-Verbindung zwischen Prozessorchips 6.4 x 10 9 Transfers pro Sekunde mit 16 Bits pro Transfer Dedizierter bi-direktionaler Kanal Gesamte Bandbreite: 25.6 GB/s WS 2013/14, 9.12.-16.12.2012 Folie 19

3.1 Einführung Multi-Core-Architekturen OpenMP: Anwender-Programmierschnittstelle (API) für Speicher-gekoppelte Multiprozessoren Compiler-Direktiven Bibliothek unterstützender Funktionen OpenMP arbeitet in Verbindung mit Fortran, C, oder C++ Modell des gemeinsamen Speichers Synchronisation und Interaktion der Prozessoren untereinander durch gemeinsame Variablen Processor Processor Processor Processor Memory WS 2013/14, 9.12.-16.12.2012 Folie 20

3.1 Einführung Multi-Core-Architekturen Fork/Join-Parallelismus zu Beginn nur Master-Thread aktiv Master-Thread führt sequentiellen Kode aus Fork: Master-Thread erzeugt oder erweckt zusätzliche Threads um parallelen Kode auszuführen Join: am Ende des parallelen Kodes sterben Threads bzw. werden ausgesetzt Master Thread Other threads fork Time join fork join WS 2013/14, 9.12.-16.12.2012 Folie 21

3.1 Einführung Multi-Core-Architekturen Speicher-gekoppeltes Modell vs. Nachrichten-gekoppeltes Modell Speicherkopplung: (shared-memory model) Anzahl der aktiven Threads zu Beginn und am Ende des Programms 1 Anzahl ändert sich dynamisch während der Programmausführung Nachrichtenkopplung: (message-passing model) alle Prozesse sind während der Ausführung eines Programms aktiv WS 2013/14, 9.12.-16.12.2012 Folie 22

3.1 Einführung Multi-Core-Architekturen Inkrementelle Parallelisierung inkrementelle Parallelisierung: Prozess des schrittweisen Übertragens eines seriellen Programms in ein paralleles Programm Speicher-gekoppeltes Modell Ausführen und Messen sequentielles Programm inkrementelles Parallelisieren Beenden wenn weiterer Aufwand nicht mehr lohnt Beispiel: OpenMP (Open Multiprocessing) Nachrichten-gekoppeltes Modell Übertragung sequentiell nach parallel erfordert mehr Aufwand, da Übertragung in einem großen statt in vielen kleinen Schritten erfolgt Beispiel: MPI (Message Passing Interface) WS 2013/14, 9.12.-16.12.2012 Folie 23

3.1 Einführung Multi-Core-Architekturen Beispiel Parallelisierung von Schleifen in C Programm häufig in for-schleifen Datenparallelität gegeben for (i = 0; i < N; i++) a[i] = b[i] + c[i]; OpenMP verwendet möglichst einfachen Mechanismus um anzuzeigen, wann Iterationen einer Schleife parallel ausgeführt werden können Compiler generiert automatisch Kode, der weitere den Iterationen zugeordnete Threads durch Fork/Join-Operationen erzeugt Verwendung von pragma Compiler-Direktiven steht für pragmatische Information ( pragmatic information ) Möglichkeit der Kommunikation Programmierer und Compiler Compiler obliegt es Pragma-Anweisungen zu ignorieren Syntax: allgemein #pragma omp <rest of pragma> Beispiel: #pragma omp parallel for for (i = 0; i < N; i++) a[i] = b[i] + c[i]; WS 2013/14, 9.12.-16.12.2012 Folie 24

3.1 Einführung Multi-Core-Architekturen Kanonische Form der Steuerungssyntax einer prinzipiell parallelisierbaren for-schleife kein vorzeitiges Schleifenende z.b. goto, return, break erlaubt: continue, exit, for(index start;index index index index index end; index ) index inc inc index index inc index inc index index index inc WS 2013/14, 9.12.-16.12.2012 Folie 25

3.1 Einführung Multi-Core-Architekturen Ausführungskontext (execution context) jeder Thread hat seinen eigenen Ausführungskontext Ausführungskontext: Adressraum, der alle Variablen enthält auf die Thread möglicherweise zugreift Inhalte eines Ausführungskontextes: statische Variablen dynamisch allozierte Datenstrukturen im Heap Variablen auf dem Stack zur Laufzeit zusätzlicher Laufzeit-Stack für vom Thread aufgerufene Funktionen gemeinsame und private Variablen gemeinsame Variablen gleiche Adresse im Ausführungskontext eines jeden Thread private Variable verschiedene Adresse im Ausführungskontext eines jeden Thread Thread-übergreifend geschützt WS 2013/14, 9.12.-16.12.2012 Folie 26

3.1 Einführung Multi-Core-Architekturen gemeinsame und private Variablen int main (int argc, char *argv[]) { int b[3]; char *cptr; int i; cptr = malloc(1); #pragma omp parallel for for (i = 0; i < 3; i++) b[i] = i; Heap Stack i b Master Thread (Thread 0) cptr i i Thread 1 WS 2013/14, 9.12.-16.12.2012 Folie 27

3.1 Einführung Multi-Core-Architekturen Deklarieren privater Variablen neues Schleifen-Beispiel for (i = 0; i < m; i++) for (j = 0; j < n; j++) a[i][j] = MIN(a[i][j],a[i][k]+tmp); beide Schleifen können parallel ausgeführt werden. Welche wählen? Korngröße: Anzahl Schritte bis zu einer Synchronisation bzw. Kommunikation möglichst große Korngröße höherer Gewinn bei paralleler Ausführung daher Parallelisierung der äußeren Schleife reduziert Anzahl an fork/join-operationen jeder Thread braucht eigene private Kopie der Variable j WS 2013/14, 9.12.-16.12.2012 Folie 28

3.1 Einführung Multi-Core-Architekturen ansonsten: einzelne Threads verändern unkoordiniert globale Variable j Private clause (Zusatz) Angabe mittels pragma Zusatz private ( <variable list> ) #pragma omp parallel for private(j) for (i = 0; i < m; i++) for (j = 0; j < n; j++) a[i][j] = MIN(a[i][j],a[i][k]+tmp); WS 2013/14, 9.12.-16.12.2012 Folie 29

3.1 Einführung Multi-Core-Architekturen manchmal gewünscht: private Variable erbt zu Beginn Wert der gemeinsamen Variablen Beispiel: x[0] = complex_function(); for (i = 0; i < n; i++) { for (j = 1; j < 4; j++) x[j] = g(i, x[j-1]); answer[i] = x[1] x[3]; } Zusatz firstprivate(<variable list>) x[0] = complex_function(); #pragma omp parallel for private(j) firstprivate(x) for (i = 0; i < n; i++) { for (j = 1; j < 4; j++) x[j] = g(i, x[j-1]); answer[i] = x[1] x[3]; } WS 2013/14, 9.12.-16.12.2012 Folie 30

3.1 Einführung Multi-Core-Architekturen Gegenstück: gewünscht: Thread, der sequentiell betrachtet, die letzte Iteration ausführt, soll Wert wieder in globale Variable zurückspeichern. Beispiel: for (i = 0; i < n; i++) { x[0] = 1.0 ; for (j = 1; j < 4; j++) x[j] = x[j-1] * (i+1); sum_of_powers[i] = x[0] + x[1] + x[2] + x[3]; } n_cubed = x[3]; Zusatz lastprivate(<variable list>) #pragma omp parallel for private(j) firstprivate(x) lastprivate(x) for (i = 0; i < n; i++) { x[0] = 1.0 ; for (j = 1; j < 4; j++) x[j] = x[j-1] * (i+1); sum_of_powers[i] = x[0] + x[1] + x[2] + x[3]; } n_cubed = x[3]; WS 2013/14, 9.12.-16.12.2012 Folie 31

3.2 GPGPUs Eine kurze Geschichte der Grafikkarten ursprünglich: Graphics Card steuert Monitor an Mitte 80er: Grafikkarten mit 2D-Beschleunigung angelehnt an Arcade- und Home-Computer frühe 90er: erste 3D-Beschleunigung: Matrox Mystique, 3dfx Voodoo Rastern von Polygonen WS 2013/14, 9.12.-16.12.2012 Folie 32

3.2 GPGPUs Eine kurze Geschichte der Graphikkarten ursprünglich keine einheitliche Programmierschnittstelle herstellerspezifische Lösungen (3dfx Glide bzw. Matrox Simple Interface) Anfang der 90er: OpenGL etabliert in professionellem Umfeld Microsofts Direct3D zunächst unterlegen gewinnt Marktanteile dank häufiger Verbesserungen Ende der 90er: Grafikkarten übernehmen Koordinaten-Transformation und Beleuchtung (z.b. NVIDIA GeForce 256) Begriff Graphics Processing Unit wird erfunden WS 2013/14, 9.12.-16.12.2012 Folie 33

3.2 GPGPUs Beispiel: Direct3D 10 Pipeline WS 2013/14, 9.12.-16.12.2012 Folie 34

3.2 GPGPUs 2000er: zunächst nur Fixed-Function-Pipeline (FFP) Shader-Programme bieten mehr Flexibilität als FFP Pixel-Shader modellieren Oberflächen Vertex-Shader modifizieren Gitterpunkte Shader-Programme ursprünglich nur einfache Listen 2002: ATI Radeon 9700 kann Loops in Shadern ausführen Heute: Shader Turing-vollständig Hersteller: ATI und NVIDIA Massenmarkt niedrige Preise WS 2013/14, 9.12.-16.12.2012 Folie 35

3.2 GPGPUs GPGPUs GPGPU = General Purpose Graphics Processing Unit Grafikkarten zunehmend flexibler programmierbar stetig wachsende Leistung geeignet für Streamprozessing geringes Verhältnis IO-zu-Rechenlast Datenparallelität (SIMD-Verarbeitung) Ausrichtung auf Spiele: single precision wichtiger als double precision WS 2013/14, 9.12.-16.12.2012 Folie 36

3.2.1 GPGPU-Architektur Aufbau GPGPU WS 2013/14, 9.12.-16.12.2012 Folie 37

3.2.1 GPGPU-Architektur Eigenschaften von GPGPUs viele, aber einfache Cores keine Sprungvorhersage etc. gruppiert in Multi-Prozessoren (Vektorprozessoren) Probleme bei nicht einheitlichen Sprüngen viele Register großer globaler Speicher Bandbreite: >100 GB/s Latenz: ~400 Taktzyklen kleine, schnelle on-chip Shared-Memory-Blöcke WS 2013/14, 9.12.-16.12.2012 Folie 38

3.2.1 GPGPU-Architektur Allgemeines Architekturschema einer Multithread-fähigen sog. Streaming Multiprozessoreinheit (SM) WS 2013/14, 9.12.-16.12.2012 Folie 39

3.2.1 GPGPU-Architektur Speicherhierarchie (Speicherräume) einer GPU: Globaler Speicher Untergebracht im externen DRAM Gleich aufgeteilt in SMs zugewiesenen Adressräumen Nicht explizit zugreifbar von CUDA-Programm Zu einem Zeitpunkt nur ein Thread zugreifbar Gemeinsamer Speicher Untergebracht in SM-spezifischen SRAM-Bänken SM-spezifisch Gekoppelt an Thread-Block (s. später) WS 2013/14, 9.12.-16.12.2012 Folie 40

3.2.1 GPGPU-Architektur Lokaler Speicher Thread-spezifisch im SM-externen DRAM untergebracht Ausgleich Performanz-Verlust: Caching im gemeinsamen SM-Speicher dieser konfigurierbar Spezielle Speicher Texturen Konstanten Beides sind Konstantenspeicher, die zu Beginn einer Berechnung auf der Grafikkarte von der CPU beschreibar sind WS 2013/14, 9.12.-16.12.2012 Folie 41

3.2.1 GPGPU-Architektur Hardware-Details: NVIDIA G80 NVIDIA G80 Multiprozessor Vektorprozessor beinhaltet: 8 Shader: Single-Precision-Float- und Integer-Rechenwerk 1 Double Precision Unit (DPU) 2 Special Function Units (SFU) Sinus etc. 4096 Register 16 KB Shared Memory WS 2013/14, 9.12.-16.12.2012 Folie 42

3.2.1 GPGPU-Architektur Hardware-Details: NVIDIA GT100 (a.k.a. Fermi) Vektorprozessor, beinhaltet: 32 Shader: Integer-Rechenwerk und Single-Precision-Float oder Double Precision mit halber Geschwindigkeit 16 Load-/Store-Units 4 Special Function Units (SFU) Sinus etc. 64 KB Shared Memory/Cache Aufteilbar in Cache für einzelne Threads und Gemeinsamen Speicher für alle SPs 32 K Register WS 2013/14, 9.12.-16.12.2012 Folie 43

3.2.1 GPGPU-Architektur Blockdiagramm Layout der Fermi-Architektur Entnommen aus Nvidia_Fermi_Computer_Architecture_WhitePaper.pdf Ablaufplanung / Verteilung (Scheduler / Dispatcher) Registerspeicher SM-Prozessor SP-Prozessor Load/Store-Units SFU-Prozessor L1 Cache / Shared Memory WS 2013/14, 9.12.-16.12.2012 Folie 44

3.2.1 GPGPU-Architektur Speicherhierarchie: Register (am schnellsten) Shared Memory/L1 Cache entweder 16 KB Cache und 48 KB Shared Memory oder 48 KB Cache und 16 KB Shared Memory L2 Cache 768 KB ca. 260 GB/s Bandbreite DRAM 1-6 GB ca. 130 GB/s Bandbreite Latenz ca. 400 Takte WS 2013/14, 9.12.-16.12.2012 Folie 45

3.2.2 CUDA-Programmiermodell CUDA unterstützt ein Thread-paralleles und Daten-paralleles Programmierparadigma Jedoch Unterschied zu anderen Thread-parallelen Zerlegungen Alle Threads müssen die gleichen Operationen ausführen In diesem Sinne: Datenparallelität Nvidia bezeichnet dies als: SIMT (Single Instruction Multiple Threading) Möglich ist jedoch Wechsel von Threads, genauer ganzen Thread-Feldern, während einer Applikation WS 2013/14, 9.12.-16.12.2012 Folie 46

3.2.2 CUDA-Programmiermodell Veranschaulichung: Datenparallelität 2D/3D-Feld (Data-Grid) in Blöcke partitionieren Jeder Block enthält einzelne nicht weiter zerlegbare Elemente Auf jedem Element die gleiche Operation anwenden Bearbeitung verschiedener Felder zeitlich nacheinander möglich WS 2013/14, 9.12.-16.12.2012 Folie 47

3.2.2 CUDA-Programmiermodell Übertragen auf Threads und kooperative Thread-Felder Dieses und folgende Bilder entnommen aus: Nvidia Programming Guide Vers. 2.3.1, 2009 WS 2013/14, 9.12.-16.12.2012 Folie 48

3.2.2 CUDA-Programmiermodell Übertragen auf Threads und kooperative Thread-Felder WS 2013/14, 9.12.-16.12.2012 Folie 49

3.2.3 CUDA-Programmierung CUDA Programmierung in C Function-Offloading: einzelne Funktionen laufen auf GPGPU (Kernels) bzw. CPU spezieller Compiler (nvcc) separiert Code drei Funktionstypen: host laufen auf CPU device laufen auf GPGPU global laufen auf GPGPU (können aber nur von CPU aufgerufen werden) drei Speichertypen: normaler Speicher im CPU-RAM device im RAM der GPGPU shared im Shared-Memory auf den Multi-Prozessoren WS 2013/14, 9.12.-16.12.2012 Folie 50

3.2.3 CUDA-Programmierung Darstellung zeitlicher Ablauf eines CUDA-Programms Heterogene Programmierung Serieller Kode läuft auf der CPU Paralleler Kode läuft auf der GPU Dimension von Grid und Thread-Blöcken wählbar dim3 dimblock0(1,12) ; dim3 Grid0(2,3) ; Kernel0<<<dimGrid0,dimBlock0>>>(,, ); bzw. dim3 dimblock1(1,9); dim3 Grid1(3,2); Kernel1<<<dimGrid,1dimBlock1>>>(,, ); WS 2013/14, 9.12.-16.12.2012 Folie 51

3.2.3 CUDA-Programmierung Cuda Memory Management CUDA-API-Aufrufe: Allokation/Deallokation von GPGPU-RAM Transfer GPGPU-RAM -> CPU-RAM, CPU-RAM -> GPGPU-RAM cudamalloc(, ) ; cudamemcpy(,, cudamemcpydevicetohost) ; cudamemcpy(,, cudamemcpyhosttodevice) ; (CUDA)-Kernels: Transfer GPGPU-RAM <-> Shared-Memory GetElement(, ) greift auf Device-Speicher zu shared float As[BLOCK_SIZE] ; As[row] = GetElement(...,...) ; WS 2013/14, 9.12.-16.12.2012 Folie 52

3.2.3 CUDA-Programmierung 1. CUDA - Programmbeispiel: Hello World WS 2013/14, 9.12.-16.12.2012 Folie 53

3.2.3 CUDA-Programmierung CUDA: Hello World: WS 2013/14, 9.12.-16.12.2012 Folie 54

3.2.3 CUDA-Programmierung CUDA: Vektor-Addition-Beispiel Kode für GPU // Device code global void VecAdd(float* A, float* B, float* C) { int i = blockdim.x * blockidx.x + threadidx.x; } if (i < N) C[i] = A[i] + B[i]; WS 2013/14, 9.12.-16.12.2012 Folie 55

3.2.3 CUDA-Programmierung CUDA: Vektor-Addition-Beispiel Kode für CPU // Host code int main() { int N =...; size_t size = N * sizeof(float); // Allocate input vectors h_a and h_b in host memory float* h_a = (float *) malloc(size); float* h_b = (float *) malloc(size); float* h_c = (float *) malloc(size); // Enter values in h_a and h_b... // Allocate vectors in device memory float* d_a, d_b, d_c; cudamalloc((float**)&d_a, size); cudamalloc((float**)&d_b, size); cudamalloc((float**)&d_c, size); // Copy vectors from host memory to device memory cudamemcpy(d_a, h_a, size, cudamemcpyhosttodevice); cudamemcpy(d_b, h_b, size, cudamemcpyhosttodevice); WS 2013/14, 9.12.-16.12.2012 Folie 56

3.2.3 CUDA-Programmierung CUDA: Vektor-Addition-Beispiel Kode für CPU // Invoke kernel int threadsperblock = 256; int blockspergrid = (N + threadsperblock 1) / threadsperblock; VecAdd<<<blocksPerGrid, threadsperblock>>>(d_a, d_b, d_c); // Copy result from device memory to host memory // h_c contains the result in host memory cudamemcpy(h_c, d_c, size, cudamemcpydevicetohost); // Output h_c... // Free device memory cudafree(d_a); cudafree(d_b); cudafree(d_c); } WS 2013/14, 9.12.-16.12.2012 Folie 57

3.2.4 Fortgeschrittene CUDA-Programmierung Thread-Scheduling: Kernel = Funktion auf Grafikkarte viele Threads um Parallelität der GPGPU zu nutzen und Speicherlatenz zu verdecken wie gezeigt: Threads gruppiert in Blöcken Thread-Blöcke gruppiert in Grid Grid und Blöcke können 1D bis 3D sein Thread-IDs: Koordinaten blockidx, threadidx. WS 2013/14, 9.12.-16.12.2012 Folie 58

3.2.4 Fortgeschrittene CUDA-Programmierung Thread-Scheduling: Thread-Blöcke werden auf Multiprozessoren verteilt Multiprozessoren brechen Blöcke in Warps auf Warps = kleinere Thread-Gruppen (meist 32 Threads) Warps bestehen aus zwei Half-Warps alle Threads eines Warps: quasi-parallele Ausführung Problem bei divergenten Branches: serielle Abarbeitung WS 2013/14, 9.12.-16.12.2012 Folie 59

3.2.4 Fortgeschrittene CUDA-Programmierung Thread-Scheduling Problem-Zerlegung: viele Blöcke alle Multiprozessoren beschäftigt viele Threads je Block Speicherlatenz verdecken aber: je weniger Threads je Block, desto mehr Shared Memory je Thread verfügbar Daumenregel: doppelt so viele Blöcke wie Multiprozessoren 256 Threads je Block Praxis: viel Experimentieren notwendig um optimale Aufteilung zu finden WS 2013/14, 9.12.-16.12.2012 Folie 60

3.2.4 Fortgeschrittene CUDA-Programmierung Speicherzugriff Thread mit Nummer x im Warp Aligned: Thread x greift auf Adresse 128 k + 4 x zu Coalescing: Alle Zugriffe eines Warps können in eine Transaktion von 128 Byte zusammengefasst werden Coalescing bringt beste Performance, benötigt meist Alignment alte GPUs (Compute Capability 1.0 bzw. 1.1) ineffizienter als neue (Compute Capability 1.2) Bei Schreiben auf dieselbe Adresse: Warp Serialize (serielle Ausführung der Threads eines Warps) WS 2013/14, 9.12.-16.12.2012 Folie 61

3.2.4 Fortgeschrittene CUDA-Programmierung Speicherzugriff: Coalescing, Compute Capability 1.1 k-ter Thread greift auf k-tes Wort in 128-Byte-Segment zu, nicht alle Threads müssen teilnehmen. OK, 1 Transaktion: Out of Sequence, 16 Transaktionen: Misaligned, 16 Transaktionen: WS 2013/14, 9.12.-16.12.2012 Folie 62

3.2.4 Fortgeschrittene CUDA-Programmierung Speicherzugriff: Coalescing, Compute Capability 1.2 Transaktionen können 32, 64 oder 128 Byte groß sein, kleinere Transaktionen um Bandbreite zu sparen. 1 Transaktion, 64 Byte: 2 Transaktionen, 64 bzw. 32 Byte: 1 Transaktion, 128 Byte: WS 2013/14, 9.12.-16.12.2012 Folie 63

3.2.4 Fortgeschrittene CUDA-Programmierung Speicherzugriff Kopiert Vector src nach dst Offset verschiebt Alignment bei falschem Alignment kein Coalescing daher schlechter Durchsatz Richtigen offset finden durch Probieren, dann besserer Durchsatz WS 2013/14, 9.12.-16.12.2012 Folie 64

3.2.4 Fortgeschrittene CUDA-Programmierung Beispiel: Matrix-Multiplikation Scheinbar einfache Aufgabe häufig Teilproblem beim wissenschaftlichen Rechnen Beispiele: Computergrafik Optik Matrizenmechanik Schwierigkeit: wenig Berechnung aber viel Speicherzugriff Ziel: Speicherzugriffe so organisieren, dass maximale Bandbreite erreicht wird. WS 2013/14, 9.12.-16.12.2012 Folie 65

3.2.4 Fortgeschrittene CUDA-Programmierung Beispiel: Matrix-Multiplikation Folgende Beispiele: Multiplikation von float-matrizen Dimension: 1024 x 1024 gemessene Zeiten gelten für eine Matrix-Multiplikation Hardware: NVIDIA GeForce GTS 250 Performance-Unterschiede: 2 Größenordnungen WS 2013/14, 9.12.-16.12.2012 Folie 66

3.2.4 Fortgeschrittene CUDA-Programmierung Matrix-Multiplikation: naiver Algorithmus Zeit: 1.032s Probleme: Matrizen werden mehrfach ausgelesen kaum Coalescing beim Speicherzugriff WS 2013/14, 9.12.-16.12.2012 Folie 67

3.2.4 Fortgeschrittene CUDA-Programmierung Matrix-Multiplikation: transponiert Erwartung: Matrix B ist transponiert gegeben Zeit: 1.415s ~40% langsamer Gegensatz: CPUs sind mit diesem Algorithmus schneller WS 2013/14, 9.12.-16.12.2012 Folie 68

3.2.4 Fortgeschrittene CUDA-Programmierung Matrix-Multiplikation: Texture Caching Matrizen A und B über Texture-Units lesen (Caching), Zeit: 0.046s, ~20 schneller. Problem: Textur-Caches haben begrenzte Größe, daher werden nicht alle Zugriffe im Cache fündig. WS 2013/14, 9.12.-16.12.2012 Folie 69

3.2.4 Fortgeschrittene CUDA-Programmierung Matrix-Multiplikation: Shared Memory WS 2013/14, 9.12.-16.12.2012 Folie 70

3.2.4 Fortgeschrittene CUDA-Programmierung Matrix-Multiplikation: Shared Memory Matrizen kachelweise lesen/schreiben on-chip Shared Memory dient als schneller Puffer Synchronisation wichtig Schleife: Beide Kacheln lesen Synchronisation Kachelstreifen multiplizieren Synchronisation Zeit: 0.018s ~55 x schneller Problem: Bank Conflicts bei Shared Memory WS 2013/14, 9.12.-16.12.2012 Folie 71

3.3 GPGPUs Zusammenfassung GPGPUs haben viele, aber einfach gestaltete Cores Programmierung mittels Function-Offloading sehr viele Threads wegen Parallelität und Latenz vom GPGPU-RAM Threads sind in Blöcken zusammengefasst Blöcke sind im Grid zusammengefasst on-chip Shared Memory dient als schneller Zwischenspeicher Transfer CPU-RAM zu GPGPU-RAM via API-Funktionen WS 2013/14, 9.12.-16.12.2012 Folie 72