This shows you the differences between two versions of the page.
|
app:laboratoare:05 [2022/10/31 14:46] emil.slusanschi |
app:laboratoare:05 [2025/11/12 11:20] (current) alexandru.bala [MPI_Gather] |
||
|---|---|---|---|
| Line 36: | Line 36: | ||
| MPI_Init(&argc, &argv); | MPI_Init(&argc, &argv); | ||
| MPI_Comm_size(MPI_COMM_WORLD, &numtasks); | MPI_Comm_size(MPI_COMM_WORLD, &numtasks); | ||
| - | MPI_Comm_rank(MPI_COMM_WORLD,&rank); | + | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
| MPI_Get_processor_name(hostname, &len); | MPI_Get_processor_name(hostname, &len); | ||
| if (rank == MASTER) | if (rank == MASTER) | ||
| - | printf("MASTER: Number of MPI tasks is: %d\n",numtasks); | + | printf("[Hostname %s] MASTER: Number of MPI tasks is: %d\n", hostname, numtasks); |
| else | else | ||
| - | printf("WORKER: Rank: %d\n",rank); | + | printf("[Hostname %s] WORKER: Rank: %d\n", hostname, rank); |
| MPI_Finalize(); | MPI_Finalize(); | ||
| Line 50: | Line 50: | ||
| Funcții: | Funcții: | ||
| - | * ''MPI_Init'' - se inițializează programul MPI, mai precis se creează contextul în cadrul căruia rulează procesele. Argumentele din linie de comandă sunt pasate către contextul de rulare a proceselor. | + | * ''MPI_Init'' - se inițializează programul MPI, mai precis se creează contextul în cadrul căruia rulează procesele. Argumentele din linia de comandă sunt pasate către contextul de rulare a proceselor. |
| * ''MPI_Comm_size'' - funcție care determină numărul de procese (numtasks) care rulează în cadrul comunicatorului (de regulă MPI_COMM_WORLD) | * ''MPI_Comm_size'' - funcție care determină numărul de procese (numtasks) care rulează în cadrul comunicatorului (de regulă MPI_COMM_WORLD) | ||
| * ''MPI_Comm_rank'' - funcție care determină identificatorul (rangul) procesului curent în cadrul comunicatorului. | * ''MPI_Comm_rank'' - funcție care determină identificatorul (rangul) procesului curent în cadrul comunicatorului. | ||
| Line 81: | Line 81: | ||
| * ''tag'' (↓) - identificator al mesajului | * ''tag'' (↓) - identificator al mesajului | ||
| * ''communicator'' (↓) - comunicatorul în cadrul căruia se face trimiterea datelor între cele două procese | * ''communicator'' (↓) - comunicatorul în cadrul căruia se face trimiterea datelor între cele două procese | ||
| - | MPI_Send este o funcție blocantă. Mai precis, programul se blochează până când bufferul dat ca prim parametru poate fi refolosit, chiar dacă nu se execută acțiunea de primire a mesajului transmis de procesul curent (MPI_Recv). Dacă apare cazul în care procesul P1 trimite date (MPI_Send) la procesul P2, iar P2 nu are suficient loc în buffer-ul de recepție (buffer-ul nu are suficient loc liber sau este plin) atunci P1 se va bloca. | + | MPI_Send este o funcție blocantă. Mai precis, programul se blochează până când buffer-ul dat ca prim parametru poate fi refolosit, chiar dacă nu se execută acțiunea de primire a mesajului transmis de procesul curent (MPI_Recv). Dacă apare cazul în care procesul P1 trimite date (MPI_Send) la procesul P2, iar P2 nu are suficient loc în buffer-ul de recepție (buffer-ul nu are suficient loc liber sau este plin), atunci P1 se va bloca. |
| ==== MPI_Recv ==== | ==== MPI_Recv ==== | ||
| Line 93: | Line 93: | ||
| * ''tag'' (↓) - identificator al mesajului | * ''tag'' (↓) - identificator al mesajului | ||
| * ''communicator'' (↓) - comunicatorul în cadrul căruia se face trimiterea datelor între cele două procese | * ''communicator'' (↓) - comunicatorul în cadrul căruia se face trimiterea datelor între cele două procese | ||
| - | * ''status'' - conține date despre mesajul primit, ''MPI_Status'' fiind o structură ce conține informații despre mesajul primit (sursa, tag-ul mesajului, dimensiunea mesajului). Dacă nu dorim să ne folosim de datele despre mesajul primit, punem ''MPI_STATUS_IGNORE'', prin care se ignoră status-ul mesajului. | + | * ''status'' (↑) - conține date despre mesajul primit, ''MPI_Status'' fiind o structură ce conține informații despre mesajul primit (sursa, tag-ul mesajului, dimensiunea mesajului - trebuie apelată funcția ''MPI_Get_Count''). Dacă nu dorim să ne folosim de datele despre mesajul primit, punem ''MPI_STATUS_IGNORE'', prin care se ignoră status-ul mesajului. |
| În situația în care procesul P apelează funcția de MPI_Recv(), el se va bloca până va primi toate datele asteptate, astfel că dacă nu va primi nimic sau ceea ce primește este insuficient, P va rămâne blocat. Adică MPI_Recv() se termină doar în momentul în care buffer-ul a fost umplut cu datele așteptate. | În situația în care procesul P apelează funcția de MPI_Recv(), el se va bloca până va primi toate datele asteptate, astfel că dacă nu va primi nimic sau ceea ce primește este insuficient, P va rămâne blocat. Adică MPI_Recv() se termină doar în momentul în care buffer-ul a fost umplut cu datele așteptate. | ||
| Structura ''MPI_Status'' include următoarele câmpuri: | Structura ''MPI_Status'' include următoarele câmpuri: | ||
| - | * ''int count'' - dimensiunea datelor primite | ||
| * ''int MPI_SOURCE'' - identificatorul procesului sursă, care a trimis datele | * ''int MPI_SOURCE'' - identificatorul procesului sursă, care a trimis datele | ||
| * ''int MPI_TAG'' - tag-ul mesajului primit | * ''int MPI_TAG'' - tag-ul mesajului primit | ||
| + | * ''int MPI_ERROR'' - codul de eroare asociat operației de comunicare | ||
| - | MPI_Recv este o funcție blocantă, mai precis programul se poate bloca până când se execută acțiunea de trimitere a mesajului către procesul sursă. | + | MPI_Recv este o funcție blocantă, mai precis programul se poate bloca până când se execută acțiunea de trimitere a mesajului de către procesul sursă. |
| Un exemplu de program în care un proces trimite un mesaj către un alt proces: | Un exemplu de program în care un proces trimite un mesaj către un alt proces: | ||
| Line 117: | Line 117: | ||
| MPI_Init(&argc, &argv); | MPI_Init(&argc, &argv); | ||
| MPI_Comm_size(MPI_COMM_WORLD, &numtasks); // Total number of processes. | MPI_Comm_size(MPI_COMM_WORLD, &numtasks); // Total number of processes. | ||
| - | MPI_Comm_rank(MPI_COMM_WORLD,&rank); // The current process ID / Rank. | + | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // The current process ID / Rank. |
| MPI_Get_processor_name(hostname, &len); | MPI_Get_processor_name(hostname, &len); | ||
| Line 166: | Line 166: | ||
| MPI_Init(&argc, &argv); | MPI_Init(&argc, &argv); | ||
| MPI_Comm_size(MPI_COMM_WORLD, &numtasks); | MPI_Comm_size(MPI_COMM_WORLD, &numtasks); | ||
| - | MPI_Comm_rank(MPI_COMM_WORLD,&rank); | + | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
| MPI_Get_processor_name(hostname, &len); | MPI_Get_processor_name(hostname, &len); | ||
| Line 210: | Line 210: | ||
| * ''data'' (↓ + ↑) - reprezintă datele care sunt transmise către toate procesele. Acest parametru este de tip input pentru procesul cu identificatorul ''root'' și este de tip output pentru restul proceselor. | * ''data'' (↓ + ↑) - reprezintă datele care sunt transmise către toate procesele. Acest parametru este de tip input pentru procesul cu identificatorul ''root'' și este de tip output pentru restul proceselor. | ||
| * ''count'' (↓) - dimensiunea datelor trimise | * ''count'' (↓) - dimensiunea datelor trimise | ||
| - | * ''datatype'' (↓)- tipul datelor trimise | + | * ''datatype'' (↓) - tipul datelor trimise |
| * ''root'' (↓) - rangul / identificatorului procesului sursă, care trimite datele către toate procesele din comunicator, inclusiv lui însuși | * ''root'' (↓) - rangul / identificatorului procesului sursă, care trimite datele către toate procesele din comunicator, inclusiv lui însuși | ||
| * ''tag'' (↓) - identificator al mesajului | * ''tag'' (↓) - identificator al mesajului | ||
| Line 228: | Line 228: | ||
| * ''send_datatype'' (↓) - tipul datelor trimise către procese | * ''send_datatype'' (↓) - tipul datelor trimise către procese | ||
| * ''recv_data'' (↑) - reprezintă datele care sunt primite și stocate de către procese | * ''recv_data'' (↑) - reprezintă datele care sunt primite și stocate de către procese | ||
| - | * ''recv_count'' (↓) - dimensiunea datelor primite (de regulă dimensiunea_totală / număr_de_procese) | + | * ''recv_count'' (↓) - dimensiunea datelor primite (de regulă este egală cu send_count) |
| * ''recv_datatype'' (↓) - tipul datelor primite de către procese (de regulă este același cu send_datatype) | * ''recv_datatype'' (↓) - tipul datelor primite de către procese (de regulă este același cu send_datatype) | ||
| * ''root'' (↓) - identificatorul procesului care împarte datele și care le trimite către procesele din comunicator, inclusiv lui însuși | * ''root'' (↓) - identificatorul procesului care împarte datele și care le trimite către procesele din comunicator, inclusiv lui însuși | ||
| Line 241: | Line 241: | ||
| Semnătura funcției este următoarea: | Semnătura funcției este următoarea: | ||
| ''int MPI_Gather(void* send_data, int send_count, MPI_Datatype send_datatype, void* recv_data, int recv_count, MPI_Datatype recv_datatype, int root, MPI_Comm communicator)'', unde: | ''int MPI_Gather(void* send_data, int send_count, MPI_Datatype send_datatype, void* recv_data, int recv_count, MPI_Datatype recv_datatype, int root, MPI_Comm communicator)'', unde: | ||
| - | * ''send_data'' (↓) - reprezintă datele care trimise de fiecare proces către procesul cu id-ul root | + | * ''send_data'' (↓) - reprezintă datele trimise de fiecare proces către procesul cu id-ul root |
| * ''send_count'' (↓) - reprezintă dimensiunea bucății trimisă de fiecare proces (de regulă se pune ca fiind dimensiunea_totală / număr_de_procese). | * ''send_count'' (↓) - reprezintă dimensiunea bucății trimisă de fiecare proces (de regulă se pune ca fiind dimensiunea_totală / număr_de_procese). | ||
| * ''send_datatype'' (↓) - tipul datelor trimise de către procese | * ''send_datatype'' (↓) - tipul datelor trimise de către procese | ||
| * ''recv_data'' (↑) - reprezintă datele care sunt primite și stocate de către procesul root | * ''recv_data'' (↑) - reprezintă datele care sunt primite și stocate de către procesul root | ||
| - | * ''recv_count'' (↓) - dimensiunea datelor primite (de regulă dimensiunea_totală / număr_de_procese) | + | * ''recv_count'' (↓) - dimensiunea datelor primite (de regulă este egală cu send_count) |
| * ''recv_datatype'' (↓) - tipul datelor primite de către procesul root (de regulă este același cu send_datatype) | * ''recv_datatype'' (↓) - tipul datelor primite de către procesul root (de regulă este același cu send_datatype) | ||
| * ''root'' (↓) - identificatorul procesului care primește datele (inclusiv de la el însuși) | * ''root'' (↓) - identificatorul procesului care primește datele (inclusiv de la el însuși) | ||
| Line 259: | Line 259: | ||
| #include <stdio.h> | #include <stdio.h> | ||
| #include <stdlib.h> | #include <stdlib.h> | ||
| - | #include <mpi.h> | + | #include "mpi.h" |
| #define ROOT 0 | #define ROOT 0 | ||