semantyki programów współbieżnych
Post on 14-Jan-2016
30 Views
Preview:
DESCRIPTION
TRANSCRIPT
Semantyki programówwspółbieżnych
Determinizm programów sekwencyjnych, Nie-determinizm programów współbieżnych, “prawdziwa równoległość” vs.przeploty
(“true concurrency” vs. interleaving), Teza: wykonanie programu współbieżnego może
istotnie różnić się w zależności od systemu wykonawczego (inaczej na jednym procesorze obsługującym wiele procesów, a jeszcze inaczej na systemie rozproszonych procesorów)
Wykład10
1
Język programów
Rozpatrzmy klasę języków programowania określoną następująco:instrukcje przypisania i inne instrukcje atomowe,instrukcje złożone, tzn. Połączone średnikiem,instrukcje warunkowe if then else fi,instrukcje iteracyjne while do od,
instrukcje współbieżne cobegin P1 || ... || P
n coend
Przykład 1
cobegin p:= 0 || q:=1; p:=q coend
P:= 0 Q:=1
Cobegin
P
Q
p:=q
Coend
Gra w program
Dla każdego programu można narysować diagram, jest on jednoznacznie wyznaczony przez program.
Diagram instrukcji atomowej np. instrukcji przypisania
diagram cobegin coend
Na danym diagramie możemy grać przesuwając piony=procesory i wykonując operacje na pamięci
x:=wyr Cobegin
Coend
Przykład 1 - zaczynamy grę
P:= 0 Q:=1
Cobegin
P
Q
p:=q
Coend
Przykład 1 – pierwszy krok
P:= 0 Q:=1
Cobegin
P
Q
p:=q
Coend
Przykład 1 – drugi krok
P:= 0 Q:=1
Cobegin
P
Q
p:=q
Coend
Przykład 1 – drugi krok, 2 wersja
P:= 0 Q:=1
Cobegin
P
Q
p:=q
Coend
Przykład 1 – drugi krok, 3 wersja
P:= 0 Q:=1
Cobegin
P
Q
p:=q
Coend
Przykład 1 – drugi krok, 3 wersja, kończy lewy
P:= 0 Q:=1
Cobegin
P=0
Q
p:=q
Coend
Przykład 1 – drugi krok, 3 wersja, kończy prawy
P:= 0 Q:=1
Cobegin
P
Q=1
p:=q
Coend
Przykład 1 – drugi krok, 3 wersja, kończą obaj
P:= 0 Q:=1
Cobegin
P=0
Q=1
p:=q
Coend
Historie obliczeń
Po obejrzeniu tych kilku przykładów konfiguracji oraz konfiguracji będących ich następnikamiobejrzyjmy teraz ciąg konfiguracji stanowiący jedną historię obliczeń tego programu.
Przykład 1 – historia obliczenia, ver. 1/1
P:= 0 Q:=1
Cobegin
P=0
Q=1
p:=q
Coend
, * cobegin p:=0 || q:=1; p:=q coend>
P Q<
? ?
Przykład 1 – historia obliczenia ver. 1/ 2
P:= 0 Q:=1
Cobegin
P
Q
p:=q
Coend
, cobegin * p:=0 || * q:=1; p:=q coend>
P Q<
? ?
Przykład 1 – historia obliczenia ver.1/3
P:= 0 Q:=1
Cobegin
P
Q
p:=q
Coend
, cobegin @ p:=0 || * q:=1; p:=q coend>
P<
? ?
Q
Przykład 1 – historia obliczenia ver.1/4
P:= 0 Q:=1
Cobegin
P=0
Q
p:=q
Coend
, * cobegin * || * q:=1; p:=q coend>
P
0 ?
Q<
Przykład 1 – historia obliczenia ver.1/5
P:= 0 Q:=1
Cobegin
P=0
Q
p:=q
Coend
<v: p=0 & q=vq
, cobegin * || @q:=1; p:=q coend>
Przykład 1 – historia obliczenia ver.1/6
P:= 0 Q:=1
Cobegin
P=0
Q=1
p:=q
Coend
<v: p=0 & q=vq
, cobegin * || q:=1; *p:=q coend>
Przykład 1 – historia obliczenia ver.1/7
P:= 0 Q:=1
Cobegin
P=0
Q=1
p:=q
Coend
<v: p=0 & q=1
, cobegin * || @ p:=q coend>
Przykład 1 – historia obliczenia ver.1/8
P:= 0 Q:=1
Cobegin
P=1
Q=1
p:=q
Coend
<v: p=1 & q=1
, cobegin * || * coend>
Przykład 1 – historia obliczenia ver.1/9
P:= 0 Q:=1
Cobegin
P=1
Q=1
p:=q
Coend
<v: p=1 & q=1
, Ć> Konfiguracja końcowa
Jeden program – wiele obliczeń
Wiemy, że jeden program współbieżny może mieć wiele różnych obliczeń dla tych samych danych początkowych.Prześledźmy to.
Przykład 1 – historia obliczenia ver.2/1
P:= 0 Q:=1
Cobegin
P
Q
p:=q
Coend
<v: p=vp & q=v
q , * cobegin p:=0 || q:=1; p:=q coend>
Zapis powyższej konfiguracji początkowej
Przykład 1 – historia obliczenia ver. 2/ 2
P:= 0 Q:=1
Cobegin
P
Q
p:=q
Coend
<v: p=vp & q=v
q , cobegin * p:=0 || * q:=1; p:=q coend>
Przykład 1 – historia obliczenia ver.2/3
P:= 0 Q:=1
Cobegin
P=0
Q
p:=q
Coend
<v: p=0 & q=vq
, cobegin * || @q:=1; p:=q coend>
Przykład 1 – historia obliczenia ver.2/4
P:= 0 Q:=1
Cobegin
P
Q=1
p:=q
Coend
<v: p=vp & q=1
, cobegin *p:=0 || * p:=q coend>
Przykład 1 – historia obliczenia ver.2/5
P:= 0 Q:=1
Cobegin
P
Q=1
p:=q
Coend
<v: p=vp & q=1
, cobegin *p:=0 || @ p:=q coend>
Przykład 1 – historia obliczenia ver.2/6
P:= 0 Q:=1
Cobegin
P
Q=1
p:=q
Coend
<v: p=vp & q=1
, cobegin *p:=0 || * coend>
Przykład 1 – historia obliczenia ver.2/7
P:= 0 Q:=1
Cobegin
P
Q=1
p:=q
Coend
<v: p=vp & q=1
, cobegin @ p:=0 || * coend>
Przykład 1 – historia obliczenia ver.2/8
P:= 0 Q:=1
Cobegin
P=0
Q=1
p:=q
Coend
<v: p=0 & q=1
, cobegin * || * coend>
Przykład 1 – historia obliczenia ver.2/9
P:= 0 Q:=1
Cobegin
P=0
Q=1
p:=q
Coend
<v: p=0 & q=1
, Ć>
Porównanie
Widzieliśmy dwa różne obliczenia dla tego samego programu, Czy mogą być inne? Które z nich są dopuszczalne? Które z nich są możliwe? Zwróćmy uwagę na to, że pierwsze obliczenie daje w wyniku p=1, a drugie p=0. Oznaczmy program literą K. Wyrażenie logiczne ŕ p Ů ŕ Řp odczytujemy: możliwe, że po wykonaniu programu K zmienna p ma wartość prawda i możliwe, że po (innym) wykonaniu programu K zmienna p ma wartość fałsz. Znak ŕ czytamy: możliwe Znak czytamy: konieczne
Drzewo możliwych obliczeń
Zbiór możliwych obliczeń pozwoli nam utworzyć drzewo- korzeniem drzewa jest konfiguracja początkowa <v, * P> gdzie v jest początkowym stanem pamięci, stanem zmiennych, P jest programem do wykonania.
- wspólne początkowe segmenty obliczeń utożsamiamy
Drzewo możliwych obliczeń
<v: p=vp & q=v
q , * cobegin p:=0 || q:=1; p:=q coend>
<v: p=vp & q=v
q , cobegin * p:=0 || * q:=1; p:=q coend>
<v: p=vp & q=v
q , cobegin @p:=0 || * q:=1; p:=q coend> <v: p=v
p & q=v
q , cobegin * p:=0 || @q:=1; p:=q coend>
<v: p=vp & q=v
q , cobegin @p:=0 || @q:=1; p:=q
coend>
< p=0 & q=1
, cobegin * || @ p:=q coend>
<v: p=1 & q=1
, cobegin * || * coend>
... ...
<p=1 & q=1, Ć
<v: p=vp & q=v
q , cobegin @p:=0 || @ p:=q
coend>
<v: p=0 & q=vq
, cobegin * || @q:=1; p:=q
coend>
< p=0 & q=1 , cobegin * || @p:=q coend>
<p=1 & q=1, Ć
<p=0 & q=1 ,cobegin * || @p:=q >
<v: p=1 & q=1
, cobegin * || *
coend>
<p=1 & q=1, Ć
Tu historia w ver. 1Tu historia w ver. 2
Drzewo możliwych obliczeń – MAX
<v: p=vp & q=v
q , * cobegin p:=0 || q:=1; p:=q coend>
<v: p=vp & q=v
q , cobegin * p:=0 || * q:=1; p:=q coend>
<v: p=vp & q=v
q , cobegin @p:=0 || * q:=1; p:=q coend> <v: p=v
p & q=v
q , cobegin * p:=0 || @q:=1; p:=q coend>
<v: p=vp & q=v
q , cobegin @p:=0 || @q:=1; p:=q
coend>
< p=0 & q=1
, cobegin * || @ p:=q coend>
<v: p=1 & q=1
, cobegin * || * coend>
... ...
<p=1 & q=1, Ć
<v: p=vp & q=v
q , cobegin @p:=0 || @ p:=q
coend>
<v: p=0 & q=vq
, cobegin * || @q:=1; p:=q
coend>
< p=0 & q=1 , cobegin * || @p:=q coend>
<p=1 & q=1, Ć
<p=0 & q=1 ,cobegin * || @p:=q >
<v: p=1 & q=1
, cobegin * || *
coend>
<p=1 & q=1, Ć
ARB i MAX
Semantyka ARB – arbitralne przeploty instrukcji atomowych.Opisuje systemy wykonawcze w których procesory mogą trochę poczekać pomiędzy zakończeniem jednej instrukcji a rozpoczęciem kolejnej. Przeploty stosuje się także do analizy procesów działających na jednym procesorze (np.Unix).
Semantyka MAX – maksymalne zaangażowanie procesorów.Opisuje systemy wykonawcze w których procesor nie może się powstrzymać przed rozpoczęciem wykonywania następnej instrukcji gdy tylko jest możliwość jej wykonania. Zakładamy tu, że w wyniku niezdeterminowanej konkurencji procesorów o zasoby niezbędne do wykonania bieżących instrukcji wybrany zostanie jakiś maksymalny niekonfliktowy zbiór instrukcji do rozpoczęcia wykonywania.
Zróbmy to w Loglanie
Nie mamy kompilatora tego języka. Czy jest to dla nas przeszkodą?
Język którym się dotąd posługujemy dopuszcza by procesy dzieliły się dostępem do wsólnych zmiennych, procesy w Loglanie nie mogą mieć wspólnych zmiennych. Na ile to jest istotne?
Stwórzmy proces zmienna. Procesy lewy i prawy mogą mieć jako argumenty procesy. Wykorzystamy to.
Program w LoglanieProgram MaxArb;
unit zmiennaB: process(node: integer); var value: Boolean; unit podaj: function: Boolean; begin result := value end podaj; unit zapisz: procedure(nval: Boolean); begin value := nval end zapisz;begin return;enable podaj, zapisz;do accept od;end zmiennaB;unit lewy: process(node:integer, || unit prawy: process(node: integer, a: zmiennaB); || a,b: zmiennaB);begin || begin return; || return; call a.zapisz(false) || call b.zapisz(true);end lewy; || call a.zapisz(b.podaj);
|| end prawy;var p, q: zmiennaB, lw: lewy, pr: prawy;
begin p: =new zmiennaB(...); resume(p); q:= new zmiennaB(...); resume(q); lw:= new lewy(..., p); pr := new prawy(..., p, q); resume(lw); resume(pr);
end MaxArb
Objaśnienia i zadania Mam nadzieję, że czytelniczki i czytelnicy tych stron widzą w
jaki sposób odwzorowany został program z instrukcją cobegin na program w Loglanie.
Procesy p i q typu zmiennaB zachowują się tak jak komórki pamięci – udostępniają swoje metody odczytu i zapisu.
Procesy lw i pr zgłaszają swe żądania procesom p i q. Zauważmy, że te ostatnie procesy nie mogą równocześnie obsługiwać żądań pochodzących z procesów lw i pr.
Proponuję wykonać odpowiednie eksperymenty alokując te cztery procesy na jednym lub na czterech procesorach. Co się stanie? Dodaj odpowiednie testy.
W tym programie nie zrealizowano instrukcji coend. Zrób to.
Dodaj prawidłowe zakończenie procesów p i q.
cobegin p:=0 || while p do x:= x+1 od coend
top related