Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

PROGRAMAREA MULTICALCULATOARELOR

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "PROGRAMAREA MULTICALCULATOARELOR"— Μεταγράφημα παρουσίασης:

1 PROGRAMAREA MULTICALCULATOARELOR
OCCAM APLICATII PARALELE PE UN HIPERCUB MPI PVM

2 CARACTERISTICI ALE PROGRAMARII MULTICALCULATOARELOR
-nu exista spatiu unic de adresa (programarea fara memorie partajata); -programul paralel se executa ca o multime de procese concurente, numai cu memorie locala; -comunicatia intre procese se face prin transfer de mesaje (operatie „send” dintr-un proces <-> operatie „receive” a altui proces); -nu exista variabile partajate (fara mecanisme de protectie a accesului la acestea). Limbaje de programare in transfer de mesaje: -limbaje secventiale (Pascal, C, Fortran) cu extensii pentru transmisia si receptia mesajelor; -limbaje de programare paralela speciale: Ada, Occam, Linda, Orca, SR, Parlog, Emerald, etc. Biblioteci de comunicatie: -PVM: Parallel Virtual Machine; -MPI: Message Passing Interface.

3 LIMBAJUL OCCAM -realizat in 1986 de INMOS;
-bazat pe limbajul CSP (Communicating Sequential Processes) din 1978; -algoritm paralel -> colectie de procese asincrone, care comunica prin canale; -canalul = entitate abstracta de comunicatie, punct la punct, directionata, sincrona si fara buffer intre doua procese paralele.

4 Procese fundamentale:
-asignare: variabila := expresie -citire dintr-un canal de comunicatie: canal ? variabila -scriere intr-un canal de comunicatie: canal ! expresie -orice alt proces = structura ierarhica de subprocese; -subproces = colectie de procese mai simple executate in serie sau in paralel pe acelasi transputer sau pe transputere diferite; -procesele: create static (nu se pot crea dinamic) in momentul compilarii.

5 Operatori de constructie (constructori) pentru definirea proceselor complexe:
-SEQ creaza un proces complex dintr-un numar de procese minore care se vor executa secvential: SEQ proces_1 proces_2 proces_3 proces_n -PAR creaza un proces complex care lanseaza executia paralela a mai multor procese: PAR proces_1 proces_2 proces_3 proces_n

6 -IF creaza un proces complex care lanseaza in executie unul din procesele componente, corespunzand primei conditii adevarate (testarea se face in ordinea scrierii conditiilor): IF conditie_1 proces_1 conditie_2 proces_2 conditie_3 proces_3 conditie_n proces_n

7 -ALT creaza un proces complex care lanseaza in executie un singur proces corespunzand primului canal de intrare care este gata de comunicatie: ALT canal_1 ? x proces_1 canal_2 ? x proces_2 canal_3 ? x proces_3 canal_n ? x proces_n Ordinea specificarii canalelor nu conteaza, selectia se face in functie de momentul de timp cand canalul este gata de comunicatie.

8 -nu se pot defini variabile partajate intre doua procese (chiar daca procesele se executa pe acelasi transputer). => Canalele de comunicatie Occam sunt sincrone si fara buffer: (procesel A si B fac parte din componentele unei constructii PAR).

9 Aplicatie: calculul unei aproximatii a numarului π:
=> prin integrare numerica (inaltimea fiecarui dreptunghi este valoarea functiei in mijlocul subintervalului respectiv).

10 Algoritmul secvential:
#define n sum = 0.0; w = 1/n; for (i=0; i<n; i++) { x = (i+0.5)*w; sum += 4/(1+x*x); } sum *=w; => Timpul de calcul este O(n).

11 Se considera o retea de p transputere inlantuite, primul transputer fiind conectat la calculatorul gazda: =>fiecarui transputer: n/p subintervale pentru suma ariilor dreptunghiurilor. Etape: 1)fiecare transputer calculeaza secvential si insumeaza n/p arii; 2)fiecare transputer primeste de la vecinul dreapta suma partiala, o insumeaza cu propria valoare si o trimite la vecinul stanga, astfel incat se obtine rezultatul in nodul 0.

12 VAL INT p IS 8: VAL INT n IS 1024: [p] CHAN OF REAL chan: --vector de canale INT s: SEQ s:=n/p PAR i=0 FOR p-1 --vector de procese paralele REAL x, partial_sum, w: SEQ partial_sum:=0.0 w:=1/n x:=((i*s)+0.5)*w SEQ j=0 FOR s-1 SEQ partial_sum:=partial_sum+(4/(1+x*x)) x:=x+w partial_sum=partial_sum*w

13 --transferul sumelor partiale si acumulare in procesorul 0
IF i=p-1 chan[p-1] ! partial_sum i<p-1 SEQ REAL sum: chan[i+1] ? sum chan[i] ! sum+partial_sum

14 APLICATII PARALELE PE UN HIPERCUB
Algoritmi pe un hipercub Structura hipercub -> implementarea unui numar mare de algoritmi necesitand comunicatii all-to-all. Sablon: un formular de program care poate fi completat cu informatii specifice aplicatiei pentru implementarea unui algoritm paralel. Hipercubul conecteaza fiecare din toate cele P taskuri (procesoare) la log2P alte taskuri. -model SPMD; -initial: o variabila de stare <- o data furnizata la intrare; -log2P pasi; -la fiecare pas fiecare task: -schimba starea locala cu unul din vecini; -combina mesajul primit de la vecin cu starea curenta -> starea urmatoare; => rezultatul: starea generata la pasul final.

15 procedure hypercube (myid, input, logp, output)
begin state=input //starea locala init cu input for i=0,logp-1 //repeta de logp ori dest=myid XOR 2i //determina vecinul send state -> dest //schimba datele receive message <- dest state=OP(state,message) //executa operatia endfor output=state //rezultatul final end Implementarea unui algoritm particular: prin definirea operatiei OP.

16 Reducere de vector  Algoritmul pecedent se poate utiliza pentru o reducere de vector utilizand orice operator comutativ asociativ (ex: adunare, maxim, inmultire). Reducerea a patru vectori de lungime N=4 distribuiti la patru taskuri => algoritmul in log24=2 pasi. La fiecare pas fiecare task: -executa schimbul a N date cu un vecin; -realizeaza N operatii de combinare.

17 In cazul general de reducere vectoriala fiecare task dintre P taskuri:
-furnizeaza un vector de N valori; -executa N operatii separate de reducere; => vector de N rezultate. Reducerea: in log2P pasi. Timpul necesar:   Treducere = log2P (ts + N (tw + top)) unde -top = timpul cerut de operatia de reducere; -tw = timpul de comunicatie; -ts = timpul de lansare (start-up). Algoritmul este eficient pentru valori mici ale lui N (cand predomina timpul de lansare).

18 Varianta a algoritmului: algoritm recursiv cu injumatatire => reducerea semnificativa a volumului mesajelor comunicate. Algoritmul aplicat de doua ori: in faza de reducere fiecare procesor comunica si combina N/2 date in prima iteratie, apoi jumatate N/4 in a doua, etc. => fiecare procesor comunica in total N(P-1)P date in log2P pasi. Se obtine suma globala, iar vectorul rezultat de N componente este uniform distribuit la cele P procese.

19 Timpul consumat: Solutia trimite de doua ori mai multe mesaje, dar cu mai putine date si face mai putine calcule => mai eficient pentru anumte valori ale lui N si P, si pe anumite masini.

20 Broadcast Similar: se poate defini un algoritm eficient de broadcast. N valori localizate in nodul radacina sunt trasnmise la toate cele P-1 noduri, utilizand un arbore binar de comunicatie.

21 Timpul necesar: Tbroadcast = log2P (ts + twN) Algoritmul: eficient pentru valori mici ale lui N si P. Pentru valori mari ale lui N si P multe procesoare sunt inactive cea mai mare parte a timpului si Tbroadcast este dominat de log2P twN. => mai eficient sa se sparga mesajul in componente mai mici si sa se routeze componentele separat prin reteaua hipercub. Timpul necesar : Tbroadcast = 2(ts log2P + twN)

22 Transpunerea de matrici.
Matricea A de transpus si transpusa A' sunt distribuite printre procese => executia algoritmului implica comunicatii. Se considera o descomunere pe coloane a celor doua matrici repartizate proceselor => comunicatii all-to-all. Algoritmul: P-1 pasi. La fiecare pas fiecare task: interschimba N2/P2 date cu un alt task. Timpul necesar:

23 N=P=8 => log2P pasi.. Fiecare proces are o singura coloana din A, iar in final fiecare va avea o singura linie din A'. La fiecare pas fiecare proces: schimba ½ din datele sale (reprezentate umbrit in desen). In partea a doua a desenului: sursele componentelor detinute de procesul 0, la fiecare pas al algoritmului.

24 Procesele sunt partitionate in doua seturi: taskurile corespunzatoare din cele doua seturi interschimba ½ dintre datele lor: taskurile 0…p/2-1 comunica jumatatea inferioara a datelor lor, iar taskurile P/2…P-1 comunica jumatatea superioara. Aceasta partitionare si interschimb se repeta pana cand fiecare set contine un singur task. Daca fiecare dintre cele log2P mesaje are dimensiunea N2/(2P) timpul necesar este: Algoritmul hipercub transmite aprox. P/log2P mai putine mesaje, dar de (log2P)/2 ori mai multe date. Algoritmul hipercub: eficient in probleme mici cu timp de lansare mare si timp de transfer mic!

25 Sortare Algoritm de sortare "mergesort" pentru N valori (multiplu al numarului de procesoare P=2d). Algoritmul secvential: daca lungimea secventei de intrare <2 atunci return partitioneaza secventa de intrare in doua jumatati sorteaza cele doua subsecvente utilizand acelasi algoritm fuzioneaza cele doua subsecvente sortate => secventa de iesire Exemplu: Timpul necesar: O(N log2N). Solutia paralela: necesita doi algoritmi: "compare-exchange" si "parallel merge".

26 Compare-exchange: fuzioneaza doua secvente ordonate de lungime M, continute in taskurile A si B.
-ambele taskuri contin M valori si toate elementele din A sunt ≤ elementele din B; -fiecare task trimite datele sale la celalalt task; -taskul A identifica M elemente cele mai mici, iar restul le descarca (necesitand intre M/2 pana la M comparatii); -taskul B identifica M elemente cele mai mari. Exemplu: M=4.

27 Parallel Merge. Un algoritm “parallel merge" executa o operatie de fuzionare peste doua secvente de lungime M2d, fiecare distribuita peste 2d taskuri pentru a produce o secventa singulara sortata de lungime M2d+1 distribuita peste 2d+1 taskuri. Aceasta se obtine prin utilizarea sablonului de comunicatie hipercub. Exemplu: algoritmul paralel merge-sort in hipercuburi: Intr-un hipercub de dimensiune d fiecare task executa d operatii de comparatie si interschimb. Sagetile orientate de la taskul "high" catre taskul "low" in fiecare interschimb.

28 Fiecare din cele 2d+1 taskuri se implica in d+1 pasi compara-interschimba, cate un pas cu fiecare vecin. Fiecare nod executa algoritmul general, aplicand la fiecare pas urmatorul operator: if ( myid AND 2i > 0 ) then state = compare_exchange_high(state,message) else state = compare_exchange_low(state,message) endif Operatorul logic AND este utilizat pentru a determina daca taskul este "high" sau "low" intr-un interschimb particular, iar myid si i sunt ca in algoritmul general.

29 Mergesort. Algoritmul “parallel mergesort" (fiecare task):
procedure parallel_mergesort(myid, d, data, newdata) begin data = sequential_mergesort(data) for dim = 1 to d data = parallel_merge(myid, dim, data) endfor newdata = data end -fiecare task sorteaza secventa sa locala utilizand mergesort secvential; -utilizand structura de comunicatie hipercub: fiecare dintre cele P=2d taskuri executa algoritmul mergesort paralel de d ori pentru subcuburi de dimensiune 1..d; -fuziunea paralela numarul i: ia doua secvente fiecare distribuita peste 2i-1 taskuri si genereaza o secventa sortata distribuita peste 2i taskuri; -dupa d astfel de fuziuni se obtine o singura lista distribuita peste 2d taskuri.

30 Analiza performantei. Numarul total de operatii comparatie-interschimb este:
Fiecare operatie de comparatie-interschimb necesita un mesaj continand N/P date => timpul necesar de comunicatie per procesor: sunt cuprinse sortarea initiala din procesor (implica Nlog2(N/P) comparatii) si comparatiile executate in timpul fazei de comunicatie (cel putin Nd(d+1)/2 comparatii) => timpul total pentru cele P procesoare:

31 Algoritmul perfect echilibrat
=> se presupune ca timpii inactivi sunt neglijabili. Astfel:

32 Programarea aplicatiilor paralele pe nCUBE-2
nCUBE-2 ( de la nCUBE Corporation) cu 8192 de noduri (procesor RISC, 32 biti, 64 MB memorie) conectate in retea hipercub. Primitivele de transfer de mesaje in reteaua hipercub -> C si Fortran. Transmisia (neblocanta) de mesaje: int nwrite (char * buffer, int dim, int address, int type); unde: type: tipul de transfer de mesaje (sincron sau asincron); buffer: adresa de memorie (in procesul care executa functia) de unde se transmite mesajul; dim: lungimea mesajului; address: adresa de destinatie a mesajului (un nod, grup de noduri la "multicast", toate nodurile la "broadcast").

33 Receptia (blocanta): int nread (char * buffer, int dim, int source, int type); Identificarea nodului curent (in care se desfasoara executia functiei): void whoami (int * node, int * res1, int *res2, int *cube); unde: node: pointer la variabilele in care whoami depune numarul (eticheta) nodului; cube: pointer la variabila in care se depune dimensiunea subcubului alocat programului curent; res1, 2: nu se utilizeaza. Proiectarea algoritmului: -se partitioneaza programul intr-un numar de procese; -se distribuie aceste procese nodurilor sistemului.

34 Exemplu: calculul aproximatiei numarului π.
/*functia de transfer de mesaje in hipercub*/ void fan_in (float *value, int node, int d) { int dest, i, source, type; float temp; type=FANIN; for (i=d-1; i>=0; i--) if (node<(1<<i)) { //00..00XX..X 0 in pozitia i source=node^(1<<i); nread (&temp, sizeof(float), &source, &type); *value+=temp; } else if (node<(1<<(i+1))) { //00..01XX..X dest=node^(1<<i); nwrite(value,sizeof(float),dest, type);

35 /*functia principala a programului*/
void main (int argc, char *argv[]) { #define n 1024 int i; int d; /*dimensiunea hipercubului*/ int p; /*numar de noduri*/ int node; /*eticheta nodului curent*/ int s; /*numar de subintervale/procesor*/ float x; /*mijloc dreptunghi pe axa x*/ float w=1/n; /*latimea intervalului*/ int res1, res2; float sum; whoami (&node, &res1, &res2, &d); p=1<<d; /*2 la puterea d*/ s=n/p; /*se presupune n divizibil cu p*/ sum=0.0; x=((node*s)+0.5)*w; for (i=node*s; i<(node+1)*s; i++) { sum+=4/(1+x*x); x+=w; } fan_in (&sum, node, d); if (node==0) /*rezultat nodul 0*/ printf ("Aproximatia numarului pi este %f\n", sum);

36 Etape: -fiecare nod calculeaza un rezultat partial pentru n/p subintervale (n = numar total de subintervale, p = numar de procesoare); -etapa de comunicatie pentru calcularea sumei finale. Fiecare nod: -executa functia main (fiecare nod are o copie) -> calcule locale; -apeleaza functia de transfer de mesaje fan_in. p procesoare => subcub d-dimensional (apel functie whoami: p = 2d). Rezultatul final (suma rezultatelor partiale in p noduri) => nodul 0 (00...0).

37 Comunicatia in hipercub:

38 Performante. Fiecare procesor executa n/p pasi pentru rezultatul partial, iar comunicatia necesita log2p pasi: -timpul de executie: -accelerarea: -eficienta:

39 BIBLIOTECA MPI -biblioteca de functii C sau subrutine Fortran => comunicatia intre procese; Avantaje: -portabilitatea codului sursa; -implementari eficiente pe o varietate de platforme (inclusiv Unix si Windows NT/XP); -functionalitate (tipuri diferite de comunicatie, tipuri de date definite de utilizator, topologii definite de utilizator); Dezavantaje: -mecanismul de lansare a unei aplicatii MPI dependent de platforma; -nu permite gestiunea dinamica a proceselor (modificarea numarului de procese in timpul rularii).

40 Forma generala a unui program MPI:
include fisiere header MPI declaratii variabile initializarea mediului MPI executa operatii si transfer de mesaje incheie mediu MPI => functiile MPI: rezultat intreg = cod succes / insucces; daca cod  MPI_SUCCESS => eroare!

41 Comunicatori -transferul de mesaje intre procese: in cadrul unor comunicatori. -comunicator initial predefinit: MPI_COMM_WORLD (cuprinde toate procesele) -se pot defini noi comunicatori; -in cadrul unui comunicator fiecare proces are un identificator („rank”); -un proces poate sa apartina la mai multi comunicatori in acelasi timp, cu identificatori diferiti.

42 Functii pentru gestiunea mediului MPI
   MPI_Init (&argc,&argv) initializeaza mediul MPI, unde parametrii functiei reprezinta argumentele liniei de comanda. MPI_Comm_size (comm,&size) furnizeaza pentru comunicatorul comm numarul de procese componente size. MPI_Comm_rank (comm,&rank) furnizeaza identificatorul procesului care a apelat-o (rank) in cadrul comunicatorului (comm). MPI_Finalize () incheie mediul de executie MPI.

43 Exemplu: utilizarea unor functii de gestiune a mediului MPI.
#include "mpi.h" #include <stdio.h> int main(int argc,char *argv) { int numtasks, rank, rc; rc = MPI_Init(&argc,&argv); if (rc != MPI_SUCCESS) { printf ("Error starting MPI program. Terminating.\n"); MPI_Abort(MPI_COMM_WORLD, rc); } MPI_Comm_size(MPI_COMM_WORLD,&numtasks); MPI_Comm_rank(MPI_COMM_WORLD,&rank); printf ("Number of tasks= %d My rank= %d\n", numtasks,rank); /******* do some work *******/ MPI_Finalize(); return 0;

44 Comunicatii punct-la-punct
=> comunicatie punct-la-punct: un proces transmite (executa “send”) si al doilea receptioneaza (executa “receive”).

45 Functiile utilizate pentru transmisie sunt:
Functiile utilizate pentru receptie sunt:

46 Pentru comunicatia blocanta standard se utilizeaza la transmisie:
MPI_Send (&buf,count,datatype,dest,tag,comm) care, transmite din zona buf, count date de tipul datatype la procesul destinatie dest, din cadrul comunicatorului comm, mesajul avand identificatorul tag. Pentru receptie: MPI_Recv (&buf,count,datatype,source,tag,comm,&status) datele fiind recptionate in zona buf la procesul care a apelat functia, in lungime count de tipul datatype, de la procesul sursa source din cadrul comunicatorului comm, mesajul avand identificatorul tag. Informatii de stare pentru mesajul receptionat sunt depuse la status.

47 Exemplu: utilizarea functiilor de transmisie / receptie blocante.
#include "mpi.h" #include <stdio.h> int main(int argc,char *argv[]) { int numtasks, rank, dest, source, rc, count, tag=1; char inmsg, outmsg='x'; MPI_Status Stat; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); MPI_Comm_rank(MPI_COMM_WORLD, &rank);

48 if (rank == 0) { dest = 1; source = 1; rc = MPI_Send(&outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD); rc = MPI_Recv(&inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat); } else if (rank == 1) { dest = 0; source = 0; rc = MPI_Get_count(&Stat, MPI_CHAR, &count); printf("Task %d: Received %d char(s) from task %d with tag %d \n", rank, count, Stat.MPI_SOURCE, Stat.MPI_TAG); MPI_Finalize(); return 0;

49 Transmisia si receptia neblocante:
-faza de initiere a operatiei; -faza de asteptare pentru terminarea operatiei. Initierea transmisiei: MPI_Isend (&buf,count,datatype,dest,tag,comm,&request) Initierea receptiei: MPI_Irecv (&buf,count,datatype,source,tag,comm,&request) (parametrii asemanatori cu functiile blocante).

50 Pentru incheierea unei operatii de transmisie sau receptie fara blocare:
MPI_Wait (&request,&status)  functie blocanta si MPI_Test (&request,&flag,&status)  functie neblocanta pentru o singura cerere transmisie / receptie   MPI_Waitall (count,&array_of_requests,&array_of_statuses) functie blocanta si MPI_Testall (count,&array_of_requests,&flag,&array_of_statuses) functie neblocanta pentru mai multe cereri.

51 Exemplu: comunicatie punct-la-punct neblocanta.
#include "mpi.h" #include <stdio.h> int main(int argc,char *argv) { int numtasks, rank, next, prev, buf[2], tag1=1, tag2=2; MPI_Request reqs[4]; MPI_Status stats[4]; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); MPI_Comm_rank(MPI_COMM_WORLD, &rank);

52 prev = rank-1; next = rank+1; if (rank == 0) prev = numtasks - 1; if (rank == (numtasks - 1)) next = 0; MPI_Irecv(&buf[0], 1, MPI_INT, prev, tag1, MPI_COMM_WORLD, &reqs[0]); MPI_Irecv(&buf[1], 1, MPI_INT, next, tag2, MPI_COMM_WORLD, &reqs[1]); MPI_Isend(&rank, 1, MPI_INT, prev, tag2, MPI_COMM_WORLD, &reqs[2]); MPI_Isend(&rank, 1, MPI_INT, next, tag1, MPI_COMM_WORLD, &reqs[3]); { executa secventa de operatii } MPI_Waitall(4, reqs, stats); MPI_Finalize(); return 0; }

53 Comunicatii colective
-un numar mai mare de procese comunica intre ele in diferite moduri; -avantaje in raport cu operatiile punct-la-punct: -reducerea posibilitatii de eroare; -reducerea numarului de linii de program; -sursa este mai lizibila pentru depanare si modificare; -viteza de executie creste.

54 Broadcast: un singur proces trimite cate o copie a unei date la toate celelalte procese dintr-un grup. MPI_Bcast (&buffer,count,datatype,root,comm) Procesul root trimite blocul de date din buffer de lungime count si tip datatype la toate procesele din cadrul comunicatorului, fiecare proces plasand datele in memoria sa in zona buffer.

55 Scatter: un bloc de date (un tablou de un anumit tip) de la un proces este impartit in bucati si distribuit uniform la diferite procese. MPI_Scatter (&sendbuf,sendcnt,sendtype,&recvbuf, recvcnt,recvtype,root,comm) Procesul root trimite din zona sendbuf de lungime sendcnt si tip sendtype la fiecare proces al comunicatorului comm cate un set de date depus in zona recvbuf, de lungime recvcnt si tip recvtype.

56 Gather colecteaza blocuri de date de la un grup de procese si le reasambleaza in ordinea corecta la un singur proces. MPI_Gather (&sendbuf,sendcnt,sendtype,&recvbuf, recvcount,recvtype,root,comm) Procesul root receptioneaza in recvbuf de lungime recvcount si tip recvtype cate un bloc de date de la fiecare proces al comunicatorului comm din zona sendbuf lungime sendcnt si tip sendtype.

57 Reducere: un singur proces (procesul radacina) colecteaza datele de la celelalte procese dintr-un grup si le combina pe baza unei operatii intr-o singura data. MPI_Reduce (&sendbuf,&recvbuf,count,datatype,op,root,comm) Datele de la toate procesele comunicatorului comm din zona sendbuf lungime count si tip datatype sunt prelucrate cu operatia de reducere op si rezultatul inscris la procesul root in zona recvbuf.

58 Operatia poate sa fie:

59 Sincronizare: prelucrarile pot continua numai daca toate procesele au ajuns intr-un anumit punct al prelucrarilor. MPI_Barrier (comm) Blocheaza procesele comunicatorului comm pe masura ce functia este apelata de catre acestea pana cand toate procesele comunicatorului au apelat aceasta functie. La revenirea din functie toate procesele sunt sincronizate.

60 Exemplu: operatie „scatter” pentru liniile unei matrici.
#include "mpi.h" #include <stdio.h> #define SIZE 4 int main(int argc,char *argv[]) { int numtasks, rank, sendcount, recvcount, source; float sendbuf[SIZE][SIZE] = { {1.0, 2.0, 3.0, 4.0}, {5.0, 6.0, 7.0, 8.0}, {9.0, 10.0, 11.0, 12.0}, {13.0, 14.0, 15.0, 16.0} }; float recvbuf[SIZE];

61 MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); if (numtasks == SIZE) { source = 1; sendcount = SIZE; recvcount = SIZE; MPI_Scatter(sendbuf,sendcount,MPI_FLOAT,recvbuf,recvcount, MPI_FLOAT,source,MPI_COMM_WORLD); printf("rank= %d Results: %f %f %f %f\n",rank,recvbuf[0], recvbuf[1],recvbuf[2],recvbuf[3]); } else printf("Must specify %d processors. Terminating.\n",SIZE); MPI_Finalize(); return 0;

62 Biblioteca PVM -functii portabile de nivel inalt pentru C si Fortran -> comunicatia in cadrul unui grup de procese; -compozitia grupului de procese este dinamica => cost suplimentar destul de ridicat; -un multicalculator (o retea de calculatoare) -> calculator virtual paralel, prin transfer de mesaje; -permite controlul proceselor, transmiterea si receptia mesajelor, sincronizarea intre procese. Masina virtuala paralela PVM : -procesele server PVM (demonii PVM); -biblioteca de functii PVM.

63 Initializarea masinii virtuale PVM: prin lansarea procesului server master cu functia:
pvm_start_pvmd urmata de apelul functiei de setare a optiunilor de comunicatie: pvm_setopt Pe procesorul server master : hostfile (numele statiilor, caile de fisiere executabile, caile pentru procesele server (demonii) din fiecare statie, contul utilizatorului, parola etc.). Adaugare statii noi: pvm_addhosts Excludere statii: pvm_delhosts

64 Oprirea masinii virtuale:
  pvm_halt Atasarea la masina virtuala PVM :   pvm_mytid => identificator de task (tid), numar intreg pe 32 de biti. Crearea dinamica de procese:   pvm_spawn Exemplu:   numt=pvm_spawn ("my_task", NULL, PvmTaskDefault, 0, n_task, tids); creaza n_task procese care executa programul "my_task". Rezultatul functiei este numarul efectiv de procese create (numt). Identificatorul fiecarui task creat este depus intr-un element al vectorului tids. Un proces poate parasi configuratia masinii PVM:   pvm_exit sau poate fi terminat de alt proces:   pvm_halt (tid)

65 Exemplu: program "Hello World!":
main() { int cc, tid, msgtag; char buf[100]; printf("i'm t%x\n", pvm_mytid()); cc = pvm_spawn("hello_other", (char**)0, 0, "", 1, &tid); if (cc == 1) { msgtag = 1; pvm_recv(tid, msgtag); pvm_upkstr(buf); printf("from t%x: %s\n", tid, buf); } else printf("can't start hello_other\n"); pvm_exit(); }

66 Modele de programare ale interfetei PVM
-SPMD (Single Program Multiple Data): n instante ale aceluiasi program sunt lansate ca n taskuri ale unei aplicatii paralele, folosind comanda spawn de la consola PVM sau manual in cele n statii simultan. Initializarea mediului de programare: specificarea statiilor pe care se executa cele n taskuri (nu se apeleaza pvm_spawn). -MPMD (Multiple Program Multiple Data): unul sau mai multe taskuri sunt lansate in diferite statii si acestea creaza dinamic alte taskuri.

67 Comunicatia punct-la-punct
Mesaj: proces A -> proces B => procesul A initializeaza bufferul de transmisie: int pvm_initsend (int encode); (encode stabileste tipul de codare a datelor in buffer) => identificator al bufferului de transmisie in care se depun datele impachetate cu: pvm_pack Transmiterea mesajului: int pvm_send (int tid, int msgtag); (functie blocanta) tid = identificatorul mesajului de receptie, msgtag = tipul mesajului (specifica prelucrari la receptie) => valoarea 0 pentru transmisie corecta si –1 la eroare.

68 Receptia: int pvm_recv (int tid, int msgtag); (functie blocanta) tid = identificatorul procesului sursa. Receptia: si pentru orice transmitator (tid = -1) si orice tip de mesaj (msgtag = -1). => identificatorul bufferului de receptie (bufid), de unde datele sunt extrase cu: pvm_unpack Receptia neblocanta: pvm_nrecv

69 Comunicatia colectiva:
Atasarea unui proces la un grup (daca grupul nu exista, el este creat):   int pvm_joingroup (char *group_name); => 0 pentru procesul care creaza grupul si valoarea cea mai mica disponibila in grup pentru fiecare proces urmator (un proces poate sa apartina la unul sau mai multe grupuri). Parasirea unui grup de catre un proces: int pvm_lvgroup (char *group_name); Obtinerea de informatii despre grup: pvm_getinst => identificatorul instantei procesului in grup; pvm_getid => identificatorul procesului; pvm_gsize => dimensiunea grupului.

70 Comunicatiile colective (intre procesele membre ale unui grup) :
int pvm_bcast (char *group_name, int msgtag); difuzeaza asincron mesajul cu flagul msgtag din bufferul de transmisie al procesului apelant catre toate procesele membre ale grupului group_name (procesul apelant poate sa fie sau nu membru al grupului). int pvm_gather (void *g_arrray, void *myarray, int dim, int type, int msgtag, char *group_name, int root); colecteaza mesajele cu flagul msgtag, de la toate procesele grupului, in procesul radacina (definit de utilizator) root, colectarea facandu-se in vectorul g_array, de dimensiune dim si tip type. Fiecare proces trebuie sa apeleze pvm_gather.

71 int pvm_scatter (void. myarray, void
int pvm_scatter (void *myarray, void *s_arrray, int dim, int type, int msgtag, char *group_name, int root); distribuie uniform tuturor proceselor din grup un vector de date de tipul type, cu numele s_array si de dimensiune dim, aflat in spatiul de adresa al procesului radacina root. Fiecare proces apeleaza pvm_scatter. Receptia se face in vectorul my_array. int pvm_reduce (int operation, void *myvals, int dim, int type, int msgtag, char *group_name, int root); efectueaza operatia de reducere paralela intre toate procesele membre ale unui grup. Argumentul operation defineste operatorul de reducere (PvmMin, PvmMax, PvmSum, PvmProduct). Fiecare proces efectueaza operatia de reducere a datelor din vectorul local de date myvals, de tipul type, de dimensiune dim, iar valoarea rezultata este transferata procesului radacina root, care obtine valoarea de reducere finala. int pvm_barrier (char *group_name, int ntasks); sincronizeaza procesele membre ale unui grup (procesul este blocat pana cand un numar ntasks procese din grupul group_name au apelat aceasta functie).

72 Exemplu: operatia de reducere paralela in masina virtuala PVM.
#include #include "pvm3.h" #define NTASKS 4 int main () { int mytid, tids[NTASKS-1], groupid, sum, info; /*crearea grupului de comunicatie*/ mytid=pvm_mytid(); groupid=pvm_joingroup("summax"); sum=groupid; /*primul proces creaza celelalte NTASK-1 procese*/ if (groupid==0) { info=pvm_spawn("summax",NULL,PvmTaskDefault," ", NTASKS-1, tids); printf("GroupId=%d spawned %d tasks\n", groupid, info); }

73 /*bariera prin inghetare pana ce NTASKS procese s-au alaturat grupului*/
pvm_freezgroup("summax", NTASKS); /*calculul sumei in grup*/ pvm_reduce (PvmSum, &sum, 1, PVM_INT, 1, "summax", 0); /*procesul 0 tipareste rezultatul*/ if (groupid==0) { printf("sum=%d\n", sum); } /*sincronizare pentru ca toate procesele sa execute operatia inainte de parasirea grupului*/ pvm_barrier ("summex", NTASKS); pvm_lvgroup ("summax"); pvm_exit(); return 0;


Κατέβασμα ppt "PROGRAMAREA MULTICALCULATOARELOR"

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google