Grundlagen der Programmierung 2 Parallele Verarbeitung Prof. Dr. Manfred Schmidt-Schauÿ Künstliche Intelligenz und Softwaretechnologie 31. Mai 2006 Teile und Herrsche (Divide and Conquer) Entwurfsmethode für Algorithmen 1. 2. 3. Teile das Problem in kleinere Unterprobleme (Divide) Löse rekursiv die entstehenden Unterprobleme (Conquer) Setze die Lösungen zusammen. Instanzen : • • • • Mergesort Quicksort Intervallhalbierung (kein Zusammensetzen) schnelle Berechnung ganzzahliger Potenzen Grundlagen der Programmierung 2 - 1 - Divide-and-Conquer: Laufzeiten Bei sequentiellen Programmen kann man oft erreichen, dass ein O(n) Laufzeitanteil verbesserbar ist zu O(log(n)) Notwendig dazu: Summe der Größen der Teilprobleme Grundlagen der Programmierung 2 ≤ Größe des Problems - 2 - Beispiel: Türme von Hanoi Gegeben Stapel von verschieden großen Scheiben von oben nach unten größer werdend Aufgabe: Umstapeln auf einen anderen Stapel. Erlaubt ist ein weiterer Hilfsstapel Bedingung: Es darf niemals eine Scheibe auf einer kleineren liegen Lösung: mittels Teile-und-Herrsche: Grundlagen der Programmierung 2 - 3 - Beispiel: Türme von Hanoi 1 n-1 n 2 n n-1 3 n-1 n Grundlagen der Programmierung 2 - 4 - Beispiel: Türme von Hanoi (2) Notwendige Bewegungen für n: 1. n − 1 Scheiben von 1 nach 3 mit 2 als Hilfsstapel 2. Scheibe n von 1 nach 2 3. n − 1 Scheiben von 3 nach 2 mit 1 als Hilfsstapel Grundlagen der Programmierung 2 - 5 - Beispiel: Türme von Hanoi (2) Haskell-Algorithmus zum Ermitteln der Bewegungen. Die Nr. der Stapel wird als Argument mitübergeben. -hanoi: Stapel, Stapelnr, Zielstapelnr Hilfstapelnr: hanoi xs a b c = hanoiw (reverse xs) a b c hanoiw [] _ _ _ = [] hanoiw xa a b c = (hanoiw (tail xa) a c b) ++ ((head xa ,(a,b)) : (hanoiw (tail xa) c b a)) Grundlagen der Programmierung 2 - 6 - Parallele Algorithmen und deren Ressourcenbedarf Themen: Nebenläufigkeit, Parallelität, Ressourcenverbrauch Parallelisierung von Algorithmen Amdahl-Gesetz Gustafson-Barsis Gesetz Beispielalgorithmen in Haskell Grundlagen der Programmierung 2 - 7 - Nebenläufigkeit und Parallelität Prozesse und Kommunikation Prozess: eigenständig ablaufende Rechnung mit eigenem Speicher wie Rechner; kann interne Berechnungen und Ein-Ausgabe durchführen P,Q nebenläufig wenn diese unabhängig voneinander ausgeführt (concurrent) werden können. P,Q parallel, Grundlagen der Programmierung 2 wenn sie nebenläufig sind und gleichzeitig ablaufen. - 8 - Klassifikation der parallelen Rechnerarchitekturen nach Flynn Bezüglich paralleler Instruktionssequenzen und Parallelität der Verarbeitung von Daten: • • • • SISD: Single instruction, single data stream (SISD): Sequentieller Rechner ohne Parallelität. MISD:Multiple instruction, single data stream: kommt so gut wie nicht vor: Man könnte redundante (Doppel-) Verarbeitung hier einordnen. SIMD: Single instruction, multiple data streams: Gleiche Verarbeitung. viele gleichartige Daten: z.B. Vektorprozessor. MIMD:Multiple instruction, multiple data streams: Mehrere Prozessoren lassen verschiedene Programme auf verschiedenen Daten ablaufen: Verteilte Systeme. Grundlagen der Programmierung 2 - 9 - Parallele und verteilte Berechnungen • PRAM: parallel random access machine • Verteilte Berechnung, lose Kopplung • massiv parallel, enge Kopplung • Grid-Computing • Vektorrechner, Feldrechner • Pipelining Grundlagen der Programmierung 2 - 10 - PRAM: parallel random access machine • Mehrere Prozesse (Prozessoren), gemeinsamer Hauptspeicher, • unabhängiges Lesen und Schreiben • Unterscheidung verschiedener Modelle: Lesen- und/oder Schreiben; exklusiv oder konkurrierend (EREW, CRCW, CREW). Grundlagen der Programmierung 2 - 11 - Verteilte Berechnungen, lose Kopplung • • • • Mehrere unabhängige Rechner kommunizieren über ein Netzwerk arbeiten gemeinsam an einer Berechnung Programme / Programmteile können völlig verschieden sein. Weitere Unterscheidung: Gleichberechtigte Rechner; oder hierarchisch (Master/ Slave) bzw. (Client / Server). • Z.B. PVM: Parallel Virtual Machine Grundlagen der Programmierung 2 - 12 - massiv parallel, enge Kopplung • • • • • Viele unabhängige, gleiche Prozessoren Kopplung über ein schnelles Netzwerk arbeiten gemeinsam an einer Berechnung. I.a: Gleiches Programm, verschiedene Daten. Oft feste Topologie: Hyperwürfel, ähnliche Netzwerke, Z.B. Hardware für künstliche neuronale Netze. Grundlagen der Programmierung 2 - 13 - Grid-Computing • Viele Workstations/ PCs rechnen gemeinsam an einer Aufgabe • verschiedene Hardware / Betriebssystem ist möglich • I.a. : Rechner haben das gleiche Programm, aber verschiedene Daten Grundlagen der Programmierung 2 - 14 - Vektorrechner • Ein Programm steuert parallele Berechnungen auf HW-Arrays: • Gleiche Prozedur, verschiedene Datenelemente • Sinnvoller Einsatz: Wettersimulationen, numerische Berechnungen • SIMD (single instruction, multiple data) Grundlagen der Programmierung 2 - 15 - Pipelining • • • • I.a. parallele Ausführung von Maschinenkode auf der Hardware eines Prozessor Befehlsbearbeitung wird in kleinere Einheiten zerlegt, die dann nacheinander, versetzt abgearbeitet werden. Weitere Beschleunigung durch Mehrfachauslegung von internen Einheiten Grundlagen der Programmierung 2 - 16 - Maße für den parallelen Ressourcenverbrauch Modell auf der Programmiersprachenebene: Auswertung durch einzelne Reduktionsschritte (z.B. Haskell) • sequentieller Einzelschritt • paralleler Einzelschritt = Grundlagen der Programmierung 2 mehrere unabhängige, gleichzeitige Einzelschritte - 17 - Maße für den parallelen Ressourcenverbrauch Basis ist das PRAM-Modell: • mehrere, nicht unterscheidbare Prozessoren • gemeinsamer Hauptspeicher • Befehlsabarbeitung ist synchron getaktet. • pro Einzelschritt einer parallelen Auswertung • ist ein Prozessor notwendig #parallele Reduktionsschritte = #paralleler Schritte bis zum Ergebnis #notwendige Prozessoren = maximale Anzahl gleichzeitiger sequentieller Einzelschritte in einem parallelen Schritt Grundlagen der Programmierung 2 - 18 - Beispiel: Parallele Auswertung Skalarproduktberechnung: (a1, . . . , an) ∗ (b1, . . . , bn) = a1 ∗ b1 + . . . + an ∗ bn 1. Schritt: 2. Schritt: Werte die Produkte parallel aus Addiere die Ergebnisse Grundlagen der Programmierung 2 - 19 - Parallele Reduktion; konservativ / spekulativ • Die Parallelisierung ist konservativ, wenn nur Auswertungen durchgeführt werden, die für das Erreichen des Resultats notwendig sind. • Die Parallelisierung ist spekulativ, wenn auch Reduktionen durchgeführt werden können, von denen zum Zeitpunkt der Ausführung nicht bekannt ist, ob diese für das Berechnen des Resultats notwendig sind. Grundlagen der Programmierung 2 - 20 - Parallele Reduktion: Beispiel spekulativ: Die parallele Reduktion von s und t in if cond then s else t konservativ: Die parallele Reduktion von s und t in s * t Grundlagen der Programmierung 2 - 21 - Parallele Reduktion: Maßzahlen Algorithmus sei gegeben, sei E die Eingabe, und p die Anzahl der erlaubten Prozessoren. τ (E, p) τ (E, 1) τ (E, ∞) minimale Anzahl der parallelen Reduktionsschritte bis zum Ergebnis, wenn man p unabhängige Reduktionsschritte gleichzeitig pro Schritt machen darf ist die Anzahl der Einzel-Reduktionsschritte bei sequentieller Auswertung. entspricht dann der Anzahl der parallelen Reduktionsschritte bis zum Ergebnis, wenn es keine obere Schranke für die Anzahl gleichzeitiger Reduktionen (#Prozessoren) gibt. τ (E, 1) Optimistische Erwartung: τ (E, p) ≈ . p Grundlagen der Programmierung 2 - 22 - Parallele Reduktion: Beschleunigung Vereinfachende Annahme im folgenden: die Kennzahlen hängen nur vom Algorithmus ab; proportional zur Eingabegröße E; D.h., für alle p: τ (E, p) = |E| ∗ τ (p); meist kann |E| gekürzt werden. (relative) parallele Beschleunigung := τ (1) τ (p) Die parallele Beschleunigung ist eine Zahl zwischen 1 und p ≥ 1, ≤ p, da man sequentiell reduzieren kann, da maximal p Prozessoren und man eine parallele Reduktion zu einem Ergebnis sequentiell nachvollziehen kann. Grundlagen der Programmierung 2 - 23 - Parallele Reduktion: Beschleunigung maximale parallele Beschleunigung τ (1) τ (1) q := = lim . p→∞ τ (p) τ (∞) parallele Beschleunigung bei unbeschränkter Anzahl von Prozessoren. sequentieller Zeit-Anteil des Algorithmus := 1/q. Grundlagen der Programmierung 2 - 24 - Parallele Reduktion: Effizienz parallele Effizienz := = τ (1) p ∗ τ (p) Anteil der für den Algorithmus nutzbaren gesamten Leistung aller Prozessoren Beispielhafte Zahlen: Zeit Beschleunigung Effizienz Grundlagen der Programmierung 2 τ (1) 1000 1 1 τ (3) 500 2 66,6% τ (4) 400 2,5 62,5% - 25 - Parallele Effizienz τ (1) ist eine Zahl zwischen 1 und 1/p. p ∗ τ (p) 1 optimal: alle Prozessoren tragen zur zur Berechnung bei 1/p schlecht: Berechnung ist im wesentlichen sequentiell Grundlagen der Programmierung 2 - 26 - Weitere Maßzahlen w(p) die verrichtete Arbeit Gesamt-Anzahl von Einzelschritten Es gilt stets: w(p) ≥ τ (1) w(p) τ (p) mittlere Anzahl beschäftigter Prozessoren w(p) p ∗ τ (p) mittlere Auslastung Grundlagen der Programmierung 2 - 27 - Amdahls Gesetz Begrenzung der parallelen Beschleunigung Amdahl-Annahmen zur Problemstruktur (≈ für alle Eingaben) T = Tpar + Tseq Gesamtzeit T hat parallelen und sequentiellen Anteil Tpar Verhältnis ist konstant. Tseq Beispiel map f xs Sequentieller Anteil: mindestens ein Listendurchlauf Grundlagen der Programmierung 2 - 28 - Amdahls Gesetz (2) Beschleunigung durch p Prozessoren: Tpar + Tseq (1/p) ∗ Tpar + Tseq Bei unendlich vielen Prozessoren: Tpar + Tseq Beschleunigung ≤ Tseq Beispiel Wenn sequentieller Anteil = 5%, dann ist Beschleunigung maximal 20 Grundlagen der Programmierung 2 - 29 - Gustafson-Barsis Gesetz Gustafson-Barsis-Annahme: T = Tseq + p ∗ Tp T Tseq p ∗ Tp Zeit für einen Prozessor fester sequentiellen Anteil, z.B. Initialisierung auf p Prozessoren verteilbare Berechnungszeit Tseq ergibt sich: Mit α = Tp Beschleunigung Grundlagen der Programmierung 2 = α+p Tseq + p ∗ Tp = Tseq + Tp α+1 - 30 - Gustafson-Barsis Gesetz: Beispiel Anwendung von f auf alle Elemente eines Arrays der Länge n a[1], . . . , a[n] Tseq Tp → f a[1], . . . , f a[n] Initialisierungszeit Zeit zum Berechnen von f x. Wenn Tseq = Tp, dann Beschleunigung mit n Prozessoren = Grundlagen der Programmierung 2 1+n 2 - 31 - Beispiele: Algorithmen und Parallelisierung in Haskell vereinfachtes Modell in Haskell: unabhängige Transformationen können parallel durchgeführt werden. Annahme: beliebig viele Prozessoren verzögerte Reduktion und gerichteter Graph bzw. let-Darstellung. Jede Transformation benötigt eine Zeiteinheit. #parallel mögliche Transformationen = #Prozessoren Grundlagen der Programmierung 2 - 32 - Beispiele quadratsumme 3 4 −→ (3*3)+(4*4) −→ 9+16 −→ 25. 2 Prozessoren; 3 Zeiteinheiten werden benötigt Grundlagen der Programmierung 2 - 33 - Beispiel: Fakultät fakt 3 −→ if 3 == 1 then 1 else 3*(fakt (3-1)) −→ if False then 1 else 3*(if 2 == 1 then 1 else 2*(fakt (2-1) ) −→ 3*(if False then 1 else 2*(if 1 == 1 then 1 else 1*(fakt (1-1))) −→ 3*(2*(if True then 1 else 1*(if 0 == 1 then 1 else 1*(fakt0))) −→ 3*(2*(1)) −→ 3*(2) −→ 6 7 parallele Auswertungsschritte bei 4 Prozessoren. Die parallele Zeit ist O(n). Mehr Prozessoren helfen nicht. Grundlagen der Programmierung 2 - 34 - Beispiel: Fakultät Man kann (fakt n) in paralleler Zeit O(log(n)) berechnen: Idee: Benutze Divide-and-Conquer: 1 ∗ 2 ∗ 3... ∗ n = 1 ∗ 2 ∗ . . . ∗ (n/2) ∗ (n/2 + 1) ∗ . . . ∗ n usw. Grundlagen der Programmierung 2 - 35 - Beispiel map quadrat [1..n]. Auswertungssequenz: map quadrat [1..n] 1: map quadrat [2..n] 1: 4: (map quadrat [3..n]) Benötigt O(n) parallele Schritte. Grundlagen der Programmierung 2 - 36 - Summation von n Zahlen in einer Liste Zwei Algorithmen für Summe im Vergleich: sum [] = 0 sum (x:xs) = x+ (sum xs) Benötigt O(n) parallele Reduktionsschritte. Grundlagen der Programmierung 2 - 37 - Summation von n Zahlen in einem balancierten binären Baum: data BBaum a = BBlatt a | Bknoten (BBaum a) (BBaum a) sumbt (Bblatt x) = x sumbt (Bknoten bl br) = (sumbt bl) + (sumbt br) Bei Tiefe h: 2 ∗ (h + 1) parallele Schritte, d.h., log2(n) + 1 . sehr gut für parallele Verarbeitung geeignet Grundlagen der Programmierung 2 - 38 - Summation von n Zahlen in einem balancierten binären Baum mittels schnellem foldbt foldbt (+) 0 "(((1,2),3),(4 ,5))" --> foldbt (+) (foldbt (+) 0 "(4 ,5)") "((1,2),3)" --> foldbt (+) (foldbt (+) (foldbt (+) (foldbt (+) 0 "5") ................. --> "4") "3") 1+ (2+ (3+ (4+ 5)))) Die Problematik ist: Obwohl sich die foldbt exponentiell ausbreiten: Die Summe 1+ (2+ (3+ (4+ 5))) ist sequentiell D.h., man braucht mindestens O(n) parallele Schritte foldbt nicht geeignet zur Parallelisierung Grundlagen der Programmierung 2 - 39 - Paralleles Sortieren von (verschiedenen) Zahlen Nachweis: Parallelisierung kann Sortieren beschleunigen. Merge-Sort: die zerlegten Listen sind parallel sortierbar. Aber: Mischen ist sequentiell, Zerlegen ebenfalls Man benötigt an parallelen Reduktionen 2 ∗ n + 2 ∗ (n/2) + 2 ∗ (n/4) + . . . = 4 ∗ n D.h. O(n). Grundlagen der Programmierung 2 - 40 - Eine Parallelisierung des Bubble-Sort Gegeben: Array der Länge n odd-even transposition sort: Vergleiche benachbarte Elemente und vertausche, falls nötig Notwendig sind (n + 1) ‘div‘ 2 Prozessoren. Im ersten Schritt vergleiche Werte mit Indizes (1,2), (3,4), (5,6) . . . , im zweiten Schritt (2,3), (4,5), (6,7), (8,9),. . . . Man kann nachweisen, dass nach n Schritten das Feld sortiert ist. Man erhält: • parallele Laufzeit: O(n) • parallele Beschleunigung: ∼ log(n)) • parallele Effizienz: ∼ log(n)/n • Gesamtanzahl an Operationen: ∼ n ∗ n Grundlagen der Programmierung 2 - 41 - Paralleles Sortieren Es gibt Parallelisierungen, die in O((log(n))2) laufen. Es gibt komplizierte Parallelisierungen, die laut Experten sogar nur O(log(n)) Zeit benötigen. Parallele Sortieralgorithmen: Sortiernetzwerke Grundlagen der Programmierung 2 - 42 - Parallelisierung: Bemerkungen Teile-und Herrsche kann sehr gut parallelisierbare Algorithmen ergeben Aber nicht immer: z.B. hanoi Sequentielle optimierte Algorithmen (Scan) ergeben i.a. schlecht parallelisierbare Algorithmen Hand-Parallelisierung auf der Programmiersprachenebene: nur Anwendungsnische Stete Beschleunigung der sequentiellen CPUs holt den Vorteil paralleler Architekturen immer wieder ein Grundlagen der Programmierung 2 - 43 - Parallelisierung: Bemerkungen Wo ist Parallelisierung aktuell lohnend? • auf Prozessorebene • implizit durch den Compiler • Number Crunching: wie z.B. Wettervorhersage • Grid Computing: viele gleichartige Daten, gleiches Programm Supercomputer sind Parallelrechner mit (aktuell) bis zu 131.072 Prozessoren. Grundlagen der Programmierung 2 - 44 - Ein Ausflug in die Komplexitätstheorie Theoretische Klassifikation von Problemklassen: Effizient Parallelisierbare Probleme: Pippenger) NC ( Nick’s Class“) ” (Nikolaus Definition: Eine Problemklasse is in NC, wenn die Probleme in polylogarithmischer Zeit, O(log c(n)) für ein c > 0 mit polynomiell vielen Prozessoren bearbeiten werden können. Es gilt N C ⊆ PTime. d.h. NC-Probleme haben einen Polynomial-ZeitAlgorithmus Vermutung: N C ⊂ PTime. Dadurch ist es manchmal möglich, nachzuweisen, dass man eine Problemklasse nicht auf diese günstige Weise parallelisieren kann. Grundlagen der Programmierung 2 - 45 - Beispiel: NC NC-Probleme (d.h. gutartig parallelisierbar): Sortieren von Zahlen. Summation von n Zahlen in einem balancierten Baum. Zeitschätzung: • n Prozessoren • in Zeit O(log (n)) die Blätter ermitteln • die Ergebnisse in Zeit log (n) (parallel) addieren. Grundlagen der Programmierung 2 - 46 - Beispiel: nicht in NC Ein Problem nicht in NC: (Vermutlich) D.h. nicht effizient parallelisierbar Gegeben ein Schaltnetz (UND/ ODER / NICHT-Knoten, Gerichteter Graph) Boolesche Werte an den Eingängen Berechne die Wert an den Ausgängen Grundlagen der Programmierung 2 - 47 -