Algorithmische Skelette

Slides:



Advertisements
Ähnliche Präsentationen
Fast Fourier Transformation
Advertisements

Matrixmultiplikation
Datenparallele Algorithmische Skelette in Muesli
Objektorientierte Programmierung
Einführung in die Programmierung Zusammenfassung
Fortgeschrittenen Praktika
6. Der OpenMP Standard Direktiven-basiertes API zur Programmierung von Parallelrechnern mit gemeinsamem Speicher für FORTRAN, C und C++
3. Kapitel: Komplexität und Komplexitätsklassen
5. Sortier-Algorithmen Vorbemerkungen:
der Universität Oldenburg
Gliederung des Inhalts
Sortierverfahren Richard Göbel.
Java: Dynamische Datentypen
Sortierverfahren Richard Göbel.
Java: Grundlagen der Sprache
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (10 - Suchverfahren) T. Lauer.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen Halbzeit: Was haben wir bisher gelernt? Prof. Th. Ottmann.
Seminar parallele Programmierung SS 2003

EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 12 Claudio Moraga, Gisbert Dittrich FBI Unido
Sebastian Grahn Sebastian Kühn
XDoclet ETIS SS05.
PRJ 2007/1 Stefan Dissmann Motivation Problem: gleiche Datenstrukturen werden für verschiedene Objekte gebraucht: z.B. Listen von Studierenden, Kunden,
3.+4. Übungsblatt Abstraktion, Modultypen und OO Erweiterung des Entwurfs Benutzbarkeitsbeziehungen 11. Mai 2006 Dipl.-Inform. Christian Fuß.
Portierung von Java nach C
Vortrag: Ingo Gensch, Mathias Reich am:
DVG Klassen und Objekte
Prof. Dr. Gerhard Schmidt pres. by H.-J. Steffens Software Engineering SS 2009Folie 1 Objektmodellierung Objekte und Klassen Ein Objekt ist ein Exemplar.
Einführung in die Programmierung Wintersemester 2013/14 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmierung
GWDG – Kurs Parallelrechner-Programmierung mit MPI MPI Punkt-zu-Punkt-Kommunikation Oswald Haan
Agenda Motivation Grundlagen der Matrix-Vektor-Multiplikation
Programmierung paralleler Algorithmen mit MPI
Rekursion mit Listen: Quicksort
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Sortieralgorithmen Sortieren von Arrays.
Einführung in die Programmierung
Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmiersprache C 3.Tag Institut für Mathematische Optimierung - Technische Universität Braunschweig.
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
Polynome und schnelle Fourier-Transformation
Einführung in die Programmierung Wintersemester 2009/10 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmierung Wintersemester 2012/13 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmierung Wintersemester 2009/10 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Programmierung Wintersemester 2009/10 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Programmierung Wintersemester 2008/09 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Einführung in die Programmierung Wintersemester 2009/10 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmierung Wintersemester 2011/12 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmierung Wintersemester 2011/12 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmierung
Einführung in die Programmierung Wintersemester 2012/13 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund.
Einführung in die Programmiersprache C 4
Parallel Matrix Multiplication
Informatik 1 Letzte Übung.
Technische Informatik Reihungen – Felder - Arrays.
2.4 Rekursion Klassifikation und Beispiele
PHP: Operatoren und Kontrollstrukturen
Javelin Internet-based parallel computing using Java.
1 // Heap als ADT // JW: V1.0 // Vorlage gemaess EED-Quelltext // #include #include // für double pow (double d, int i) #include // fuer INT_MIN.
Einführung in die Programmierung mit Java
G. Gröger - Einführung in die Programmierung mit Java - 1. Semester - WS 02/ Übungsaufgabe vom Logische Ausdrücke 1.true & false | true 2.(10>2)
eSkel – edinburgh Skeleton library
Tutorium Software-Engineering SS14 Florian Manghofer.
Vortrag Einführung in AspectJ. Gliederung 1 Einleitung 2 Querschnittsfunktionalitäten in AspectJ 2.1 Sprachelemente 3 Beispiel 4 Join Point Modell 5 Weaving.
 Präsentation transkript:

Algorithmische Skelette Michael Bruland Michael Hüllbrock Münster, den 12.06.03

Gliederung Motivation Grundlegende Technologien Algorithmische Skelette Alternativen zur Implementierung mittels Bibliothek Fazit

1 Motivation (1) „Low-Level-Programmierung“ auf Parallelrechnern häufig erforderlich Kommunikationsprobleme wie Deadlocks oder Starvation schnell möglich Einsatz von Programmiersprachen speziell für Parallelrechner erfordert neue Einarbeitung  häufig Scheu vor Nutzung neuer Programmiersprachen  Lernkurveneffekte

1 Motivation (2) Portierbarkeit von Programmen erwünscht Einsatz von Bibliotheken zur Erweiterung bestehender Programmiersprachen Programmiermuster für Parallelrechner

Gliederung Motivation Grundlegende Technologien Algorithmische Skelette Alternativen zur Implementierung mittels Bibliothek Fazit

2 Grundlegende Technologien Funktionen höherer Ordnung (Higher-Order-Functions) Parametrisierte Datentypen Partielle Applikationen Verteilte Datenstrukturen

2.1 Funktionen höherer Ordnung Gleichstellung von Funktionen und Werten in funktionalen Sprachen Funktion mit Funktionen und/oder Ergebnissen als Argumenten Neustrukturierung von Problemen aufgrund allgemeingültiger Berechnungsschemata möglich, durch Funktionsparameter an Kontext anpassbar Bsp.: wendet eine Funktion auf alle Werte einer Kollektion an

2.2 Parametrisierte Datentypen Schablonen von Berechnungsvorschriften Typen erst durch Übergabe von Parametern in Klassendefinition festgelegt Überprüfung zur Laufzeit auf Typsicherheit Implementierung in C++ durch Templates

2.3 Partielle Applikationen Funktionen, die mit weniger Argumenten angewendet werden können als eigentlich benötigt Anwendung auf restliche Argumente führt zum selben Ergebnis wie Auflösen der Ursprungsfunktion Ermittlung der letzten einstelligen Funktion und Rückgabe an weitere Funktionen Currying als Identifikation mehrstelliger Funktionen mit einstelligen Funktionen höherer Ordnung Ausgangsfunktion: Mit Currying:

2.4 Verteilte Datenstrukturen (1) Kollektionen wie Listen, Arrays oder Matrizen Verteilung auf die partizipierenden Prozessoren Aufteilung durch verschiedene Verfahren möglich Blockpartitionierung Zyklische Partitionierung …

2.4 Verteilte Datenstrukturen (2) Bsp.: Aufteilung einer Matrix auf 4 Prozessoren Prozessor1 Prozessor2 Prozessor3 Prozessor4

2.5 Eigenschaften von C++ für die Nutzung von Skeletten Polymorphismus Partielle Applikationen durch Currying ermöglicht Parametrisierte Datentypen durch Templates template <class E> class DistributedArray{…}

Gliederung Motivation Grundlegende Technologien Algorithmische Skelette Alternativen zur Implementierung mittels Bibliothek Fazit

3 Algorithmische Skelette (1) Programmiermuster für Interaktion und Rechenoperationen zwischen Prozessen Vorimplementierte, parametrisierte Komponenten Globale Sichtweise bei Implementierung Entweder Sprachkonstrukte oder Inhalte in Bibliotheken Realisierung basiert auf MPI Abstraktion von „Low-Level-Programmierung“ Hardwareabhängige Implementierung  Portierbarkeit der Programme

3 Algorithmische Skelette (2) Aufbau der Bibliothek in C++ Verteilte Datenstruktur ist Klasse Nutzung der algorithmischen Skelette durch Methodenaufrufe der Klassen

3.1 Klassifikation algorithmischer Skelette Datenparallele Skelette Rechenskelette Kommunikationsskelette Taskparallele Skelette

3.2 Datenparallele Skelette (1) Ermöglichen Ortstransparenz Beherrschung von Datenparallelität Aufteilung der Daten auf die Prozessoren Steuerung der Prozessoren, wo welche Daten bearbeitet werden sollen Bsp.: map oder fold

3.2 Datenparallele Skelette (2) Bsp.: Geometrisch Daten werden partitioniert und auf die Prozessoren verteilt Kommunikation zwischen benachbarten Prozessoren möglich Ergebnisse werden von einem Prozess geordnet Anwendung: Vektorberechnung

3.2 Datenparallele Skelette (3) Nach Campbell 1996

3.2.1 Rechenskelette (1) Arbeiten Elemente einer verteilten Datenstruktur parallel ab Map: wendet eine Funktion auf Teile einer verteilten Datenstruktur an Fold: kombiniert alle Elemente einer verteilten Datenstruktur sukzessive mit einer Verknüpfungsfunktion h

3.2.1 Rechenskelette (2) Bsp.: Fold Verknüpfungsfunktion h ist E plus(E,E) A ist eine verteilte (4x4)-Matrix A.fold(plus) bildet die Summe über alle Elemente

3.2.2 Kommunikationsskelette (1) Tauschen Partitionen einer verteilten Datenstruktur aus Realisierung basiert auf MPI Kein Austausch individueller Nachrichten erlaubt → Probleme wie Deadlock, Starvation etc. werden verhindert

3.2.2 Kommunikationsskelette (2) Bsp.: A.permutePartition(f) Partition (an Prozessor i) wird an Prozessor f(i) gesendet Weiteres Kommunikationsskelett: rotate

3.3 Taskparallele Skelette (1) Verarbeiten Strom von Eingabewerten in Menge von Ausgabewerten Teilen den Prozessoren Tätigkeiten zu Tätigkeit kann Funktion oder wiederum Skelett sein  Verschachtelung von Skeletten möglich Kann mit Funktion oder partieller Applikation aufgerufen werden

3.3 Taskparallele Skelette (2) Bsp.: Farm Anzahl der Prozessoren ist gleich Anzahl der Worker Auswahl vom Farmer nicht-deterministisch Quelle: Kuchen 2002

3.3 Taskparallele Skelette (3) Initial-Prozess template <class O> class Initial: public Process{ public: Initial(O* (*f)(Empty)) void start() }

3.3 Taskparallele Skelette (4) Farm-Prozess template<class I, class O> class Farm: public Process{ public: Farm(Process& worker, int n) void start() }

3.3 Taskparallele Skelette (5) Final-Prozess template <class I> class Final: public Process{ public: Final(void(*f)(I)) void start() }

3.3 Taskparallele Skelette (6) Bsp.: Divide and Conquer Probleme werden rekursiv in Subprobleme unterteilt Lösung der Subprobleme erfolgt unabhängig von einander und parallel Je nach Implementierung unterschiedliche Anforderungen an Struktur Unterstützung von konservativer und spekulativer Parallelität Anwendung: Quicksort, Branch and Bound

3.3 Taskparallele Skelette (7) Nach Campbell 1996

3.3 Taskparallele Skelette (8) Bsp.: Branch and Bound Anwendung: Optimierungsprobleme Vorgehensweise: n Worker-Kopien durch Konstruktoraufruf Verknüpfung mit internem Controller Teillösungen werden vom Controller im Heap gesammelt, falls besser als bestehende Suboptimale Lösungen werden verworfen

3.3 Taskparallele Skelette (9) Bsp.: Branch and Bound template <class I> class BranchAndBound:public Process{ public: BranchAndBound(Process& worker, int n, bool (* lth)(I,I), bool (* isSolution)(I)) void start() }

3.4 Das 2-Ebenen-Modell (1) Modell zur Kombination von task- und datenparallelen Skeletten äußere Ebene: miteinander verzahnte taskparallele Skelette innere Ebene: sequentielle Programme und datenparallele Skelette

3.4 Das 2-Ebenen-Modell (2) Aufgabe: Ein Musikstück soll von Hintergrundrauschen befreit werden, Hall hinzugefügt werden, in ein best. Dateiformat (z.B. wav) konvertiert werden Lösung mit 2-Ebenen-Modell: Äußere Ebene : Pipeline Innere Ebene : sequentielle Bearbeitung oder datenparalleles Skelett

3.5 Zusätzliche Funktionen Keine Skelette Flexible Optimierung des Quellcodes Lokale und globale Sichtweise möglich Beispiele: getLocalRows() gibt die Anzahl der lokal verfügbaren Zeilen zurück getRows() gibt die Anzahl der Zeilen der gesamten verteilten Matrix zurück isLocal (int i, int j) ist wahr, wenn das Element mit dem Index i,j lokal verfügbar ist …

3.6 Laufzeitverhalten (1) Skelette sind ein abstraktes Konstrukt Wie hoch sind die Performanzeinbußen von Skeletten gegenüber einer „reinen“ MPI Implementierung? Vergleich von 5 Beispielprogrammen auf einer Siemens hpcLine mit 4 bzw. 16 Prozessoren

3.6 Laufzeitverhalten (2) Beispiel n Skelette MPI Quotient Matrix Multiplikation 1024 35.203 29.772 1.18 Kürzester Pfad 393.769 197.979 1.99 Gauss’sches Eliminationsverfahren 13.816 9.574 1.44 FFT 218 2.127 1.295 1.64 Samplesort 1.599 † - Quelle: Kuchen 2002

3.6 Laufzeitverhalten (3) Beispiel n Skelette MPI Quotient Matrix Multiplikation 1024 8.624 6.962 1.24 Kürzester Pfad 93.825 44.761 2.10 Gauss’sches Eliminationsverfahren 7.401 4.045 1.83 FFT 218 0.636 0.403 1.58 Samplesort 0.774 † - Quelle: Kuchen 2002

3.6 Laufzeitverhalten (4) Fazit Laufzeitverhalten: Skelette sind um den Faktor 1,2 bis 2,1 langsamer als „reines“ MPI Grund: Overhead bei der Parameterübergabe Fehlende Optimierungsroutinen

3.7 Beispiele mit algorithmischen Skeletten 3.7.1 Gauß‘sches Eliminationsverfahren 3.7.2 Matrixmultiplikation

3.7.1 Gauß (1) Eliminationsverfahren nach Gauß Lösungsmenge und Rang einer n x (n+1) Matrix Hier: zusätzliche Voraussetzung a1,1 ≠ 0 Idee: Reduzierung der Variabeln durch Addition/Subtraktion der einzelnen Zeilen mit der Pivotzeile

3.7.1 Gauß (2) #include „Skeleton.h“ inline double init(const int a, const int b){ return (a==b) ? 1.0 : 2.0;} inline double copyPivot(const DistributedMatrix<double>&A, int k, int i, int j, double Pij){ return A.isLocal(k,k) ? A.get(k,k) : 0;}

3.7.1 Gauß (3) inline void pivotOp(const DistributedMatrix<double>& Pivot, int rows,int firstrow, int k, double** A){ double Alk; for (int l=0; l<rows; l++){ Alk = A[l][k]; for (int j=k; j<=Problemsize; j++) if (firstrow+1 == k) A[l][j] = Pivot.getLocalGlobal(0,j); else A[l][j] -= Alk * Pivot.getLocalGlobal(0,j);}}

3.7.1 Gauß (4) void gauss(DistributedMartix<double>& A){ DistributedMatrix<double> Pivot(sk_numprocs,Problemsize+1,0.0,sk_numprocs,1); for (int K=0; k<Problemsize; k++){ Pivot.mapIndexInPlace(curry(copyPivot)(A)(k)); Pivot.broadcastPartition(k/A.getLocalRows(),0); A.mapPartitionInPlace(curry(pivotOp)(Pivot,A.getLocalRows(); A.getFirstRow(),k));}}

3.7.1 Gauß (5) int main(int argc, char **argv){ try{ InitSkeletons(argc, argv); DistributedMatrix<double> A(Problemsize,Problemsize+1,&init,sk_numprocs, 1); gauss(A); A.show(); TerminateSkeletons();} catch(Exception&){cout << “Exception” << endl <<flush;} }

3.7.1 Gauß (6) Ausführung auf 3-Prozessor-Maschine Pivot.mapIndexInPlace(curry(copyPivot)(A)(k)) kopiert die Pivotzeile (I) in eine p x (n+1), also eine 3x4 Matrix broadcastPartition übermittelt diese Zeile weiter Mit mapPartitionInPlace wird auf jeder Partition der Matrix parallel pivotOP ausgeführt

3.7.1 Gauß (7) die Zeile II wird mit -(9/6 * I) addiert und die Zeile III mit –(3/6 * I) Weitere Schritte analog

3.7.2 Matrixmultiplikation (1) Idee: Multiplikation zweier verteilter Matrizen A und B durch Blockpartitionierung und Aufteilung auf n Prozessoren

3.7.2 Matrixmultiplikation (2) #include „Skeleton.h“ #include „math.h“ inline int negate(const int a) {return –a;} inline int add(const int a, const int b) {return a+b;} template <class C> C sprod (const DistributedMatrix<C>& A, const DistributedMatrix<C>& B, int i, int j, C Cij){ C sum=Cij; for(int k=0;k<A.getLocalRows();k++) sum+=A.getGlobalLocal(i,k))*B.getLocalGlobal(k,j); return sum;}

3.7.2 Matrixmultiplikation (3) template <class C> DistributedMatrix<C> matmult(DistributedMatrix<C> A,DistributedMatrix<C> B){ //assumption: A, B have same square shape A.rotateRows(& negate); B.rotateCols(& negate); DistributedMatrix<C> R(A.getRows(),A.getCols(),0, A.getBlocksInCol(),A.getBlocksInRow()); for(int i=0;i<A.getBlocksInRow();i++){ R.mapIndexInPlace(curry(sprod<C>)(A)(B)); A.rotateRows(-1); B.rotateCols(-1);} return R;}

3.7.2 Matrixmultiplikation (4) int main(int argc, char **argv){ try{ InitSkeletons(argc,argv)); int sqrtp=(int) (sqrt(sk_numprocs)+0.1); DistributedMatrix<int> A(Problemsize,Problemsize, & add, sqrtp, sqrtp); DistributedMatrix<int> B(Problemsize,Problemsize, & add, sqrtp,sqrtp); DistributedMatrix<int> C=matmult(A,B); C.show(); TerminateSkeletons();} catch(Exception&){cout << “Exception” << endl << flush;}; }

Gliederung Motivation Grundlegende Technologien Algorithmische Skelette Alternativen zur Implementierung mittels Bibliothek Fazit

4 Alternativen zur Bibliothek P3L SkIE

4.1 P3L (1) Pisa Parallel Programming Language Basiert auf C++ Skelette farm, map, pipe und loop sind vordefiniert <skelettname> <bezeichner> in(<par>) out(<par>) <prozedur> in(<p>) out(<p>) end <skelettname>

4.1 P3L (2) farm myfarm in(int inputA, int inputB) out(int output) p in(inputA,inputB) out(output) end farm Anzahl der Worker wird vom Compiler selbstständig ermittelt Compiler versucht den Speedup zu maximieren „Mapping Problem“ wird durch implementation templates gelöst

4.1 P3L (3) Ausführung in 3 Stufen: Emitter empfängt Datenstrom und verteilt ihn an die Worker Worker führen Prozesse aus und geben das Ergebnis an den Collector Collector empfängt Ergebnisse und schreibt sie in den Ausgabekanal

4.2 SkIE (1) Skeleton-based Integrated Enviroment Vorteile gegenüber P3L Breitere Sprachunterstützung (C, C++, F90, Java, …) Einbindung von MPI und HPF Grafische Benutzeroberfläche (VisualSkIE) Analysetools

4.2 SkIE (2)

4.2 SkIE (3) Phase 1: Generieren des Codes und globale Optimierungen Anwendungsentwicklung mit SkIE in 3 Phasen: Phase 1: Generieren des Codes und globale Optimierungen Phase 2: Debugging Phase 3: Performanzanalyse

Gliederung Motivation Grundlegende Technologien Algorithmische Skelette Alternativen zur Implementierung mittels Bibliothek Fazit

5 Fazit (1) Skelette befreien den Programmierer von Problemen der parallelen Hardware Portierbarkeit von Programmen Globale Sichtweise bei Konzeption und Programmierung Kommunikationsprobleme wie Deadlock oder Starvation können nicht vorkommen Integration einer Bibliothek in eine bekannte Sprache überbrückt „Berührungsängste“

5 Fazit (2) Vermeidung von Lernkurveneffekten durch Nutzung bekannter Programmiersprachen Kostenabschätzungen möglich Performanzeinbußen sind im akzeptablem Rahmen

Fragen / Diskussion