PD Stefan Bosse
Universität Bremen, FB Mathematik & Informatik
SS 2020
Version 2020-06-02 sbosse@uni-bremen.de |
Für die Visualisierung und Analyse von nebenläufigen Prozessen und Aktionen
Zustands-Raum Diagramme beschreiben die möglichen Zustands-Entwicklungen - das Verhalten - von parallelen Programmen.
Computer sind endliche Zustandsautomaten. Der Zustandsübergang wird durch die Programminstruktionen hervorgerufen.
Der Zustand S eines parallelen Programms welches aus N Prozessen Pi besteht setzt sich zusammen aus folgenden Tupeln:
Die Berechnung ändert globale und lokale Variablen (Datenfluss) sowie Instruktionszeiger (Kontrollfluss) und führt zu einer Zustandsänderung comp: si → sj.
Wesentliche Zustandsänderung ist die Änderung von lokalen und globalen Speicher.
Variablen sind Bestandteil von Ausdrücken und erlauben zwei Operationen: {read,write}
1: var x: read(x) ⇔ RHS value(x) → ε (value(x))
2: write(x,v) ⇔ LHS reference(x) → x := v
Der Zugriff auf globale und somit geteilte Variablen muss atomar sein, d.h. immer nur ein Prozess kann den Wert einer Variable lesen oder einen neuen Wert schreiben.
Der parallele Zugriff auf eine geteilte Ressource muss aufgelöst werden (Konflikt): i.A. mutualer Ausschluss durch Sequenzialisierung der parallelen Zugriffe!
1: write(X,v1) || write(X,v2) || x3:=read(X) →
2: write(X,v1); read(X,x3); write(X,v2) |
3: x3=read(X); write(X,v2); write(X,v2) | ..
1: var V1,V2,...
2: process p1(a1,a2,...) process p2(a1,a2,...)
3: var v1,v2,.... var v1,v2,....
4: <Instruktion1 i1> <Instruktion1 i1>
5: <Instruktion2 i2> <Instruktion1 i2>
6: Vi := ε(ai,vi,Vi) Vi := ε(ai,vi,Vi)
7: vi := ε(ai,vi,Vi) vi := ε(ai,vi,Vi)
8: end end
Bei einem sequenziellen Programm ist das Ergebnis einer Berechnung (d.h. die Werte aller Variablen) deterministisch allein durch die Anweisungssequenz und die Eingabedaten gegeben, und kann beliebig oft wiederholt werden - immer mit dem gleichen Ergebnis → Reihenfolge aller Anweisungen der Berechnung vorgegeben und fest
Bei einem parallelen Programm können mehrere Anweisungen verschiedener Prozesse gleichzeitig ausgeführt werden bzw. konkurrieren.
Die Reihenfolge parallel ausgeführter Anweisungen von einzelnen Prozessen kann hingegen undeterministisch = zufällig sein!!
Jeder der Prozesse kann als nächster den Zustand des Programms ändern.
Ein Zustands-Raum Diagramm beschreibt die Änderung des Programmzustandes als sequenzielle Auswertung aller möglichen Prozessaktivitäten.
Das Diagramm ist ein gerichteter Graph, dessen Knoten den aktuellen Programmzustand s ∈ S beschreiben, und dessen Kanten die möglichen Zustandsübergänge beschreiben.
Es gibt einen ausgewiesen Startzustand (Initialisierung) und einen oder mehrere Endzustände.
Gibt es mehrere Endzustände liegt wohl möglich ein Entwurfsfehler vor, da das Programm unterschiedliche Endergebnisse liefern kann.
Wähle (entferne) einen beliebigen Prozess px aus der Prozessliste P* und setze P*:= {pn| pn ∈ P* ∧ pn ∉ px}
Evaluiere die nächste Instruktion ix,n von px und berechne die Wirkung auf lokale und globale Variablen sowie den Instruktionszeiger Ix,n.
Erzeuge einen neuen Zustandsknoten sj/=x , füge ihn zur Liste S*:=S* ∪ {sj} hinzu und verbinde ihn mittels einer Kante tx→j mit dem aktuellen Ausgangszustand sx
Wiederhole Schritt 3 bis 5 für alle anderen verbleibenden Prozesse p ∈ P bis P*={}
Setze S**:=S*. Für jeden Knoten sx ∈ S** wiederhole die Schritte 2 bis 6. Iteriere Schritt 7 bis alle Prozesse terminiert sind oder keine Zustandsänderung mehr auftritt.
1: Sequenzielles Programm Paralleles Programm
2: for i := 1 to 3 do i1 process p1
3: for i := 1 to 3 do i1
4: end
5: process p2
6: for j := 1 to 3 do i2
7: end
In dem bisherigen Programmiermmodell gibt es nur globale Variablen als globale geteilte Ressourcen, die konkurrierend von Prozessen gelesen und beschrieben werden können.
Die globalen Variablen dienen dem Datenaustausch = Kommunikation zwischen den Prozessen (Shared Memory Model!).
Atomare Operationen, Schreibweise |A| werden in einem Schritt ausgeführt und können nicht durch andere Prozesse unterbrochen werden (keine Interferenz).
t1: |X := v|
Zusammengesetzte Ausdrücke können aus mehreren Berechnungsschritten bestehen, so ist z. B. X := X + 1
als Ganzes nicht mehr atomar!
1: t1: |temp=X|
2: t2: |X:=temp+1|
1: var X := 1
2: INCR(X) DECR(X)
3: process p1 process p2
4: var t:=0 var t:=0
5: t := X t := X
6: X := t + 1 X := t - 1
7: end end
Nicht atomare Aktionen (Sequenz von Aktionen) mit globalen Ressourcen müssen durch Mutuale Ausschlusssynchronisation geschützt werden → Schutz von kritischen Codebereichen ⇒ Datenkonsistenz!
Eine Semaphore S ist ein Zähler s>0 der niemals negative Werte annehmen kann.
Es gibt zwei atomare Operationen die von einer Menge von Prozessen P={p1,p2,…} auf einer Semaphore S angewendet werden können:
Definition 1.
1: operation down(S) ∈ p:
2: |if s > 0
3: then s := s - 1
4: else WAITERS+(S,p),block(p)|
5: operation up(S) ∈ p:
6: |if s = 0 and WAITERS(S) ≠ []
7: then pi=WAITERS-(S),unblock(pi)
8: else s := s + 1|
1: semaphore S(1)
2: ... down(S) |i1,i2,i3,..,in)| up(S) ...
1: var X := 1
2: semaphore S := 1
3: INCR(X) DECR(X)
4: process p1 process p2
5: var t:=0 var t:=0
6: down(S) down(S)
7: t := X t := X
8: X := t + 1 X := t - 1
9: up(S) up(S)
10: end end
Petri-Netze für die Modellierung, Analyse, und Implementierung von Parallelen Systemen und Digitallogik
Petri-Netze eignen sich für die Darstellung paralleler Prozesse und deren Analyse des dynamischen Verhaltens
Ein Petri-Netz ist ein Quadrupel PN = <S,T,E,A> mit
Das dynamische Verhalten der Petri-Netze wird mittels von Markierungen beschrieben (Tokens).
Es gibt eine Markierungsfunktion M: S → N mit N={0,1,2..}, die die Anzahl der Markierungen M(s), s ∈ S einer Stelle s angibt.
Eine Stelle kann keine, eine, oder mehrere Markierungen besitzen (aufnehmen). Es kann eine maximale Kapazität k einer Stelle geben, die Übergänge beeinflusst (k-begrenzte Stellen, im Gegensatz zu unbegrenzten mit k → ∞).
Eine Markierung kann durch Übergänge t ∈ T von eine Stelle s1 ∈ S zu einer anderen s2 ∈ S übertragen werden.
Jedem Übergang t ∈ T ist eine Menge von Eingangsstellen SE ∈ S zugeordnet (mindestens eine Stelle).
Jedem Übergang ist eine Menge von Ausgangsstellen SA ∈ S zugeordnet (mindestens eine Stelle).
Ein Übergang kann schalten, d.h. Markierungen von den Eingangs- zu den Ausgangsstellen übertragen, wenn alle Eingangsstellen wenigstens eine Markierung besitzen.
Eine Kante kann eine Gewichtung g besitzen, die die Anzahl der gleichzeitig zu übertragenden Markierungen angibt.
Verschiedene Grundsituationen und Vorbedingungen (Guards/Aktivierung) für Übergänge |
|
Verschiedene Grundsituationen für die Synchronisation bei paralleler Aktivierung von Teilnetzen |
|
Stellen S können Lager/Kontainer für Daten/Ressourcen (Markierungen/Tokens) repräsentieren, meistens mit einer Kapazität k > 1!
FIFO-Queues wären Implementierungen solcher Kontainer!
Übergänge T können mit Prozessen oder Operationen verknüpft sein, die Daten/Ressourcen verarbeiten.
Datenflussgraphen können in solche ST Netze abgebildet werden.
ST Petri-Netze können ebenfalls zur Darstellung kombinatorischer und sequenzieller Digitallogiksysteme verwendet werden.
Dabei werden Stellen Signalwerten, und Übergängen Signaländerungen zugeordnet.
Die Plätze der Eingangssignale werden explizit mit Markierungen versehen.
Anmerkung: Das PN bildet einen Zustandsübergangsgraphen (STG) ab!
Prozesse p∈P führen (sequenziell) Anweisungen durch.
Dabei werden Prozesse auf Übergänge t∈T abgebildet, die mit der sequenziellen Ausführung von Anweisungen bei deren Aktivierung verknüpft sind.
Markierungen aktivieren Prozesse und dienen der Synchronisation.
Parallelisierung durch spezielle Fork-Übergänge und Synchronisation durch spezielle Join-Übergänge.
Reaktive Systeme:
Transformatorische Systeme:
Eine Datenabhängigkeit in der Informatik ist eine Situation, in der sich eine Programmanweisung (Anweisung) auf die Daten einer vorhergehenden Anweisung bezieht.
Ein Datenabhängigkeitsgraph G = (I, E) besteht aus einer Menge von Instruktionen I und einer Menge transitiver Relationen R = I x I, mit (a, b) in R falls die Instruktion a vor b bewertet werden muss.
Mit anderen Worten, es gibt eine Kante von a nach b:
wenn a vor b ausgewertet werden muss.