Domänenspezifische Programmoptimierung für das Hochleistungsrechnen Christian Lengauer – p.1/25 Domänenspezifische Programmierung Allzweckprogrammierung Domänenspezifische Programmierung – p.2/25 Domänenspezifische Programmierung Allzweckprogrammierung universale Sprachen (Fortran, C, Pascal, C++, Java, ML, Haskell) hochentwickelte Programmierumgebungen (Struktureditoren, Compiler, Debugger, Laufzeitsysteme) grosser Kundenkreis grosses Investitionspotential Domänenspezifische Programmierung – p.2/25 Domänenspezifische Programmierung Allzweckprogrammierung universale Sprachen (Fortran, C, Pascal, C++, Java, ML, Haskell) hochentwickelte Programmierumgebungen (Struktureditoren, Compiler, Debugger, Laufzeitsysteme) grosser Kundenkreis grosses Investitionspotential Domänenspezifische Programmierung begrenzte Anzahl von Konstrukten, begrenzte Ausdruckskraft (lexx/yacc, Reduce/Mathematica, “Produktlinien”) spezielle Programmstrukturen ermöglichen spezielle Optimierungen oft kleinerer Kundenkreis kleineres Investitionspotential – p.2/25 Vorgehensweisen Verwendung einer Programmbibliothek in einer Allzwecksprache Eigenbau einer Sprache (DSL) und deren Programmierumgebung – p.3/25 Vorgehensweisen Verwendung einer Programmbibliothek in einer Allzwecksprache Vorteil: fast völlige Übernahme von Allzwecktechnologie Nachteil: Implementierung weiß nichts über die Domäne uninformative Fehlermeldungen keine domänenspezifischen Optimierungen Eigenbau einer Sprache (DSL) und deren Programmierumgebung – p.3/25 Vorgehensweisen Verwendung einer Programmbibliothek in einer Allzwecksprache Vorteil: fast völlige Übernahme von Allzwecktechnologie Nachteil: Implementierung weiß nichts über die Domäne uninformative Fehlermeldungen keine domänenspezifischen Optimierungen Eigenbau einer Sprache (DSL) und deren Programmierumgebung Vorteil: völlige Kontrolle über Sprache und Implementierung Nachteil: keine Verwendung von Allzwecktechnologie – p.3/25 Vorgehensweisen Verwendung einer Programmbibliothek in einer Allzwecksprache Vorteil: fast völlige Übernahme von Allzwecktechnologie Nachteil: Implementierung weiß nichts über die Domäne uninformative Fehlermeldungen keine domänenspezifischen Optimierungen Eigenbau einer Sprache (DSL) und deren Programmierumgebung Vorteil: völlige Kontrolle über Sprache und Implementierung Nachteil: keine Verwendung von Allzwecktechnologie “Einbettung” domänenspezifischer Strukturen in eine Allzwecksprache Basissprache plus domänenspezifischer Zusatz – p.3/25 Vorgehensweisen Verwendung einer Programmbibliothek in einer Allzwecksprache Vorteil: fast völlige Übernahme von Allzwecktechnologie Nachteil: Implementierung weiß nichts über die Domäne uninformative Fehlermeldungen keine domänenspezifischen Optimierungen Eigenbau einer Sprache (DSL) und deren Programmierumgebung Vorteil: völlige Kontrolle über Sprache und Implementierung Nachteil: keine Verwendung von Allzwecktechnologie “Einbettung” domänenspezifischer Strukturen in eine Allzwecksprache Basissprache plus domänenspezifischer Zusatz Trennung: Allzwecktechnologie domänenspezifische Technologie – p.3/25 Skeletale Programmierung Anwendungsprogrammierer Skelettprogrammierer – p.4/25 Skeletale Programmierung Anwendungsprogrammierer programmiert im Wesentlichen in einer Basissprache ruft einige domänenspezifische Unterprogramme auf: Skelette bleibt unberührt von maschinennahen Aspekten der Parallelität Skelettprogrammierer – p.4/25 Skeletale Programmierung Anwendungsprogrammierer programmiert im Wesentlichen in einer Basissprache ruft einige domänenspezifische Unterprogramme auf: Skelette bleibt unberührt von maschinennahen Aspekten der Parallelität Skelettprogrammierer implementiert Skelette mit Hochleistungsparallelität – p.4/25 Skeletale Programmierung Anwendungsprogrammierer programmiert im Wesentlichen in einer Basissprache ruft einige domänenspezifische Unterprogramme auf: Skelette bleibt unberührt von maschinennahen Aspekten der Parallelität Skelettprogrammierer implementiert Skelette mit Hochleistungsparallelität Vorteile Trennung von Allzweck- und domänenspezifischer Technologie Skelettsammlungen sind mehr als Programmbibliotheken! – p.4/25 Skelettdomäne: Divide-and-Conquer Tiefe Grad Zeit Raum Mergesort n log n log n 2 stat. stat. 2D konvexe Hülle n log n log n 2 stat. stat. 2D Komp.markierung n (log n)2 log n 4 stat. stat. Batcher Sort n (log n)2 (log n)2 2 stat. stat. n 2 dyn. dyn. Quicksort n2 Komplexität Algorithmus 3 stat. stat. n n Matrixprodukt n2.81 log n 7 stat. stat. Dreiecksmatrixinversion n2.81 log n 2 stat. stat. n Königinnen exponential n stat. dyn. Max. Independent Set exponential Tautologie-Checker exponential Frequent Set exponential log n n1.58 Karatsuba Polynomprodukt n n 2 dyn. dyn. n 2 dyn. dyn. n 2 dyn. dyn. – p.5/25 Divide-and-Conquer-Hierarchie: Tasks dcA Skelett time dcB space dcC Einschränkung Anwendung unabhängige quicksort, Teilprobleme maximum independent set dcB feste Rekursionstiefe n Königinnen dcC fester Teilungsgrad k Karatsuba Integerprodukt (k =3) dcA – p.6/25 Divide-and-Conquer-Hierarchie: Daten dcD/dcE dcD Blockrekursion dcF Dreiecksmatrixinversion (k =2), Batcher sort (k =2) dcE elementweise Operationen Matrix-Vektor-Produkt (k =4) dcF Kommunikation zwischen Karatsuba Polynomprodukt (k =3), korrespondierenden Elementen bitonisches Mischen (k =2), FFT (k =2), Strassen Matrixprodukt (k =7) – p.7/25 Skeletale Programmierung mit – p.8/25 Skeletale Programmierung mit Programmierstil: funktional Typpolymorphie und Funktionen höherer Ordnung geeignet für prototypischen Entwurf – p.8/25 Skeletale Programmierung mit Programmierstil: funktional Typpolymorphie und Funktionen höherer Ordnung geeignet für prototypischen Entwurf Basissprache: Haskell gereift, stabil und verbreitet hat indizierte Datenstrukturen (Comprehensions) – p.8/25 Skeletale Programmierung mit Programmierstil: funktional Typpolymorphie und Funktionen höherer Ordnung geeignet für prototypischen Entwurf Basissprache: Haskell Domänenspezifische Charakteristiken: gereift, stabil und verbreitet hat indizierte Datenstrukturen (Comprehensions) Striktheit auf bestimmten, endlichen Datenstrukturen ungewöhnliche Repräsentation bestimmter Datenstrukturen (Liste = erweiterbares Array) – p.8/25 Domänenspezifische Listendarstellung Index Konstruktor f Element n Länge – p.9/25 Domänenspezifische Listendarstellung Element n Länge inits [a,b,c,d ] [ [ ],[a],[a,b],[a,b,c],[a,b,c,d] ] ( i . ( j . [a,b,c,d ] !! j) i) 5 [i | i [0..100000], odd i ] [1,3,5,...,99999] ( i . 2i+1) 50000 Ausdruck Wert -Rep. Index Konstruktor f – p.9/25 Skelette in – p.10/25 Skelette in Das Skelett: speziell markierte Funktion höherer Ordnung – p.10/25 Skelette in Das Skelett: speziell markierte Funktion höherer Ordnung Die Skelettparameter: Übersetzungszeitparameter + Laufzeitparameter Implizit: Typ und Größe der aktuellen Übersetzungszeitparameter – p.10/25 Skelette in Das Skelett: speziell markierte Funktion höherer Ordnung Die Skelettparameter: Übersetzungszeitparameter + Laufzeitparameter Implizit: Typ und Größe der aktuellen Übersetzungszeitparameter Der Skelettrumpf: zwei Ausprägungen: Algorithmisches Skelett = Spezifikation Architekturskelett = Implementierung – p.10/25 Skelette in Das Skelett: speziell markierte Funktion höherer Ordnung Die Skelettparameter: Übersetzungszeitparameter + Laufzeitparameter Implizit: Typ und Größe der aktuellen Übersetzungszeitparameter Der Skelettrumpf: zwei Ausprägungen: Algorithmisches Skelett = Spezifikation Architekturskelett = Implementierung Haskell-Code, der Zielcode in C+MPI generiert Herleitungsmethode: je nach Wahl des Skelettprogrammierers – p.10/25 Skelettübersetzung und -ausführung – p.11/25 Skelettübersetzung und -ausführung Skelettübersetzung: kontextspezifisch Konsequenz: potentiell mehrere Zielrümpfe Preis: Codewachstum – p.11/25 Skelettübersetzung und -ausführung Skelettübersetzung: kontextspezifisch Konsequenz: potentiell mehrere Zielrümpfe Preis: Codewachstum Skelettausführung: wie üblich, unter Ausnutzung der Laufzeitparameter JIT-Anpassung möglich (aber bis jetzt nicht verfolgt) – p.11/25 Skelettübersetzung und -ausführung Skelettübersetzung: kontextspezifisch Konsequenz: potentiell mehrere Zielrümpfe Preis: Codewachstum Skelettausführung: wie üblich, unter Ausnutzung der Laufzeitparameter JIT-Anpassung möglich (aber bis jetzt nicht verfolgt) Prinzipien: abstrakte Interpretation partielle Auswertung – p.11/25 Skelette in – p.12/25 Skelette in HDC−Quellprogramm dcA p b d c x – p.12/25 Skelette in HDC−Quellprogramm algorithmisches Skelett dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x – p.12/25 Skelette in HDC−Quellprogramm algorithmisches Skelett dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x Architekturskelett C/MPI−generierender Haskell−Code – p.12/25 Skelette in HDC−Quellprogramm algorithmisches Skelett dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x Architekturskelett C/MPI−generierender C/MPI−Zielcode Haskell−Code – p.12/25 Skelette in HDC−Quellprogramm algorithmisches Skelett dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x Architekturskelett C/MPI−generierender C/MPI−Zielcode Haskell−Code C/MPI−Zielcode – p.12/25 Skelette in algorithmisches Skelett HDC−Quellprogramm dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x Compiler− information Architekturskelett C/MPI−generierender C/MPI−Zielcode Haskell−Code aufrufspezifischer C/MPI−Zielcode – p.12/25 Unterschied zu Programmbibliotheken – p.13/25 Unterschied zu Programmbibliotheken Aufrufmechanismus Übersetzungszeitparameter + Laufzeitparameter – p.13/25 Unterschied zu Programmbibliotheken Aufrufmechanismus Übersetzungszeitparameter + Laufzeitparameter Kontextsensitivität der Implementierung Übersetzungszeitparameter spezialisieren die Implementierung implizite Ausnutzung von Information über den Aufrufkontext multiple, optimierte Zielcodeversionen eines Skelettrumpfes – p.13/25 Unterschied zu Programmbibliotheken Aufrufmechanismus Übersetzungszeitparameter + Laufzeitparameter Kontextsensitivität der Implementierung Übersetzungszeitparameter spezialisieren die Implementierung implizite Ausnutzung von Information über den Aufrufkontext multiple, optimierte Zielcodeversionen eines Skelettrumpfes Optimierungsprinzipien abstrakte Interpretation (gewinnt semantische Information über das Programm) partielle Auswertung (nutzt diese zu einer Spezialisierung des Zielcodes) – p.13/25 Skelettimplementierung – p.14/25 Skelettimplementierung Prinzip Spezifikation recX = iterative Form itX Transition von Haskell nach C+MPI – p.14/25 Skelettimplementierung Prinzip Spezifikation recX = iterative Form itX Transition von Haskell nach C+MPI dcA Zeit- und Raumaufteilung dynamisch z.Zt. kein Lastenausgleich – p.14/25 Skelettimplementierung Prinzip Spezifikation recX = iterative Form itX Transition von Haskell nach C+MPI dcA Zeit- und Raumaufteilung dynamisch z.Zt. kein Lastenausgleich dcF Zeit- und Raumaufteilung statisch Abhängigkeiten regulär aber nicht affin Ähnlichkeiten mit Polytopenmodell z.Zt. Größeninferenz zur Laufzeit – p.14/25 dcA: n Königinnen dcA :: (a->Bool) -> (a->b) -> (a->[a]) -> (a->[b]->b) -> a -> b dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) queens :: Int -> [[Int]] queens n = dcA p b d c (n,([],[0..n-1])) where p (n,_) = n==0 b (_,(placed,_)) = [placed] d (n,(placed,remain)) = let diagonal_attack i = or [ (length placed - j) == abs (i - placed!!j) | j <- [0..length placed -1] ] in [ (n-1,(placed++[i], filter (/=i) remain)) | i <- filter (\j -> not (diagonal_attack j)) remain ] c _ = concat Beispieleingabe: 4,([],[0,1,2,3])) Beispielausgabe: [[1,3,0,2],[2,0,3,1]] – p.15/25 Performanz: n Königinnen speedup auf Parsytec GCel-1024 (Paderborn) 160 140 120 12 100 80 60 11 40 10 20 0 0 32 64 128 256 512 # processors – p.16/25 AH HH HL LH HH BL AL BH BH AL AH Karatsuba Polynomprodukt SH LH HH + HL AH + AL BL SH LL SL LL HL + LH BH + BL SL LL – p.17/25 Karatsuba Polynomprodukt karatsuba :: [Int] -> [Int] -> [Int] karatsuba a b = let basic xy = (0, fst xy * snd xy) divide i xs = if i<2 then xs!!i else ((fst (xs!!0) + fst (xs!!1)), (snd (xs!!0) + snd (xs!!1))) combine i [h,l,m] = if i==0 then (fst h, (fst l + snd m - snd h - snd l)) else ((snd h + fst m - fst h - fst l), snd l) n = ilog2 (length a) x = zip a b z = dcF 3 2 2 basic divide combine n x in map fst z ++ map snd z – p.18/25 Performanz: Karatsuba Polynomprodukt speedup auf Parsytec GCel-1024 (Paderborn) 400 350 32768 300 250 16384 dcF 200 dcA rel. to seq. dcF 150 16384 100 8192 50 0 0 27 81 243 729 # processors – p.19/25 Batcher sort: bitonic merge (dcF) in dcD Schedule: 5 4 2 5 4 8 2 7 5 4 7 2 3 3 8 2 3 1 7 5 4 6 5 7 1 [2,1] 6 8 3 6 8 2 1 1 2 3 [3,1] 8 6 5 7 3 4 5 6 4 5 [2,2] [3,0] 2 4 5 7 8 6 3 1 2 4 3 1 [1,1] [2,0] 3 8 6 1 4 5 7 2 4 2 1 [0,0] [1,0] 6 1 8 3 7 1 6 [3,2] 8 7 6 7 8 [3,3] – p.20/25 Batcher sort: dcD instantiated with dcF batcherSort :: [Int] -> [Int] batcherSort xs = (dcD 2 [2] [2] basic divide combine n [xs]) !! 0 where n = ilog2 (length xs) basic x = x divide _ [x] = [[left x],[right x]] combine lev _ [[x],[y]] = let sub = dcF 2 2 2 b d c lev (x ++ reverse y) in [[left sub, right sub]] where b x = x d s [x,y] = if s==0 then min x y else max x y c s l = l!!s – p.21/25 Ist eine eingebettete Sprache? Ja! Nein! – p.22/25 Ist eine eingebettete Sprache? Ja! Basissprache: Haskell Zusatzkonstrukte: Skelette Allzwecktechnologie: Compiler Domänenspezifische Technologie: Architekturskelette Nein! – p.22/25 Ist eine eingebettete Sprache? Ja! Basissprache: Haskell Zusatzkonstrukte: Skelette Allzwecktechnologie: Compiler Domänenspezifische Technologie: Architekturskelette Nein! Allzweckcompiler speziell gefertigt! – p.22/25 Ist eine eingebettete Sprache? Ja! Basissprache: Haskell Zusatzkonstrukte: Skelette Allzwecktechnologie: Compiler Domänenspezifische Technologie: Architekturskelette Nein! Allzweckcompiler speziell gefertigt! zu enge Kopplung von Compiler und Skeletten spezifisches Verhalten vom Allzweckcompiler gefordert Allzweckseite nicht standard und nicht auswechselbar – p.22/25 Parallelität, eingebettet in Haskell algorithmisches Skelett HDC−Quellprogramm dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x Compiler− information Architekturskelett C/MPI−generierender C/MPI−Zielcode Haskell−Code aufrufspezifischer C/MPI−Zielcode – p.23/25 Parallelität, eingebettet in Haskell algorithmisches Skelett HDC−Quellprogramm dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x Compiler− information Architekturskelett C/MPI−generierender C/MPI−Zielcode Haskell−Code aufrufspezifischer C/MPI−Zielcode – p.23/25 Parallelität, eingebettet in Haskell Haskell−Quellprogramm algorithmisches Skelett dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x Architekturskelett C/MPI−generierender C/MPI−Zielcode Haskell−Code aufrufspezifischer C/MPI−Zielcode – p.23/25 Parallelität, eingebettet in Haskell Haskell−Quellprogramm algorithmisches Skelett dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x Architekturskelett DS−Quellcode C/MPI−Zielcode aufrufspezifischer C/MPI−Zielcode – p.23/25 Parallelität, eingebettet in Haskell Haskell−Quellprogramm algorithmisches Skelett dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x Architekturskelett DS−Quellcode C/MPI−Zielcode aufrufspezifischer C/MPI−Zielcode – p.23/25 Parallelität, eingebettet in Haskell Haskell−Quellprogramm algorithmisches Skelett dcA p b d c x = if p x then b x else c x (map (dcA p b d c) (d x)) dcA p b d c x Architekturskelett DS−Quellcode C/MPI−Zielcode aufrufspezifischer C/MPI−Zielcode – p.23/25 Paralleles map, eingebettet in Haskell f f xs encode toVector xs fclos map vxs mapIntVector interpret (DPAR (V "n") (constSeq [Atom (Select (DB 1)), Atom (Call fclos)] )) fromVector vxs ys ys map f [x1, . . . , xn] = [f x1, . . . , f xn] – p.24/25 Verbleibende Herausforderungen – p.25/25 Verbleibende Herausforderungen Ehrliche Einbettung Konstante: Basissprache und Schnittstelle Variante: domänenspezifische Sprache und DSO-Compiler – p.25/25 Verbleibende Herausforderungen Ehrliche Einbettung Konstante: Basissprache und Schnittstelle Variante: domänenspezifische Sprache und DSO-Compiler Anwendungsprogrammierer Wahl des Algorithmus Wahl der Datenstrukturen Wahl der Skelette Anpassung der Anwendung an die Skelette – p.25/25 Verbleibende Herausforderungen Ehrliche Einbettung Konstante: Basissprache und Schnittstelle Variante: domänenspezifische Sprache und DSO-Compiler Anwendungsprogrammierer Wahl des Algorithmus Wahl der Datenstrukturen Wahl der Skelette Anpassung der Anwendung an die Skelette Skelettprogrammierer Stabilität der Skelettbibliothek Kompositionalität der Performanz von Skeletten – p.25/25