Structuri în MPI
În MPI putem să schimbăm date de tipul struct. Putem să facem acest lucru creând mai întâi un nou tip de date MPI (MPI_Datatype), folosind MPI_Type_create_struct căruia îi precizăm numărul câmpurilor de fiecare tip și mărimea lor din structură, așezarea câmpurilor în memorie (folosind offsets și MPI_Aint).
Semnătura funcției MPI_Type_create_struct este următoarea:
int MPI_Type_create_struct(int count, const int array_of_blocklengths[], const MPI_Aint array_of_displacements[], const MPI_Datatype array_of_types[], MPI_Datatype *newtype)
Și are următorii parametri:
- count (↓) - număr de blocuri (de asemenea, numărul de intrări în vectorii array_of_types, array_of_displacements și array_of_blocklengths)
- array_of_blocklengths[] (↓) - numărul de elemente din fiecare bloc
- MPI_Aint array_of_displacements[] (↓) - deplasarea octeților pentru fiecare bloc
- array_of_types[] (↓) - tipul de elemente din fiecare bloc
- *newtype (↑) - noul tip de date
sugestie
Deplasarea octeților pentru fiecare bloc se calculează cu ajutorul funcției offsetof. Mai multe detalii despre folosirea ei puteți găsi aici: tutorialspoint.
Exemplu de folosire:
#include <mpi.h>
#include <stdio.h>
#include <stddef.h>
// structura aflata la baza tipului custom
typedef struct {
float f1, f2;
char c;
int i[2];
} custom_type;
int main(int argc, char *argv[]) {
int numtasks, rank, source = 0, dest = 1, tag = 1;
custom_type t;
MPI_Datatype customtype, oldtypes[4];
int blockcounts[4];
MPI_Aint offsets[4];
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
// campul f1
offsets[0] = offsetof(custom_type, f1);
oldtypes[0] = MPI_FLOAT;
blockcounts[0] = 1;
// campul f2
offsets[1] = offsetof(custom_type, f2);
oldtypes[1] = MPI_FLOAT;
blockcounts[1] = 1;
// campul c
offsets[2] = offsetof(custom_type, c);
oldtypes[2] = MPI_CHAR;
blockcounts[2] = 1;
// campul i
offsets[3] = offsetof(custom_type, i);
oldtypes[3] = MPI_INT;
blockcounts[3] = 2;
// se defineste tipul nou si se comite
MPI_Type_create_struct(4, blockcounts, offsets, oldtypes, &customtype);
MPI_Type_commit(&customtype);
if (rank == 0) {
t.f1 = 0.5;
t.f2 = -1.2;
t.c = 'a';
t.i[0] = 0;
t.i[1] = 1;
MPI_Send(&t, 1, customtype, dest, tag, MPI_COMM_WORLD);
} else if (rank == 1) {
MPI_Recv(&t, 1, customtype, source, tag, MPI_COMM_WORLD, &status);
printf("Received custom type with f1=%.1f, f2=%.1f, c=%c, i[0]=%d, i[1]=%d\n", t.f1, t.f2, t.c, t.i[0], t.i[1]);
}
// se elibereaza tipul nou cand nu se mai foloseste
MPI_Type_free(&customtype);
MPI_Finalize();
}