71
Sveučilište u Split, Prirodoslovno – matematički fakultet PARALELNO PROGRAMIRANJE: ZBIRKA RIJEŠENIH ZADATAKA PRIPREMILI: TONĆI DADIĆ I MARIN AGLIĆ ČUVIĆ RADNA VERZIJA ZBIRKE RIJEŠENIH ZADATAKA ZA POTREBE KOLEGIJA PARALELNO PROGRAMIRANJE 17.07.2016. Dopunjeno: 08.09.2016.

PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Embed Size (px)

Citation preview

Page 1: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

P A RA L EL N O P RO G RA M I RA N JE : Z B I RKA R I J EŠ EN I H Z A D A TA KA

PRI PRE MI L I : TON ĆI DA D IĆ I M ARI N AG LI Ć ČU VI Ć

RADN A VERZ I JA Z B IRKE RI JEŠENI H Z ADA T AKA ZA PO T REBE K OLE GI JA P AR A LELN O PR OGR A MI RA N JE

17.07.2016.

Dopunjeno: 08.09.2016.

Page 2: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

SADRŽAJ

Uvod ............................................................................................................................................ 1

Model dijeljene memorije (TPL) .................................................................................................. 2

1. Zadatak ................................................................................................................................ 3

RJEŠENJE .................................................................................................................................................. 3

2. Zadatak ................................................................................................................................ 6

RJEŠENJE .................................................................................................................................................. 6

3. Zadatak ................................................................................................................................ 7

RJEŠENJE .................................................................................................................................................. 7

4. Zadatak .............................................................................................................................. 10

RJEŠENJE ................................................................................................................................................ 10

Podaci.cs ............................................................................................................................................ 10

Program.cs ......................................................................................................................................... 11

5. Zadatak .............................................................................................................................. 14

RJEŠENJE ................................................................................................................................................ 14

6. Zadatak .............................................................................................................................. 15

RJEŠENJE ................................................................................................................................................ 15

7. Zadatak .............................................................................................................................. 18

RJEŠENJE ................................................................................................................................................ 18

8. Zadatak .............................................................................................................................. 20

RJEŠENJE ................................................................................................................................................ 20

9. Zadatak .............................................................................................................................. 25

RJEŠENJE ................................................................................................................................................ 25

10. Zadatak .......................................................................................................................... 27

RJEŠENJE ................................................................................................................................................ 27

11. Zadatak .......................................................................................................................... 31

RJEŠENJE ................................................................................................................................................ 31

12. Zadatak .......................................................................................................................... 34

RJEŠENJE ................................................................................................................................................ 34

13. Zadatak .......................................................................................................................... 38

RJEŠENJE ................................................................................................................................................ 38

Model slanja poruka (Message Passing Interface - MPI) ............................................................ 40

1. Zadatak .............................................................................................................................. 41

RJEŠENJE ................................................................................................................................................ 41

2. Zadataka ............................................................................................................................ 44

RJEŠENJE ................................................................................................................................................ 44

3. Zadatak .............................................................................................................................. 46

RJEŠENJE ................................................................................................................................................ 46

Page 3: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

4. Zadatak .............................................................................................................................. 50

RJEŠENJE ................................................................................................................................................ 50

5. Zadatak .............................................................................................................................. 52

RJEŠENJE ................................................................................................................................................ 53

6. Zadatak .............................................................................................................................. 56

RJEŠENJE ................................................................................................................................................ 56

7. Zadatak .............................................................................................................................. 60

RJEŠENJE ................................................................................................................................................ 60

8. Zadatak .............................................................................................................................. 63

RJEŠENJE ................................................................................................................................................ 63

9. Zadatak .............................................................................................................................. 67

RJEŠENJE ................................................................................................................................................ 67

Page 4: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

1

UVOD

Ova zbirka riješenih zadataka se sastoji od većine zadataka prikupljenih iz kolokvija i ispitnih rokova

koje su studenti pisali u akademskoj godini 2015./2016. Rješenja zadataka su prikupljena rješenja

profesora, asistenta i studenata. Studentska rješenja su provjerena te ispravljena u slučaju da se

tokom provjere ustanovila neka pogreška.

Zbirka se sastoji od dva osnovna dijela koja odgovaraju kolokvijima koje studenti pišu: Model dijeljene

memorije (uz pomoć Task Parallel Library-a) i model slanja poruka (uz pomoć Message Passing

Interface-a). Sva rješenja su dana u C# kodu. Od studenata se očekuje da su upoznati s osnovama C#-a,

objektno orijentiranog programiranja te strukturama podataka i algoritmima u C#-u.

Page 5: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

2

M O DEL D I JEL JEN E M E M O RI JE ( TP L )

Page 6: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

3

1. ZADATAK

Za ovaj zadatak dobili ste mapu Zadatak-1. Vaš zadatak je napraviti program koji će izgenerirati

kolekciju s N slučajnih brojeva u rasponu [0, 100>. Nakon toga će stvoriti X task-ova koji će te brojeve

preraspodijeliti u 3 druge kolekcije. U jednu će ići svi parni brojevi, u drugu će ići svi prosti (bez broja

2), a u treću svi ostali elementi. Nakon što se program izvrši, ove tri kolekcije moraju sadržavati

odgovarajuće elemente te suma broja elemenata u te tri kolekcije zajedno mora biti jednaka N.

Zahtjevi:

a. Kolekcije koje imate na raspolaganju su: ConcurrentStack, ConcurrentBag, ConcurrentQueue, ConcurrentDictionary;

b. N i X moraju biti deklarirani unutar Main metode; c. Odabranu kolekciju morate izgenerirati u posebnoj metodi kojoj će to biti povratna

vrijednost. Izgeneriraj mora primiti broj N koji će kazati koliko elemenata je potrebno izgenerirati.

d. Metoda Razdvoji prima odabranu kolekciju kao parametar i X koji predstavlja broj Task-ova. Metoda Razdvoji stvara X task-ova koji izvlače elemente iz poslane kolekcije te ih razvrstavaju u gore navedene tri. Sve tri kolekcije zajedno na kraju moraju sadržavati sve elemente originalne kolekcije.

Ispišite: elemente kolekcije s parnim brojevima, zatim one s prostim, a nakon nje one s ostalim

elementima. Ispišite koliko elemenata ove tri kolekcije imaju zajedno.

RJEŠENJE

using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Zadatak_1 { class Program { private const int par = 0; private const int prim = 1; private const int ostali = 2; private static ConcurrentQueue<int> Izgeneriraj(int N) { ConcurrentQueue<int> q = new ConcurrentQueue<int>(); Random rnd = new Random(); for (int i = 0; i < N; i++) { q.Enqueue(rnd.Next(1, 100)); } return q; } private static bool IsPrim(int n) {

Page 7: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

4

if (n == 2) return true; for (int k = 2; k < (int)Math.Sqrt(n); k++) { if (n % k == 0) return false; } return true; } private static ConcurrentQueue<int>[] Razdvoji(ConcurrentQueue<int> input, int nTasks) { ConcurrentQueue<int>[] ret = new ConcurrentQueue<int>[3]; for (int i = 0; i < 3; i++) { ret[i] = new ConcurrentQueue<int>(); } List<Task> tasks = new List<Task>(); for (int i = 0; i < nTasks; i++) { Task t = Task.Factory.StartNew(() => { while (input.Count > 0) { int n; if (input.TryDequeue(out n)) { if (n % 2 == 0) { ret[par].Enqueue(n); } else if (IsPrim(n)) { ret[prim].Enqueue(n); } else { ret[ostali].Enqueue(n); } } } } ); tasks.Add(t); } Task.WaitAll(tasks.ToArray<Task>()); return ret; } static void Main(string[] args) { int N = 100; int X = 10; ConcurrentQueue<int> gen = Izgeneriraj(N); ConcurrentQueue<int>[] res = Razdvoji(gen, X);

Page 8: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

5

int M = res[0].Count + res[1].Count + res[2].Count; Console.WriteLine("Ukupni Broj elemenata: {0}", M); for (int i = 0; i < 3; i++) { int n; while (res[i].Count > 0) { if (res[i].TryDequeue(out n)) { Console.Write("{0} ", n); } } Console.WriteLine(); } Console.ReadLine(); } } }

Page 9: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

6

2. ZADATAK

Za ovaj zadatak dobili ste mapu Zadatak-2. Na raspolaganju imate biblioteku sa SumPrefix algoritmom

koja sadrži metode Reduce, DownSweep i Prescan. Iskoristite SumPrefix algoritam za pronaći najmanji

zajednički višekratnik niza brojeva. Ocijenite složenost algoritma uzimajući da je složenost algoritma

pronalaska najmanjeg zajedničkog višekratnika za dva broja O(1). Niz mora biti veličine potencije broja

2.

HINT: Najmanji zajednički višekratnik za dva broja se može dobiti formulom |𝑎∗𝑏|

gcd(𝑎,𝑏) gdje je gcd(a, b)

najveći zajednički djelitelj brojeva a i b.

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LIB; namespace Zadatak_2 { class Program { private static int Nzd(int x, int y) { int ret = 1; for (int k = 1; k <= (int)Math.Min(x, y); k++) { if (x % k == 0 && y % k == 0) ret = k; } return ret; } static void Main(string[] args) { int[] P = new int[] { 2, 4, 6, 12, 30, 40, 60, 120}; SumPrefixIdeal<int> spi = new SumPrefixIdeal<int>(P); int zm = spi.Reduce((x, y) => { return x * y / Nzd(x, y); } ); // Vremenska složenost O(log(P.Length)) Console.WriteLine("zm = {0}", zm); Console.ReadLine(); } } }

Page 10: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

7

3. ZADATAK

Za ovaj zadatak dobili ste mapu Zadatak-3. Na raspolaganju imate biblioteku sa SumPrefix algoritmom

koja sadrži metode Reduce, DownSweep i Prescan. Ove metode koristite prilikom izrade svoje metode

SelektirajParne koja će vratiti novi niz koji sadrži samo parne elemente originalnog niza te mu je

veličina jednaka broju parnih elemenata iz originalnog niza. Redoslijed kojim se parni elementi

pojavljuju u nizu ne smije biti promijenjen. U nizu se nalaze isključivo prirodni brojevi.

Npr.

Ulaz:

Izlaz:

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LIB; namespace Zadatak_3 { class Program { /// <summary> /// Kopira polje a paralelnon na N procesora. /// Vremenska složenost: O(1) (uz N = a.Length) /// </summary> /// <param name="a">Ulazno polje koje se kopira</param> /// <param name="N">Broj procesora</param> /// <returns>Potpuna kopija ulaznog polja</returns> private static int[] Copy(int[] a, int N) { int[] ret = new int[a.Length]; List<Task> tasks = new List<Task>(); for (int i = 0; i < N; i++) { Task t = Task.Factory.StartNew((object obj) => { int index = (int)obj; ret[index] = a[index]; }, i); tasks.Add(t); } Task.WaitAll(tasks.ToArray<Task>()); // Barijera: sinkronizacija zadataka return ret; } /// <summary>

1 2 3 4 6 8 7 10

2 4 6 8 10

Page 11: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

8

/// Postavlja indikatore parnosti u polje R: /// Ako je P[index] paran onda je R[index] jednak 1 inače je 0. /// V. složenost: O(1) /// </summary> /// <param name="P">Ulazno polje</param> /// <param name="R">Polje indikatora parnosti</param> /// <param name="N">Broj procesora</param> private static void PostaviIndikatoreParnosti(int[] P, int[] R, int N) { // Ako je P[index] paran onda je R[index] 1 inače je 0. List<Task> tasks = new List<Task>(); for (int i = 0; i < N; i++) { Task t = Task.Factory.StartNew((object obj) => { int index = (int)obj; if (P[index] % 2 == 0) { R[index] = 1; // paran broj -> indikator = 1 } else { R[index] = 0; // neparan broj -> indikator = 0 } }, i); tasks.Add(t); } Task.WaitAll(tasks.ToArray<Task>()); // Barijera: sinkronizacija zadataka } /// <summary> /// Postavlja parne brojeve u rezultat onim redom kako se nalaze u ulaznom polju: /// ako je R[index] == 1 onda S[Q[index]] = P[index]; /// V. složenost: O(1) /// </summary> /// <param name="P">ulazno polje</param> /// <param name="R">indikatori parnih brojeva</param> /// <param name="Q">indeksi u polju rezultata</param> /// <param name="S">polje rezultata</param> /// <param name="N">broj procesora</param> private static void PostaviParneURezultat(int[] P, int[] R, int[] Q, int[] S, int N) { List<Task> tasks = new List<Task>(); for (int i = 0; i < N; i++) { Task t = Task.Factory.StartNew((object obj) => { int index = (int)obj; if (R[index] == 1) { S[Q[index]] = P[index]; // paran broj -> indikator = 1 } }, i); tasks.Add(t); } Task.WaitAll(tasks.ToArray<Task>()); // Barijera: sinkronizacija zadataka }

Page 12: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

9

static void Main(string[] args) { int[] P = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }; // dužina niza = potencija broja 2 int N = P.Length; // Broj procesora = dužina niza int[] R = new int[P.Length]; // indikatori: 1 = paran, 0 = neparan PostaviIndikatoreParnosti(P, R, N); // O(1) // Ne traži se, ali pomaže vlastitom razmišljanju Console.WriteLine("P = {0}", Helper<int>.WriteArray(P)); Console.WriteLine("R = {0}", Helper<int>.WriteArray(R)); // sačuvati R int[] Q = Copy(R, N); // O(1) SumPrefixIdeal<int> spi = new SumPrefixIdeal<int>(Q); int nParnih = spi.Prescan((x, y) => x + y, 0); // Q sada sadrži indekse odredišnog niza. O(log(P.Length)) Console.WriteLine("Q = {0}", Helper<int>.WriteArray(Q)); int[] S = new int[nParnih]; // prenošenje: PostaviParneURezultat(P, R, Q, S, N); // O(1) // Vremenska složenost: O(1 + 1 + log(P.Length) + 1) = O(log(P.Length) Console.WriteLine("S = {0}", Helper<int>.WriteArray(S)); Console.ReadLine(); } } }

Page 13: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

10

4. ZADATAK

Koristeći C#-ov TPL napravite program u kojem će se generirati dvije matrice A i B slučajnih brojeva u

rasponu [1, 10] s time da su matrice kvadratne, a broj redaka se unosi. Matrice su jednakih dimenzija,

ali se pune slučajno izgeneriranim elementima. Koristeći Task-ove napravite da se paralelno za matricu

A računa suma elemenata po redcima i za matricu B produkt elemenata po stupcima. Dva task-a koji

pokreću ove paralelne radnje zovemo glavni task-ovi. Isto tako se same sume i produkti računaju

paralelno na način da se po jedan redak matrice A da svakom Task-u koji računa sumu elemenata,

odnosno po jedan stupac matrice B da svakom Task-u koji računaju produkt elemenata. U

ConcurrentQueue spremajte izračunate sume i produkte, iz koje matrice dolaze te indeks stupca ili

retka kojem pripadaju. Preporuča se korištenje klase koja će sadržavati ove vrijednosti te da se

jednostavno u kolekciju ConcurrentQueue spremaju elementi te klase.

Preporuča se redovito pokretanje i testiranje te pristup „korak po korak“.

RJEŠENJE

PODACI.CS

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Zadatak_4 { // S obzirom na to da se očekuje da u konkurentni red spremimo više informacija: // - izračunate sume i produkti iz matrica A i B // - za matricu A se računa suma po retcima // - za matricu B se računa produkt po stupcima // - iz koje matrice sume i produkti dolaze // - indeks retka ili stupca iz kojeg dolaze class Podaci { private int broj; private int redakIliStupac; public int Broj { get { return broj; } set { broj = value; } } public int RedakIliStupac { get { return redakIliStupac; } set { redakIliStupac = value; } } private string matrica; public string Matrica { get { return matrica; } set { matrica = value; }

Page 14: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

11

} public override string ToString() { return "Broj "+broj+", redak/stupac "+redakIliStupac+", matrica "+matrica; } } }

PROGRAM.CS

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.Collections.Concurrent; namespace Zadatak_4 { class Program { // Metoda za generiranje slučajnih elemenata u rasponu [0, 10] private static void NapuniMatricu(int[,] A) { Random rnd=new Random(); for (int i = 0; i < (int)Math.Sqrt(A.Length); i++) { for (int j = 0; j < (int)Math.Sqrt(A.Length); j++) { A[i, j] = rnd.Next(1, 11); } } } // Za matricu A se računa suma po retcima // Važno je da se suma po retcima računa paralelno private static void MatricaA(int[,] A, ConcurrentQueue<Podaci> cRed, int unos) { List<Task> listaTaskova = new List<Task>(); for (int i = 0; i < unos; i++) { Task t = Task.Factory.StartNew((obj) => { int k = (int)obj; Podaci pd = new Podaci(); int suma = 0; for (int j = 0; j < unos; j++) { suma += A[k, j]; } pd.Matrica = "A"; pd.Broj = suma; pd.RedakIliStupac = k; cRed.Enqueue(pd); }, i); listaTaskova.Add(t); } Task.WaitAll(listaTaskova.ToArray());

Page 15: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

12

} // Za matricu B se računa produkt po stupcima // Važno je da se svaki stupac da po jednome tasku private static void MatricaB(int[,] B, ConcurrentQueue<Podaci> cRed, int unos) { List<Task> listaTaskova = new List<Task>(); for (int i = 0; i < unos; i++) { Task t = Task.Factory.StartNew((obj) => { int k = (int)obj; Podaci pd = new Podaci(); int produkt = 1; for (int j = 0; j < unos; j++) { produkt *= B[j, k]; } pd.Matrica = "B"; pd.RedakIliStupac = k; pd.Broj = produkt; cRed.Enqueue(pd); }, i); listaTaskova.Add(t); } Task.WaitAll(listaTaskova.ToArray()); } static void Main(string[] args) { Console.Write("Unesite broj redaka Matrice :> "); int unos = int.Parse(Console.ReadLine()); int[,] A=new int[unos, unos]; int[,] B=new int[unos, unos]; ConcurrentQueue<Podaci> cRed = new ConcurrentQueue<Podaci>(); Task[] nizTaskova=new Task[2]; NapuniMatricu(A); NapuniMatricu(B); // Računanje sume i računanje produkta se vrši paralelno // Uočite da se u metodama MatricaA i MatricaB dodatno još radi paralelno obrada redaka, odnosno // stupaca. // U ovome zadatku t1 i t2 zovemo glavnim taskovima, ali isto tako smo ih mogli nazvati "roditeljima" // Task-ove koji se stvaraju unutar mo\emo, a i ne moramo, nazvati radnicima, slugama ili "djecom" // Sama terminologija nije važna, služi samo da bi opisala nekakvu organizaciju Task-ova Task t1 = Task.Factory.StartNew(() => MatricaA(A, cRed, unos)); nizTaskova[0] = t1; Task t2 = Task.Factory.StartNew(() => MatricaB(B, cRed, unos)); nizTaskova[1] = t2; Task.WaitAll(nizTaskova); while (cRed.Count>0) { Podaci pd; if (cRed.TryDequeue(out pd)) Console.WriteLine(pd.ToString()); } Console.ReadLine();

Page 16: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

13

} } }

Page 17: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

14

5. ZADATAK

Za ovaj zadatak dobili ste mapu Zadatak-2 koja sadrži implementaciju SumPrefix algoritma. Koristeći

SumPrefix algoritam ispitajte je li u nizu jednak broj parnih i neparnih elemenata.

Implementacija mora biti potpuno paralelna, uključujući i provjeru svakog elementa niza. Ograničite se

na to da je niz veličine potencije broja 2.

RJEŠENJE

using System; using System.Collections.Generic; using System.Threading.Tasks; using LIB; namespace Zadatak_5 { class Program { private static void Parnost(int[] R, int[] P) { List<Task> listaTaskova = new List<Task>(); for (int i = 0; i < P.Length; i++) { // Paralelna provjera svakog elementa niza - je li element paran ili neparan Task t = Task.Factory.StartNew((obj) => { int k = (int)obj; R[k] = P[k] % 2 == 0 ? 1 : 0; }, i); } } static void Main(string[] args) { int[] P = { 1, 2, 3, 5, 6, 0, 9, 12 }; int[] R=new int[P.Length]; Parnost(R, P); SumPrefixIdeal<int> sumPrefix=new SumPrefixIdeal<int>(R); // Uz pomoć Reduce metode paralelno se provjerava niz -> ima li jednak broj parnih ili neparnih // elemenata int nParnih=sumPrefix.Reduce((x,y)=>x+y); Console.WriteLine("Niz {0} jednako parnih i neparnih elemenata", 2*nParnih==P.Length? "ima":"nema"); Console.ReadLine(); } } }

Page 18: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

15

6. ZADATAK

Koristeći C#-ov TPL napravite program koji će tražiti od korisnika unos broja N te pokrenuti 3 različita

Task-a. Jedan od Task-ova će svako 300 milisekundi u odabranu kolekciju dodavati N slučajno

generiranih elemenata u rasponu [1, 10]. Drugi Task mora iz odabrane kolekcije konstantno izbacivati

elemente i to K elemenata, gdje je K slučajno generirani broj koji predstavlja koliko elemenata će se u

jednom prolazu izbaciti. Treći Task ispisuje elemente kolekcije u istom redu za svaki prolaz petlje, a tek

kad je jedan prolaz petlje ispunjen ispisuje novi red. U slučaju da je red prazan, ne smije se ništa

ispisati. Kako bi Main metoda bila što kraća, zadatke koje svaki Task-ova mora izvršiti izdvojite u

posebne metode: Puni, Prazni i Printaj. Pritiskom tipke enter svi Task-ovi moraju završiti, a zatim

glavna nit na kojoj se izvršava metoda Main. Za prekid izvršavanja koristite CancellationToken. Metoda

Cancel se smije samo jednom pozvati unutar Main metode.

Primjer ispisa:

RJEŠENJE

using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; namespace Zadatak_6 { class Program { // Metode Puni, Prazni i Printaj se moraju po zadatku napraviti // CancellationToken u svakoj od metoda služi da se detektira kada je zatražen prekid // Parametar seed je sjeme za random generator private static void Puni(int n, CancellationToken ct, int seed, ConcurrentQueue<int> cq) { Random rnd = new Random(seed); // Dok nije zatražen prekid while (!ct.IsCancellationRequested) {

Page 19: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

16

// Uspavamo nit na 300 milisekundi Thread.Sleep(300); for (int i = 0; i < n; i++) { int num = rnd.Next(0, 11); cq.Enqueue(num); } } } private static void Prazni(CancellationToken ct, int seed, ConcurrentQueue<int> cq) { Random rnd = new Random(seed); while (!ct.IsCancellationRequested) { // k može biti bilo koji broj između 0 i broja elemenata int k = rnd.Next(0, cq.Count + 1); // k elemenata ćemo pokušati izbaciti for (int i = 0; i < k; i++) { // Inicijaliziramo br na neku pocetnu (bezveznu vrijednost) int br = 0; // Pokusamo izbaciti element iz kolekcije // Ako uspijemo, onda će vrijednost biti spremljena u br. // out -> radili na OOP // br vrijednost nećemo koristiti cq.TryDequeue(out br); } } } private static void Printaj(CancellationToken ct, ConcurrentQueue<int> cq) { while (!ct.IsCancellationRequested) { if (!cq.IsEmpty) { // Kontrolna varijabla koja sluzi za sprjecavanje printanja praznog reda u slucaju // da se izmedu provjere u if-u i ulaska u foreach petlju izbace svi elementi kolekcije bool printed = false; foreach (var el in cq) { printed = true; Console.Write(el + " "); } if(printed) Console.WriteLine(); } } } static void Main(string[] args) {

Page 20: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

17

Console.Write("Unesi n:> "); // Traži se unos broja n int n = int.Parse(Console.ReadLine()); ConcurrentQueue<int> cq = new ConcurrentQueue<int>(); CancellationTokenSource cts = new CancellationTokenSource(); CancellationToken ct = cts.Token; Task t1 = Task.Factory.StartNew(() => Puni(n, ct, 1, cq)); Task t2 = Task.Factory.StartNew(() => Prazni(ct, 2, cq)); Task t3 = Task.Factory.StartNew(() => Printaj(ct, cq)); // Nakon pritiska tipke <ENTER> pozvat ćemo prekid na CancellationTokenSourceu Console.ReadKey(); Console.WriteLine("Zatražen prekid..."); cts.Cancel(); Task.WaitAll(t1, t2, t3); Console.WriteLine("Prekinuto..."); // Drugim pritiskom na tipku <ENTER> izlazimo iz programa Console.Read(); } } }

Page 21: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

18

7. ZADATAK

Za ovaj zadatak dobili ste mapu Zadatak-2 koja sadrži implementaciju SumPrefix algoritma. Za slučajno

generirani niz bool vrijednosti primijenite logičke operatore AND, OR i XOR na cijeli generirani niz. XOR

napravite kao metodu koja prima dvije bool vrijednosti i vraća bool vrijednost. XOR se može zapisati

kao: (a OR b) AND NOT(a AND b). Ograničite se na to da je niz veličine potencije broja 2. Ispišite

generirani niz vrijednosti te rezultate logičkih operatora. Primjena različitih logičkih operatora se mora

izvršiti paralelno. Svi izračuni za svaki od logičkih operatora se mora izvršiti paralelno.

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LIB; namespace Zadatak_7 { class Program { private static bool Xor(bool a, bool b) { return (a || b) && !(a && b); } static void Main(string[] args) { bool[] niz = new bool[8]; Random rnd = new Random(); for(int i = 0; i < niz.Length; i++) { int br = rnd.Next(0, 10); niz[i] = br % 2 == 0; } // rekli smo vec da su operacije SumPrefix algoritma takve da mijenjaju originalni niz // Stoga moramo napraviti dovoljan broj kopija // Helper je staticka klasa u LIB-u dobivenom sa zadatkom, a Copy je pomoćna metoda za kopiranje // niza definirana u toj statickoj klasi var orNiz = Helper<bool>.Copy(niz); var andNiz = Helper<bool>.Copy(niz); var xorNiz = Helper<bool>.Copy(niz); // cilj je da sve logički operatori budu primijenjeni paralelno te da se paralelno obrade svi nizovi Task<bool> or = Task.Factory.StartNew(() => { SumPrefixIdeal<bool> sumPrefix = new SumPrefixIdeal<bool>(orNiz); // Da dobijemo rezultat primjene OR operatora na cijeli niz bool vrijednosti paralelno return sumPrefix.Reduce((x, y) => x || y);

Page 22: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

19

}); Task<bool> and = Task.Factory.StartNew(() => { SumPrefixIdeal<bool> sumPrefix = new SumPrefixIdeal<bool>(andNiz); // Da dobijemo rezultat primjene AND operatora na cijeli niz bool vrijednosti paralelno return sumPrefix.Reduce((x, y) => x && y); }); Task<bool> xor = Task.Factory.StartNew(() => { SumPrefixIdeal<bool> sumPrefix = new SumPrefixIdeal<bool>(xorNiz); // Da dobijemo rezultat primjene OR operatora na cijeli niz bool vrijednosti paralelno return sumPrefix.Reduce((x, y) => Xor(x, y)); }); // Cekamo da svaki od Task-ova zavrsi Task.WaitAll(or, and, xor); // ispisujemo originalni niz koji je nepromijenjen Console.WriteLine("\nOriginalni niz:> "); foreach(var el in niz) { Console.Write(el + " "); } Console.WriteLine(); // Ispisujemo rezultate Console.WriteLine("OR: " + or.Result); Console.WriteLine("AND: " + and.Result); Console.WriteLine("XOR: " + xor.Result); Console.ReadLine(); } } }

Page 23: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

20

8. ZADATAK

Koristeći C#-ov TPL napravite program koji će tražiti od korisnika unos broja N te pokrenuti N različitih

Task-ova. N može biti bilo koji prirodan broj. Napravite da svaki od Task-ova generira slučajne brojeve

u rasponu od [0, 100] te prekida generiranje nakon X sekundi, gdje je X slučajan broj različit za svaki

Task. Između generiranja dva broja umetnite pauzu u izvršavanju od 500 milisekundi. Za generiranje

slučajnih brojeva, sjeme Random-a mora biti različito za svaki od Task-ova i različit pri svakom

pokretanju.

Dodatni Task ispisuje one elemente koji su se pojavili u svim Task-ovima. Ovo se događa dok N Task-

ova generira brojeve.

Ukoliko se takav element nije pojavio, ispišite samo one elemente koji se najviše puta pojavljuju.

Svi Task-ovi moraju istovremeno generirati elemente.

Main se završava pritiskom tipke Enter, ali ne prije nego svi Task-ovi završe s izvršavanjem.

Za prekide izvršavanja koristite CancellationToken. Vodite računa o tome da svaki Task mora u

konačno vrijeme završiti s izvršavanjem.

NAPOMEA: Pripazite da se može dogoditi da jedan Task više puta izgenerira isti broj, ali to ne znači da ga

je svaki Task izgenerirao.

HINT: Koristite dva ConcurrentDictionarya: ConcurrentDictionary<int, ConcurrentBag<int>>.

Primjer ispisa:

SLIKA 1 GORE – POSTOJE ELEMENTI KOJI SU SE POJAVILI U SVIH N TASK-OVA. ISPOD – NE POSTOJE TAKVI

ELEMENTI.

RJEŠENJE

using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Zadatak_8 { class Program {

Page 24: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

21

// U dict konkurentnoj kolekciji dictionary ključ će biti izgenerirani broj, a vrijednost // konkurentni red u kojem će se nalaziti identifikacije za svaki task // -> na ovaj način može znati koji taskovi su izgenerirali element. private static ConcurrentDictionary<int, ConcurrentQueue<int>> dict = new ConcurrentDictionary<int, ConcurrentQueue<int>>(); // ova konkurentna kolekcija služi kao backup gornje kolekcije private static ConcurrentDictionary<int, ConcurrentQueue<int>> counting = new ConcurrentDictionary<int, ConcurrentQueue<int>>(); // metoda inače ne mora vračati ništa, ali zbog testiranja je bilo stavljeno List<int> private static List<int> Generate(CancellationToken ct, int j) { List<int> lista = new List<int>(); Random rnd = new Random(j * DateTime.Now.Millisecond); while (!ct.IsCancellationRequested) { // želimo svako 500 milisekundi izgenerirati element Thread.Sleep(500); // generiramo slučajan broj int num = rnd.Next(0, 100); // vrijednosti konkurentnog dictionarya su konkurentni redovi, stoga ih moramo // instancirati var newQueue = new ConcurrentQueue<int>(); // u red dodamo identifikaciju trenutnog taska newQueue.Enqueue(j); // u konkurentni dictionary pokušavamo dodati za ključ neki element // u slučaju da on ne postoji dodati će se skupa s newQueue konkurentnim redom koji je gore // kreiran i ispunjen identifikatorom trenutnog taska dict.AddOrUpdate(num, newQueue, (x, y) => { // ukoliko postoji element s ključem num (neki drugi task ga je npr. taman dodao), // poziva se ovaj update lambda izraz u kojem se ispituje postoji li u // vrijednosti pod tim ključem element jednak j // -> pita se nalazi se li već id trenutnog taska u kolekciji koja je vrijednost pod // ključem "num" if (!y.Contains(j)) { // ako ne postoji, to znači da je trenutni task izgenerirao broj koji je netko prije već // izgenerirao pa samo dodaj u kolekciju identifikator trenutnog taska y.Enqueue(j); } return y; }); // isto kao i za dict counting.AddOrUpdate(num, newQueue, (x, y) =>

Page 25: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

22

{ if (!y.Contains(j)) { y.Enqueue(j); } return y; }); // task u listu dodaje sve elemente koje je izgenerirao // ova lista služi samo za testiranje lista.Add(num); } return lista; } static void Main(string[] args) { Console.Write("Unesi N:> "); int n = int.Parse(Console.ReadLine()); List<Task<List<int>>> tasks = new List<Task<List<int>>>(); CancellationTokenSource ctsWatcher = new CancellationTokenSource(); CancellationToken ct = ctsWatcher.Token; for (int i = 0; i < n; i++) { int j = i; Random rnd = new Random(j); CancellationTokenSource cts = new CancellationTokenSource(); Task<List<int>> t = Task.Factory.StartNew(() => Generate(cts.Token, j)); tasks.Add(t); // nakon određenog broja sekundi će se automatski zatražiti prekid tokena cts.CancelAfter(TimeSpan.FromSeconds(rnd.Next(0, 10))); } // Task koji promatra dict kolekciju te ispisuje elemente koji su se pojavili // u svih N taskova Task<List<int>> watcher = Task.Factory.StartNew(() => { // lista repeated sadrži elemente koji su se pojavili u svim taskovima // ova lista nam nije nužno bila potrebna jer služi samo da bismo kasnije // nakon što task završi pitali postoji li element koji se pojavio u svim taskovima, a // za tu svrhu smo mogli jednostavno iskoristiti bool vrijednost List<int> repeated = new List<int>(); // dok se cancellation tokenom ne zatrazi prekid while (!ct.IsCancellationRequested) { // filtriraju se elementi koji su se pojavili u svim taskovima

Page 26: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

23

var filtered = dict.Where(x => x.Value.Count == n); foreach (var el in filtered) { Console.Write(el.Key + " "); ConcurrentQueue<int> value = new ConcurrentQueue<int>(); // u listu repeated stavljamo sve elemente koji su se pojavili u svim taskovima repeated.Add(el.Key); // ovaj task mora pokušati ukloniti element pod nekim ključem iz dict-a dict.TryRemove(el.Key, out value); } if (filtered.Any()) Console.WriteLine(); } return repeated; }); Task.WhenAll(tasks).Wait(); ctsWatcher.CancelAfter(TimeSpan.FromSeconds(1)); // rezultat watchera je lista koja sadrži sve elemente koji su se pojavili u svim taskovima // ako takav element ne postoji, ova lista će biti prazna // lista nam služi samo za ovu provjeru // u slučaju da se nijedan broj nije pojavio u svim taskovima, potrebno je ispisati // elemnte koji su se najviše puta pojavili if (!watcher.Result.Any()) { // nađemo koliko se puta pojavio element koji se pojavio u najviše task-ova // NAPOMENA: uočite da nigdje u zadatku ne brojimo višestruka pojavljivanja unutar jednog taska! Console.WriteLine("\nMaxs:> "); var max = counting.Max(x => x.Value.Count); // nađemo sve elemente koji su se pojavili max broj puta i uzmemo ih // na način da uzmemo samo ključeve iz dictionarya // uočite koji dictionary koristimo var maxs = counting.Where(x => x.Value.Count == max).Select(x => x.Key); // Ispis u jednu liniju maxs.ToList().ForEach(x => Console.Write(x + " ")); } // Prilikom testiranja otkomentira se ovaj kod //Console.WriteLine("\nTEST:"); //Test(Task.WhenAll(tasks).Result); Console.ReadLine(); }

Page 27: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

24

// Pomocna metoda za testiranje: #region za testiranje private static void Test(List<int>[] els) { Dictionary<int, int> dict = new Dictionary<int, int>(); for(int i = 0; i < els.Length; i++) { foreach(var el in els[i].Distinct()) { if (dict.ContainsKey(el)) { dict[el]++; } else { dict.Add(el, 1); } } } dict.Where(x => x.Value == els.Length).Select(x => x.Key).ToList().ForEach(Console.WriteLine); } #endregion } }

Page 28: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

25

9. ZADATAK

Za ovaj zadatak dobili ste mapu Zadatak-2. Na raspolaganju imate biblioteku sa SumPrefix algoritmom

koja sadrži metode Reduce, DownSweep i Prescan. Za zadanih 2n riječi odredite je li paran ili neparan

broj riječi s parnim brojem slova. Paralelno odredite sadrži li pojedina riječ paran broj znakova.

Iskoristite dobivenu biblioteku kako biste odredili postoji li paran ili neparan broj riječi čija je duljina

paran broj.

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LIB; namespace Zadatak_9 { class Program { public static int[] ProvjeraNiza(string[] niz) { int N = niz.Length; int[] rez = new int[N]; List<Task> tasks = new List<Task>(); for(int i=0;i< N;i++) { Task t = Task.Factory.StartNew((obj) => { // Punimo pomocni niz s jedinicama i nulama koji će nam pomoći da paralelno // odredimo koliko je parnih riječi int indeks = (int)obj; if (niz[indeks].Length % 2 == 0) rez[indeks] = 1; else rez[indeks] = 0; },i); tasks.Add(t); } Task.WaitAll(tasks.ToArray()); return rez; } static void Main(string[] args) { string[] nizRijeci = { "aaaa", "bcba", "aaaac", "aaa" }; //2 rijeci sa parnim i 2 sa neparnim brojem slova int[] ParneRijeci = ProvjeraNiza(nizRijeci); Console.WriteLine("Niz sa indeksima 1 za parne rijeci: "+Helper<int>.WriteArray(ParneRijeci));

Page 29: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

26

int[] KopiParne = Helper<int>.Copy(ParneRijeci); SumPrefixIdeal<int> spi = new SumPrefixIdeal<int>(KopiParne); int brojParnihiRijeci = spi.Reduce((a, b) => a + b); if (brojParnihiRijeci % 2 == 0) Console.WriteLine("Niz ima paran broj riječi sa parnim brojem slova. (Broj takvih riječi je "+brojParnihiRijeci+" )"); else Console.WriteLine("Niz ima neparan broj riječi sa parnim brojem slova. (Broj takvih riječi je " + brojParnihiRijeci + " )"); } } }

Page 30: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

27

10. ZADATAK

Koristeći C#-ov TPL napravite program koji će tražiti od korisnika unos broja N, gdje N / 2 označava broj

Task-ova koje zovemo roditeljima, a još N Task-ova zovemo djecom. Neka je M = N / 2 oznaka za broj

roditelja.

M stvorenih roditelja u metodi CreateAndRunChildren kreira po dva Task-a koja smatramo njihovom

djecom. Od tih dva Taska-a, jedan svako 500 milisekundi kreira 100 slučajnih brojeva u rasponu [1,

100] i ubacuje ih u kolekciju, a drugi pokušava izbaciti elemente i to na način da prvo odredi slučajan

broj K iz raspona [0, 1000], a zatim pokuša izbaciti K elemenata iz iste kolekcije. Izbačene elemente

stavlja u jednu kolekciju koja je zajednička svim ovakvim Task-ovima. Dakle, ta kolekcija je zajednička

svoj djeci koja izbacuju elemente i svi ih ubacuju u tu kolekciju.

Pritiskom tipke <ENTER> prvi put, prekida se izvršavanje SVIH Task-ova.

Nakon što svi Task-ovi završe, potrebno je odrediti koji Task je izbacio, odnosno ubacio u zajedničku

kolekciju, najviše parnih elemenata te koliko i koji su to elementi (svaku informaciju ispisati u svome

redu).

Pobrinite se da svaki Task kojemu je potreban Random, ima drugačiji seed.

Ne smijete koristiti List. Gubite bodove ako koristite Concurrent kolekcije tamo gdje vam nisu

potrebne.

RJEŠENJE

using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Zadatak_10 { class Program { // Nismo nuzno morali koristit stog // zajednička kolekcija stogova u koju taskovi stavljaju generirane elemente // to su amo reći prva "djeca" // druga "djeca" izbaucju elemente iz ovih kolekcija. // Elemente koje izbace stavljamo u kolekciju dict deklariranu ispod private static ConcurrentStack<int>[] stacks; // kolekcija koja je zajednicka svoj "djeci" koja izbacuju elemente // buduci da moramo znati koliko je parnih elemenata koje "dijete" ubacilo, odnosno izbacilo // iz gornje kolekcije, koristimo konkurentni dictionary. // svako "dijete" koje izbacuje će imati identifikator - budući da jedno "dijete" // izbacuje po "roditelju", dovoljno je koristiti identifikator "roditelja" za ključ // u dictionaryu // -> ključevi su jedinstveni identifikatori za svako opisano dijete private static ConcurrentDictionary<int, Stack<int>> dict; private static void CreateChildren(int seed, CancellationToken ct)

Page 31: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

28

{ ConcurrentStack<int> ourStack = new ConcurrentStack<int>(); // gore instancirani ourStack postavljamo kao stog na indeksu određenom sa seed stacks[seed] = ourStack; Task t1 = Task.Factory.StartNew(() => { Random rnd = new Random(seed); while (!ct.IsCancellationRequested) { Thread.Sleep(500); for (int i = 0; i < 100; i++) { // u gore instancirani stog stavljamo slučajno generirani element ourStack.Push(rnd.Next(0, 100)); } } }); Task t2 = Task.Factory.StartNew(() => { Random rnd = new Random(seed * 2); while (!ct.IsCancellationRequested) { int k = rnd.Next(0, 1000); for (int i = 0; i < k; i++) { int value = 0; // drugo "dijete" pokušava izbaciti iz stoga element if (ourStack.TryPop(out value)) { // instanciramo stog, dodamo vrijendnost varijable value u taj stog Stack<int> stack = new Stack<int>(); stack.Push(value); // u dict dodamo ključ skupa s vrijednosti (stogom) ukoliko ne postoji // ukoliko ključ postoji, zove se lambda izraz koji dodaje element value u stog dict.AddOrUpdate(seed, stack, (x, y) => { y.Push(value); return y; }); } } } }); Task.WaitAll(t1, t2); } static void Main(string[] args) { Console.WriteLine("Enter number of tasks:> ");

Page 32: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

29

int n = -1; // tražimo unos sve dok se ne unese paran broj n while (n % 2 != 0) { n = int.Parse(Console.ReadLine()); if (n % 2 != 0) { Console.WriteLine("morate unjeti paran broj"); } } int m = n / 2; // instanciramo niz konkurentnih stogova stacks = new ConcurrentStack<int>[m]; // instanciramo dictionary dict = new ConcurrentDictionary<int, Stack<int>>(); // lista za roditelje List<Task> parents = new List<Task>(); CancellationTokenSource cts = new CancellationTokenSource(); for (int i = 0; i < m; i++) { int j = i; Task parent = Task.Factory.StartNew(() => CreateChildren(j, cts.Token)); parents.Add(parent); } Console.ReadLine(); // poziv na cancel nakon prvog <ENTER> cts.Cancel(); // Cekanje da "roditelji" zavrse -> pogledajte metodu CreateChildren -> zbog Task.WaitAll // "roditelji" mogu zavrsiti tek kad "dijeca" zavrse Task.WaitAll(parents.ToArray()); // uzmi sve vrijednosti iz dict: dict.Values // filtriraj one koje su razlicite od null: .Where(x => x != null) // uzmi Max broj pojavljivanja parnih elemenata: .Max(x => x.Count(y => y % 2 == 0)) var max = dict.Values.Where(x => x != null).Max(x => x.Count(y => y % 2 == 0)); // pobjednik je prvi kojem je broj pojavljivanja parnih elemenata (u vrijednosti, Value) // jednak maksimumu: max var winner = dict.First(x => x.Value.Count(y => y % 2 == 0) == max); foreach (var el in dict) { Console.WriteLine("El " + el.Key + " :> "); el.Value.ToList().ForEach(x => Console.Write(" " + x)); Console.WriteLine("\nEl pairs:> ");

Page 33: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

30

el.Value.Where(x => x % 2 == 0).ToList().ForEach(x => Console.Write(" " + x)); Console.WriteLine("\nNum pairs:> "); Console.WriteLine(el.Value.Count(x => x % 2 == 0)); Console.WriteLine(); } Console.WriteLine("The winner:> " + winner.Key); Console.Write("Num elements:> "); Console.WriteLine(winner.Value.Count(x => x % 2 == 0)); Console.WriteLine("Elements:> "); winner.Value.Where(x => x % 2 == 0).ToList().ForEach(x => Console.Write(" " + x)); Console.ReadLine(); } } }

Page 34: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

31

11. ZADATAK

Za ovaj zadatak dobili ste mapu Zadatak-2. Na raspolaganju imate biblioteku sa SumPrefix algoritmom

koja sadrži metode Reduce, DownSweep i Prescan. Za zadanu matricu NxN odredite u kojim retcima

matrice se nalazi paran broj parnih elemenata. N je jednak 2^x gdje je x pozitivan cijeli broj. Retci se

moraju paralelno obrađivati, kao I računanje koliko parnih elemenata u svakom ima.

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LIB; namespace Zadatak_11 { class Program { static void Main(string[] args) { Console.WriteLine("unesi x"); int x = int.Parse(Console.ReadLine()); Random r = new Random(); int n = (int)Math.Pow(2.0, x); Console.Write("n {0}", n); int[][] ma = new int[n][]; for (int i = 0; i < n; i++) { ma[i] = new int[n]; for (int j = 0; j < n; j++) { ma[i][j] = r.Next(0, 10); } } int[] R = new int[n]; List<Task> tasks = new List<Task>(); int[][] ra = new int[n][]; Console.WriteLine(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { Console.Write(" " + ma[i][j]); } Console.WriteLine(); } Console.WriteLine(); for (int i = 0; i < n; i++) {

Page 35: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

32

ra[i] = new int[n]; int k = i; // napravit ćemo po task za svaki red da se paralelno odradi pretvorba u 0 i 1 za // matricu ra Task t = Task.Factory.StartNew(() => { for (int j = 0; j < n; j++) { if (ma[k][j] % 2 == 0) ra[k][j] = 1; else ra[k][j] = 0; } }); tasks.Add(t); } // cekajmo da taskovi koji su do sada kreirani zavrse Task.WaitAll(tasks.ToArray()); // Izbrisimo iz kolekcije taskove za koje znamo da su gotovi tasks.Clear(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { Console.Write(" " + ra[i][j]); } Console.WriteLine(); } int[] brojaci = new int[n]; for (int i = 0; i < n; i++) { int j = i; // Uz pomoć taska paralelno obrađujemo redove Task t = Task.Factory.StartNew(() => { int[] lop = Helper<int>.Copy(ra[j]); // uz pomoć SumPrefix algoritma paralelno zbrajamo (brojimo) elemente (uz pomoć metode Reduce) SumPrefixIdeal<int> sumPrefix = new SumPrefixIdeal<int>(lop); brojaci[j] = sumPrefix.Reduce((a, y) => a + y); }); tasks.Add(t); } Task.WaitAll(tasks.ToArray<Task>()); // Ispisimo u kojim retcima se nalazi paran broj parnih elemenata: for(int i = 0; i < brojaci.Length; i++) {

Page 36: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

33

if (brojaci[i] % 2 == 0) Console.WriteLine("Redak: " + i); } Console.ReadLine(); } } }

Page 37: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

34

12. ZADATAK

Koristeći C#-ov TPL napravite program koji će tražiti od korisnika unos brojeva M i N. Navedeni brojevi

predstavljaju dimenziju matrice koja se generira, a sastoji se od realnih brojeva u rasponu od 0 do 5.

Nazovimo ovu matricu P.

Matrica W je također dimenzija MxN te se automatski generira, ali od realnih brojeva u rasponu [0, 1].

Niz brojeva O se također generira automatski od realnih brojeva u rasponu [0, 1] te je duljine N.

Napravite program u kojemu će N niti istovremeno izračunati umnožak odgovarajućeg stupca matrice

P i odgovarajućeg stupca matrice W pri čemu je stupac matrice P transponiran kako bi množenje bilo

moguće. Rezultat umnoška će biti 1 broj. Nakon izračunatog umnoška, računa se njegova razlika s

odgovarajućim elementom niza O. Ova razlika se sprema u zajedničku kolekciju svih Task-ova.

Proširite program na način da se cijeli postupak od generiranja matrica P i niza 0 (matrica W se ne

generira ponovno) do izračuna ponovi barem 10 puta pri čemu se u zajedničku kolekciju pamte sve

razlike po iteraciji.

Na koncu ispišite sve izračunate razlike iz zajedničke kolekcije.

RJEŠENJE

using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Zadatak1 { class Program { // Metoda kojom cemo generirati matricu. Saljemo joj granice i dimenzije matrice // Svejedno je predstavili matricu stvarnim dvodimenzionalnim nizom int[,] ili // nizom nizova int[][] private static double[,] GenerateMatrix(int min, int max, int m, int n) { Random rnd = new Random(); double[,] matrica = new double[m, n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { // buduci da nema gotove metode za generiranje double brojeva unutar raspona, nisu se gubili bodovi ako // double broj nije u zadanom rasponu matrica[i, j] = Math.Round(rnd.NextDouble() * (max - min) + min, 2); // u zadatku se nije trazilo zaokruziti vrijednost, ali je lakse pratiti } }

Page 38: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

35

return matrica; } private static void PrintMatrix(double[,] matrix) { for (int i = 0; i < matrix.GetLength(0); i++) { for (int j = 0; j < matrix.GetLength(1); j++) { Console.Write(matrix[i, j] + "\t"); } Console.WriteLine(); } } static void Main(string[] args) { Rjesenje(); Console.ReadLine(); } private static void Rjesenje() { Console.WriteLine("Unesi m:> "); int m = int.Parse(Console.ReadLine()); Console.WriteLine("Unesi n:> "); int n = int.Parse(Console.ReadLine()); double[,] P = GenerateMatrix(0, 5, m, n); // ako zelimo pamtiti za svaku iteraciju (ponavljanje) sve razlike, potreban nam je dvodimenzionalni niz // ako nema ponavljanja od 10 puta, onda se koristii razlike ili razlike2 // razlike3 nije potreban ako ne radimo ponavljanja 10 puta double[,] razlike3 = new double[10, n]; // ova for petlja nije potrebna ako necemo raditi ponavljanje 10 puta for (int ponavljanje = 0; ponavljanje < 10; ponavljanje++) { double[,] W = GenerateMatrix(0, 1, m, n); double[] O = new double[n]; Random rnd = new Random(); for (int i = 0; i < n; i++) { O[i] = Math.Round(rnd.NextDouble(), 2); } // Ne moramo nuzno svaki put nanovo ispisivati matricu P, ali pomaze da vidimo sve podatke za svaku od iteracija, a uz to // je i jednostavnije promijeniti zadatak od bez iteracija do 10 iteracija (posljednja komponenta zadatka) Console.WriteLine(ponavljanje + ". Matrica P:"); PrintMatrix(P); Console.WriteLine(ponavljanje + ". Matrica W:"); PrintMatrix(W);

Page 39: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

36

Console.WriteLine(ponavljanje + ". Niz O:"); for (int i = 0; i < n; i++) { Console.Write(O[i] + "\t"); } Console.WriteLine(); // Bez ponavljanja od 10 puta List<Task> tasks = new List<Task>(); // Ako zelimo znati na kojem mjestu je koja razlika, onda necemo koristit ConcurrentBag, vec mozemo koristiti niz // pa na odgovarajuce pozicije postavljati razlike ConcurrentBag<double> razlike = new ConcurrentBag<double>(); // umjesto ConcurrentBag-a smo mogli koristiti niz double[] razlike2 = new double[n]; for (int i = 0; i < n; i++) { int j = i; // Paralelno po stupcima zelimo ici i mnoziti odgovarajuce elemente Task t = Task.Factory.StartNew(() => { double kombinacija = 0; for (int k = 0; k < m; k++) { kombinacija = kombinacija + P[k, j] * W[k, j]; } razlike.Add(kombinacija - O[j]); // na odgovarajucu poziciju stavljamo razliku odgovarajuce kombinacije i elementa niza O razlike2[j] = kombinacija - O[j]; razlike3[ponavljanje, j] = kombinacija - O[j]; }); tasks.Add(t); } Task.WaitAll(tasks.ToArray()); } /* * OVE ISPISE KORISTIMO KADA RADIMO BEZ PONAVLJANJA 10 PUTA. Ne moramo oba. Ovisi koristimo li razlike ili razlike2 ili oba * foreach (var el in razlike) { Console.Write(el + " "); } Console.WriteLine("\n\nIspravnim redosljedom: "); // foreach u jednoj liniji: razlike2.ToList().ForEach(x => Console.Write(x + "\t"));

Page 40: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

37

*/ // Ispis koji koristimo kada radimo sa 10 ponavljanja: // Ako vam je jednostavnije ispis ste mogli raditi prilikom svakog ponavljanja, niste morali nakon svih. for(int i = 0; i < 10; i++) { Console.WriteLine("Ponavljanje " + i + ":"); for(int j = 0; j < n; j++) { Console.Write(razlike3[i, j] + "\t"); } Console.WriteLine(); } Console.WriteLine(); } } }

Page 41: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

38

13. ZADATAK

Za ovaj zadatak dobili ste mapu Zadatak-2. Na raspolaganju imate biblioteku sa SumPrefix algoritmom

koja sadrži metode Reduce, DownSweep i Prescan. Matrica NxN se automatski generira paralelno po

retcima. N je potencija broja 2.

Izračunajte sumu redaka matrice te rezultate spremite u novi niz. Pri tome se suma za elemente

svakog jednog retka računa paralelno, a uz to se i sami retci paralelno obrađuju. Za novi niz paralelno

odredite broj neparnih elemenata. Ispišite niz suma i izračunati broj neparnih elemenata.

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using LIB; namespace Zadatak_2 { class Program { static void Main(string[] args) { int n = 4; int[][] matrix = new int[n][]; List<Task> tasks = new List<Task>(); for(int i = 0; i < n; i++) { int j = i; Random rnd = new Random(j * DateTime.Now.Millisecond); Task t = Task.Factory.StartNew(() => { matrix[j] = new int[n]; for(int k = 0; k < n; k++) { matrix[j][k] = rnd.Next(0, 10); } }); tasks.Add(t); } Task.WaitAll(tasks.ToArray()); int[] pomocniNiz = new int[n]; int[] sume = new int[n]; tasks.Clear(); for(int i = 0; i < n; i++) {

Page 42: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

39

int j = i; Task t = Task.Factory.StartNew(() => { SumPrefixIdeal<int> row_spi = new SumPrefixIdeal<int>(matrix[j]); sume[j] = row_spi.Reduce((x, y) => x + y); // ternarni operator pomocniNiz[j] = sume[j] % 2 == 1 ? 1 : 0; }); tasks.Add(t); } // moramo pricekati da se izracunaju sve sume Task.WaitAll(tasks.ToArray()); SumPrefixIdeal<int> spi = new SumPrefixIdeal<int>(pomocniNiz); int brNeparnih = spi.Reduce((x, y) => x + y); Console.WriteLine("Sume: "); foreach(var el in sume) { Console.Write(el + "\t"); } Console.WriteLine(); Console.WriteLine("Broj neparnih: " + brNeparnih); Console.ReadLine(); } } }

Page 43: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

40

M O DEL S LA N JA P O R UKA ( M ES S A G E P A S S IN G IN TERFA CE - M P I )

Page 44: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

41

1. ZADATAK

Na raspolaganju su vam metode Send i Recv. Napravite niz delegata koji se sastoji od sljedećih

elemenata:

1. Delegat koji prima jedan element i vraća isti taj element

2. Delegat koji prima jedan element i vraća zbroj primljenog elementa i broja 5

3. Delegat koji prima jedan element i vraća produkt tog elementa sa zbrojem tog elementa i

broja 3

Svaki proces osim procesa s rankom 0 slučajno odabire jedan delegat i njega koristi. Sjeme funkcije

random kod svih procesa mora biti različito. Proces s rankom 0 izgenerira jedan element u rasponu od

1 do 100 (1 i 100 uključeno). Proces s rankom 0 taj element šalje svom sljedbeniku koji primjeni

odabrani delegat nad tim elementom te rezultat pošalje svom sljedbeniku koji ponovno primjenjuje

svoj odabrani delegat, itd. dok se ne dođe do posljednjeg procesa. Posljednji proces stvara niz koji

sadrži konačan rezultat te ga šalje svom prethodniku. Prethodnik u niz dodaje svoj rezultat te dobiveni

niz šalje svom prethodniku, itd. dok se ne dođe do procesa s rankom 0. Proces s rankom 0 na poziciju s

indeksom 0 stavlja izgenerirani broj i u konačnici ispisuje dobiveni niz.

Npr. neka je izgeneriran broj 5 i neka su 4 procesa. Procesi s rankovima 1, 2 i 3 su redom odabrali

delegate 2, 1 i 3 (gore navedene). Proces s rankom 0 šalje element 5 procesu s rankom 1 koji primjeni

odabrani delegat 2 i dobije rezultat 10 koji šalje dalje procesu s rankom 2 koji primjeni svoj delegat,

rezultat je 10, i taj rezultat se šalje procesu s rankom 3. Rank 3 primjeni delegat 3 i dobije rezultat 130.

Rank 3 zatim stvara niz koji sadrži na zadnjoj poziciji element 130 te ga šalje ranku 2 koji dodaje

element 10 te šalje niz ranku 1 koji dodaje element 10. Rank 0 kada primi niz doda na prvu poziciju

element 5 te u konačnici ispiše niz elemenata: 5, 10, 10, 130.

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MPI; namespace Zadatak_1 { class Program { static void Main(string[] args) { using (new MPI.Environment(ref args)) { Intracommunicator comm = Communicator.world; Func<int, int> f1 = (x) => x; Func<int, int> f2 = (x) => x + 5; Func<int, int> f3 = (x) => x * (x + 3); Func<int, int>[] nizDelegata = { f1, f2, f3}; // Niz delegata if (comm.Rank == 0) { Random rnd = new Random(comm.Rank); int broj = rnd.Next(1, 11); //Smanjeno na (1, 11) jer broj postaje prevelik

Page 45: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

42

// Broj kojeg generira proces s rankom 0 comm.Send(broj, comm.Rank+1, comm.Rank); int [] niz=new int[comm.Size]; // Receive će čekati dok ne dobije odgovor od svoga prethodnika comm.Receive(comm.Rank+1, comm.Rank+1, ref niz); // na nultu poziciju stavljamo broj koji je slučajno izgeneriran niz[comm.Rank] = broj; Console.WriteLine("Rank {0}, broj {1}", comm.Rank, broj); Console.WriteLine("Ispis niza :"); foreach (var item in niz) { Console.Write(item + " "); } } // Ovo je blok koda kojeg će ivršavati predzadnji proces (s rankom n - 1) else if (comm.Rank == comm.Size - 1) { Random rnd = new Random(comm.Rank); int odabir = rnd.Next(3); // Od prethodnika primamo njegov rezultat int primljeni = comm.Receive<int>(comm.Rank - 1, comm.Rank - 1); // na primljeni element primjenjujemo odabrani delegat // variajbla broj će sadržavati rezultat primjene delegata int broj = nizDelegata[odabir](primljeni); // Kreira se niz koji ćemo morati poslati nazad prema procesu s rankom 0 // niz će sadržavati među rezultate i konačan rezultat, a u konačnici kada // dođe do procesa sa rankom 0, proces s rankom 0 će ubaciti // inicijalno izgenerirani broj int[] niz=new int[comm.Size]; // varijablu broj, tj. rezultat primjene delegata, spremamo na odgovarajuće mjesto u nizu. niz[comm.Rank] = broj; // Niz je potrebno poslati prethodniku koji mora poslati niz svome prethodniku, itd. do // procesa sa rankom 0. comm.Send(niz, comm.Rank-1, comm.Rank); Console.WriteLine("Rank {0}, odabir {1}, primljeni {2}, broj {3}", comm.Rank, odabir, primljeni, broj); } // Ovaj blok koda ce se izvrsavati za sve procese koji nisu s rankom 0 i n - 1 else { Random rnd = new Random(comm.Rank); int odabir = rnd.Next(3);

Page 46: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

43

int primljeni = comm.Receive<int>(comm.Rank-1, comm.Rank-1); int broj = nizDelegata[odabir](primljeni); comm.Send(broj, comm.Rank + 1, comm.Rank); int[] niz=new int[comm.Size]; // Od sljedbenika primamo niz s rezultatima i medurezultatima comm.Receive(comm.Rank+1, comm.Rank+1, ref niz); niz[comm.Rank] = broj; comm.Send(niz, comm.Rank - 1, comm.Rank); Console.WriteLine("Rank {0}, odabir {1}, primljeni {2}, broj {3}", comm.Rank, odabir, primljeni, broj); } } } } }

Page 47: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

44

2. ZADATAKA

Na raspolaganju su vam metode Scatter i Gather. Napravite MPI program u kojem proces s rankom 0

generira niz od N slučajnih brojeva u rasponu [1, 4], gdje je N broj procesa. Koristeći metodu Scatter

proces s rankom 0 podijeli elemente svim procesima. Procesi kada prime element x izgeneriraju novi

niz brojeva u rasponu [0, x] duljine N. Proces s rankom 0 prima uz pomoć metode Gather sve

izgenerirane nizove u matricu (niz nizova) te ga ispisuje.

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MPI; namespace Zadatak_2 { class Program { static void Main(string[] args) { using (new MPI.Environment(ref args)) { Intracommunicator comm = Communicator.world; int[] niz = new int[comm.Size]; Random rnd = new Random(comm.Rank); if (comm.Rank == 0) { for (int i = 0; i < niz.Length; i++) { niz[i] = rnd.Next(1, 5); } } // Cijeli ovaj kod sa scatterom i elementom druginiz -> dakle generiranjem niza nije potrebno // stavljati unutar if-else blok. Razmislite zasto? // Uvjerite se da uistinu razumijete razlog i da znate prepoznati kada // za neki komad koda nije potrebno provjeravati koji proces ga izvršava // Scatter-om salje elemente svim procesima ukljucujuci i sebi int x = comm.Scatter(niz, 0); // druginiz je za niz koji će proces s nekim rankom izgenerirati nakon sto primi broj int[] druginiz = new int[comm.Size]; for (int i = 0; i < druginiz.Length; i++) { druginiz[i] = rnd.Next(x + 1); } int[][] podaci=comm.Gather(druginiz, 0);

Page 48: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

45

// Dovoljno je jednom izvršiti ispis if (comm.Rank == 0) { Console.WriteLine("Ispis matrice"); foreach (var item in podaci) { foreach (var el in item) { Console.Write(el + " "); } Console.WriteLine(); } } } } } }

Page 49: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

46

3. ZADATAK

Na raspolaganju su vam metode Send i Recv. Napravite MPI program u kojem proces s rankom 0

generira niz od N elemenata u rasponu od [1, 100000], gdje je N broj pokrenutih MPI procesa.

Rank 0 šalje niz u krug (point-to-point komunikacija) te svaki proces odabire odgovarajući element iz

niza i u novom Tasku računa najveći zajednički djelitelj prvog elementa niza i odabranog elementa.

Npr. proces s rankom 2 će računati najveći zajednički djelitelj između broja koji se u nizu nalazi pod

indeksom 0 i onog koji se nalazi na indeksu 2. Proces s rankom 0 ne računa najveći zajednički djelitelj.

Proces s rankom 0 šalje u krug uređeni par vrijednosti (Tuple) – signal i kraj. Uređeni par se šalje point-

to-point komunikacijom i na prvome mjestu (signal) ima vrijednost true dok se ne dođe do procesa čiji

Task nije završio. U tom slučaju se nastavlja slati novi uređeni par kojemu je vrijednost na prvome

mjestu false. U slučaju da proces s rankom 0 dobije takvu poruku, mora nastaviti slati uređene parove

(true, false).

Ako je svakome od procesa Task završio, proces s rankom 0 će dobiti uređeni par (true, false). Nakon

toga proces s rankom 0 inicira point-to-point komunikaciju slanjem uređenog para (true, true) što

signalizira svim procesima da ispišu pronađenog zajedničkog djelitelja. Kada se poruka vrati do ranka 0,

on ispisuje poruku "Gotovo".

Primjer kreiranja uređenog para u C#-u:

Tuple<bool, bool> par = Tuple.Create(true, false)

Primjer ispisa:

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MPI; namespace Zadatak_3 { class Program { // Euklidov algoritam private static int Gcd(int a, int b) { if (b == 0) return a; else return Gcd(b, a % b); } static void Main(string[] args) {

Page 50: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

47

using (new MPI.Environment(ref args)) { Intracommunicator comm = Communicator.world; int n = comm.Size; // Prvo uzmemo rank od svog sljedbenik i prethodnika int next = comm.Rank == n - 1 ? 0 : comm.Rank + 1; int prev = comm.Rank == 0 ? n - 1 : comm.Rank - 1; // druga bool vrijednost signalizira kraj // prva bool vrijednost signalizira jesu li svi procesi zavrsili sa svojim taskovima var pair = Tuple.Create(true, false); // Za početak rank 0 mora napraviti niz i poslati ga point-to-point komunikacijom if (comm.Rank == 0) { int[] niz = new int[n]; Random rnd = new Random((comm.Rank + 1) * DateTime.Now.Millisecond); for (int i = 0; i < n; i++) { niz[i] = rnd.Next(1, 100001); } // Ispisemo elemente niza foreach(var el in niz) { Console.Write(" " + el); } Console.WriteLine(); comm.Send<int[]>(niz, next, 0); } int[] dobiveniNiz = new int[n]; if (comm.Rank != 0) { // Ako se radi o ranku razlicitom od 0, potrebno je primiti niz koji je // rank 0 poslao i prosljediti ga dalje dobiveniNiz = comm.Receive<int[]>(prev, 0); comm.Send<int[]>(dobiveniNiz, next, 0); } if (comm.Rank == 0) { // čekamo dok rank 0 ne primi niz koji je sam poslao // ovo je samo osiguranje da ne pocmemo slati par (TUPLE) dok // niz ne napravi puni krug comm.Receive<int[]>(prev, 0); // Saljemo par elemenata koji je inicijaliziran gore (true, false) comm.Send<Tuple<bool, bool>>(pair, next, 0); } // Svaki element uzima svoj broj // Uzimamo odgovarajuci element

Page 51: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

48

int mojBroj = dobiveniNiz[comm.Rank]; // uzimamo prvi element int prvi = dobiveniNiz[0]; // U novom tasku, procesi krecu s racunanjem najveceg zajednickog djelitelja // izmedu prvog elementa i uzetog (rank 0 ne mora ovo racunati, ali ovdje smo // to zanemarili) Task<int> t = Task.Factory.StartNew(() => Gcd(mojBroj, prvi)); // Petlja ce se ponavljati dok proces ne dobije poruku (true, true) while (!pair.Item1 || !pair.Item2) { // ako se radi o procesu s rankom 0 if (comm.Rank == 0) { // proces prima poruku tipa Tuple koja moze biti: // - false, false -> nekome task nije zavrsio i ne signaliziramo kraj // - true, false -> svima je task zavrsio i signalizira se kraj pair = comm.Receive<Tuple<bool, bool>>(prev, 0); // pretpostavimo u novom paru da ce dok poruka pair stigne do sljedeceg procesa // task zavrsiti -> zato postavljamo prvu bool vrijednost na true // u slucaju da je poruka primljena (true, false) -> to znaci da su svi // zavrsili sa svojim taskovima pa trebamo poslati (true, true) // u slucaju da je poruka primljena (false, false) -> to znaci da netko nije // zavrsio sa svojim taskom pa trebamo poslati (true, false). // U svakom slucaju, drugo polje (bool) nove poruke kreirane ispod je jednako // vrijednosti prve poruke koja je primljena (gore comm.Receive) pair = Tuple.Create(true, pair.Item1); // Salje se nova poruka comm.Send<Tuple<bool, bool>>(pair, next, 0); // U slucaju da je kreirana poruka: // - true, true -> potrebno je ispisati da je Gotovo -> (true, true) će biti // samo ako je primljena poruka (true, false) if (pair.Item1 && pair.Item2) { Console.WriteLine("Gotovo"); } } else { // prima se poruka od ranka 0 ili prethodnika pair = comm.Receive<Tuple<bool, bool>>(prev, 0); // kreira se poruka koju ce ovaj rank poslati dalje. // vrijednost drugog polja se prosljeduje jer o njemu odlucuje // Rank 0.

Page 52: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

49

// vrijednost prvog polja postavljamo na vrijednost svojstva // "je li task gotov" && vrijednost provg polja // ako bilo koji task nije gotov, do ranka 0 će doći poruka (false, false) pair = Tuple.Create(t.IsCompleted && pair.Item1, pair.Item2); // saljemo novu poruku comm.Send<Tuple<bool, bool>>(pair, next, 0); // ako je proces dobio poruku (true, true) ispisuje svoj rezultat if(pair.Item1 && pair.Item2) { Console.WriteLine("comm.Rank: " + comm.Rank + " rezultat: " + t.Result); } } } } } } }

Page 53: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

50

4. ZADATAK

Na raspolaganju su vam metode Scatter i Gather. Napravite MPI program u kojem proces s rankom 0

generira matricu od NxN slučajnih brojeva u rasponu [1, 100], gdje je N broj procesa. Koristeći metodu

Scatter proces s rankom 0 podijeli retke svim procesima. Svaki proces filtrira proste brojeve svog retka

u novi niz od N elemenata. Npr. ako je proces dobio redak: [1, 4, 3, 6, 5], novi (filtrirani) niz će biti: [3,

5, 0, 0, 0]. Proces s rankom 0 skupi sve nove nizove u matricu te ju ispiše.

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MPI; namespace Zadatak_4 { class Program { static void Main(string[] args) { using (new MPI.Environment(ref args)) { Intracommunicator comm = Communicator.world; int N = comm.Size; int[] noviRed = new int[N]; int[][] matrica = new int[N][]; for (int i = 0; i < N; i++) { noviRed[i] = 0; } int[][] matricaR = new int[N][]; for (int i = 0; i < N; i++) { matricaR[i] = new int[N]; } if (comm.Rank == 0) { // Mnozimo sa DateTime.Now.Millisecond da bismo dobili razliciti seed // prilikom pokretanja Random rnd = new Random((comm.Rank + 1) * DateTime.Now.Millisecond); for (int i = 0; i < N; i++) { matrica[i] = new int[N]; } for (int i = 0; i < N; i++)

Page 54: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

51

{ for (int j = 0; j < N; j++) { matrica[i][j] = rnd.Next(1, 101); } } Console.WriteLine("\n izgenerirana matrica: \n "); for (int i = 0; i < N; i++) { Console.WriteLine("\n"); for (int j = 0; j < N; j++) { Console.Write(matrica[i][j] + "\t"); } } } // Svi koji pozovu Scatter dobiju jedan red matrice int[] red = comm.Scatter<int[]>(matrica, 0); // Indeks za novi red koji punimo elementima int k = 0; for (int i = 0; i < N; i++) { int b = 0; for (int j = 2; j <= Math.Sqrt(red[i]); j++) { if (red[i] % j == 0) b++; } if (b == 0) { noviRed[k] = red[i]; k++; } } // Gather služi za prikupljanje elemenata iz različitih procesa // buudći da prikupljamo nizove, rezultat će biti matrica matricaR = comm.Gather<int[]>(noviRed, 0); if (comm.Rank == 0) { Console.WriteLine("\n Rezultirajuca matrica: \n"); for (int i = 0; i < N; i++) { Console.WriteLine("\n"); for (int j = 0; j < N; j++) { Console.Write(matricaR[i][j] + "\t"); } } } } } } }

Page 55: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

52

5. ZADATAK

Na raspolaganju sam vam metode Send i Recv. Napravite MPI program u kojemu se među N procesa

bira voditelj. Procesi su složeni u prsten te znaju tko im je prethodnik i tko im je sljedbenik. Procesi

primaju poruku samo od svog prethodnika, a šalju samo svom sljedbeniku. Bilo koji broj procesa može

yatražiti da postane voditelj (1 do N), ali točno jedan u konačnici postaje voditelj. Proces zatraži da

postane voditelj tako što pošalje poruku sa svojim ID-om i tagom 0 sljedbeniku.

Za ovaj program potrebna su dva tipa poruka koje možete razlikovati po tagu poruke. Na početku bilo

koji broj procesa (može 1, a mogu i svi) šalje poruku sa svojim ID-om.

Nakon toga proces ulazi u petlju koja se izvršava dok ne sazna tko je voditelj. U slučaju da proces primi

poruku s tagom 0, uspoređuje primljeni ID sa svojim ID-om te se razlikuju 3 slučaja:

1. Ukoliko je primljeni ID manji od vlastitog, proces šalje poruku s istim tagom i svojim ID-om

2. Ukoliko je primljeni ID veći od vlastitog, proces šalje poruku s istim tagom i primljenim ID-om

3. Ukoliko je primljeni ID jednak vlastitom, to znači da je ID prošao cijeli krug i ne postoji netko s

većim ID-om. U tom slučaju ovaj proces postaje voditelj te šalje poruku sa svojim ID-om i

drugačijim tagom, npr. 1.

Ako proces primi poruku s tagom 1, a ujedno taj proces nije odabrani voditelj, proces zabilježi primljeni

ID kao ID voditelja (svi procesi moraju na kraju znati tko je voditelj) te prosljedi poruku svome susjedu

(sljedbeniku). Ako je poruku s tagom 1 primio proces koji je voditelj, zabilježi sebe kao voditelja, ali ne

šalje poruku dalje.

Napomena: Kako biste razlikovali tip poruke morate koristit Probe metodu. Objekt koji dobijete kao

rezultat ima svojstv koje kaže koji je tag poruke. S Probe ne primate poruku, dakle i dalje je potrebno

pozvati Receive.

Primjer ispisa:

Page 56: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

53

RJEŠENJE

using MPI; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Zadatak_5 { class Program { static void Main(string[] args)

Page 57: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

54

{ using (new MPI.Environment(ref args)) { Intracommunicator comm = Intracommunicator.world; var id = comm.Rank; int numProcesses = comm.Size; var prev = id > 0 ? id - 1 : numProcesses - 1; var next = id < numProcesses - 1 ? id + 1 : 0; Console.WriteLine("Šaljem svoju nominaciju..."); comm.Send<int>(id, next, 0); var leaderId = -1; // moramo ponavljati slanje poruka u krug sve dok se ne odredi voditelj // ne znamo koliko će to puta biti while (true && leaderId == -1) { // probe metoda da vidimo koja poruka čeka // s obzirom na to da ne znamo koji je tag poruke koju možemo očekivati // koristimo za drugi parametar Communicator.anyTag var probe = comm.Probe(prev, Communicator.anyTag); // poruku s tagom 0 primamo kada voditelj još uvijek nije poznat if(probe.Tag == 0) { Console.WriteLine("Čekam poruku s tagom 0..."); int got = comm.Receive<int>(prev, 0); // 3 slučaja opisana u zadatku if(id > got) { Console.WriteLine("Moj id: " + id + " je veći od primljenog: " + got); comm.Send<int>(id, next, 0); } else if (id < got) { Console.WriteLine("Dobiveni id: " + got + " je veći od mog: " + id); comm.Send<int>(got, next, 0); } else { Console.WriteLine("Dobiven vlastiti ID: " + id); Console.WriteLine("Šaljem poruku s tagom 1..."); comm.Send<int>(id, next, 1); } } // kada je odabran voditelj, onda ćemo primiti od njega ili od prethodnika // poruku s tagom 1 else if(probe.Tag == 1) { Console.WriteLine("Dobio poruku s tagom 1..."); leaderId = comm.Receive<int>(prev, 1);

Page 58: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

55

// ako ja nisam voditelj, dakle, moj id je različit od onoga kojeg sam primio // onda ću poslati dalje id voditelja -> leaderId // u suprotnom znači da sam dobio porukom svoj id, to znači // da su sada svi upoznati sa tim da sam ja voditelj jer je poruka krenula od mene, // išla u krug i ponovno došla do mene -> moj id (leaderId) je napravio puni krug if (leaderId != id) { comm.Send<int>(leaderId, next, 1); } } } // Svi procesi ispisuju tko je odabrani voditelj: Console.WriteLine("Voditelj je: " + leaderId); } } } }

Page 59: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

56

6. ZADATAK

Na raspolaganju su vam metode Send i Recv. Napravite MPI program u kojem N – 1 proces pokušava

pogoditi zamišljeni broj procesa s rankom 0. Procesi su složeni u prstenastu strukturu gdje je svakom

procesu s rankom R proces s rankom R + 1 (osim posljednjeg, kojemu je sljedbenik proces s rankom 0).

Proces s rankom 0 zamišlja jedan broj i šalje u krug niz veličine N – 1. Svi procesi osim procesa s

rankom 0 po primitku tog niza pokušavaju pogoditi zamišljeni broj procesa 0 na način da svoj element

spremaju u dobiveni niz te prosljeđuju niz svome sljedbeniku. Dakle, niz ide u krug. Ovaj postupak se

ponavlja sve dok proces s rankom 0 ne ustanovi da je neki od procesa pogodio njegov zamišljeni broj.

U slučaju da proces s rankom 0 ustanovi da je neki proces pogodio zamišljeni broj ( u ovome trenutku

niz je napravio puni krug te sadrži sve pokušaje ostalih procesa ), mora poslati poruku sa signalom za

prekid kako bi svi procesi znali da je broj pogođen te mogli završiti s izvršavanjem.

Očito će vam u ovome zadatku trebati 2 različita tipa poruka. Kako biste to mogli napraviti potrebne su

vam poruke s Tagom 0 i 1. Sjetite se da Tag određuje tip poruke koju šaljemo i očekujemo. Da bismo

mogli saznati koji tip poruke nam je poslan, prije samog primitka poruke, moramo dobiti informacije o

poruci koju ćemo primiti. To znači da je potrebno koristiti metodu Probe. Koristite je na sljedeći način:

var probe = comm.Probe(proces_od_kojeg_primamo_poruku, Communicator.anyTag);

S obzirom da procesi ne znaju koju poruku mogu očekivati, onda u Probe metodu šaljemo

Communicator.anyTag kao drugi parametar da označimo da želimo ispitati bilo koju poruku koju ćemo

sljedeću primiti. Je li Tag jednak 0 jednostavno ispitamo probe.Tag == 0.

Nakon što je pogođen zamišljeni broj, potrebno je ispisati poruku o tome te ispisati koji proces je

pogodio broj.

Nijedan Random ne smije imati istu seed vrijednost. Slučajni brojevi su u rasponu [1, 100].

Primjer ispisa:

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MPI; namespace Zadatak_6 { class Program { static void Main(string[] args) { using (new MPI.Environment(ref args))

Page 60: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

57

{ Intracommunicator comm = Communicator.world; Random rnd = new Random(comm.Rank); int myNumber = rnd.Next(0, 100) + 1; // Uočite da je niz za 1 manji od N int[] guesses = new int[comm.Size - 1]; int winner = 0; // Odredimo sljedbenika i prethodnika var next = comm.Rank == comm.Size - 1 ? 0 : comm.Rank + 1; var prev = comm.Rank == 0 ? comm.Size - 1 : comm.Rank - 1; // Potreban nam je nekakav signal kako bismo znali kada je broj pogođen, ćime // prestajemo dalje pogađati bool terminate = false; // Ako je Rank 0 if (comm.Rank == 0) { // Ovo za provjeru ispisujemo koji je broj zamisljen. // Linija se može i zakomentirati Console.WriteLine("Zamisljeni broj: " + myNumber); // šaljemo niz guesses u kojeg će ostali procesi spremati svoje pokušaje pogađanja broja comm.Send<int[]>(guesses, next, 0); } // Budući da procesi moraju pogađati broj dok ne pogode zamišljeni broj procesa sa rankom 0, // potrebna je while petlja while (!terminate) { // Probe metoda nam je potrebna kako bismo mogli provjeriti koji tag ima // sljedeća poruka koju ćemo primiti: // 1. poruka sa tagom 0 predstavlja poruku koja se šalje dok još broj nije pogođen // 2. poruka sa tagom 1 predstavlja poruku koja se šalje nakon što je broj pogođen // Communicator.anyTag -> očekujemo poruku s bilo kakvim tagom // Probe ne prima poruku, samo daje informacije o onoj koja čeka da bude primljena var probe = comm.Probe(prev, Communicator.anyTag); // Ako ima poruke i njen tag je 0 (još nismo poruku primili) if (probe != null && probe.Tag == 0) { // Ako je rank različit od 0 if (comm.Rank != 0) { // procesi koji nisu glavni proces ( s rankom 0 ), primaju niz pokušaja guesses = comm.Receive<int[]>(prev, 0); // generiraju jedan broj koji predstavlja pokušaj pogotka int myGuess = rnd.Next(0, 100) + 1;

Page 61: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

58

// Ovo nije bitno, može se iskomentirati Console.WriteLine(comm.Rank + " : " + myGuess); // Proces na odgovarajuću poziciju postavi svoj pokušaj // budući da je broj elemenata u nizu za 1 manji od broja procesa, // svaki proces s nekim rankom Rank, postavlja svoj element na index Rank - 1 guesses[comm.Rank - 1] = myGuess; // proces šalje svom sljedbeniku poruku comm.Send<int[]>(guesses, next, 0); } else { // proces s rankom 0 prima poruku guesses = comm.Receive<int[]>(prev, 0); // ako se među pokušajima pogodaka nalazi zamišljeni broj if (guesses.Contains(myNumber)) { // Array.FindIndex -> metoda za lakše pronalaženje indeksa nekog elementa u // nizu. // winner je index elementa koji je pogodio broj // uočite da proces s rankom 0 iz niza pokušaja može izvući koji proces // je pogodio broj winner = Array.FindIndex(guesses, x => x == myNumber); // signal za prekid postavljamo na true jer je broj pogođen terminate = true; // signal za prekid šaljemo dalje, ali ovaj put poruka ima tag 1 comm.Send<bool>(terminate, next, 1); } else { // ako se među pokušajima ne nalazi zamišljeni broj, niz pokušaja // se šalje ponovno u krug comm.Send<int[]>(guesses, next, 0); } } } // ako poruka čeka da ju proces primi i tag je 1 else if (probe != null && probe.Tag == 1) { // postavi signal za prekid na primljenu vrijednost terminate = comm.Receive<bool>(prev, 1); if (comm.Rank != comm.Size - 1) { // ako ovaj proces nije posljednji u komunikaciji, onda prosljeđuje signal za prekid comm.Send<bool>(terminate, next, 1); } } } if (comm.Rank == 0) {

Page 62: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

59

// ispisimo zamisljeni broj procesa sa rankom 0 Console.WriteLine("Pogoden je moj broj: " + myNumber); // winner je index, rank 0 je glavni koji zamišlja broj i ne sudjeluje u takmičenju // stoga je Rank pobjednika winner + 1 Console.WriteLine("Winner is:> " + ( winner + 1 ) ); } } } } }

Page 63: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

60

7. ZADATAK

Na raspolaganju su vam metode Scatter i Gather. Napravite MPI program u kojem proces s rankom 0

generira niz od N elemenata gdje je N broj procesa. Elementi niza su u rasponu [0, 100]. Koristeći

metodu Scatter proces pošalje svim ostalim procesima, uključujući sebe jedan od elemenata. Svi

procesi moraju pronaći proste faktore dobivenog elementa.

Proces s rankom 0 sve proste faktore skuplja u jednu matricu te ispisuje.

RJEŠENJE

using System; using System.Collections.Generic; using MPI; namespace Zadatak_7 { class Program { // Metoda koja provjerava je li broj prost private static bool IsPrime(int a) { if (a == 2) return true; else { for (int i = 2; i <= Math.Ceiling(Math.Sqrt(a)); i++) { if (a % i == 0) return false; } } return true; } // Metoda koja će pronaći sve proste faktore do a private static int[] FindPrimeNumbers(int a) { // proste faktore spremamo u listu primes List<int> primes = new List<int>(); // pamtimo originalni element koji je poslan u metodu // zbog jednostavni ćemo a mijenjati int original = a; // u petlji moramo provjeriti sve brojeve od 2 do originala jesu li // prosti for (int i = 2; i <= original ; i++) { // ako je neki broj prost if (IsPrime(i)) { // prosti faktori za neki broj se mogu ponavljati više puta: // npr. za 12 je rastav na proste faktore 12 = 2 * 2 * 3 // u while petlji, dok god je a djeljiv s i, u listu prostih faktora // primes dodajemo i. // ujedno svakom iteracijom cjelobrojno dijelimo a s i

Page 64: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

61

// -> zato smo sačuvali original while (a % i == 0) { primes.Add(i); a = a / i; } } } // Na kraju vratimo listu prostih faktora u glavnu metodu return primes.ToArray(); } static void Main(string[] args) { using (new MPI.Environment(ref args)) { Intracommunicator comm = Communicator.world; // n je broj procesa int n = Communicator.world.Size; int[] array = new int[n]; // da nam random bude drugačiji za svaki proces Random rnd = new Random(comm.Rank); // napuni niz elemenata if (comm.Rank == 0) { for (int i = 0; i < n; i++) { array[i] = rnd.Next(1, 101); Console.WriteLine("num: " + array[i]); } } // podijeli elemente svima, uključujući sebi int s = comm.Scatter<int>(array, 0); // Svaki proces ispisuje koji je element niza dobio Console.WriteLine("s: " + s); // pronalazimo sve proste faktore broja int[] primes = FindPrimeNumbers(s); // skupljamo proste faktore pozivom metode Gather // sve proste faktore skupljene stavljamo u gathered matricu int[][] gathered = comm.Gather<int[]>(primes, 0); // Rank 0 će izvršiti ispis if (comm.Rank == 0) { for (int i = 0; i < gathered.Length; i++) { for (int j = 0; j < gathered[i].Length; j++) { Console.Write(gathered[i][j] + " "); } Console.WriteLine(); } }

Page 65: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

62

} } } }

Page 66: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

63

8. ZADATAK

Na raspolaganju su vam metode Send i Recv. Napravite MPI program u kojem N – 1 proces pokušava

pogoditi zamišljeni broj procesa s rankom 0. Procesi su složeni u prstenastu strukturu gdje je svakom

procesu s rankom R proces s rankom R + 1 sljedbenik (osim posljednjeg, kojemu je sljedbenik proces s

rankom 0).

Proces s rankom 0 zamišlja jedan broj i šalje u krug niz veličine N – 1. Svi procesi osim procesa s

rankom 0 po primitku tog niza pokušavaju pogoditi zamišljeni broj procesa 0 na način da svoj element

spremaju u dobiveni niz te prosljeđuju niz svome sljedbeniku. Dakle, niz ide u krug. Ovaj postupak se

ponavlja 10 puta. A prilikom svakog ponavljanja svi pokušaji se pamte u matrici H.

Nakon što se 10 puta ponovi pogađanje broja proces s rankom 0 određuje pobjednika. Pobjednik je

onaj koji je maksimalan broj puta pogodio zamišljeni broj. U slučaju da nitko nijednom nije pogodio

zamišljeni broj, pobjednik je onaj kojemu je prosjek pokušaja najbliži zamišljenom broju. Proces s

rankom 0 ispisuje matricu pokušaja H, a zatim ispod nje pobjednika i informacije o pobijedi:

Pobjednik je proces s rankom X koji je broj Y pogodio Z puta;

Pobjednik je proces s rankom X kojemu je srednja vrijednost pokušaja Y te je time najbliža zamišljenom

broju Z.

Nijedan Random ne smije imati istu seed vrijednost. Slučajni brojevi su u rasponu [1, 100].

Napomena: ovo je pojednostavljeni 6. zadatak.

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MPI; namespace Zadatak3 { class Program { static void Main(string[] args) { using(new MPI.Environment(ref args)) { Intracommunicator comm = Communicator.world; // broj procesa int n = comm.Size; // Da random bude razlicit za svaki proces Random rnd = new Random(comm.Rank * DateTime.Now.Millisecond); // barem 10 pokusaja mora imati svaki proces. // treba nam matrica u koju cemo spremati pokusaje svakog procesa. // neka pokusaj bude red, a proces stupac int[][] matrica = new int[10][];

Page 67: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

64

for(int i = 0; i < 10; i++) { // matrica je niz ciji su elementi nizovi. Na poziciji i instanciramo novi niz (novi element niza matrica) // proces sa rankom 0 nije ukljucen jer on ne pogada matrica[i] = new int[n - 1]; } // samo proces sa Rankom 0 ce ovaj broj imat razlicit od 0 int zamisljeniBroj = 0; int next = comm.Rank == comm.Size - 1 ? 0 : comm.Rank + 1; int prev = comm.Rank == 0 ? comm.Size - 1 : comm.Rank - 1; if(comm.Rank == 0) { // zadani raspon je [1, 100] zamisljeniBroj = rnd.Next(1, 101); } // komunikacija koja se mora izvrsiti 10 puta for(int i = 0; i < 10; i++) { if(comm.Rank == 0) { comm.Send<int[]>(matrica[i], next, 0); int[] dobiveniPokusaji = comm.Receive<int[]>(prev, 0); // osvjezimo redak matrice matrica matrica[i] = dobiveniPokusaji; } else { int[] dobiveniNiz = comm.Receive<int[]>(prev, 0); int pokusaj = rnd.Next(1, 101); // sjetite se da proces s rankom 0 nije ukljucen. Zato je potrebno indeks na ovaj nacin izracunati dobiveniNiz[comm.Rank - 1] = pokusaj; comm.Send<int[]>(dobiveniNiz, next, 0); } } // odredivanje pobjednika na osnovu 2 razlicite situacije if(comm.Rank == 0) { // potrebno je ispisati pokusaje i pronaci pobjednika for(int i = 0; i < 10; i++) { Console.WriteLine("Pokusaj " + i + ":> "); for(int j = 0; j < n - 1; j++) { Console.Write(matrica[i][j] + "\t"); } Console.WriteLine(); }

Page 68: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

65

// u ovaj niz cemo spremiti koliko puta je koji proces pogodio zamisljeni broj, ovako je najjednostavnije int[] brojanjePogodaka = new int[n - 1]; for (int i = 0; i < 10; i++) { for (int j = 0; j < n - 1; j++) { if(matrica[i][j] == zamisljeniBroj) { brojanjePogodaka[j]++; } } } // je li itko pogodio? bool pogodio = brojanjePogodaka.Any(x => x > 0); if(pogodio) { int max = 0; int maxi = -1; for(int i = 0; i < n - 1; i++) { if(brojanjePogodaka[i] > max) { max = brojanjePogodaka[i]; maxi = i; } } Console.WriteLine("Pobjednik je proces s rankom " + (maxi + 1) + " koji je broj " + zamisljeniBroj + " pogodio " + max + " puta."); } else { double[] brojanjeSrednjeVrijednosti = new double[n - 1]; for(int i = 0; i < n - 1; i++) { int sumaPokusaja = 0; for(int j = 0; j < 10; j++) { sumaPokusaja = matrica[j][i] + sumaPokusaja; } // izracunaj srednju vrijednost brojanjeSrednjeVrijednosti[i] = (double)sumaPokusaja / 10; } int mini = 101; double min = 101; double srednjaVrijednost = 0; for(int i = 0; i < n - 1; i++) { if(Math.Abs(zamisljeniBroj - brojanjeSrednjeVrijednosti[i]) < min) {

Page 69: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

66

mini = i; min = Math.Abs(zamisljeniBroj - brojanjeSrednjeVrijednosti[i]); srednjaVrijednost = brojanjeSrednjeVrijednosti[i]; } } Console.WriteLine("Pobjednik je proces s rankom " + (mini + 1) + " kojemu je srednja vrijednost " + srednjaVrijednost + " te je time najbliza zamisljenom broju " + zamisljeniBroj); } } } } } }

Page 70: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

67

9. ZADATAK

Na raspolaganju su vam metode Scatter i Gather. Napravite MPI program u kojem proces s rankom 0

generira niz od N elemenata gdje je N broj procesa. Elementi niza su u rasponu [0, 100]. Koristeći

metodu Scatter proces pošalje svim ostalim procesima, uključujući sebe jedan od elemenata. Svi

procesi moraju pronaći binarni oblik dobivenog elementa. Binarni oblik treba biti zapisan kao niz

znakova.

Proces s rankom 0 sve binarne oblike skuplja u jednu matricu te ispisuje.

RJEŠENJE

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MPI; namespace Zadatak4 { class Program { static string[] Binarno(int broj) { List<string> bin = new List<string>(); while (broj != 0) { int ostatak = broj % 2; bin.Add(ostatak.ToString()); broj /= 2; } bin.Reverse(); return bin.ToArray(); } static void Main(string[] args) { using (new MPI.Environment(ref args)) { Intracommunicator comm = Communicator.world; // broj procesa int n = comm.Size; // Da random bude razlicit za svaki proces Random rnd = new Random((comm.Rank + 1) * DateTime.Now.Second); int[] niz = new int[n]; if (comm.Rank == 0) { for (int i = 0; i < niz.Length; i++) { niz[i] = rnd.Next(0, 101);

Page 71: PARALELNO PROGRAMIRANJE: Z IRKA RIJEŠENIH ...mapmf.pmfst.unist.hr/~tdadic/ParalelnoProgramiranje/...Sveučilište u Split, Prirodoslovno – matematički fakultet 1 UVOD Ova zbirka

Sveučilište u Split, Prirodoslovno – matematički fakultet

68

Console.Write(niz[i] + " "); } } // posalji po element svakom procesu uz pomoc scatter metode int x = comm.Scatter<int>(niz, 0); string[] binarno = Binarno(x); // dohvati rezultirajuce nizove binarnih vrijednosti uz pomoc gather metode string[][] matrica = comm.Gather<string[]>(binarno, 0); if (comm.Rank == 0) { Console.WriteLine("\nMatrica:"); for (int i = 0; i < matrica.Length; i++) { for (int j = 0; j < matrica[i].Length; j++) { Console.Write(matrica[i][j] + " "); } Console.WriteLine(); } } } } } }