410 likes | 515 Views
Semantyki programów współbieżnych. Determinizm programów sekwencyjnych, Nie-determinizm programów współbieżnych, “prawdziwa równoległość” vs.przeploty (“true concurrency” vs. interleaving) ,
E N D
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 || ... || Pn coend
Przykład 1 cobegin p:= 0 || q:=1; p:=q coend Cobegin P P:= 0 Q:=1 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 przypisaniadiagram cobegin coend • Na danym diagramie możemy grać przesuwając piony=procesory i wykonując operacje na pamięci Cobegin x:=wyr Coend
Przykład 1 - zaczynamy grę Cobegin P P:= 0 Q:=1 Q p:=q Coend
Przykład 1 – pierwszy krok Cobegin P P:= 0 Q:=1 Q p:=q Coend
Przykład 1 – drugi krok Cobegin P P:= 0 Q:=1 Q p:=q Coend
Przykład 1 – drugi krok, 2 wersja Cobegin P P:= 0 Q:=1 Q p:=q Coend
Przykład 1 – drugi krok, 3 wersja Cobegin P P:= 0 Q:=1 Q p:=q Coend
Przykład 1 – drugi krok, 3 wersja, kończy lewy Cobegin P=0 P:= 0 Q:=1 Q p:=q Coend
Przykład 1 – drugi krok, 3 wersja, kończy prawy Cobegin P P:= 0 Q:=1 Q=1 p:=q Coend
Przykład 1 – drugi krok, 3 wersja, kończą obaj Cobegin P=0 P:= 0 Q:=1 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 Cobegin P=0 P:= 0 Q:=1 Q=1 p:=q Coend P Q , * cobegin p:=0 || q:=1; p:=q coend> < ? ?
Przykład 1 – historia obliczenia ver. 1/ 2 Cobegin P P:= 0 Q:=1 Q p:=q Coend P Q , cobegin * p:=0 || * q:=1; p:=q coend> < ? ?
Przykład 1 – historia obliczenia ver.1/3 Cobegin P P:= 0 Q:=1 Q p:=q Coend Q P , cobegin @ p:=0 || * q:=1; p:=q coend> < ? ?
Przykład 1 – historia obliczenia ver.1/4 Cobegin P=0 P:= 0 Q:=1 Q p:=q Coend Q P , * cobegin * || * q:=1; p:=q coend> < 0 ?
Przykład 1 – historia obliczenia ver.1/5 Cobegin P=0 P:= 0 Q:=1 Q p:=q Coend <v: p=0 & q=vq , cobegin * || @q:=1; p:=q coend>
Przykład 1 – historia obliczenia ver.1/6 Cobegin P=0 P:= 0 Q:=1 Q=1 p:=q Coend <v: p=0 & q=vq , cobegin * || q:=1; *p:=q coend>
Przykład 1 – historia obliczenia ver.1/7 Cobegin P=0 P:= 0 Q:=1 Q=1 p:=q Coend <v: p=0 & q=1, cobegin * || @ p:=q coend>
Przykład 1 – historia obliczenia ver.1/8 Cobegin P=1 P:= 0 Q:=1 Q=1 p:=q Coend <v: p=1 & q=1, cobegin * || * coend>
Przykład 1 – historia obliczenia ver.1/9 Cobegin P=1 P:= 0 Q:=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 Cobegin P P:= 0 Q:=1 Q p:=q Coend <v: p=vp & q=vq , * cobegin p:=0 || q:=1; p:=q coend> Zapis powyższej konfiguracji początkowej
Przykład 1 – historia obliczenia ver. 2/ 2 Cobegin P P:= 0 Q:=1 Q p:=q Coend <v: p=vp & q=vq , cobegin * p:=0 || * q:=1; p:=q coend>
Przykład 1 – historia obliczenia ver.2/3 Cobegin P=0 P:= 0 Q:=1 Q p:=q Coend <v: p=0 & q=vq , cobegin * || @q:=1; p:=q coend>
Przykład 1 – historia obliczenia ver.2/4 Cobegin P P:= 0 Q:=1 Q=1 p:=q Coend <v: p=vp & q=1, cobegin *p:=0 || * p:=q coend>
Przykład 1 – historia obliczenia ver.2/5 Cobegin P P:= 0 Q:=1 Q=1 p:=q Coend <v: p=vp & q=1, cobegin *p:=0 || @ p:=q coend>
Przykład 1 – historia obliczenia ver.2/6 Cobegin P P:= 0 Q:=1 Q=1 p:=q Coend <v: p=vp & q=1, cobegin *p:=0 || * coend>
Przykład 1 – historia obliczenia ver.2/7 Cobegin P P:= 0 Q:=1 Q=1 p:=q Coend <v: p=vp & q=1, cobegin @ p:=0 || * coend>
Przykład 1 – historia obliczenia ver.2/8 Cobegin P=0 P:= 0 Q:=1 Q=1 p:=q Coend <v: p=0 & q=1, cobegin * || * coend>
Przykład 1 – historia obliczenia ver.2/9 Cobegin P=0 P:= 0 Q:=1 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ŕKp Ů ŕKŘ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=vq , * cobegin p:=0 || q:=1; p:=q coend> <v: p=vp & q=vq , cobegin * p:=0 || * q:=1; p:=q coend> <v: p=vp & q=vq , cobegin * p:=0 || @q:=1; p:=q coend> <v: p=vp & q=vq , cobegin @p:=0 || * q:=1; p:=q coend> ... <v: p=vp & q=vq , cobegin @p:=0 || @q:=1; p:=q coend> ... Tu historia w ver. 2 Tu historia w ver. 1 <v: p=vp & q=vq , cobegin @p:=0 || @ p:=q coend> < p=0 & q=1, cobegin * || @ p:=q coend> <v: p=0 & q=vq , cobegin * || @q:=1; p:=q coend> <v: p=1 & q=1, cobegin * || * coend> <p=0 & q=1,cobegin * || @p:=q > < p=0 & q=1, cobegin * || @p:=q coend> <p=1 & q=1, Ć> <v: p=1 & q=1, cobegin * || * coend> <p=1 & q=1, Ć> <p=1 & q=1, Ć>
Drzewo możliwych obliczeń – MAX <v: p=vp & q=vq , * cobegin p:=0 || q:=1; p:=q coend> <v: p=vp & q=vq , cobegin * p:=0 || * q:=1; p:=q coend> <v: p=vp & q=vq , cobegin * p:=0 || @q:=1; p:=q coend> <v: p=vp & q=vq , cobegin @p:=0 || * q:=1; p:=q coend> ... <v: p=vp & q=vq , cobegin @p:=0 || @q:=1; p:=q coend> ... <v: p=vp & q=vq , cobegin @p:=0 || @ p:=q coend> < p=0 & q=1, cobegin * || @ p:=q coend> <v: p=0 & q=vq , cobegin * || @q:=1; p:=q coend> <v: p=1 & q=1, cobegin * || * coend> <p=0 & q=1,cobegin * || @p:=q > < p=0 & q=1, cobegin * || @p:=q coend> <p=1 & q=1, Ć> <v: p=1 & q=1, cobegin * || * coend> <p=1 & q=1, Ć> <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 Loglanie Program 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.