In the following code I’m trying to pass a mixed data struct of a double and an int using MPI one-sided communication via MPI windows. This is all illustrated in the following.
#include <stdio.h>
#include <mpi.h>
// ----------------------------------------------------------------------------
typedef struct
{
double a;
int n;
} STRUCT1;
// ----------------------------------------------------------------------------
void deregister_mpi_type(MPI_Datatype type)
{
MPI_Type_free(&type);
}
// ----------------------------------------------------------------------------
MPI_Datatype register_struct_type()
{
constexpr std::size_t num_members = 2;
int lengths[num_members] = {1, 1};
MPI_Aint offsets[num_members];
MPI_Aint base;
MPI_Datatype dTypes[num_members] = {MPI_DOUBLE_PRECISION, MPI_INT};
STRUCT1 s1 = {};
MPI_Get_address(&s1, offsets);
MPI_Get_address(&s1.n, offsets+1);
base = offsets[0];
for(int i=0; i < num_members; ++i) offsets[i] = MPI_Aint_diff(offsets[i], base);
MPI_Datatype dType;
MPI_Type_create_struct(num_members, lengths, offsets, dTypes, &dType);
MPI_Type_commit(&dType);
return dType;
}
// ----------------------------------------------------------------------------
int main (int argc, char *argv[])
{
int my_rank, size, right, left;
STRUCT1 snd_buf;
STRUCT1 *rcv_buf;
double sum;
int i;
int count;
MPI_Status status;
MPI_Request request;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
right = (my_rank+1) % size;
left = (my_rank-1+size) % size;
MPI_Datatype AType = register_struct_type();
MPI_Win window;
MPI_Win_allocate( (MPI_Aint) sizeof(STRUCT1), sizeof(STRUCT1), MPI_INFO_NULL, MPI_COMM_WORLD, &rcv_buf, &window );
sum = 0;
count = 0;
snd_buf.n = my_rank;
snd_buf.a = 1;
printf("RANK[%i] a: %fn", snd_buf.n, snd_buf.a);
MPI_Aint zero_disp = 0;
for( i = 0; i < size; i++)
{
MPI_Win_fence(0, window);
MPI_Put(&snd_buf, 1, AType, right, zero_disp, 1, AType, window);
MPI_Win_fence(0, window);
snd_buf.n = rcv_buf->n;
snd_buf.a = rcv_buf->a;
sum += rcv_buf->n;
count += rcv_buf->a;
}
MPI_Win_free(&window);
deregister_mpi_type(AType);
printf(" PE [%2d] Sum = %i Count = %fn", my_rank, sum, count);
MPI_Finalize();
}
I’m using OpenMPI 3.1 and the code compiles and builds an executable.
The Sum should be the sum of the process numbers while the Count should be the number of processes / processors. But, for me, I see the opposite. Please run more with more than -np 3 when you test.
If the struct uses all doubles or all ints, then the results are as expected. To successfully test that one needs to change some variable declarations and format specifications in the printf statements.
So, there are 2 questions. Is it possible to use a structure like this with one-sided communication? If so, what do I have wrong in the example code shown above?
6