nsp1 - Freie Universität Berlin

 Documents

 39 views
of 36
All materials on our website are shared by users. If you have any questions about copyright issues, please report us to resolve them. We are always happy to assist you.
Description
Algorithmen und Programmierung IV: Nichtsequentielle Programmierung Klaus-Peter Löhr Freie Universität Berlin SS 2003 Inhalt 1 Einführung 2 Nebenläufige…
Share
Transcript
Algorithmen und Programmierung IV: Nichtsequentielle Programmierung Klaus-Peter Löhr Freie Universität Berlin SS 2003 Inhalt 1 Einführung 2 Nebenläufige Prozesse 3 Interaktion über Objekte 4 Ablaufsteuerung 5 Implementierung 6 Interaktion über Nachrichten 1 Einführung Zur Erinnerung: Fachterminologie Englisch/Deutsch siehe http://www.babylonia.org.uk 1.1 Nichtsequentielle Programme und Prozesse Was? Warum? Wie? Sequentielle Programme versus Nichtsequentielle Programme 1.1.1 Was ist Nichtsequentialität? Aktion = Ausführung einer Programmanweisung, einer Maschineninstruktion, eines Mikroprogrammbefehls, ..... je nach betrachteter Abstraktionsebene Programmablauf besteht aus Aktionen und heißt sequentiell (sequential), wenn er aus einer Folge von zeitlich nicht überlappenden Aktionen besteht, parallel (parallel), wenn er nicht sequentiell ist Achtung: ein und derselbe Ablauf kann auf einer Abstraktionsebene sequentiell, auf einer anderen parallel sein ! Beispiel 1: x = 3; y = 7; { x = x+1; y = 2*y; } z = x+y; beschreibt einen sequentiellen Ablauf von 5 Aktionen (genauer: Zuweisungen) - aber auf Hardware-Ebene könnten manche dieser Zuweisungen parallel ausgeführt werden! Beispiel 2: Manche Programmiersprachen erlauben explizit parallele Abläufe, ohne sie vorzuschreiben, z.B. x = 3; y = 7; (x,y) = (x+1,2*y); z = x+y; aber auf Hardware-Ebene könnte das hier gezeigte multiple assignment auch wie x = x+1; y = 2*y; ausgeführt werden (oder in umgekehrter Reihenfolge!) Terminologie: • eine Programmiersprache heißt nichtsequentiell (nebenläufig, concurrent), [konkurrierend – falsche Übersetzung] wenn sie Konstrukte enthält, die explizit parallele Abläufe zulassen • ein Programm oder Programmteil heißt nichtsequentiell, wenn es solche Konstrukte verwendet. Typische Nebenläufigkeitskonstrukte identifizieren Programmteile als Prozesse: Def.: Ein Prozess (process) ist ein Programmteil, der – sobald er gestartet wurde – unabhängig vom Rest des Programms ablaufen kann Ein Prozess kann sequentiell oder nichtsequentiell sein. Häufig ist mit „Prozess“ „sequentieller Prozess“ gemeint.  Nebenläufigkeitsanweisung (concurrent statement) Statement = . . . . . | ConcurrentStatement . ConcurrentStatement = CO Processes OC . Processes = Process { || Process } . Process = StatementSequence . z.B. x = 3; y = 7; CO x = x+1; || y = 2*y; OC z = x+y; Semantik: Die Prozesse einer Nebenläufigkeitsanweisung werden unabhängig voneinander ausgeführt. Die Nebenläufigkeitsanweisung ist beendet, wenn alle Prozesse beendet sind. x = 3; y = 7; CO x = x+1; || y = 2*y; OC z = x+y;  Gabelungsanweisung (fork statement) ForkStatement = FORK Process . Process = Statement . z.B. x = 3; y = 7; FORK x = x+1; y = 2*y; z = x+y; Semantik: Die Gabelungsanweisung startet den angegebenen Prozess. (Wann dieser beendet ist, ist nicht bekannt!) z.B. x = 3; Elternprozess y = 7; FORK x = x+1; Kindprozess y = 2*y; ? ? z = x+y; Bemerkung: Es wird grundsätzlich unterstellt, daß Prozeduren eintrittsinvariant implementiert sind; somit ist folgendes unproblematisch: ... FORK p(x+1); FORK p(x+2); p(x+3); ... 1.1.2 Warum nichtsequentielle Programmierung?  Effizienz durch schnellere parallele Ausführung – sofern entsprechende Hardware vorhanden  Problemlösungsstruktur soll im Programm gut sichtbar sein („Problemorientierung statt Maschinenorientierung“) ...; x = x+1; y = 2*y; ... ? ...; y = 2*y; x = x+1; ... ? ...; CO x = x+1; || y = 2*y; OC ...  Systemarchitektur: Mehrprozessbetrieb (multitasking) bei - Betriebssystemen, - Datenbanksystemen, - Echtzeitsystemen, motiviert durch Effizienzüberlegungen und konkurrierende Nutzung knapper Ressourcen 1.1.3 Wie wird nichtsequentiell programmiert? Zentrale Begriffe:  Prozess  Interaktion zwischen Prozessen  Synchronisation von Prozessen 1.1.3.1 Prozessbegriff „Prozess“ ist ein schillernder Begriff – mit unterschiedlichsten Definitionen:  unabhängig ausführbarer Teil eines Programms  Programmablauf (!)  virtueller Prozessor (Betriebssystem!)  industrieller Prozess (Prozessrechner!) u.a. Manchmal muß auch zwischen „Prozess“ und „Inkarnation eines Prozesses“ unterschieden werden: PROCESS void p(int i) {.....} „Prozess“ ... START p(x); START p(y); START p(x); erzeugt Inkarnation (Exemplar, instance) [Instanz – falsche Übersetzung] des Prozesses p oder aber auch „erzeugt Prozess, der p ausführt“ 1.1.3.2 Interaktion zwischen Prozessen z.B. über gemeinsame Variable: CO ... time = clock(); ... || ... write(time); ... OC CO ... decrement(seats); ... || ... increment(seats); ... OC Def.: Zwei Prozesse, die nebenläufig auf eine gemeinsame Variable x zugreifen, stehen miteinander in Konflikt (conflict, interference) bezüglich x, wenn mindestens einer der Prozesse x verändert. Konflikte sind meistens unerwünscht (1.2) und werden durch Synchronisationsmaßnahmen unterbunden 1.1.3.3 Synchronisation Prozesse laufen grundsätzlich asynchron, d.h. unabhängig voneinander und mit nicht vorhersagbaren relativen Geschwindigkeiten Beispiel: CO p(x); || q(y); OC r(z); Es bleibt offen, ob p oder q zuerst fertig ist. Und: „heute so, morgen so“! Die schließende Klammer OC synchronisiert die beiden Prozesse, bevor mit r fortgefahren wird Synchronisation bei Gabelungsanweisung: FORK p(x); q p q(y); JOIN; r(z); r JOIN-Anweisung bewirkt Synchronisation des Elternprozesses mit einem Kindprozess durch eventuelles Warten (auf die Beendigung des Kindprozesses) 1.2 Nichtdeterminismus Der Ablauf eines sequentiellen Programms ist immer deterministisch – d.h. gleiche Eingaben führen zu gleichen Zustandsfolgen – und das Ergebnis ist determiniert – d.h. gleiche Eingaben liefern gleiche Ausgaben (sofern nicht explizit mit Zufallszahlen gearbeitet wird) Asynchronie führt in der Regel zu nichtdeterministischen Abläufen – möglicherweise aber trotzdem zu determinierten Ergebnissen. 1.2.1 Zeitschnitte dienen der Veranschaulichung nichtsequentieller, insbesondere nichtdeterministischer Abläufe: Prozess 1 Prozess 2 . . . . time = „10:59“ . . time = „11:00“ time = clock(); write(time); „11:00“ ! . . „10:59“ !! . . time = „11:00“ Prozess 1 Prozess 2 . . . . seats = 17 seats = 16 a = seats; b = seats; seats = 17 a = a-1; b = b-2; seats = 16 seats = a; seats = b; seats = 15 seats = 14 seats = 15 ! seats = 16 !! Ergebnis determiniert nichtdeterminiert Ablauf deterministisch immer - nichtdeterministisch möglich meistens 1.2.2 Unteilbare Anweisungen verhalten sich so, als würden sie „zeitlos“ ausgeführt (ohne dass „Zwischenzustände“ beobachtet werden könnten) (statt „unteilbar“ auch atomar, indivisible, atomic) (Beachte: in 1.2.1 wurde stillschweigend vorausgesetzt, daß die dortigen Anweisungen unteilbar sind.) Achtung! Annahmen über die Unteilbarkeit selbst einfachster Anweisungen sind häufig nicht gerechtfertigt. Sprachbeschreibungen sind häufig unpräzise in Bezug auf die Unteilbarkeit. Implementierungen können auf subtile Weise die Unteilbarkeit verletzen. Im Zweifelsfall konservative Betrachtungsweise: Das Lesen bzw. Schreiben einer Arbeitsspeicherzelle durch eine Maschineninstruktion ist unteilbar. Beispiel: wenn Zeichenfelder keine Objekte sind, ist das Lesen/Schreiben einer entsprechenden Variablen nicht unteilbar: Prozess 1 Prozess 2 . . clock = „11:00“ . . time = „10:59“ time = clock; //time[0]=clock[0]; time = „10:59“ //time[1]=clock[1]; time = „11:59“ write(time); „11:59“ ! //time[2]=clock[2]; time = „11:59“ //time[3]=clock[3]; time = „11:09“ //time[4]=clock[4]; time = „11:00“ Klassifikation von Variablen in höheren Programmiersprachen:  einfache Variable (simple variable): wird von der Hardware unteilbar gelesen/geschrieben  private Variable (private variable) eines Prozesses: wird nur von diesem Prozes benutzt  gemeinsame Variable (shared variable) mehrerer Prozesse: nicht privat Präzisierung der Unteilbarkeit (wenn wegen lückenhafter Beschreibung der Sprache und/oder ihrer Implementierung erforderlich):  Ein Ausdruck ist unteilbar, wenn seine Auswertung keine Nebenwirkungen hat und während der Auswertung höchstens eine – zudem einfache – gemeinsame Variable höchstens einmal gelesen wird.  Eine Zuweisung v = A ist unteilbar, wenn entweder – v privat und A unteilbar ist oder – v einfach ist und A sich nur auf private Variable bezieht Angesichts oft ungesicherter Verhältnisse wünschenswertes Sprachkonstrukt: Klammerung mit   AtomicExpression =  Expression  AtomicStatement =  Statement  Semantik: Während ein Prozess einen atomaren Ausdruck auswertet bzw. eine atomare Anweisung ausführt, ruhen alle anderen Prozesse (Synchronisation!) (Aber: Die Praktikabilität von   lässt zu wünschen übrig! 3.1) Beispiele: CO ...  seats = seats-1;  ... || ...  seats = seats-2;  ... OC void get(int n){ ...  seats = seats – n;  ... } ... CO get(1); || get(2); || get(3); OC ...
Related Search
We Need Your Support
Thank you for visiting our website and your interest in our free products and services. We are nonprofit website to share and download documents. To the running of this website, we need your help to support us.

Thanks to everyone for your continued support.

No, Thanks