Java für das Hochleistungsrechnen [Special Section, Comm. of the ACM, Okt. 2001] Entwicklung: 1998: Gründung des Java Grande Forums Mai 2000: Spezialausgabe der Zeitschrift Concurrency: Practice & Experience Okt. 2001: Spezialsektion in der Zeitschrift Communications of the ACM Java Grande Forum: Aufgaben Evaluierung der Sprache Java und ihres Laufzeitsystems für Grand Challenge Anwendungen Fokussierung der Java Grande Gemeinde (jährliche Konferenz bis 2003) Erstellung von Benchmarks, APIs, Verbesserungsempfehlungen, etc. Warum Java für HPC? um die Fülle der Java-Programmierer zu erreichen (Bibliotheksfundus) um Geldgeber zu erreichen für Dinge, die sich nicht ohne Weiteres mit Fortran und C tun lassen. 1/17
Wie mit Java umgehen? Kurzfristig: Kopieren gängiger HPC-Technologie nach Java SPMD-Parallelität (PVM, MPI) Kommunikation zwischen JVMs sofort umsetzbar im Wettbewerb mit Fortran und C Längerfristig: Entwicklung neuer HPC-Technologie für Java Vorteile von Java gegenüber Fortran und C: Portierbarkeit des Bytecodes Objektorientierung Fadenparallelität dynamische Parallelität (echtes MIMD) irreguläre Parallelität Optimierungen während der Laufzeit (JIT) Java anpassen Sich an Java anpassen + fokussierte Entwicklung Sprachlimitierungen bestimmen neuer Technologie die Entwicklung Akzeptanzrisiko + große Benutzergemeinde. 2/17
Was spricht gegen Java für HPC? Java ist interpretiert + schneller Vertrieb + hohe Sicherheit + einfacher, universaler Compiler langsame Ausführung + Dos&Don ts-liste für HPC-Programmierung in Java [Boisvert et al. 2001] Java ist eine große Sprache kleine Sprachen sind effizienter implementierbar: statischer Speicher (klassisches Fortran) schneller als per Hand verwalteter dynamischer Speicher (C) schneller als automatisch verwalteter dynamischer Speicher (Java) Fallstudie: klassisches Fortran fünfmal schneller als C, da Compiler keinen Code für Aliastests einfügen muss Java ist nicht auf HPC ausgerichtet Websprache Betonung auf Sicherheit, Portabilität, Objektorientierung, Verteiltheit Effizienz zweit- oder drittrangig. 3/17
Java und Numerik Sprachänderungen: von Java Grande instigiert strictfp: Methodenattribut zur Einhaltung bitreproduzierbarer, standardisierter Gleitpunktarithmetik auf allen Zwischenresultaten aufgenommen in Java 1.2 mittels eines Java Special Request im vorherigen Java-Standard war Bitreproduzierbarkeit zwingend Bitreproduzierbarkeit verbietet Optimierungen unter Ausnutzung von Assoziativität, Kommutativität, etc. fastfp: Methodenattribut zur Benutzung maschinenspezifischer Hardware Beispiel: float-multiply-add (FMA) zur Vektormultiplikation Java Special Request versandet Weiteres Problem: unpassende Datentypen für komplexe Zahlen und Arrays beides sind Objekte: umständliche Syntax von Operationen (Methodenaufrufe) Referenz- statt Wertsemantik Effizienzverluste (dynamische Speicherverwaltung) Java-Arrays haben zusätzliche, schlechte Eigenschaften sie müssen nicht rechteckig sein es kann Aliasing zwischen Elementen bestehen. 4/17
Modellierung komplexer Zahlen für HPC in Java [IEEE CSE Papier von Boisvert et al. 2001] Komplexe Zahlen sind Objekte: Complex a = new Complex(5,2); Complex b = a.plus(a); Complex c = b; Nachteile: umständliche Syntax unnötige Dynamik der Speicherverwaltung Behandlung inkonsistent mit anderen Basistypen (Referenzgleichheit, nicht Wertgleichheit) Lösungsansatz: zusätzlicher Basistyp complex complex ist Wertepaar von Doubles complex ist Obertyp von double Präprozessor transformiert syntaktisch gezuckerte Operationen auf complex-werten in Operationen auf double-paaren. 5/17
Modellierung von Arrays für HPC in Java (1) [Comm.ACM(CACM)- und JavaGrande(JG)-Papier von Moreira et al. 2001] Array-Problem im Bild (CACM: Abb. 1) Fallstudie: BLAS-Programme dgemv (JG: Abb. 2) dgemm (JG: Abb. 3) Option 1: mit einem Klassenpaket eine Klasse pro Dimensionalität und Elementtyp (CACM: Abb. 5) Beispiel: intarray3d = new intarray3d(m,n,p) Compilermethoden für rechteckige Arrays anwendbar Operationen auf Elementen und Arraysektionen (à la HPF) Vor-und Nachteile: + JVM kann unverändert bleiben (Portabilität) für bestimmte Optimierungen einfache, lokale Änderungen der JVM nötig Dimensionalität begrenzt (im vorgestellten Paket: 7) Leistungsportabilität nur bei festgelegtem Arraylayout bequeme Syntax für Methodenaufrufe notwendig. 6/17
Modellierung von Arrays für HPC in Java (2) Probleme mit der bequemen Syntax für Methodenaufrufe: Darstellung: Sequenz von punktweisen Operationen (JG: Abb. 4, 5(a)) Updates und Nebenwirkungen greifen für jedes Array-Element separat eine aggregierte Operation, d.h. multiple Zuweisung aller Array-Elemente (JG: Abb. 5(b), 5(c)) Sonderfälle für das ganze Array greifen vor dem Update des ersten Array-Elementes Updates aller Array-Elemente erfolgen nach der Auswertung aller Array-Elemente Achtung: punktweise und aggregierte Updates können zu unterschiedlichen Resultaten und Sonderfallverhalten führen Implementierungsoptionen: führe Overloading arithmetischer Operatoren ein + Arraypackage muss nur installiert sein, wo man es braucht große Sprachänderung (Java hat kein Overloading) erweitere die Syntax der Kernsprache Arraypackage ist Teil der allgemeinen Installation + geringere Auswirkung auf die Sprachdefinition von Java. 7/17
Modellierung von Arrays für HPC in Java (3) Option 2: mit einer neuen JVM Shape-Analyse von Arrays (im Speziellen einfach, generell schwierig) Speicheranalyse zur Zeit der Allokation und bei jedem Arrayzugriff (Dichtheitsanalyse) Beispiel: double[][] A = new double[m+1][n+1] (JC: Abb. 6) anfangs: Dichtheitsmarke gesetzt Änderung der Arraysstruktur Löschen der Dichtheitsmarke Beispiele: A[i] = new double[2*n] A[i] = B[i] Vor-und Nachteile: + keine Sprachänderung Rechteckigkeit manchmal schwer zu erkennen: double[][] a = new double[m][]; for (int i=0; i<m; i++) a[i] = new double[n]; schwerwiegende JVM-Erweiterungen keine arrayspezifischen neuen Operatoren (z.b. Sektionierung). 8/17
Modellierung von Arrays für HPC in Java (4) Option 3: mit neuen Sprachkonstrukten Beispiel: float [*,*] Y = new float [n,m] Zugriff mit normaler Indizierungsnotation (JG: Abb. 7-8) Sektionen in jeder Dimension möglich Transformationen in eindimensionale Arrays auf Java-Ebene (JG: Abb. 9-10) Vor-und Nachteile: + Bytecode und JVM unverändert + unbeschränkte Dimensionalität starke Sprachänderungen einige Komplikationen (z.b. nicht als Rückgabewert benutzbar, da Menge von Variablen; man kann aber einen Resultparameter vorbereiten). 9/17
Das Java Sonderfallmodell [Comm.ACM-Papier von Moreira et al. 2001] Java Standard: alle Zeiger auf Null prüfen (positiv Sonderfall) alle Arrayzugriffe auf Grenzverletzung prüfen (positiv Sonderfall) präzises Sonderfallmodell: alle Effekte vor dem Sonderfall sichtbar alle Effekte nach dem Sonderfall nicht sichtbar Problem: Komplikationen entstehen durch Umordnung von Operationen spekulative Ausführung Lösungsansatz: Versionierung von Schleifensätzen (CACM: Abb. 2). 10/17
Hoare-Axiome für abstrakte Datentypen. 11/17 Bemerkung: Javas Monitor garantiert nicht B(cond) in post(cond.wait) Klasse: sequentiell zugreifbar Synchronisation: keine Beweisregeln: Konstruktormethoden: {Pre} Init {I} andere Methoden: {Pre(Op) I} Op {Post(Op) I} die Invariante I beschreibt den Zustand der Daten zwischen Zugriffen Monitor: parallel zugreifbar Synchronisation: short-term: gegenseitiger Ausschluss der Methodenaufrufe (problemunabhängig) mid-term: Suspendierung und Reaktivierung bezügl. eines Monitorzustandes mitgelieferter abstrakter Datentyp condition: Datum: FIFO-Schlange von Prozessidentifikatoren Methoden: wait zur Suspendierung und signal zur Reaktivierung Beweisregeln: wie gehabt, und zusätzlich für Schlange cond: {I} cond.wait {I B(cond)} {I B(cond)} cond.signal {I}
Monitore in Java Datenobjekt: Klasseninstanz [Andrews: Kap. 6.1+5, Dahls Monitorpapier] Short-Term Scheduling: (Warteschlange: Entry Queue) Methodenattribut synchronized Objektmethode: Klassenmethode: atomar bzgl. Aufrufen anderer......objektmethoden desselben Fadens...Klassenmethoden derselben Klasse Mid-Term Scheduling: (Warteschlange: Condition Queue) mit Operationen: wait() / notify() (in unseren Pufferprogrammen in den Operationen auf einer Semaphore untergebracht) es gibt nur eine Condition Queue pro Monitor (nicht eine pro Bedingung) nach Aufwachen kann man sich des erwarteten Zustandes nur in Spezialfällen sicher sein (z.b. in unseren Pufferprogrammen) i.a. ist eine Warteschleife notwendig Javas Signalisierungsschema: signal + continue. 12/17
Signalisierungsstrategien (wechselseitig simulierbar) signal + continue (SC): (von Greg Andrews empfohlen) Signalisierer: macht weiter (d.h. nicht blockierend ) Signalisierter: Condition Queue Entry Queue Sprachen: Java signal + exit (SX): (führt zu Operationsfragmentierung) Signalisierer: verläßt Monitor endgültig Signalisierter: Condition Queue kritische Region Sprachen: Concurrent Pascal signal + wait (SW): Signalisierer: Entry Queue Signalisierter: Condition Queue kritische Region Sprachen: Modula, Euclid signal + urgent wait (SU): Signalisierer: Urgent Queue (eine Entry Queue mit höherer Priorität) Signalisierter: Condition Queue kritische Region Sprachen: Pascal-Plus automatisch (AS): implizites SC Sprachen: Owickis GPL (await-statement). 13/17
Signalisierung in Java (1) Vorteile: [Andrews] nur eine Condition Queue für alle Bedingungen: Entlastung der Implementierung nicht blockierend: einfachere Beweisregeln für wait und signal die Nachbedingung von wait und die Vorbedingung von signal müssen weniger Übereinstimmung zeigen als bei SW und SU = Monitoroperationen können isoliert konzipiert werden einfache Flächensignalisierung: signalall muss in SW und SU sorgfältig iterativ simuliert werden: jeder signalisierte Prozess muss einen Nachfolger explizit Aufwecken falsche Simulation: do not empty(c) signal(c) od (Nichttermination, wenn Prozesse wieder in c enden) Nachteile: im Allgemeinen Warten in einer Schleife notwendig für mehrere Condition Queues spezielle Klasse notwendig Priorität der Schlangen nicht spezifiziert größere Priorität für Entry als für Condition Queue möglich Konsequenz: Gefahr des Verhungerns. 14/17
Signalisierung in Java (2) EMonitor-Klasse: [EMonitor-Papier] korrekte Schlangenprioritäten unpriorisierte und priorisierte Condition Queues Signalisierungsstrategien: SC, SW, SX. 15/17
Ein Paket-Switching-System Buffer M InputStream M M OutputStream P P P Input Transfer Output. 16/17
Verklemmungsgefahr bei Monitorhierarchien Struktur des Systems: ein Paketpuffer zwei Listen von Indizes in den Puffer für Ein- und Ausgabepakete Prozesse zur Paketeingabe, -konversion und -ausgabe Problematisches Szenario: eines von mehreren... Bei einem vollen Puffer entnimmt der Transferprozess ein Paket. Der Eingabeprozess schiebt sofort ein Paket nach. Nach der Konversion will der Transferprozess das Paket wieder ablegen. Er wird im Monitor OutputStream suspendiert. Deshalb kann der Ausgabeprozess den Puffer nicht leeren. Der Transferprozess selbst kann es auch nicht; er ist suspendiert. Verklemmung! Moral: Vermeide Monitorzugriffshierarchien! Zyklischer Puffer: (jeweils mit Argument 1, 3, 5) java BounderBuffer0 i (Monitorhierarchie: Verklemmung) java BounderBuffer1 i (keine Hierarchie: keine Verklemmung) java BounderBuffer2 i (keine Monitore: keine Verklemmung). 17/17