Mit Virtuellen Maschinen
Prof. Dr. Stefan Bosse
Universität Koblenz - FB Informatik - FG Praktiksche Informatik
Stefan Bosse - VPP - Modul D Parallele Programmierung ::
Grundlagen der parallelen Programmierung
Unterscheidung zwischen Parallelisierung im Daten- und Kontrollfluß von Programmen
Prozessmodelle und Prozesskonstruktoren
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
Die Verarbeitungseinheiten sind Knoten eines gerichteten Graphens, die Kanten beschreiben den Datenfluss und bilden die Datenpfade. Die Verarbeitungseinheiten müssen aktiviert werden.
Der Kontrollfluss kann durch Zustandsübergangsdiagramme beschrieben werden.
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
Programmanweisungen werden Zuständen S1,S2,.. zugeordnet.
Einfache Anweisungen (Berechnungen) werden jeweils einem Zustand, komplexe Anweisungen i.A. mehreren Unterzuständen zugeordnet.
Programm-, Kontroll-, und Datenflussgraphen
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
In vielen Programmen werden dieselben Operationen auf unterschiedliche Elemente einer Datenstruktur angewendet. Im einfachsten Fall sind dies die Elemente eines Feldes.
Wenn die angewendeten Operationen unabhängig voneinander sind, kann diese verfügbare Parallelität dadurch ausgenutzt werden, um die zu manipulierenden Elemente der Datenstruktur auf verschiedene Prozessoren zu verteilen, so dass jeder Prozessor die Operation auf den ihm zugeordneten Elementen ausführt.
Parallelität im Datenpfad → Feine Granularität
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
Bei der Datenparallelität wird unterschieden zwischen:
Parallele Ausführung der gleichen Instruktion auf verschiedenen Daten (Vektorparallelität) → Vektoranweisung
Ausführung verschiedener Instruktionen die nur Daten verarbeiten (reine Datenanweisungen, keine Kontrollpfadverzweigungen)
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
Zur Ausnutzung der Datenparallelität wurden sequenzielle Programmiersprachen zu datenparallelen Programmiersprachen erweitert. Diese verwenden wie sequenzielle Programmiersprachen einen Kontrollfluß, der aber auch datenparallele Operationen ausführen kann.
Häufig werden Vektoranweisungen deklarativ und nicht prozedural imperativ beschrieben.
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
a(1 : n) = b(0 : n − 1) + c(1 : n) ⇔for (i=1:n) a(i) = b(i-1) + c(i)end
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
Datenabhängigkeiten können zwischen der linken und rechten Seite einer Datenzuweisung bestehen, so dass
Daher ist folgende Vektoranweisung nicht in die folgende Schleife sequenziell transformierbar:
a(1 : n) = a(0 : n − 1) + a(2 : n + 1) ≠for (i=1:n) a(i) = a(i-1) + a(i+1)end
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
Datenparallelität benötigt i.A. keine weitere Synchronisation
Aber Datenabhängigkeiten können zu einer impliziten oder expliziten Synchronisation führen (z.B. mit Queues)
Durch die Verwendung von Queues (oder allg. Kommunikationskanälen) werden Datenabhängigkeiten über einen Blockierungsmechanismus (Verzögerung) aufgelöst. Es gibt Produzenten und Konsumenten. Der Konsument wird solange blockiert bis der Produzent (i.a. der vorherige Prozess) Daten liefert. Umgekehrt kann ein Produzent verzögert werden wenn ein Konsument noch nicht zur Aufnahme neuer Daten bereit ist.
P1→Q1→P2→Q2→P3…Q(t):t→{⊥d∈DQ
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
Parallelität im Kontrollpfad (Zustandsautomat) auf Instruktions- und Prozessebene → Grobe Granularität je nach Anzahl der Instruktionen pro Prozess (Task)
Gebundene Instruktionsblöcke sind Parallelprozesse (Par Prozesskonstruktor)
Bekannt als Multithreading als Programmier- und Ausführungsmodell (z.B. pthreads)
Instruktionsparallelität benötigt i.A. Synchronisation zwischen den einzelnen Prozessen
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallelisierungsklassen
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Fluss und Pfadgraphen
Ein Datenpfad beschreibt die Verbindung von Komponenten zur Implementierung des Datenflusses → Strukturbeschreibung
Der Kontrollfluss beschreibt die zustandsbasierte Steuerung einer Berechnung
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Daten- und Kontrollpfade
Jeder generische Mikroprozessor und i.A. jedes anwendungsspezifische Digitallogiksystem läßt sich in die zwei funktionale Bereiche aufteilen:
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Daten- und Kontrollpfade
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Daten- und Kontrollpfade
Der Programmfluss kann in Daten- und Kontrollfluss zerlegt werden, die jeweils im Daten- und Kontrollpfad eines Datenverarbeitungssystems verarbeitet werden.
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Daten- und Kontrollpfade
Ein (prozedurales/imperatives) Programm besteht aus mindestens einem Daten- und Kontrollpfad (oder Fluss)
Ein Programm ist aus einer Vielzahl von Komponenten zusammengesetzt → Komposition
Komposition von Datenfluss und Datenpfad:
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Daten- und Kontrollpfade
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Funktionale Programmierung
Funktionale Programmierung beschreibt grundlegend den Datenpfad. Es gibt keinen Zustand und keinen expliziten Kontrollfluß.
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Funktionale Komposition
Eine Berechnung setzt sich aus der verschachtelten und verketteten Applikation von Funktionen zusammen, die jeweils aus elementaren Ausdrücken E={ε1,ε2,..} bestehen → Funktionale Komposition F(X)=f1(f2(f3..(X)))
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Funktionale Komposition
1,2.0,'c',"hello",x,y,z
x+y
(x+1)*(y-1)*z
x < 0
a and b or c
if x < 0 then x+1 else x-1
f(x,y,z)
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Funktionale Komposition
Entspricht dem mathematischen Modell was auf Funktionen und Ausdrücken gründet mit den Methoden
Zeitliches Modell: unbestimmt (t ↦ 0), Auswertereihenfolge nicht festgelegt
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Funktionale Komposition
Beispiel für Funktionsdefinition und Applikation
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Funktionale Komposition von Systemen
Parallelisierung durch Modellierung unterschiedlich detailierter Datenflussdiagramme, die untereinander einen hierarchischen Zusammenhang aufweisen.
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Map&Reduce - Funktional
Grundprinzip ist Divide&Conquer Ansatz. Eine Datemenge D wird in Elemente di zerlegt (oder Partitionen). Die können unabhängig voneinander mittels einer Funktion F in Ausgabedaten Do transformiert werden (Mapping). Anschliessend können diese Elemente mit einer Funktion G reduziert werden (Reduce).
l=[ν1,ν2,..]l'=map(l,x => f(x))l''=reduce(l',(a,b) => g(a,b))
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Map&Reduce - Lua
Im Idealfall findet ein 1:1 Mapping statt, d.h. alle Berechnungen mit F finden parallel in eigenen Prozessen statt
Realistischer ist die Verarbeitung von Partitionen von Prozessen, d.h. eine Mischung aus Sequenz und paralleler Verarbeitung (mit sog. Worker Prozessen)
Die Worker Prozesse werden entweder vorab als Pool oder zur Laufzeit gestartet und verarbeiten partitionierte Daten
Es kann eine funktionale Kette aufgebaut werden die den Datenfluss beschreibt.
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Map&Reduce - Lua
┌――――――――――――――――――――――――――――――――┐│ Data List │└――┬――――――――┬――――――――┬――――――――┬――┘ │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ ┌―――――┐ ┌―――――┐ ┌―――――┐ ┌―――――┐│ f │ │ f │ │ f │ │ f │└――┬――┘ └――┬――┘ └――┬――┘ └――┬――┘ │ │ │ │ │ ┌――――┐ │ │ ┌――――┐ │ └―┤ g ├―┘ └―┤ g ├―┘ └―┬――┘ └――┬―┘ │ │ │ ┌―――――┐ │ └――――――┤ g ├―――――┘ └―――――┘
Datenflussgraph von Map&Reduce (vertikal) und (mögliche) Parallelisierung (horizontal)
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Map&Reduce - Lua
local options = {workers = 2, remap=true, schedule="circular", mapchunks=true}-- Input datalocal data = {34,35,36,37,38,39,40,41}-- Worker Functionlocal function worker (set,id) -- set ist ganze Partition! local results = T{} for i = 1,#set do results:push(fib(set[i])) end return resultsend
-- Parallel Processinglocal Parallel = require('parallel')local p = Parallel:new(data,options)function sum (x,y) return x+y endp:time(): map(worker): apply(function (r) print(r:print()) end): reduce(sum): apply(function (r) print(r:print()) end): time()
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Map&Reduce - Lua
local options = {workers = 2, remap=true, schedule="circular", mapchunks=false}-- Input datalocal data = {34,35,36,37,38,39,40,41}-- Worker Functionlocal function worker (n,index,id) -- hier jetzt Aufruf mit einzelnen Daten, -- zerlegung und Zusammenfügung -- einer Partition (chunk) dann in parallel mapper return fib(n)end
-- Parallel Processinglocal Parallel = require('parallel')local p = Parallel:new(data,options)function sum (x,y) return x+y endp:time(): map(worker): apply(function (r) print(r:print()) end): reduce(sum): apply(function (r) print(r:print()) end): time()
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzielle Komposition
Eine imperative Berechnung setzt sich aus einer Sequenz I=(i1 , i2 , ..) von elementaren Anweisungen A={a1,a2,..} zusammen →
Sequenzielle Komposition i1 ; i2 ; ...
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzielle Komposition
x+1, a*(b-c)*3, x<(a+b), ...
x := a+b
if a < b then x := 0 endwhile x < 100 do x:=x+1 end
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzielle Komposition
Man fasst die Sequenz I als ein imperatives Programm X == Ausführungsvorschrift zusammen.
Die Ausführung des Programms (statisch) bezeichnet man als Prozess (dynamisch)
Ein Prozess befindet sich aktuell immer in einem Zustand σ einer endlichen Menge von Zuständen Σ={σ1 , σ2 , ..}.
Der gesamte Zustandsraum Σ des Prozesses setzt sich aus dem
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzielle Komposition
Der Fortschritt eines sequenziellen Programms bedeutet ein Änderung des Kontroll- und Datenzustandes → Zustandsübergänge
Die Zustandsübergänge können durch ein Zustandsübergangsdiagramm dargestellt werden.
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Das Prozeßmodell
Es werden zwei Prozesstypen unterschieden:
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess
START
)RUN
)END
)AWAIT
), z.B. Verfügbarket von EingabedatenBLOCKED
), z.B. P1(suspend)-P2(wakeup) PaareREADY
)Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess
PS={START,RUN,END}PS∗={AWAIT,BLOCKED,READY}ps(P)∈PS∪PS∗
Befindet sich der Prozess im Ausführungszustand RUN
(also ausführend), dann werden strikt sequenziell die Instruktionen des Programs I={i1,i2,..,in} ausgeführt.
Dabei ist jede Instruktion eine Anweisung aus der endlichen Anweisungsmenge A={a1,..} der Maschine (z.B. Bytecode Anweisung add(x,y)
).
Ein Wechsel des Ausführungszustandes führt nicht zu einer Änderung der Instruktionsreihenfolge.
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess: Zeitliches Modell
i1:t1↦i2:t2↦i3:t3↦..↦in:tn mitt1<t2<t3<..<tnT=∑iti−ti−1
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess
Das Konzept der Prozessblockierung ist elementar für kommunizierende Prozesse
Kommunikation: Lesen und Schreiben von Daten, Ein- und Ausgabe, Netzwerknachrichten, usw.
Befindet sich ein Prozess im Ausführungszustand AWAIT
wartet dieser auf ein Ereignis:
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess
Das Ausführungsmodell von Lua unterstützt die Blockierung des Programmflusses
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess
Tatsächlich gibt es in Lua auf programmatischer Ebene aber nur einen einzigen Kontrollfluß und Pfad (eine VM Instanz)!
Koro 1 Koro 2
┌─────────┐ ┌─────────┐
│ │ resume │ │
│ 1 │ ┌────▶│ 4 │
│ 2 │ │ │ 5 │
│ 3 yield ├─────┐ │ ┌───┤ 6 yield │
│ 7 │◀──┐ │ │ │ │ 9 │
│ 8 read ├─┐ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │
└────┬────┘ │ │ │ │ │ └────┬────┘
│ ▼ │ ▼ │ ▼ │
┌────┴────────┴─────┴──────────┴────────┬+
│ LUA VM Instanz │
└───────────────────────────────────────┘
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess
co1 = coroutine.create(function () for i=1,10 do print("co1", i) coroutine.yield() end end)co2 = coroutine.create(function () for i=1,10 do print("co2", i) coroutine.yield() end end)coroutine.resume(co1)coroutine.resume(co2)...
Asymmetrische Koroutinen in Lua
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess
Über die Eventloop Bibliothek libuv (multithreaded) und Lua Bindungen luv stehen neben Threads auch Fibers zur Verfügung. Luv Fibers sind symmetrische Koroutinen, werden aber auch strikt sequenziell und nicht präemptiv verarbeitet!
Achtung: Die klassischen Lua Koroutinen sind inkompatibel zu Luv (da alle IO Operationen über die uv Bibliothek laufen). In lvm gibt es eine alternative Implementierung corof die auf Fibers aufbaut. Diese ist automatisch aktiviert (als Ersatz unter dem gleichen Namen coroutine).
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess
co1 = luv.fiber.create(function () for i=1,5 do print("co1", i) luv.fiber.yield() end print("co1 finished.") end)co2 = luv.fiber.create(function () for i=1,5 do print("co2", i) luv.fiber.yield() end print("co2 finished.") end)co1:ready()co2:ready()co1:join()co2:join()print ("Done.")
Luv Fibers: Symmetrische Koroutinen in lvm/luv
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Sequenzieller Prozess
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallele Prozesse
Ausgangspunkt sind sequenzielle Prozesse
Ein sequenzieller Prozess Ps besteht aus einer Sequenz von Anweisungen I=(i1 ; i2 ;..) (Berechnungen), die schrittweise und nacheinander ausgeführt werden: Ps=P(i1 ; i2 ; .. ; in) ⇒ p1 ↦ p2 ↦ .. ↦ pn
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallele Komposition
Datenverarbeitungssystem als paralleler Prozess kann aus einer Vielzahl nebenläufig ausgeführter Prozesse P={P1, P2, P3,...} bestehen
Parallele Komposition P=P1 ∥ P2 ∥ P3 ∥ ..
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Paralleler Prozess
P=(P1∥P2∥..∥Pn)⇔PARi1i2..in
Lua
Par({ function (pid) .. end, function (pid) .. end,..},{ -- shared environment v = ε, ..})
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Paralleler Prozess
P1∥P2∥..∥Pn⇒P1;P2;..;PnP1∥P2⇒P1;P2⇒P2;P1!
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Paralleler Prozess: Zeitliches Modell
P=P1∥P2∥..∥PnP1=(i1,1:t1,1;i1,2,:t1,2;..)⋯Pn=(in,1:tn,1;in,2:tn,1;..), mitti,1<ti,2<..<ti,m∀Prozess mit m Instr. und t(P)=[t1,t2]=[t1,1,t1,q]∪[t2,1,t2,r]∪..∪[tn,1,tn,s]t1=min{t1,1,t2,1,..,tn,1}t2=max{t1,q,t2,r,..,tn,s} T=t2−t1
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Prozessflussdiagramme
Beispiel eines Prozessflussdiagramms für vier Prozesse. P1 startet P3, und P2 spaltet P4 ab. (mit P_,i = Instruktion(P,i))
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Paralleler Prozess
Ein neuer paralleler Prozess kann durch den entsprechenden Prozesskonstruktor erzeugt werden
Geschieht dies innerhalb eines Prozesses Pi so wird dessen Prozessausführung blockiert bis alle Teilprozesses des parallelen Prozessen terminiert sind!
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Paralleler Prozess
P1;//P2;P3=P1;P3∥P2//P1;//P2;P3=P1∥P2∥P3
Lua
Fork({ function (pid) .. end, function (pid) .. end, .. },{ -- shared environment})
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Parallele Prozesse in Lua
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Lua - Ausführungsmodelle
Isolierte Programmprozesse ohne direkte Synchronisation und Datenaustausch zwischen den VMs
Synchronsiation nur über
Jeder Prozess führt eine VM aus ohne (zunächst) direkte Kopplung und Kommunikation mit anderen Prozessen
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Lua - Ausführungsmodelle
Es werden parallele Prozesse auf Threads abgebildet die bestenfalls 1:1 auf den CPUs / Cores ausgeführt werden, ansonsten durch einen Scheduler im Zeitmultiplexverfahren ausgeführt werden → Kontrollpfadparallelität
Prozesse können synchronisiert auf geteilte Objekte (konkurrierend) zugreifen:
Prozessblockierung blockiert den gesamten Thread (somit auch alle Fibers)
Jeder parallele Prozess in einem Thread läuft in eigener VM Instanz
Daten können nicht zwischen VMs ausgetauscht werden (Automatisches Speichermanagement und GC) → nur Austausch über Serialisierung und Kopie von Daten oder geteilte Byte Datenspeicher (Shared Buffer)!
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Lua - Ausführungsmodelle
Es werden konkurrierende (aber nicht notwendig nebenläufige) Prozesse (Koroutinen) auf Fibers abgebildet die grundsätzlich in Lua nur sequenziell durch einen Scheduler im Zeitmultiplexverfahren ausgeführt werden.
Diese Prozesse können synchronisiert auf geteilte Objekte (nicht nebeläufig) zugreifen:
Prozessblockierung blockiert nur eine Koroutine
Alle quasi-parallelen Prozesse mit Fibers laufen in einer VM Instanz und teilen sich den VM Datenkontext sowie besitzen den gleichen Programmkontext (direkte Teilung von Variablen und Funktionen)
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Lua - Ausführungsmodelle
Threadmodell und Kommunikation der Prozesse mit geteilten Objekten
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Lua - Ausführungsmodelle
Asynchrone IO wird sowohl in nodejs (JavaScript) als auch in Lua (lvm) mittels der libuv Bibliothek implementiert
Fibers (Koroutinen) werden in Lua direkt durch die Lua VM verarbeitet
Threads werden über die libuv einzelnen VM Instanzen zugeordnet
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Lua - Ausführungsmodelle
docs.libuv.org/en/v1.x/design.html
Asynchrone IO mit der libuv Architektur
Stefan Bosse - VPP - Modul D Parallele Programmierung :: LVM
Parallelisierung durch multiple VM Instanzen mit Inter-VM Kommunikation
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Asynchrone Ereignisverarbeitung
Neben der Parallelisierung der reinen Datenverarbeitung (Berechnung) kann auch eine Partitionierung von Ein- und Ausgabe bzw. der Ereignisverarbeitung erfolgen
Bekanntes Beispiel: Geräteinterrupts mit einfachen Foreground-Background System mit zwei Prozessen:
Ein- und Ausgabeoperationen eines Programms können synchron (blockierend) oder asynchron (im Hintergrund verarbeitet und nicht blockierend) ausgeführt werden.
Alle Programme/Prozesse können blockieren, aber nur wenige Programmierumgebungen erlauben ein Scheduling (Multiprozessverarbeitung)
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Asynchrone Ereignisverarbeitung
x = IO1(arg1,arg2,..);y = IO2(arg1,arg2,..);z = f(x,y);
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Asynchrone Ereignisverarbeitung
IO1(arg1,arg2,..,function (res) x=res; end); IO2(arg1,arg2,..,function (res) y=res; end);z = f(x,y); -- Problem?
//P(IO1);//P(IO2);P
(P(IO1)∣∣P(IO2));P
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Asynchrone Ereignisverarbeitung
Ereignisbasierte Verarbeitung von asynchronen Operationen in lvm: Ein Lua Thread verbunden über die Eventloop mit N IO Threads
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Asynchrone Ereignisverarbeitung
Asynchrone Ereignisverarbeitung mit preemptiven (unterbechenden) Verhalten benötigt explizite Synchronisation (Locks...) zur Atomarisierung von kritischen Bereichen
Asynchrone Ereignisverarbeitung spaltet den Kontroll- und Datenfluss auf und benötigt Daten- und Ergebnissynchronisation über Prädikatfunktionen oder explizite Synchronisation:
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Asynchrone Ereignisverarbeitung
local x,y,z;function P(f,x,y,z) if x~=nil and y~=nil then return f(x,y) else return z endendIO1(arg1,arg2,..,function (res) x=res; z=P(f,x,y,z) end); IO2(arg1,arg2,..,function (res) y=res; z=P(f,x,y,z) end);
Verwendung einer Prädikatfunktion P zur Auflösung von Abhängigkeiten und Asynchronität / Unbekannter Ausführungsreihenfolge
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Synchronisierung von Callbacks
Neben der Prädikatfunktion kann Deasynchronisierung verwendet werden um den Programmfluss zu sequenzialisieren und zu synchronisieren
Dazu wird eine zusätzliche Synchronisation eingeführt die die auszuführende asynchrone Funktion blockiert
Der Kontrollfluss spaltet sich dabei auf (der Hauptfluss wird verlassen)
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Synchronisierung von Callbacks
function fooAsync (callback) .. callback(result) ..end-- Nur in Koroutine ausführbar!function fooSync () local result fooAsync(function (_result) result=_result coroutine.resume() end) coroutine.yield() return resultend
Deasync Wrapper für asynchrone Funktionen
Stefan Bosse - VPP - Modul D Parallele Programmierung :: Zusammenfassung
Parallele Prozesse werden aus nebenläufig oder verwoben ausgeführten sequenziellen Prozessen gebildet
Prozesse besitzen drei wesentliche Ausführungszustände: Bereit, Rechnend, Terminiert
Prozessynchonisation kann durch Prozessflussgraphen (PFG) dargestellt werden
Ein nachfolgender Prozess (Knoten im PFG) wird erst gestartet wenn der vorherige terminert
Prozessblockierung ist wesentliche Eigenschaft von synchronisierenden Prozessen