Slides:



Advertisements
Ähnliche Präsentationen
Imperative Programmierung
Advertisements

Monitore in Java++ Aufgabe 2 von Markus Schlebusch Christoph Reinboth Sebastian Zok Johannes Stolte Norman Zuther.
Kapitel 11 Deadlocks RW-Systemarchitekur Kap. 11.
10.2 Wechselseitiger Ausschluss in Hardware
Wiederholung Betriebssystem bietet eine Abstraktion der Hardware an:
LS 2 / Informatik Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
C Tutorium – Semaphoren –
Suche in Texten (Stringsuche )
Institut MD Universität Rostock Real-Time Linux Szenario –Board, liest (sampled) analoge Daten –produziert 8 Bit Ergebnis und gibt dieses alle 100 ms aus.
3 Prozessverwaltung  sieht einen Prozess als Objekt der Verwaltung,
der Universität Oldenburg
der Universität Oldenburg
Semaphore void Passieren (semaphore &s) { if (s > 0) { s--;
Terminierung und Deadlocks Enkhbat Daginaa Betreuerin Prof. Heike Wehrheim Totale Korrektheit.
Kapitel 6.1 Nebenläufigkeit und wechselseitiger Ausschluss
Systeme 1 Kapitel 7 Deadlocks WS 2009/10.
Kapitel 7.2 Dining philosophers problem
FH-Hof Deadlocks Richard Göbel. FH-Hof Deadlock - Definition Menge von Prozessen ist an einem Deadlock beteiligt: wenn jeder Prozess in dieser Menge auf.
Kapitel 10 Nebenläufigkeit und wechselseitiger Ausschluss
Nebenläufige Programmierung
ARRAY oder FELD oder VEKTOR
V AdresseWert public static void main(...){ int[] v; v=new int[2]; } Was veranlasst diese Anweisung im Arbeitsspeicher ? Es wird im Arbeitsspeicher.
Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.
1 Named Pipes alias FIFO Haben einen Eintrag im Dateisystem und sind somit durch Zugriffsrechte identifizierbar Ermöglichen die Kommunikation zwischen.
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 7 Claudio Moraga, Gisbert Dittrich FBI Unido
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 10 Claudio Moraga; Gisbert Dittrich FBI Unido
Vorlesung 10 Mutual Exclusion Peter B. Ladkin Sommersemester 2001 Universität Bielefeld Technische Fakultät.
Vorlesung 9.2: Specification Universität Bielefeld – Technische Fakultät AG Rechnernetze und verteilte Systeme Peter B. Ladkin
Prof. Dr. Bernhard Wasmayr
DVG Ablaufsteuerung
15.1 Synchronisation nebenläufiger Prozesse
Weiteres Programm Studium des Breitendurchlaufs Hierzu
Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
Implementierung von S2PL (1) Scheduler als Verwalter von Sperren auf Datenelementen sowie Warteschlangen für Sperren (Sperren-Verwalter). Transaktion 1Transaktion.
Prof. Dr. Bernhard Wasmayr VWL 2. Semester
AWA 2007 Natur und Umwelt Natürlich Leben
Grundkonzepte Java - Klassendefinition
Prof. Dr. Günter Gerhardinger Soziale Arbeit mit Einzelnen und Familien Übersicht über die Lehrveranstaltung Grundlegende Bestimmungsfaktoren der Praxis.
Prozesskoordination Prof. Dr. W. Riggert.
GWDG – Kurs Parallelrechner-Programmierung mit MPI MPI Punkt-zu-Punkt-Kommunikation Oswald Haan
Eine Einführung in die CD-ROM
BIT – Schaßan – WS 02/03 Basisinformationstechnologie HK-Medien Teil 1, 11.Sitzung WS 02/03.
Black Box Algorithmen Hartmut Klauck Universität Frankfurt SS
Kapitel 6 Nebenläufigkeit und wechselseitiger Ausschluss
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.
FORTRAN 77.
Einführung in die Programmiersprache C 4
Parallel Matrix Multiplication
Parallel Programming Condition Queues
Dynamische Datentypen
Ertragsteuern, 5. Auflage Christiana Djanani, Gernot Brähler, Christian Lösel, Andreas Krenzin © UVK Verlagsgesellschaft mbH, Konstanz und München 2012.
Prozess-synchronisation
Thread Synchronisation in JAVA
Variablenkonzept Klassisch, in Java Basistyp
Betriebssysteme Übung 2. Tutorium. Task 1 – Locks (1) Wozu Locks? Dienen dazu, exklusiven Zugriff auf eine Ressource sicherzustellen Lock = binäre Semaphore.
MINDREADER Ein magisch - interaktives Erlebnis mit ENZO PAOLO
Folie Beispiel für eine Einzelauswertung der Gemeindedaten (fiktive Daten)
Parallelisierung für Multiprozessor-Maschinen
Mehrbenutzerzugriff auf GIS-Daten
Folie Einzelauswertung der Gemeindedaten
Inf K1/2 Sj 13/14 GZG FN W.Seyboldt 1 SFZ FN Sj. 13/14 Python Klassen und Objekte.
Synchronisation paralleler Transaktionen  AIFB SS Sperrverfahren Sperrverfahren (13/18) Behandlung von Konflikten bei der Sperrvergabe.
CODA - Installation Installation der Binärdateien –Venus: Client-Programm –Vice: Server-Programm –Für Windows existiert eine Alpha-Version (Coda Client.
93 Das Monitorkonzept (nach Hoare/Brinch-Hansen 1974) Nur ein Prozess bzw. Thread kann zu einem bestimmten Zeitpunkt im Monitor aktiv sein => gegenseitiger.
Funktionen, Felder und Parameter- übergabe. Funktionsaufruf mit Feld als Parameter: Parameter = Name des Feldes.
© 2008 TravelTainment The Amadeus Leisure Group Thread-Programmierung im Qt-Framework Von: Simon Lubberich Erstbetreuer:
Pointer. * und &  Bei der Definition int var1; ○ // „normale“ Variable int *var2; ○ // Zeiger auf einen Integer int *var2 = NULL; ○ // … incl. Initialisierung.
Center for Biotechnology Bielefeld Bioinformatics Service Netzwerk - Programmierung Threads Alexander Sczyrba Jan Krüger.
Shared Memory Programmierung: Grundlagen
 Präsentation transkript:

Grundkonzepte paralleler Programmierung => MPD (Multi-threaded Parallel Distributed) Andrews (Arizona University) http://www.cs.arizona.edu/mpd

Synchronisation von Speicherzugriffen Problem: Speicherzugriffe auf gemeinsame Variablen müssen koordiniert werden Nicht-atomare Operationen erfordern exklusiven Zugriff auf globale Daten Beispiel: .... Prozess p count := 500 Prozess q ..... ....  .... local := count inc100(count) for i:=1 to 100 ->... inc100(count) count := local count := 500+?

Beispiel: MPD-Programm counter.mpd resource counter() int count = 0 # increment count by 100 process inc1000 [id = 1 to 10] { int local; int top = 100 for [j=1 to id] { # increment global counter - critical section local = count; writes(id,": get counter = ", local); write() for [k = 1 to top] { local += 1 }; nap(int(random()*100)) count = local; writes(id,": put counter = ", local); write() # wait for some time - non-critical section nap(int(random()*100)) } } final { write(count) } end counter

Synchronisationsformen Wechselseitiger Ausschluss (mutual exclusion) Bsp: geschützter Zugriff auf gemeinsame Ressourcen (s.o.) einseitige Synchronisation Bedingungssynchronisation (condition synchr.) Ereignissynchronisation (event synchr.) Ein Prozess muss auf eine Bedingung oder ein Ereignis warten, das von einem anderen Prozess ausgelöst wird. Bsp: Erzeuger-Verbraucher mit (un-)beschränktem Puffer ((un-)bounded buffer) Barrierensynchronisation (Verallgemeinerung von 2.) Eine Gruppe von Prozessen muss an einer sog. Barriere warten, bis alle Prozesse der Gruppe die Barriere erreicht haben. Bsp: Synchronisation von Schleifendurchläufen paralleler Prozesse

Race Conditions Situationen, in denen das „Wettrennen“ (race) der Prozesse beim Zugriff auf gemeinsame Ressourcen Auswirkungen auf das Ergebnis eines Programmlaufs hat. Durch Synchronisationen werden „race conditions“ vermieden. Das Wettrennen unter den Prozessen wird eingeschränkt. Gefahren durch unpassende Synchronisationen Verklemmungen (deadlocks) Aushungerungen (starvations)

Synchronisationskonstrukte: Semaphore (Dijkstra 1965) Ein Semaphor ist ein abstrakter Datentyp mit nicht-negativer Integer-Variablen (Semaphorzähler) zwei unteilbaren (atomaren) Operationen P und V P => Passieren, V => Verlassen Bei der Initialisierung wird dem Semaphor ein nicht-negativer Wert zugewiesen. Anschließend ist nur noch eine Manipulation mit den Operationen P und V möglich. P(S): Wenn S>0, dann S := S-1 sonst wird der Prozess, der P(S) ausführt, suspendiert V(S): Wenn Prozesse bei Ausführung von P(S) suspendiert wurden dann reaktiviere einen Prozess sonst S := S+1 atomar atomar binäres Semaphor: Initialisierung mit 1

Semaphore in MPD Semaphor-Deklaration: sem sem_def, sem_def Semaphor-Definition: sem id [subscripts] = expr einzelnes Semaphor Feld von Semaphoren Operationen: P(sem_id [subscripts]) V(sem_id [subscripts])

Wechselseitiger Ausschluss resource Critical_Section () const N := 20 # Anzahl Prozesse var X := 0 # gemeinsame Variable sem mutex := 1 # Semaphor zum Schutz von X process p (i:= 1 to N) # non-critical section ... # critical section P(mutex) X:=X+1 V(mutex) end Warteschlange ist als first-come-first-served FIFO-Schlange organisiert.

Beispiel: MPD-Programm counter.mpd mit Semaphor resource counter() int count = 0; sem mutex := 1; # increment count by 100 process inc1000 [id = 1 to 10] { int local; int top = 100 for [j=1 to id] { # increment global counter - critical section P(mutex) local = count; writes(id,": get counter = ", local); write() for [k = 1 to top] { local += 1 }; nap(int(random()*100)) count = local; writes(id,": put counter = ", local); write() V(mutex) # wait for some time - non-critical section nap(int(random()*100)) } } final { write(count) } end counter

Einseitige Synchronisation: Erzeuger/Verbraucher-Problem Erzeuger produziert  Verbraucher konsumiert Annahme: unbeschränkter Puffer resource Producer-Consumer (); ... sem full = 0; sem mutex = 1; process producer () var item : int while (true) { produce (item) P(mutex) enter (item) V(mutex) V(full) } ... process consumer () var item : int while (true) { P(full) P(mutex) remove (item) V(mutex) consume (item)}

Zyklische Synchronisation: P1 > P2 > P3 ... resource Critical_Section () const N := 20 # Anzahl Prozesse var X := 0 # gemeinsame Variable sem mutex[N] := (1, [N-1] 0) # Semaphorfeld process p (i:= 1 to N) # non-critical section ... # critical section P(mutex[i]) X:=X+1 V(mutex[(i mod N)+1]) end Zugriff auf kritische Abschnitte in zyklischer Reihenfolge

Fallstudie: Leser-/Schreiber-Problem Mehrere Prozesse arbeiten auf gemeinsamem Speicherbereich. Gleichzeitige Lesezugriffe sind erlaubt. Schreibzugriffe müssen exklusiv erfolgen. Lösungsansatz [Courtois, Heymans, Parnas 71, ACM] Idee: Verwalte Zähler readcount für Leseranzahl 2 Semaphore: sem rcount_mutex := 1 (Schutz für readcount) sem writing := 1 (Sperre für exklusiven Schreibzugriff) Schreibprozesse: CREW (concurrent read exclusive write) process writer () while (true) { <Daten erzeugen> P(writing) <Daten schreiben> V(writing) } end

Leseprozesse process reader () while (true) { P(rcount_mutex) if readcount == 0 { P(writing) } readcount += 1 V(rcount_mutex) <Daten lesen> readcount -= 1 if readcount == 0 { V(writing) } } end Leseranmeldung: Erster Leser besorgt Speicherfreigabe. Leserabmeldung: Letzter Leser gibt Speicher frei.

Korrektheit Das Semaphor writing schützt den Speicherbereich. Schreiber aktiv => writing ist gesetzt Kein weiterer Schreiber kann passieren. Erster Leser blockiert bei P(writing). Weitere Leser blockieren bei P(rcount_mutex). Leser aktiv => writing ist durch ersten Leser gesetzt. Schreiber wird bei P(writing) blockiert. Weitere Leser passieren writing nicht, sondern erhöhen nur den Lesezähler.

Problem: Schreiberaushungerung Wenn ständig neue Leser hinzukommen, wird readcount nie Null und die Schreiber erhalten keinen Zugang zum kritischen Bereich. Besser: Blockiere neue Leser, sobald ein Schreiber wartet. Führe neuen Zähler writecount für Leser und (wartende) Schreiber ein. neue Semaphore: sem wcount_mutex = 1 (Schutz für Schreiberzähler) sem reading = 1 (Sperre für Leser, falls Schreiber warten) =>zusätzliche Anmeldung für Schreiberprozesse, um neue Leser zu stoppen

Schreiberan- und -abmeldung P(wcount_mutex) if writecount == 0 { P(reading) } writecount += 1 V(wcount_mutex) P(writing) process writer () while (true) { <Daten erzeugen> P(writing) <Daten schreiben> V(writing) } end P(wcount_mutex) writecount -= 1 if writecount == 0 { V(reading) } V(wcount_mutex) V(writing)

Modifikation der Leseranmeldung process reader () while (true) { P(reading) P(rcount_mutex) if readcount == 0 { P(writing) } readcount += 1 V(rcount_mutex) V(reading) <Daten lesen> readcount -= 1 if readcount == 0 { V(writing) } } end blockiert neue Leser, falls Schreiber wartet oder Leser bei Anmeldung damit erster Schreiber nicht blockiert wird

Barrierensynchronisation P1 P2 . . . . Pn BARRIERE Prozesse können nur passieren, wenn alle Prozesse der Gruppe die Barriere erreicht haben.

Bsp: Iterationsverfahren zum Lösen partieller Differentialgleichungen zweidimensionales Temperaturverteilungsproblem: Ermittle die Temperaturverteilung an den Gitterpunkten im stabilen Zustand Im stabilen Zustand gilt: x,y = 1/4 (x-1,y + x+1,y + x,y-1 + x,y+1 ) . . . . . . . . . . Wasser- dampf Eisbad 0°C 100°C dünne Metallplatte 100°C Iterationsverfahren nach Jacobi (1845) – Gesamtschrittverfahren: x,y0 = geschätzter Wert, Anfangswert x,yi+1 = 1/4 (x-1,yi + x+1,yi + x,y-1i + x,y+1i ) fn²/2 Iterationen garantieren Fehler unter 10-f bei Problemgröße n (=#Gitterpunkte)

Paralleles MPD-Programm mit co ... oc resource Jacobi() const int n = 5; const int f = 3; int numiter real a [0:n+1,0:n+1], b [0:n+1,0:n+1] ... # Iteration zur Bestimmung der Werte im stabilen Zustand for [k=1 to numiter] { # 1. Phase : Neuberechnung der Werte co [i=1 to n] compute_row(i) oc # 2. Phase : Update co [i=1 to n] update_row(i) oc } end Analyse: neue Prozesse für jede Iteration und jede der beiden Phasen besser: Prozesse nur einmal erzeugen; Synchronisation mittels Barriere

Lineare Barriere mittels Zählvariable einfachste Form der Barriere Verwaltung eines Zählers Sperren aller aufrufenden Prozesse, bis Zähler Maximalwert erreicht, danach Freigabe aller Prozesse mit Semaphoren: sem arrival = 1 (Freigabe des Barrierenzugangs) sem departure = 0 (Sperren des Barrierenabgangs) var count : int = 0 global barriere sem arrival = 1, departure = 0; int count = 0 op barrier(val int n) body barriere proc barrier (n) { # Ankunftsphase P (arrival); count += 1 if (count < n) { V(arrival) } else { V(departure) } # Abgangsphase P(departure); count -= 1 if (count > 0) { V(departure) } else { V(arrival) } } end barriere

Modifiziertes MPD-Programm resource Jacobi() const int n = 5; const int f = 3; int numiter real a [0:n+1,0:n+1], b [0:n+1,0:n+1] ... process row [i=1 to n] { # Iteration for [k=1 to numiter] { # 1. Phase : Neuberechnung der Werte compute_row(i) call barriere.barrier(n) # SYNCHRONISATION # 2. Phase : Update update_row(i) } } end

Turnierbarriere mit Aufwand O(log n) Process Id´s 000 001 010 011 100 101 110 111 000 010 100 110 000 100 000 000 001 010 011 100 101 110 111 Ankunftsphase “Aggregation” Abgangsphase “Broadcast”

Turnierbarriere in MPD global barriere2 const int n = 8 # Anzahl Prozesse sem b[0:n-1] = ([n] 0) # Feld von Barrierensemaphoren op barrier(val int myid, val int n) body barriere2 proc barrier (myid,n) { int pos = 1 # Bitwertigkeiten # Ankunftsphase while ((myid / pos) mod 2 == 0 & pos < n) { P (b[myid]) # Warte auf Partner pos *= 2 } if (myid != 0) { V(b[myid-pos]) # Melde Ankunft an Partner P(b[myid]) # Abgangsphase while ( pos > 1 ) { pos = pos / 2; V(b[myid+pos]) } end barriere2 Die Barriere ist wieder- verwendbar! Turnier

Symmetrische Barriere hier nur für 2 Prozesse mit 2 Semaphoren sem b1 = 0; sem b2 = 0 P1: ...... V(b2); P(b1) ...... P2: ...... V(b1); P(b2) ........ allgemein: Butterfly-Schema, Aufwand O(log n)

Vor- und Nachteile von Semaphoren Vorteile: einfach effizient zu realisieren Nachteile: niedriges Abstraktionsniveau fehleranfällige Programmierung fehlende P-Operation => kein wechselseitiger Ausschluß fehlende V-Operation => mögliche Verklemmung unstrukturierte Programmierung P- und V-Operationen über das ganze Programm verstreut, z.B. bei bedingter Synchronisation