1 Zadanie 1: Programowanie wspóªbie»ne wiczenia 11 Przestrzenie krotek cz. 1 Obliczanie caªki oznaczonej Rozwa»my iteracyjne obliczanie caªki oznaczonej na przedziale [a, b] metod trapezów. Krok iteracji polega na obliczeniu pola trapezu wyznaczonego przez punkty a, b, f(a), f(b) i porównaniu go z sum pól trapezów zbudowanych na przedziaªach [a, c] i [c, b], gdzie c jest ±rodkiem przedziaªu [a, b]. Je±li ró»nica jest wi ksza od zadanej wielko±ci ɛ, obliczamy rekurencyjnie caªki na przedziaªach [a, c] i [c, b], z dokªadno±ci ɛ 2 ka»d, i sumujemy je. Obliczenie tych caªek powinno odbywa si wspóªbie»nie. Caªy proces powinien by realizowany przez pewn liczb nierozró»nialnych wykonawców pobieraj cych zlecenia z przestrzeni krotek i tam umieszczaj cych zarówno kolejne zlecenia jak te» wyniki. Inicjatorem oblicze«i odbiorc ostatecznych wyników jest odr bny proces zleceniodawcy, który w tym celu wywoªuje funkcj double calka(double a, double b, double epsilon). Celem zadania jest wi c napisanie tre±ci w. w. funkcji oraz procesu wykonawcy. Wykonawca powinien dziaªa w p tli niesko«czonej. double calka(double a, double b, double epsilon) { / woªana przez proces zleceniodawcy / double fa = f(a), fb = f(b); double x, calka, xp, xk, w; tsput("zlecenie %f %f %f %f %f %f", a, b, fa, fb, (fa + fb) (b a) / 2, epsilon); x = a; calka = 0.0; tsfetch("wynik?f?f?f", &xp, &xk, &w); calka += w; x += xk xp; while (x!= b); return calka; double a, b, c, fa, fb, fc, pab, pac, pcb, epsilon ; tsfetch("zlecenie?f?f?f?f?f?f", &a, &b, &fa, &fb, &pab, &epsilon); c = (a + b) / 2; fc = f(c); pac = (fa + fc) (c a) / 2; pcb = (fc + fb) (b c) / 2; if (fabs(pab (pac + pcb)) > epsilon) { tsput("zlecenie %f %f %f %f %f %f", a, c, fa, fc, pac, epsilon / 2); tsput("zlecenie %f %f %f %f %f %f", c, b, fc, fb, pcb, epsilon / 2); else { tsput("wynik %f %f %f", a, b, pab); while (1); W tym rozwi zaniu w funkcji calka pojawia si jedna do± subtelna kwestia. Ze wzgl du na zaokr glenia wyników operacji na liczbach rzeczywistych, mo»e si okaza,»e po zsumowaniu wszystkich odcinków nie tramy w punkt b. Aby unikn takiej sytuacji, mo»emy odbiera wyniki zgodnie z kolejno±ci podprzedziaªów. Odpowiedni fragment w. w. funkcji przyjmie wtedy nast puj c posta.
2 xp = a; calka = 0.0; tsfetch("wynik %f?f?f", xp, &xk, &w); calka += w; xp = xk; while (x!= b); Zadanie 2: Sortowanie b belkowe W przestrzeni krotek znajduje si ci g N liczb. Ka»da liczba to krotka w formacie "LICZBA %d %d", gdzie pierwszy element to unikalny indeks tej liczby w ci gu (z przedziaªu 0... N 1) a drugi to warto± tej liczby. Celem zadania jest napisanie wspóªbie»nego algorytmu sortowania b belkowego tego ci gu. W wersji sekwencyjnej algorytm dziaªa w przebiegach. W ka»dym przebiegu, N 1 razy wykonuje si operacj porównywania i ewentualnej zamiany elementów pierwszego z drugim, drugiego z trzecim, trzeciego z czwartym, itd. Po doj±ciu do ko«ca ci gu, przebieg si ko«czy i rozpoczynany jest nast pny, ale jedynie je±li w dopiero co zako«czonym dokonano co najmniej jednej zamiany. W wersji wspóªbie»nej proces sortowania powinien by realizowany przez pewn liczb nierozró»nialnych wykonawców. W efekcie dla dowolnych krotek "LICZBA i v" i "LICZBA j w", powinien by speªniony warunek: je±li i < j, to v w. Dodatkowo, po zako«czeniu sortowania, wszystkie procesy wykonawców powinny si poprawnie zako«czy. Nie musimy natomiast przejmowa si sprz taniem dodatkowych krotek wytworzonych podczas dziaªania algorytmu. bool koniec; int i, j, v, w; while (! tstryread("koniec")) { koniec = true; i = 0; tsfetch("liczba %d?d", i, &v); for (j = 1; j < N; ++j) { tsfetch("liczba %d?d", j, &w); if (v > w) { int tmp = v; v = w; w = tmp; koniec = false; tsput("liczba %d %d", i, v); i = j; v = w; tsput("liczba %d %d", i, v); if (koniec) { tsput("koniec"); Powy»sze rozwi zanie nie pozwala wykonawcom na wyprzedzanie si wzajemnie. Zako«czenie sortowania wymuszane jest przez pojawienie si krotki "KONIEC". Niestety jej wstawienie do przestrzeni dokonywane jest dopiero po sprawdzeniu caªego ci gu. W tym czasie wielu innych
wykonawców mogªo ju» niepotrzebnie zacz kolejny przebieg. Nie b dziemy starali si tego wyeliminowa, poniewa» sortowanie b belkowe generalnie nie jest najefektywniejsz metod sortowania. 3 Zadanie 3: Problem hetmanów Problem hetmanów polega na rozmieszczeniu N hetmanów na szachownicy N N tak, aby»aden hetman nie mógª zbi innego zgodnie z zasadami gry w szachy. Celem zadania jest napisanie algorytmu wspóªbie»nego znajduj cego wszystkie rozwi zania tego problemu. Algorytm ma do dyspozycji pewn liczb nierozró»nialnych procesów. Wszystkie wygenerowane przez nie odpowiedzi powinny by umieszczone w przestrzeni krotek. Pojedyncza odpowied¹ powinna zawiera tablic z ustawieniem wszystkich hetmanów. W rozwi zaniu mo»na skorzysta z funkcji bool konikt(int w1, int k1, int w2, int k2), która informuje, czy hetman z pola (w1, k1) bije hetmana stoj cego na (w2, k2), gdzie w1 i w2 to numery wierszy a k1 i k2 to numery kolumn. Procesy realizuj ce algorytm nie musz si ko«czy. W naszym rozwi zaniu procesy b d realizowa zlecenia, które s opisane przez krotki w formacie "ZLECENIE %d[%d] %d %d" i odpowiadaj cz ±ciowym rozwi zaniom problemu. Pierwszy element takiej krotki to n-elementowa tablica (0 n < N) liczb caªkowitych z zakresu 0... N 1, której i-ty element (0 i < n) to indeks wiersza hetmana ustawionego w i-tej kolumnie. Innymi sªowy, krotka odpowiada cz ±ciowemu rozwi zaniu, w którym hetmani zostali ju» umieszczeni w n pierwszych kolumnach. Drugi i trzeci element krotki, natomiast, to indeks odpowiednio pierwszego i ostatniego wiersza w i + 1-szej kolumnie, w którym mo»na próbowa umie±ci hetmana, aby otrzyma rozwi zanie dla n + 1 hetmanów. Zakªadamy,»e pocz tkowo przestrze«krotek zawiera pojedyncz krotk, której pierwszym elementem jest 0-elementowa tablica, drugim elementem jest liczba 0, a trzecim liczba N 1. #dene GRANULARNOSC 4 / liczba równa co najmniej 1 / int t[ N]; / cz ±ciowe rozwi zanie / int n; / liczba hetmanów w cz ±ciowym rozwi zaniu / int pw, ow; / pierwszy i ostatni wiersz do sprawdzenia / tsfetch("zlecenie?d[?d]?d?d", &n, t, &pw, &ow); if (ow pw + 1 > GRANULARNOSC) { int sw = (pw + ow) / 2; tsput("zlecenie %d[%d] %d %d", n, t, pw, sw); tsput("zlecenie %d[%d] %d %d", n, t, sw + 1, ow); else { for (int w = pw; w <= ow; ++w) { / to sprawdzenie te» mo»na próbowa zrównolegli, / / ale na potrzeby zaj darujemy sobie to / bool konf = false; for (int k = 0; k < n &&!konf; ++k) konf = konikt(w, n, k, t[k ]); if (!konf) { t[n] = w; if (n < N 1) / cz ±ciowe rozwi zanie / tsput("zlecenie %d[%d] %d %d", n + 1, t, 0, N 1); else / peªne rozwi zanie / tsput("rozwiazanie %d[%d]", N, t); / if! konf / / for w / / if / while (1); / process /
4 Zastanów si, jak wykorzystuj c dodatkowy proces koordynatora sprawi, aby procesy realizuj ce algorytm (w tym koordynator) si sko«czyªy. Zadanie 4: Problem jedz cych lozofów Zakªadamy,»e mamy N lozofów. Filozofowie s rozró»nialni ka»dy ma swój indeks z przedziaªu 0... N 1. Przestrze«krotek natomiast zawiera N krotek odpowiadaj cym widelcom w formacie "WIDELEC \%d", gdzie \%d przyjmuje warto±ci z przedziaªu 0... N 1. Rozwa»my rozwi zanie z procesem lokaja, który b dzie przyjmowaª zgªaszaj cych si lozofów, decyduj c, kiedy pozwoli usi ± im przy stole. enum { GLODNY, / lozof zgªaszaj cy si do lokaja chce usi ± / NAJEDZONY / lozof zgªaszaj cy si do lokaja chce wsta / ; process lokaj() { int wolnemiejsca = N 1; / dowlona warto± od 1 do N 1 / int kto; / indeks zgªaszaj cego si lozofa / int co; / czego chce zgªaszaj cy si lozof / if (wolnemiejsca > 0) { tsfetch("zgšoszenie?d?d", &co, &kto); else { co = NAJEDZONY; tsfetch("zgšoszenie %d?d", co, &kto); switch (co) { case GLODNY: wolnemiejsca; tsput("zgoda %d", kto); break; case NAJEDZONY: ++wolnemiejsca; break; while (1); tsput("zgšoszenie %d %d", GLODNY, i); tsfetch("zgoda %d", i); tsput("zgšoszenie %d %d", NAJEDZONY, i); while (1); Które z operacji tsput w procesie lozofa mog mie inn kolejno±? Które z operacji tsfetch w procesie lozofa mog mie inn kolejno±? Kiedy najwcze±niej mo»na wykona tsput na krotce informuj cej,»e lozof jest NAJEDZONY?
Wad tego rozwi zania jest to,»e dost p do stoªu odbywa si sekwencyjnie lokaj wpuszcza lozofów jednego po drugim. Spróbujmy zwi kszy wspóªbie»no± rozwi zania zast puj c lokaja pul biletów. Dokªadniej, zakªadamy»e pocz tkowo w przestrzeni krotek znajduje si M nierozró»nialnych biletów, gdzie M {1... N, to jest krotek o formacie "BILET". Wtedy proces lozofa mo»e wygl da nast puj co. tsfetch("bilet"); tsput("bilet"); while (1); Krotki biletów zwi kszaj wspóªbie»no±, ale stanowi dodatkowy narzut pami ciowy. Mo»emy si ich pozby, zmieniaj c schemat, wedªug którego lozofowie podnosz widelce. if (i % 2 == 0) { else { while (1); Które z rozwi za«b dzie najefektywniejsze przy parzystej liczbie lozofów, ka»dy wykonuj cy si z t sam pr dko±ci? 5