X10 Performance and Productivity at Scale Sebastian Henneberg 8. Dezember 2011 Sebastian Henneberg: X10, Performance and Productivity at Scale 1
Struktur Hintergrund Plattform Speicher- und Parallelitätsmodell Sprachkonstrukte Zusammenfassung Sebastian Henneberg: X10, Performance and Productivity at Scale 2
Geschichte Idee: Sprache für parallele und verteilte Programmierung entwickelt seit 2004 Forschungsprojekt von IBM im Watson Research Center gefördert durch HPCS-Program der DARPA wachsende Community steigende Anzahl an Publikationen Gewinner der HPC Challenge: Best Performance (2009) Workshops (2010,2011) Sebastian Henneberg: X10, Performance and Productivity at Scale 3
Inspiration Java-Frameworks: Java Party (JVM-Verbund) C++-Frameworks Message Passing Interface (MPI) Open Multi-Processing (OpenMP) Speichermodell Unified Parallel C (UPC) Co-array Fortran Fortress Chapel Sebastian Henneberg: X10, Performance and Productivity at Scale 4
Motivation Produktivität Syntax ähnlich zu Java angereichert mit neuen Sprachkonstrukten Geschwindigkeit Backends für verschiedene Umgebungen angepasst an spezielle Plattformen Skalierung PC Multicore Cluster Supercomputer Sebastian Henneberg: X10, Performance and Productivity at Scale 5
Motivation Produktivität! Syntax ähnlich zu Java angereichert mit neuen Sprachkonstrukten Geschwindigkeit Backends für verschiedene Umgebungen angepasst an spezielle Plattformen Skalierung PC Multicore Cluster Supercomputer X10: ten-times productivity boost Sebastian Henneberg: X10, Performance and Productivity at Scale 5
Typsystem streng statisch Typinferenz bei initialisierender Deklaration Referenzen anstatt Zeiger Typen werden eingeführt durch Schnittstellen Klassen structs Sebastian Henneberg: X10, Performance and Productivity at Scale 6
Paradigmen imperativ objektorientiert nebenläufig verteilt (funktional) Sebastian Henneberg: X10, Performance and Productivity at Scale 7
Paradigmen imperativ Statements mit Seiteneffekten objektorientiert nebenläufig verteilt (funktional) Sebastian Henneberg: X10, Performance and Productivity at Scale 7
Paradigmen imperativ Statements mit Seiteneffekten objektorientiert class, extends, interface, implements... (wie Java) nebenläufig verteilt (funktional) Sebastian Henneberg: X10, Performance and Productivity at Scale 7
Paradigmen imperativ Statements mit Seiteneffekten objektorientiert class, extends, interface, implements... (wie Java) nebenläufig Lokalität, Atomarität, Asynchronität, Ordnung verteilt (funktional) Sebastian Henneberg: X10, Performance and Productivity at Scale 7
Paradigmen imperativ Statements mit Seiteneffekten objektorientiert class, extends, interface, implements... (wie Java) nebenläufig Lokalität, Atomarität, Asynchronität, Ordnung verteilt message passing, global partitioned address space (funktional) Sebastian Henneberg: X10, Performance and Productivity at Scale 7
Paradigmen imperativ Statements mit Seiteneffekten objektorientiert class, extends, interface, implements... (wie Java) nebenläufig Lokalität, Atomarität, Asynchronität, Ordnung verteilt message passing, global partitioned address space (funktional) immutable state, first-class functions, closures Sebastian Henneberg: X10, Performance and Productivity at Scale 7
Paradigmen imperativ Statements mit Seiteneffekten objektorientiert class, extends, interface, implements... (wie Java) nebenläufig Lokalität, Atomarität, Asynchronität, Ordnung verteilt message passing, global partitioned address space (funktional) immutable state, first-class functions, closures X10 ist eine multiparadigmatische Sprache Der Schwerpunkt liegt auf verteilter nebenläufiger Programmierung Sebastian Henneberg: X10, Performance and Productivity at Scale 7
Syntaktische Nähe zu Java 1 p u b l i c c l a s s Factorial { 2 3 p u b l i c s t a t i c d e f main ( args : Array [ String ]) { 4 v a l n = Int. parse ( args (0)); 5 Console. OUT. println (n + "! = " + fac (n )); 6 } 7 8 p r i v a t e s t a t i c d e f fac (n: Int ): ULong { 9 v a r f : ULong = 1; 10 f o r (i i n 1..n) { 11 f *= i; 12 } 13 r e t u r n f; 14 } 15 } val: nicht-veränderbare Variable var: veränderbare Variable Sebastian Henneberg: X10, Performance and Productivity at Scale 8
C++ und Java-Backend es werden zwei Backends unterstützt x10c x10 Java-Backend.x10 x10c++ runx10 C++-Backend Sebastian Henneberg: X10, Performance and Productivity at Scale 9
C++ und Java-Backend es werden zwei Backends unterstützt x10c x10 Java-Backend.x10 x10c++ runx10 C++-Backend die Backends unterscheiden sich in Geschwindigkeit (Standard: C++) kein direkter Aufruf per./ oder mit java Vorbereitung der verteilten und nebenläufigen Umgebung Sebastian Henneberg: X10, Performance and Productivity at Scale 9
MPI und OpenMP MPI (Message Passing Interface) OpenMP (Open Multi-Processing) Features: Programmiermodell für Cluster basiert auch Nachrichtenversand Buffer werden verschickt/empfangen Features: API für parallele Ausführung basiert auf gemeinsamen Speicher die API ändert das Laufzeitverhalten Ziele: Skalierbarkeit Portabilität Performanz Ziele: Skalierbarkeit Portabilität Einfachheit Flexibel Sebastian Henneberg: X10, Performance and Productivity at Scale 10
Speichermodelle im Vergleich MPI : Speicherzugriff : Nachricht : Referenzen T i : Thread P i : Place T 1 T 2 T 3 Sebastian Henneberg: X10, Performance and Productivity at Scale 11
Speichermodelle im Vergleich : Speicherzugriff : Nachricht : Referenzen T i : Thread P i : Place MPI OpenMP T 1 T 2 T 3 T 1 T 2 T 3 Sebastian Henneberg: X10, Performance and Productivity at Scale 11
Speichermodelle im Vergleich : Speicherzugriff : Nachricht : Referenzen T i : Thread P i : Place MPI OpenMP PGAS T 1 T 2 T 3 T 1 T 2 T 3 P 1 P 2 P 3 PGAS (Partitioned Global Address Space) PGAS Datenobjekte bleiben für ihre Lebensdauer der erzeugenden Place zugeordnet Sebastian Henneberg: X10, Performance and Productivity at Scale 11
Speichermodelle im Vergleich : Speicherzugriff : Nachricht : Referenzen T i : Thread P i : Place MPI OpenMP PGAS T 1 T 2 T 3 T 1 T 2 T 3 P 1 P 2 P 3 PGAS (Partitioned Global Address Space) PGAS Datenobjekte bleiben für ihre Lebensdauer der erzeugenden Place zugeordnet Sebastian Henneberg: X10, Performance and Productivity at Scale 11
Aktivitäten Aktivitäten repräsentieren Ausführungstränge Aktivitäten erzeugen eine baumartige Struktur p : 0 p : 1 p : 2 async at at async async async finish at Sebastian Henneberg: X10, Performance and Productivity at Scale 12
async-schlüsselwort async { S } erzeugt eine neue Aktivität die S ausführt Kontrollfluss des Aufrufers kehrt sofort zurück kann nicht abgebrochen werden! läuft asynchron in aktueller Place Variablenbindungen aus umgebenden Blöcken in S sichtbar Lebenszeit muss verlängert werden! Sebastian Henneberg: X10, Performance and Productivity at Scale 13
async-schlüsselwort async { S } erzeugt eine neue Aktivität die S ausführt Kontrollfluss des Aufrufers kehrt sofort zurück kann nicht abgebrochen werden! läuft asynchron in aktueller Place Variablenbindungen aus umgebenden Blöcken in S sichtbar Lebenszeit muss verlängert werden! aufgrund des Speichermodells nicht äquivalent zu Thread.start Sebastian Henneberg: X10, Performance and Productivity at Scale 13
finish-schlüsselwort f i n i s h { S } wartet bis alle asynchronen Aktivitäten beendet sind dient der Synchronisation Sebastian Henneberg: X10, Performance and Productivity at Scale 14
finish-schlüsselwort f i n i s h { S } wartet bis alle asynchronen Aktivitäten beendet sind dient der Synchronisation aus Java 6 bekannt unter dem Namen CountDownLatch Sebastian Henneberg: X10, Performance and Productivity at Scale 14
cilk-style Fork/Join finish und async tauchen häufig miteinander auf die Kombination ermöglicht Fork/Join-Operationen 1 d e f fib (n: Int ): Int { 2 i f (n < 2) r e t u r n 1; 3 v a l x: Int ; 4 v a l y: Int ; 5 f i n i s h { 6 async x = fib (n-1); 7 async y = fib (n-2); 8 } 9 r e t u r n x+y; 10 } Sebastian Henneberg: X10, Performance and Productivity at Scale 15
cilk-style Fork/Join finish und async tauchen häufig miteinander auf die Kombination ermöglicht Fork/Join-Operationen inspiriert sind diese durch Cilk 1 d e f fib (n: Int ): Int { 2 i f (n < 2) r e t u r n 1; 3 v a l x: Int ; 4 v a l y: Int ; 5 f i n i s h { 6 async x = fib (n-1); 7 async y = fib (n-2); 8 } 9 r e t u r n x+y; 10 } 1 c i l k i n t fib ( i n t n) { 2 i f (n < 2) r e t u r n 1; 3 e l s e { 4 i n t x,y; 5 x = spawn fib (n-1); 6 y = spawn fib (n-2); 7 sync ; 8 r e t u r n x+y; 9 } 10 } Sebastian Henneberg: X10, Performance and Productivity at Scale 15
cilk-style Fork/Join finish und async tauchen häufig miteinander auf die Kombination ermöglicht Fork/Join-Operationen inspiriert sind diese durch Cilk 1 d e f fib (n: Int ): Int { 2 i f (n < 2) r e t u r n 1; 3 v a l x: Int ; 4 v a l y: Int ; 5 f i n i s h { 6 async x = fib (n-1); 7 async y = fib (n-2); 8 } 9 r e t u r n x+y; 10 } in Java 7 als Fork/Join-Framework eingeführt 1 c i l k i n t fib ( i n t n) { 2 i f (n < 2) r e t u r n 1; 3 e l s e { 4 i n t x,y; 5 x = spawn fib (n-1); 6 y = spawn fib (n-2); 7 sync ; 8 r e t u r n x+y; 9 } 10 } Sebastian Henneberg: X10, Performance and Productivity at Scale 15
at-schlüsselwort at (p) { S } synchrones Wechseln der aktuellen Place zu Place p anschließend wird S ausgeführt nach Ende von S läuft Kontrollfluss in aktueller Place weiter P 1 P 2 at(p) { } Sebastian Henneberg: X10, Performance and Productivity at Scale 16
(De-)Serialisierung bei at 1 v a r i : Int = 0; 2 v a l c = new Cell [ Int ](2); 3 v a l r = GlobalRef [ Cell [ Int ]](new Cell [ Int ](4)); 4 at( here. next ()) { 5 c ()++; // sets to 3 6 at (r) { r ()()++; } // sets to 5 7 } 8 Console. OUT. println (c ()); // prints 2 9 Console. OUT. println (r ()()); // prints 5 Referenzen aus äußeren Blocks werden kopiert, serialisiert, in Buffer geschrieben und an Ziel-Place transportiert an der Ziel-Place wird der Buffer geleert, die Objekte deserialisiert um darauf zu operieren es werden Deep Copies erstellt transient- und GlobalRef-Felder werden nicht kopiert Sebastian Henneberg: X10, Performance and Productivity at Scale 17
atomic-schlüsselwort atomic { S } führt S atomar aus atomare Blocks werden in serialisierter Ordnung ausgeführt Sebastian Henneberg: X10, Performance and Productivity at Scale 18
atomic-schlüsselwort atomic { S } führt S atomar aus atomare Blocks werden in serialisierter Ordnung ausgeführt Das synchronized-schlüsselwort in Java ist deutlich feingranularer Sebastian Henneberg: X10, Performance and Productivity at Scale 18
atomic-schlüsselwort atomic { S } führt S atomar aus atomare Blocks werden in serialisierter Ordnung ausgeführt Das synchronized-schlüsselwort in Java ist deutlich feingranularer Es gilt zu beachten: S darf nicht blockieren (kein when, next, finish) S darf keine Aktivitäten erzeugen (kein async) S darf nur lokal operieren (kein at) genannte Einschränkungen werden zur Laufzeit geprüft Sebastian Henneberg: X10, Performance and Productivity at Scale 18
when-schlüsselwort when(e) { S } blockiert Aktivität bis e als wahr ausgewertet werden kann anschließend wird S atomar ausgeführt when (true) atomic Variablen in e können jederzeit geändert werden Prädikat e wird durch busy waiting geprüft Änderung von Variablen aus e in atomic/when vermeidet Starvation durch Benachrichtigung Sebastian Henneberg: X10, Performance and Productivity at Scale 19
clock-operationen v a l c : Clock = Clock. make (); async c l o c k e d (c) { S } ermöglicht phasenweise Ausführung (phased computation) clocked (c) registriert c mit neuer Aktivität c wird mehreren asynchronen Aktivitäten zugeordnet der Aufruf c.resumeall() blockiert bis letzte Aktivität diesen Aufruf tätigt anschließend beginnt nächste Berechnungsphase Sebastian Henneberg: X10, Performance and Productivity at Scale 20
clock-operationen v a l c : Clock = Clock. make (); async c l o c k e d (c) { S } ermöglicht phasenweise Ausführung (phased computation) clocked (c) registriert c mit neuer Aktivität c wird mehreren asynchronen Aktivitäten zugeordnet der Aufruf c.resumeall() blockiert bis letzte Aktivität diesen Aufruf tätigt anschließend beginnt nächste Berechnungsphase aus Java 6 bekannt unter dem Namen CyclicBarrier Sebastian Henneberg: X10, Performance and Productivity at Scale 20
Evolution von MontyPi MontyPi berechnet die Kreiszahl π durch einen Monte-Carlo Algorithmus y x Sebastian Henneberg: X10, Performance and Productivity at Scale 21
Evolution von MontyPi MontyPi berechnet die Kreiszahl π durch einen Monte-Carlo Algorithmus y x Sebastian Henneberg: X10, Performance and Productivity at Scale 21
Evolution von MontyPi MontyPi berechnet die Kreiszahl π durch einen Monte-Carlo Algorithmus y x Sebastian Henneberg: X10, Performance and Productivity at Scale 21
Evolution von MontyPi MontyPi berechnet die Kreiszahl π durch einen Monte-Carlo Algorithmus y x Sebastian Henneberg: X10, Performance and Productivity at Scale 21
Evolution von MontyPi MontyPi berechnet die Kreiszahl π durch einen Monte-Carlo Algorithmus y x Sei p i (x, y) für i {1,..., n} und x, y [0, 1[ Sebastian Henneberg: X10, Performance and Productivity at Scale 21
Evolution von MontyPi MontyPi berechnet die Kreiszahl π durch einen Monte-Carlo Algorithmus y x Sei p i (x, y) für i {1,..., n} und x, y [0, 1[ Weiter sei h = #{p i p i 1} Sebastian Henneberg: X10, Performance and Productivity at Scale 21
Evolution von MontyPi MontyPi berechnet die Kreiszahl π durch einen Monte-Carlo Algorithmus y x Sei p i (x, y) für i {1,..., n} und x, y [0, 1[ Weiter sei h = #{p i p i 1} π 4 h n Sebastian Henneberg: X10, Performance and Productivity at Scale 21
Evolution von MontyPi (sequentiell) 4 p u b l i c s t a t i c d e f main ( args : Array [ String ]) { 5 v a l N = Int. parse ( args (0)); 6 v a l R = new Random (); 7 v a r result : Double = 0; 8 f o r (1..N) { 9 v a l x = R. nextdouble (); 10 v a l y = R. nextdouble (); 11 i f (x*x + y*y <= 1) result ++; 12 } 13 v a l pi = 4* result /N; 14 Console. OUT. println (" The value of pi is " + pi ); 15 } Sebastian Henneberg: X10, Performance and Productivity at Scale 22
Evolution von MontyPi (nebenläufig) 4 p u b l i c s t a t i c d e f main ( args : Array [ String ]) { 5 v a l N = Int. parse ( args (0)); 6 v a l A = Int. parse ( args (1)); 7 v a l result = new Cell [ Double ](0); 8 f i n i s h f o r (1..A) async { 9 v a l R = new Random (); 10 v a r myresult : Double = 0; 11 f o r (1..( N/A)) { 12 v a l x = R. nextdouble (); 13 v a l y = R. nextdouble (); 14 i f ( x* x + y* y <= 1) myresult ++; 15 } 16 atomic result () += myresult ; 17 } 18 v a l pi = 4*( result ())/ N; 19 Console. OUT. println (" The value of pi is " + pi ); 20 } Sebastian Henneberg: X10, Performance and Productivity at Scale 23
Evolution von MontyPi (verteilt) 4 p u b l i c s t a t i c d e f main ( args : Array [ String ]) { 5 v a l N = Int. parse ( args (0)); 6 v a l result = GlobalRef [ Cell [ Double ]](new Cell [ Double ](0)); 7 f i n i s h f o r (p i n Place. places ()) async at (p) { 8 v a l R = new Random (); 9 v a r myresult : Double = 0; 10 f o r (1..( N/ Place. MAX_PLACES )) { 11 v a l x = R. nextdouble (); 12 v a l y = R. nextdouble (); 13 i f ( x* x + y* y <= 1) myresult ++; 14 } 15 v a l ans = myresult ; 16 at ( result ) atomic result ()() += ans ; 17 } 18 v a l pi = 4*( result ()())/ N; 19 Console. OUT. println (" The value of pi is " + pi ); 20 } Sebastian Henneberg: X10, Performance and Productivity at Scale 24
Zitate aus den Quellen supports programming at scale in the multicore era X10 is suitable as a research prototype it will be suitable for production use language and libraries are still changing, so coding to X10 is still a bit of moving target Sebastian Henneberg: X10, Performance and Productivity at Scale 25
Gesamtbild Stand der Entwicklung: X10 wird in der Wissenschaft (weiter-)entwickelt keine industrielle Verwendung bekannt nicht-endgültige Spezifikation Schlussfolgerung: hohe Abstraktion der Programme plattformunabhängig führt viele bekannte und bewährte Techniken zusammen teilweise gar nicht oder nur sehr dürfitg dokumentiert Entwicklungsumgebung brauchbar - hat jedoch noch viel Potenzial Sebastian Henneberg: X10, Performance and Productivity at Scale 26
Alternativen Java: ProActive Parallel Suite C++: OpenMP MPI Sebastian Henneberg: X10, Performance and Productivity at Scale 27
Quellen und Referenzen Programmier-Leitfaden Spezifikation API-Dokumentation (Javadoc) Publikationen Videos/Aufzeichnungen X10DT (Eclipse IDE Erweiterung) enthält eine sehr reichhaltige Hilfe zu X10 Sebastian Henneberg: X10, Performance and Productivity at Scale 28