Sari la conținutul principal

Gather

MPI_Gather

MPI_Gather este o funcție care reprezintă inversul lui MPI_Scatter, în sensul că un proces primește elemente de la fiecare proces din comunicator, inclusiv de la el însuși, și le unifică într-o singură colecție.

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:

  • send_data (↓) - reprezintă datele care 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_datatype (↓) - tipul datelor trimise de către procese
  • 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_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)
  • communicator (↓) - comunicatorul din care fac parte procesele (de regulă MPI_COMM_WORLD)

O ilustrare a modului cum funcționează MPI_Gather:

img

Mai jos aveți un exemplu de MPI_Scatter folosit împreună cu MPI_Gather:

Exemplu
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

#define ROOT 0
#define CHUNK_SIZE 5 // numarul de elemente per proces

int main (int argc, char **argv) {
int rank, proc, a;

int* arr;
int* process_arr;
int* result_arr;

MPI_Init(&argc, &argv);

MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &proc);

if (rank == ROOT) {
arr = malloc (CHUNK_SIZE * proc * sizeof(int));
for (int i = 0; i < proc * CHUNK_SIZE; ++i) {
arr[i] = 0;
}
}

process_arr = malloc (CHUNK_SIZE * sizeof(int));
MPI_Scatter(arr, CHUNK_SIZE, MPI_INT, process_arr, CHUNK_SIZE, MPI_INT, ROOT, MPI_COMM_WORLD);

for (int i = 0; i < CHUNK_SIZE; i++) {
printf("Before: rank [%d] - value = %d\n", rank, process_arr[i]);
process_arr[i] = i;
printf("After: rank [%d] - value = %d\n", rank, process_arr[i]);
}

if (rank == ROOT) {
result_arr = malloc (CHUNK_SIZE * proc * sizeof(int));
}

MPI_Gather(process_arr, CHUNK_SIZE, MPI_INT, result_arr, CHUNK_SIZE, MPI_INT, ROOT, MPI_COMM_WORLD);

if (rank == ROOT) {
for (int i = 0; i < CHUNK_SIZE * proc; i++) {
printf("%d ", result_arr[i]);
}
printf("\n");
}

if (rank == ROOT) {
free(arr);
free(result_arr);
}

free(process_arr);

MPI_Finalize();
return 0;
}