Cz ± II Podziaª pracy 1 Tablica sortuj ca Kolejka priorytetowa to struktura danych udost pniaj ca operacje wstawienia warto±ci i pobrania warto±ci minimalnej. Z kolejki liczb caªkowitych, za po±rednictwem funkcji void wstaw ( int x ) ; int usu«min( int i ) ; korzystaj procesy: process P[ id : 1..K] { int x ; wstaw ( x ) ; x = usu«min( id ) ; Zakªadamy,»e próba pobrania elementu z kolejki pustej lub wstawienia do kolejki peªnej powinna powodowa zawieszenie procesu w oczekiwaniu na mo»- liwo± wykonania tej operacji. Zrealizuj kolejk priorytetow liczb caªkowitych przechowuj c maksymalnie N elementów. Implementacja powinna si skªada z funkcji wstaw i usu«min oraz tablicy poª czonych w ruroci g procesów pomocniczych, przechowuj cych po jednej liczbie. Rozwi zanie process P[ id : 1..K] { int x ; wstaw ( x ) ; x = usu«min( id ) ; void wstaw ( int x ) { send Q[ 1 ]. x ; int usu«min( int i ) { int x ; send Q[ 1 ]. daj ( i ) ; receive x ; return x ; 1
process Q[ id : 1..N] { int i l e = 0 ; int moja, nowa, k ; while ( true ) select { i f 2 Firma ( i l e < N id + 1) on nowa i f (++ i l e == 1) moja = nowa ; else { i f ( moja > nowa ) { int s = moja ; moja = nowa ; nowa = s ; send Q[ id + 1 ]. nowa ; i f ( i l e > 0) on daj ( k ) { i f ( id == 1) send P[ k ]. moja ; else send Q[ k ]. moja ; i f ( i l e > 0) { send Q[ id + 1 ]. daj ( id ) ; receive moja ; W pewnej rmie pracuje N pracowników. Poziom umiej tno±ci ka»dego z nich jest wyra»ony dodatni liczb caªkowit, któr pracownik poznaje, wywoªuj c funkcj int mó jpoziom ( ) ; Firma obsªuguje zlecenia K klientów, reprezentowane przez warto±ci typu zlecenie. Jedno zlecenie jest wykonywane przez grup pracowników, których suma poziomów umiej tno±ci jest równa co najmniej P > 0, a poziom ka»dego pracownika jest mniejszy od P. Pracownicy przydzieleni do zlecenia wykonuj je sekwencyjnie, zgodnie z kolejno±ci, w jakiej zgªaszali si do pracy, wywoªuj c funkcj void przetw ó rz ( z l e c e n i e &z ) ; Pierwszy pracownik dostaje zlecenie od klienta i, po przetworzeniu, przekazuje je dalej. Ostatni pracownik, po odebraniu i przetworzeniu zlecenia, oddaje je klientowi. Klient wykonuje algorytm podany w rozwi zaniu. Firma chce obsªu»y jak najwi cej zlece«klientów, w zwi zku z czym gorliwy pracownik mo»e uczestniczy parokrotnie w przetwarzaniu jednego zlecenia. Zapisz tre± procesów Pracowników oraz Firmy zarz dzaj cej ich prac. Rozwi zanie 2
type z l e c e n i e ; void i n i c j u j ( z l e c e n i e &z ) ; void konsumuj ( z l e c e n i e z ) ; int mó jpoziom ( ) ; void przetw ó rz ( z l e c e n i e &z ) ; process Klient [ id : 1..K] { z l e c e n i e z ; int pierwszy ; i n i c j u j ( z ) ; send Firma. zg ª o s z e n i e K l i e n t a ( id ) ; receive pierwszy ; send Pracownik [ pierwszy ]. z ; receive z ; konsumuj ( z ) ; process Pracownik [ id : 1..N] { z l e c e n i e z ; int komu ; bool j e s t O s t a t n i ; int poziom = mó jpoziom ( ) ; send Firma. zg ª oszeniepracownika ( id, poziom ) ; receive (komu, j e s t O s t a t n i ) ; receive z ; przetw ó rz ( z ) ; i f ( j e s t O s t a t n i ) send Klient [ komu ]. z ; else send Pracownik [ komu ]. z ; process Firma { // w e r s j a b a r d z i e j wspó ª b i e» na int suma, nk, np, poziom, pierwszy ; suma = 0 ; poprzedni = 0 ; // b r a k pracownika nk = 0 ; // b r a k k l i e n t a while ( ( suma < P) && ( nk == 0 ) ) { select { i f ( nk == 0) on zg ª o s z e n i e K l i e n t a ( nk ) { i f ( poprzedni!= 0) send Klient [ nk ]. pierwszy ; i f ( suma < P) on zg ª oszeniepracownika (np, poziom ) { suma += poziom ; i f ( poprzedni == 0) { // p i e r w s z y pracownik 3
pierwszy = np ; i f ( nk > 0) send Klient [ nk ]. pierwszy ; else send Pracownik [ poprzedni ]. ( np, f a l s e ) ; poprzedni = np ; send Pracownik [ poprzedni ]. ( nk, true ) ; // o s t a t n i process Firma { // w e r s j a z e s z ª oroczna int suma, nk, np, poziom ; // (» ywcem z Ady ) suma = 0 ; poprzedni = 0 ; receive zg ª o s z e n i e K l i e n t a ( nk ) ; while ( suma < P) { receive zg ª oszeniepracownika (np, poziom ) ; suma += poziom ; i f ( poprzedni == 0) { send Klient [ nk ]. np ; else send Pracownik [ poprzedni ]. ( np, f a l s e ) ; poprzedni = np ; send Pracownik [ poprzedni ]. ( nk, true ) ; 3 Gra w ycie Gra w ycie (ang. Life) to automat komórkowy w dwuwymiarowym ±wiecie. Komórki zorganizowane s w torus, który ma W > 1 wierszy o numerach 0.. W 1 i K > 2 kolumn o numerach 0.. K 1. Zakªadamy,»e W i K s parzyste. Przyjmujemy,»e komórka o wspóªrz dnych (a, b) s siaduje z komórk (c, d), je±li a i c ró»ni si, modulo W, nie wi cej ni» o 1 oraz b i d ró»ni si, modulo K, nie wi cej ni» o 1. Z ka»d komórk s siaduje wi c osiem innych. Komórki moga by w jednym z dwóch stanów»ywe lub martwe. Š czny stan wszystkich komórek ±wiata nazywamy generacj. W kolejnej generacji komórka jest»ywa wtedy i tylko wtedy, gdy: w poprzedniej generacji byªa»ywa i miaªa dwóch lub trzech»ywych s siadów albo, w poprzedniej generacji byªa martwa i miaªa trzech»ywych s siadów. Proces ycie czyta pocz tkow generacj. Nast pnie, korzystaj c z tablicy procesów Komórka, wyznacza generacj numer N i wypisuje j. Podaj tre± procesów Komórka przy zaªo»eniu,»e proces ycie wykonuje algorytm podany w rozwi zaniu. 4
Rozwi zanie void c z y t a j ( bool [ ] [ ] &± wiat ) ; void p i s z ( bool [ ] [ ] ± wiat ) ; process y c i e { bool [ ] [ ] ± wiat ; int i, j, ai, a j ; c z y t a j ( ± wiat ) ; for ( i = 0 ; i < W; ++i ) for ( j = 0 ; j < K; ++j ) send Komó rka [ i ] [ j ]. ± wiat [ i ] [ j ] ; for ( i = 0 ; i < W K; ++i ) { bool x ; receive ( ai, aj, x ) ; ± wiat [ a i ] [ a j ] = x ; p i s z ( ± wiat ) ; int wymien ( int di, int dj, int e, bool w) { int z = 0 ; for ( int y = 0 ; y < 2 ; ++y ) for ( int s = 0 ; s < 4 ; ++s ) i f ( y == e ) { // j a n a j p i e r w wysy ªam send Komó rka [ ( i + di + W) % W] [ ( j + dj + K) % K]. w; int d = di ; di = dj ; dj = d ; else { // a j a n a j p i e r w odbieram bool x ; receive x ; i f ( x ) ++z ; return z ; process Komó rka [ i : 0..W 1][ j : 0..K 1] { bool w; receive w; for ( int g = 0 ; g < N; ++g ) { int z = wymien (1, 0, ( i + j ) % 2, w) ; z += wymien (1, 1, i % 2, w) ; w = ( z == 3) ( z == 2 && w) ; send y c i e. ( i, j, w) ; 5
4 Mno»enie macierzy System skªadaj cy si z procesu Serwer oraz N > 0 procesów Pracownik liczy kwadraty wczytywanych macierzy rozmiaru K x K, gdzie K > 1 i K K <= N. Proces Serwer dziaªa w niesko«czonej p tli. Wczytuje w niej, funkcj void c z y t a j ( f l o a t [ ] [ ] &m) ; macierz M o rozmiarze K x K. Zgªaszaj cym si do niego procesom Pracownik przekazuje po jednym elemencie macierzy M. Nast pnie odbiera od nich elementy kwadratu macierzy M i, po zebraniu wszystkich, wypisuje wynik funkcj void p i s z ( f l o a t [ ] [ ] m) ; Pracownik, równie» w niesko«czonej p tli, odpoczywa wykonuj c void wª asnesprawy ( ) ; a nast pnie zgªasza Serwerowi gotowo± wykonania oblicze«. Otrzymuje od niego jeden element macierzy M, z wiersza i, kolumny j a od pozostaªych pracowników zdobywa wszystkie elementy z tego wiersza i kolumny. Nast pnie liczy warto± z wiersza i kolumny j w macierzy wynikowej i przekazuje j do Serwera. Zapisz tre±ci procesów Serwer i Pracownik. Postaraj si zminimalizowa rozmiar pami ci ka»dego z procesów, liczb przesyªanych komunikatów i ich rozmiar. Rozwi zanie #define N 1000 #define K 20 void wª asnesprawy ( ) ; void c z y t a j ( f l o a t [ ] [ ] &m) ; void p i s z ( f l o a t [ ] [ ] m) ; void r o z d a j ( ) { int i, j, n ; int o s t a t n i W i e r s z [K] ; int ostatniakolumna [K] ; int poprzedni [K] ; for ( i = 0 ; i < K; ++i ) { receive zg ª aszamsi (n ) ; o s t a t n i W i e r s z [ i ] = poprzedni [ i ] = n ; for ( i = 0 ; i < K 1 ; ++i ) receive zg ª aszamsi ( ostatniakolumna [ i ] ) ; ostatniakolumna [K 1 ] = o s t a t n i W i e r s z [K 1 ] ; for ( i = K 2 ; i >= 0 ; i ) { poprzedni [K 1 ] = ostatniakolumna [ i ] ; for ( j = K 2 ; j >= 0 ; j ) { receive zg ª aszamsi (n ) ; send Pracownik [ n ]. ( i, j, poprzedni [ j ], poprzedni [ j + 1 ], m[ i ] [ j ] ) ; poprzedni [ j ] = n ; 6
send Pracownik [ ostatniakolumna [ i ] ]. ( i, K 1, n, ostatniakolumna [ i + 1 ], m[ i ] [K 1 ] ) ; for ( j = 0 ; j < K 1 ; ++j ) send Pracownik [ o s t a t n i W i e r s z [ j ] ]. ( K 1, j, poprzedni [ j ], o s t a t n i W i e r s z [ j + 1 ], m[k 1 ] [ j ] ) ; send Pracownik [ o s t a t n i W i e r s z [K 1 ] ]. (K 1, K 1, poprzedni [K 1 ], poprzedni [ 0 ], m[k 1 ] [K 1 ] ) ; process Serwer { f l o a t [ ] [ ] m; c z y t a j (m) ; r o z d a j (m) ; for ( int i = 0 ; i < K K; ++i ) { int ai, a j ; f l o a t w; receive ( ai, aj, w) ; m[ a i ] [ a j ] = w; p i s z (m) ; process Pracownik [ n : 1..N] { int i, j, ni, nj ; f l o a t moja ; f l o a t [ ] wiersz, kolumna ; bool mamwiersz, mamkolumn ; wª asnesprawy ( ) ; send Serwer. zg ª aszamsi (n ) ; receive ( i, j, ni, nj, moja ) ; i f ( i == 0) { f l o a t nowakolumna [K] ; nowakolumna [ 0 ] = moja ; send Pracownik [ nj ]. budowanakolumna ( nowakolumna ) ; i f ( j == 0) { f l o a t nowywiersz [K] ; nowywiersz [ 0 ] = moja ; send Pracownik [ ni ]. budowanywiersz ( nowywiersz ) ; mamwiersz = f a l s e ; mamkolumn = f a l s e ; while (! ( mamwiersz && mamkolumn ) ) select { on budowanywiersz ( w i e r s z ) { 7
w i e r s z [ j ] = moja ; i f ( j < K 1) { send Pracownik [ nj ]. budowanywiersz ( w i e r s z ) ; else send Pracownik [ nj ]. gotowywiersz ( w i e r s z ) ; on budowanakolumna ( kolumna ) { kolumna [ i ] = moja ; i f ( i < K 1) { send Pracownik [ ni ]. budowanakolumna ( kolumna ) ; else send Pracownik [ ni ]. gotowakolumna ( kolumna ) ; on gotowywiersz ( w i e r s z ) { mamwiersz = true ; i f ( j < K 1) send Pracownik [ nj ]. gotowywiersz ( w i e r s z ) ; on gotowakolumna ( kolumna ) { mamkolumn = true ; i f ( i < K 1) send Pracownik [ ni ]. gotowakolumna ( kolumna ) ; wynik = 0. 0 ; for ( int p = 0 ; p < K; ++p) wynik += w i e r s z [ p ] kolumna [ p ] ; send Serwer. ( i, j, wynik ) ; 8