Programowanie Wpółbieżne, wyklad3

background image

4. TEORETYCZNE MODELE PROCESÓW WSPÓŁBIEŻNYCH

Teoretyczne modele uwzględniają wybrane cechy rzeczywistych procesów,
stanowiąc kompromis

pomiędzy łatwością i jakością modelowania. Konstruując model obliczeń
należy mieć na

względzie:

1) czy korzystamy z pamięci dzielonej, czy z przesyłania komunikatów (raczej
nie miesza sie

tych dwóch rzeczy);

2) jakie akcje uznajemy za elementarne, to jest wykonywane niepodzielnie
- niezależnie od

akcji innych procesów.

Przykład (Z. Manna, A. Pnueli)

Obliczyć wartość dwumianu Newtona dla n, k naturalnych, n k.
n! n · (n - 1) · ... · (n - k + 1)

( k

czynników )

k! (n - k)! 1  2 · ... · k

( k

czynników )

Wartość tego wyrażenia jest zawsze liczbą naturalną dla n, k takich, że n k.

)

(

n
k

)

(

n
k

background image

Sposób obliczenia: współbieżnie wykonujemy mnożenia w liczniku i
mianowniku, i na bieżąco

wykonujemy dzielenia - wtedy, kiedy tylko jest to możliwe (ten sposób jest
dobry, gdyż możemy

uniknąć przekroczenia zakresu arytmetyki komputera, pomimo że licznik i
mianownik oddzielnie

mogłyby ten zakres przekroczyć).

n, k - dane

l, m - zmienne pomocnicze, przyjmujące odpowiednio wartości

l : n, n-1, ... , n - k + 1

m: 1,2, ... , k

b - wartość ułamka (na początku b = 1)

Proces P

1

mnoży b przez kolejne wartości l, proces P

2

dzieli b przez kolejne

wartości m, ale

dopiero wtedy, kiedy jest to wykonalne: w żadnej chwili liczba wykonanych
dzieleń nie może

przekroczyć liczby wykonanych mnożeń, czyli musi zachodzić m n - l, aby

można było

wykonać dzielenie, zatem warunkiem wykonania dzielenia jest l + mn.

background image

{ n, k : dane }

l : n ;
m : 1 ;
b : 1 ;

while ln - k do while mk do
begin begin

P

1

: b : b l ; || P

2

: await ( l + m ) 

n ;

l : l - 1 b : b div m ;
end ; m : m + 1
end;

{ b : wynik }

Założenia: 1) zmienne n, k, b umieszczone są w pamięci wspólnej i oba
procesy używają dla nich

takich samych nazw;

2) sprawdzenia warunków oraz instrukcje podstawienia
wykonywane są niepodzielnie.

background image

Instrukcja await (wb), gdzie wb jest wyrażeniem boolowskim, zawiesza
wykonywanie procesu do

momentu, gdy zacznie zachodzić wb = true. Gdyby działanie await (wb) było
interpretowane jako:

wb ?

T F

byłoby to tak zwane aktywne czekanie (ciągłe sprawdzanie wartości wb
absorbuje moc oblicze-

niową procesora). W praktyce częściej następuje zawieszenie wykonywania
procesu przez system

operacyjny tak, aby nie marnować mocy procesora, więc bardziej adekwatnym
schematem byłby

schemat:

wb ?

T F

background image

Działanie programów sekwencyjnych często przedstawiane jest za pomocą
schematów blokowych.

Dla programów współbieżnych dogodniejszą formą ilustracji ich działania są
diagramy przejść.

stan przejście

c ?
instr

warunek logiczny instrukcja

(strażnik przejścia) wykonywana
niepodzielnie

Jeżeli dla każdego stanu zachodzi, że wszystkie przejścia wychodzące z tego
stanu mają warunki

parami wykluczające się, program nazywamy procesowo
deterministycznym
.

Omawiany przykład jest procesowo deterministyczny.

s

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 5

m = 1

b = 1

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 5

m = 1

b = 1

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 5

m = 1

b = 1

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 5

m = 1

b = 5

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 4

m = 1

b = 5

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 4

m = 1

b = 5

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 4

m = 1

b = 5

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 4

m = 1

b = 20

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 4

m = 1

b = 20

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 4

m = 2

b = 20

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 4

m = 2

b = 20

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 3

m = 2

b = 20

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 3

m = 2

b = 20

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 3

m = 2

b = 20

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 3

m = 2

b = 10

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 3

m = 2

b = 30

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 2

m = 2

b = 30

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 2

m = 3

b = 30

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 2

m = 3

b = 30

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 2

m = 3

b = 30

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 2

m = 3

b = 10

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 2

m = 3

b = 10

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 2

m = 4

b = 10

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

ln - k

?

ln - k ?

m k ?

m:m

+1

l:l -1

n = 5 k
=
3

l = 2

m = 4

b = 10

p

0

p

1

p

2

p

3

r

0

r

1

r

2

r

3

r

4

b:bl

m k ?

l + mn ?

b : b div

m

background image

W powyższym diagramie pojedyncze strzałki odpowiadają pojedynczym
operacjom niepodziel-

nym. Wielkość jednostek syntaktycznych programu, o których możemy
założyć, że będą wyko-

nane niepodzielnie, nazywamy ziarnistością

(granularity)

.

Przedstawiony program charakteryzuje się niedeterminizmem wykonania,
gdyż jego wykonanie

może być modelowane przez różne przeploty operacji niepodzielnych obu
procesów, np.

P

1

P

1

P

2

P

1

P

2

P

1

...........

lub P

1

P

1

P

1

P

2

P

1

P

2

...........

Natomiast pomimo to stan końcowy programu (wektor wartości zmiennych i
wskaźników

instrukcji) jest w każdym przypadku taki sam, niezależnie od wykonanego
przeplotu - taki

program nazywamy zdeterminowanym (wszystkie współbieżne programy
transformacyjne

powinny posiadać tę cechę).

background image

W przypadku korzystania ze wspólnej pamięci efekt wykonania programu
współbieżnego może

zależeć od ziarnistości.

Przykład

{y = 1 - wartość początkowa}

P

1

: y = y + 1 P

2

: y = y - 1

Jeżeli założymy, że instrukcje podstawienia wykonywane są niepodzielnie, to
zarówno dla prze-

plotu P

1

P

2

, jak i P

2

P

1

wynikiem wykonania będzie y = 1. W praktyce

kompilator może

przełożyć te instrukcje na następujące ciągi rozkazów maszynowych:

LOAD Rejestr1, y LOAD Rejestr2, y

P

1

: ADD Rejestr1, #1 P

2

: SUB Rejestr2, #1

STORE Rejestr1, y STORE Rejestr2,
y

(Zakładamy, że każdy proces używa swojego lokaknego rejestru).

background image

Zakładając, że wszystkie przeploty rozkazów z przekładów P

1

i P

2

dopuszczalne, otrzymujemy

trzy różne wyniki dla różnych przeplotów:

P

1

P

1

P

1

P

2

P

2

P

2

y = 1

Liczba wszystkich

przeplotów ciągu

P

1

P

1

P

2

P

1

P

2

P

2

y = 2

m - elementowego z ciągiem

n - elementowym

P

1

P

2

P

1

P

2

P

2

P

1

y = 3

(m + n) !

m !  n !

(inne przeploty dałyby jeden z tych trzech wyników). Zmniejszenie ziarnistości
spowodowało

zatem, że program przestał być zdeterminowany.

W języku inżynierskim zjawisko, kiedy wynik zależy od przypadkowych czasów
wykonania (lub,

dla układów scalonych, od przypadkowych różnic w czasach propagacji
sygnałów elektrycznych)

nazywane jest hazardem.

Nie należy projektować niczego, czego efekt wykonania mógłby zależeć od
hazardu !

wynosi

background image

Powyższy przykład był prosty, bo wszystkie występujące w nim rozkazy
maszynowe co najwyżej

raz wykonywały cykl pamięciowy. Jego analiza odnosi się więc zarówno do
wykonania z przeplo-

tem (drobnoziarnistym) na pojedynczym procesorze, jak i do wykonania
równoległego na dwóch

procesorach mających dostęp do wspólnej pamięci. Różnica mogłaby wystąpić
w przypadku,

gdyby dwa procesory równolegle wykonywały rozkazy wymagające dwóch
odwołań do pamięci -

np. rozkaz dodania zawartości akumulatora do zawartości komórki pamięci z
pozostawieniem

wyniku w pamięci. W takim przypadku do modelowania należałoby stosować
jeszcze drobniejszą

ziarnistość - na poziomie mikrorozkazów (operacjami niepodzielnymi są
odczyt / zapis z /do

pamięci i wykonanie operacji na samych rejestrach).

background image

5. NISKOPOZIOMOWE MECHANIZMY ZAPEWNIANIA
NIEPODZIELNOŚCI

OPERACJI

Możliwość zapewnienia niepodzielności operacji (będących ciągami operacji
elementarnych) na

komórkach pamięci wspólnej jest w programowaniu współbieżnym sprawą o
zasadniczym zna-

czeniu. Szczególnie w przypadku rzeczywistej równoległości widoczna jest
potrzeba zabezpiecze-

nia pojedynczym procesom prawa wyłączności dostępu (na pewien czas) do
zmiennych dzielonych,

ale w przypadku drobnoziarnistego przeplotu też to jest istotne. Ciąg instrukcji
programu operujących

na współdzielonych zasobach (pamięci dzielonej, wspólnych plikach itp.),
który powinien być wyko-

nany niepodzielnie, nazywamy sekcją krytyczną programu. Jakie są sposoby
zabezpieczania sekcji

krytycznych ?

Jeżeli współbieżność jest symulowana na pojedynczym procesorze przez system
operacyjny i sekcje

krytyczne nie są związane z pamięcią wspólną, ale innymi zasobami (pliki,
kolejki), proste operacje

na tych zasobach są dostępne w postaci wywołań funkcji systemowych.
Funkcje systemowe są

wykonywane przez jądro systemu na zamówienie procesu i niepodzielność ich
wykonania jest

zapewniana przez system operacyjny.

background image

Jeżeli mają być wykonywane operacje na pamięci wspólnej, lub bardziej złożone
operacje na

dowolnych zasobach, programista musi sam zadbać o ich zabezpieczenie.
Najprostszym mecha-

nizmem abstrakcyjnym służącym do tego celu są semafory. Podstawowym
rodzajem semafora

jest semafor binarny, będący obiektem, którego jedyne pole może przyjmować
tylko wartości

0 i 1, a jedyne operacje, jakie można na nim wykonać, to:

P (czekaj)

V (sygnalizuj)

Definicje tych operacji jest następująca:

P(S) - jeżeli S>0, to zmniejsz S o 1, w przeciwnym razie wstrzymaj
wykonywanie procesu;

V(S) - jeżeli są jakieś procesy wstrzymane przez semafor S, to wznów jeden z
nich, w przeciwnym

razie jeśli S=0, to zwiększ S o 1.

background image

Uwaga.

1) Skutek próby otwarcia otwartego semafora binarnego zależy od
implementacji. Dojście do

takiej sytuacji świadczy o błędzie w programie (i system operacyjny
zazwyczaj reaguje

sygnalizacją błędu).

2) Same operacje na semaforach muszą być wykonywane niepodzielnie. W
systemach z przeplo-

tem realizowane są jako funkcje systemowe, natomiast w sytuacji
rzeczywistej równoległości

ich implementacja musi być wspierana przez odpowiedni sprzęt
(procesory z niepodzielnymi

rozkazami typu test-and-set).

3) Niedeterminizm uruchamiania procesów czekających pod semaforem
może podlegać różnym

ograniczeniom (pojęcia związane z szeregowaniem wykonywania
procesów będą omówione

na następnym wykładzie).

background image

Przykład

Użycie semafora binarnego do zabezpieczenia sekcji krytycznej w przypadku
dwóch procesów.

{na początku S=1}

while true do while true
do

begin begin

niekrytyczna1;
niekrytyczna2;

P

1

: czekaj(S); || P

2

:

czekaj(S);

krytyczna1;
krytyczna2;

sygnalizuj(S)
sygnalizuj(S)

end end

Uwaga.

Przyjmujemy założenie, że każde wykonanie zarówno sekcji krytycznej, jak i
niekrytycznej zajmuje

skończony czas (procesy nie zapętlają się w nich ani nie zawieszają).

background image

{ S = 1 }

niekrytyczna1

krytyczna1

S > 0 ? S
= 0

S :=
S+1

niekrytyczna2

S > 0 ? S
= 0

krytyczna2

S =

S+1

Uwaga.

Gdyby w powyższym przykładzie zrównoleglić trzy takie procesy lub więcej,
wzajemne wykluczanie

byłoby dalej zapewnione, ale jeden z procesów mógłby zostać zagłodzony.

background image

Uogólnienia semafora binarnego:

1) semafor ogólny - różni się od binarnego tym, że może przyjmować dowolne
wartości naturalne,

zaś operacja V, jeżeli nie czeka żaden proces, zwiększa zawsze wartość S o 1;

2) semafor ograniczony - może przyjmować wartości naturalne z zakresu od 0
do pewnego n.

Zawieszenie procesu powoduje zarówno próba zmniejszenia wartości
semafora poniżej 0, jak

i próba zwiększenia powyżej n ;

3) semafor wielokrotny - pozwala na wykonywanie niepodzielnych operacji na
wielu wartościach

jednocześnie (będzie omówiony przy okazji opisu implementacji w systemie
Linux).

Uwaga.

W językach programowania dysponujących standardowymi zestawami instrukcji
wszystkie rodzaje

semaforów są wzajemnie zastępowalne. Do rozwiązania konkretnych problemów
jedne rodzaje mogą

jednak być wygodniejsze, niż inne.

background image

Przykład

Jeżeli w sieci lokalnej jest 5 ogólnodostępnych drukarek, to dostęp wielu
procesów do nich można

skoordynować przy użyciu semafora przyjmującego wartości 0 ... 5.

Przykład

Problem producenta i konsumenta z n - miejscowym buforem cyklicznym.

while true do while true do

begin begin

produkuj(e);
czekaj(elementy);

czekaj(miejsca); e :=
bufor(wy);

P

1

: bufor(we) := e; P

2

: wy :=

(wy + 1) mod n;

we := (we + 1) mod n;
sygnalizuj(miejsca);

sygnalizuj(elementy)
konsumuj(e)

end end

produce
nt

konsument

bufor

background image

W przypadku komunikacji przez kanał przyjmujemy, że dostępne są
niepodzielnie wykonywane

funkcje send(, expr) i receive(, e), gdzie e jest zmienną, expr jest wyrażeniem

tego samego typu,

co e, a  jest kanałem mogącym pomieścić ciąg elementów tego samego typu, co

e. Kanał może mieć

pojemność skończoną (w szczególnym przypadku 0) lub nieskończoną. Funkcja
send zawiesza wyko-

nywanie procesu, jeśli kanał jest pełny, funkcja receive zawiesza proces przy
próbie pobrania z kanału

pustego.

Przykład

Rozwiązanie problemu producenta i konsumenta przy użyciu kanału.

while true do while true do

begin begin

P

1

: produkuj(e); P

2

:

receive(, e);
send(, e)

konsumuj(e)

end end

background image

Monitory są „deklarowalnymi” obiektami mającymi zagwarantowaną
niepodzielność wykonywania

ich metod. Jest zatem niemożliwe współbieżne wykonanie operacji w jednym
monitorze, ale możliwe

w kilku różnych monitorach. Monitory są bardzo naturalnym mechanizmem
ochrony sekcji krytycz-

nych.


Document Outline


Wyszukiwarka

Podobne podstrony:
Programowanie Wpółbieżne, wyklad10
Programowanie Wpółbieżne, wyklad7
Programowanie Wpółbieżne, wyklad4
Programowanie Wpółbieżne, wyklad8
Programowanie Wpółbieżne, wyklad9
Programowanie Wpółbieżne, wyklad6
plikus pl Programowanie strukturalne, Wyklad z C
PROGRAMOWANIE APLIKACJI U.- WYKŁAD, PROG. APLIKACJI UŻYTKOWYCH- WYKŁAD 11
Języki programowania zaliczenie wykłady Języki programowania3
Języki programowania zaliczenie wykłady Wykład 5
Programowanie obiektowe, wyklad6-czesc1, Dziedziczenie wielobazowe
Zadania dodatkowe, studia wsiz, semestr 1 2, programowanie LAB wyklad, Programowanie, BFryc, 1IID, Z
program nauczania wykładnią koncepcji pedagogicznej Kwiatkowska Ratajczak, metodyka nauczania języka

więcej podobnych podstron