Parallel Lua / CSP Tutorial (Stefan Bosse) [5.2024]

Übung 5 - Parallel Lua / CSP Tutorial (Teil 1)

In dieser Übung findet eine erste Einführung in die Programmierung von parallelen Systemen nach dem CCSP Modell. Dabei steht CCSP für "Concurrent Communicating Sequential Processes" und beschreibt die Komposition und Kommunikation von sequenziellen Prozessen mit Konkurrenz. man unterscheidet:

  1. Prozesskonstruktoren
  2. Kommunikationsobjekte

Vorbereitung und Verwendung

Minimalanforderungen: lvm 1.1.12, luaos 1.6.1

  1. Der Programmcode kann in dem oberen Teilfenster eines Snippets verändert werden.
  2. Der Programmcode wird ausgeführt durch Drücken der Playtaste ▸ im unteren Teilfenster (Ausgabekonsole).
  3. Die Ausgabekonsole kann auf der rechten Seite gelöscht werden durch Drücken von ✗.
  4. Hin und wieder kann eine Aktualisierung des Ausgabefensters durch Drücken des Knopfes ↻ erforderlich sein.
  5. Bei parallelen Prozessen werden jeweils neue VM Instanzen in Threads gestartet. Wenn etwas schief läuft kann das Programm hängen und nicht terminieren (also der aktuelle Codeabschnitt). Der Abbruch kann versucht werden durch Drücken des Knopfes ◼.

Eine einfache Textausgabe (1)

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 

Prozesse

Sequenzielle Prozesse

Sequenzielle Prozesse sind in Lua (und jeder anderen imperativen/prozeduralen Programmiersprache) ein Artefakt (jedes Programm und jede Funktion ist bereits ein seq. Prozess)


Eine einfache Textausgabe (2)

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 

Aufgabe.
  1. Füge in die beiden obigen seq. Prozesse die sleep(millisec) Funktion vor der Konsolenausgabe print ein (wähle für die verzögerung Werte im Bereich 100-500 ms)

  2. Wie verhält sich das Programm? Füge die Ausgabe der Prozesszeit ein (print(time())) vor und nach dem sleep Aufruf. Alternativ kann anstelle der print die log Anweisung verwendet werden. Diese gibt die aktuelle Prozesszeit in Millisekunden zusammen mit den Argumenten aus.

  1. Was passiert wenn in einem Prozess ein Fehler auftritt? Also füge z.B. den Aufruf einer nicht definierten Funktion foo(1) ein...

Fehlerbehandlung

Benutze nur noch die Großschreibung Try().Catch().Finally() um mit der generischen und Fengari Lua VM kompatibel zu sein.


Fehlerbehandlung

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 


Fehlerbehandlung

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 


Nutzerdefinierte Signale

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 

Koroutinen

Koroutinen werden im gleichen Kontext ausgeführt. Jedoch führt die CSP Bibliothek einen lokalen geteilten Kontext ein (indem hier z.B. die print Funktion fehlt und daher durch den geteilten Kontext explizit eingeführt werden muß).

Die CSP Bibliothek stellt verschiedene Prozesskommunikationsmoethoden zur Verfügung. Dabei muss zwischen den Koroutinen (Fibers) und den parallelen Prozessen (Threads) unterschieden werden. I.a. gibt es ein zusätzliches boolesches Argument bei der Erzeugung der Kommunikationsobjekte. Ein Beispiel eines Events ist nachfolgend geziegt.

Events haben zwei Methoden:

  1. ev:await blockiert den aufrufenden Prozess (die Koroutine) bis ein Ereignis eingetreten ist;
  2. ev:wkaeup löst das Ereignis aus.

Eine einfache Textausgabe (3)

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 

Aufgabe.
  1. Ist der Co Prozess synchron? D.h. wird auf die Terminierung aller Teilprozesse gewartet?
  1. Verschiebe die sleep Operation aus Prozess 1 in Prozess 2 (Kommentar entfernen und oben einfügen). Welches Problem kann bei der Verwendung eines Eventobjekts entstehen?

Parallele Prozesse


Eine einfache Textausgabe mit Prozesskommunikation (2)

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 

Aufgabe.
  1. Was passiert im Prozessfluss wenn der Par Konstruktor mit Fork ausgetauscht wird?

Kommunikationskanäle

Aufgabe.
  1. Was läuft bei dem nächsten Beispiel falsch (beachte die Puffergröße vom Komm.kanal)?
    • Hinweis: Wenn der Par Prozess nicht terminiert, benutze den ◼ Knopf bis die Meldung mit dem Signal INTR erscheint!
    • Ggfs. Konsolenupdate durchführen (rechts, Kreispfeil)
  1. Ändere das Programm so ab dass sich beide Prozesse richtig synchronisieren und der Par Prozess terminiert.


Eine komplexere Textausgabe mit Prozesskommunikation (3)

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 

Semaphoren

\[ \text{S.counter}\ge{0}\\ \text{S.counter}=\text{S.init}+\sum\text{S:up}-\sum\text{S:down} \]

Im nächste Beispiel werden Semaphoren für die Synchronisation von parallel ausgeführten Arbeitsprozessen (Worker) mit einem Leitungsprozess (Master) verwendet. Es gibt bei der parallelen und verteilen Datenverarbeitung zwei wesentliche Phasen:

  1. Verteilungsphase (Worker werden gestartet und warten auf Daten/Start der Berechnung bzw. dem Master, Verteilung der Daten)
  2. Zusammenführungs- und Einsammlungsphase (der Master wartet auf die Worker und sammelt die Ergebnisse wieder ein)

Ein einfaches Produzenten-Konsumenten System

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 

Aufgabe.
  1. Wie ist der zeitliche Ablauf?
  1. Welchen Wert haben die Semaphorenzähler von prod und cons am Ende?
  1. Verändere das Prozesssystem derart dass der Master außerhalb des (nach dem) Worker Pool (also im Hauptprozess) ausgeführt wird. Dazu muss der Fork Prozesskonstruktor verwendet werden. Warum?

Das Deadlock Problem: Dinierende Philosophen

Das DP Problem dient als klassisches Deadlock Problem und das Auftreten von Race Conditions (Wettrennen zwischen Threads) bei geteilten Ressourcen mit konkurrierenden und nebenläufigen (asynchronen) Zugriff


Zwei dinierende Philosophen - der Auftakt!

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 

Aufgabe.
  1. Starte eine Reihe (10) von Durchläufen. Ist die Ablaufreihenfolge deterministisch?
  1. Führe in jedem Phil.prozess eine Zählschleife (for)(1,M) ein die den obigen Anweisungblock (Block) kapselt
  2. Experimentiere mit den auskommentierten random delay (sleep in Millisekunden) und der Threadwechsel mit yield
  3. Führe den Prozess aus, mit z.b. M=20 Durchläufen. Was lässt sich beobachten?
  1. Erweitere nun das parallele Prozesssystem auf N=5 Phils. Lässt sich ein Deadlock feststellen? Die Versuche müssen ggfs. mehrfach wiederholt werden (und nur auf Rechnern mit mehr als einer CPU/Core ist etwas auffälliges zu beobachten).
  1. Was passiert hier? Was führt zum Versagen des parallelen Systems?
  1. Wie kann das Versagen des Systems naiv verhindert werden?

Aufgabe

In der folgenden Aufgabe soll ähnlich wie den parallelen Zellulären Automaten eine Matrixberechnung auf vier Prozesse verteilt und partitioniert werden. Dabei gibt es zwei Phasen:

  1. Es wird die elementweise Addition C=A+B duchgeführt
\[ \hat{{C}}=\hat{{A}}+\hat{{B}},{c}_{{{i},{j}}}={a}_{{{i},{j}}}+{b}_{{{i},{j}}} \]
  1. Es wird die Summe aller Elemente und der Mittelwert berechnet:
\[ \overline{{C}}=\frac{{\sum\hat{{C}}}}{{\left|\hat{{C}}\right|}} \]

mit |M|: Anzahl der Elemente der Matrix M.

Kooperative Parallele Matrixberechnung

  1. Implementiere im nachfolgenden Programmcode die Verteilungs- und Zusammenführungsphase der vier Arbeiterprozess durch einen Master(prozess) gemäß obigen Produzenten-Konsumenten Beispiel mit Semaphoren. Beide Phasen der Berechnung sind getrennt auszuführen.

  2. Überprüfe zuvor die Mittelwertberechnung durch direkte Berechnung (in Schleifen):

\[ {m}{e}{a}{n}=\frac{{\sum{\left(\hat{{A}}+\hat{{B}}\right)}}}{{\left|\hat{{A}}\right|}}=?\overline{{C}} \]

Partitionierte Parallele Datenverarbeitung (Zwei Phasen)

 ▸ 
 ◼ 
 ✗ 
 ↻ 
 ≡ 



Hilfe



Einreichung (Assignment #2024-52509 )



Prüfen



Bewerten (Lehrer)




Created by the NoteBook Compiler Ver. 1.27.2 (c) Dr. Stefan Bosse (Wed May 29 2024 13:24:31 GMT+0200 (Central European Summer Time))