i have a probelm with mpi and MPI_Allgather and MPI_pack. I have structure :
typedef struct{
float a;
int b;
int c[];
}struc_t;
I intialize my structure :
struc_t* test=(struc_t*)malloc(sizeof(struc_t)+200*sizeof(int));
And i would like send a array of my structure with MPI_Allgather :
int sizeSend,sizeRcv;
char *bufferSend,*bufferRecv;
int positionSend,PositionRecv;
MPI_Pack_size(10, MPI_MYTYPE , MPI_COMM_WORLD , &sizeSend);
MPI_Pack_size(10*nbProc, MPI_MYTYPE , MPI_COMM_WORLD , &sizeRcv);
MPI_Status statut;
The code of MPI_MYTYPE:
MPI_Aint offsets[3],extent;
int blockcounts[3];
MPI_Datatype oldtypes[3];
MPI_Datatype TAB;
MPI_Type_contiguous(nb,MPI_INT,&TAB);
MPI_Type_commit(&TAB);
offsets[0]=0;
oldtypes[0] = MPI_FLOAT;
blockcounts[0] = 1;
MPI_Type_extent(MPI_FLOAT, &extent);
offsets[1]=extent;
oldtypes[1] = MPI_INT;
blockcounts[1] = 1;
MPI_Type_extent(MPI_INT, &extent);
offsets[2]=extent + offsets[1];
oldtypes[2] = TAB;
blockcounts[2] =1;
MPI_Type_struct(3, blockcounts, offsets, oldtypes, dptr);
MPI_Type_commit(MPI_MYTYPE);
I create my pack :
positionSend=0;
positionRcv=0;
bufferSend = (char*) malloc(sizeSend);
bufferRecv = (char*) malloc(sizeRcv);
for(i=0;i<10;i++){
struc_t *elm = getElement(i);
MPI_Pack(&elm->a,1,MPI_FLOAT,bufferSend,sizeSend,&positionSend,MPI_COMM_WORLD);
MPI_Pack(&elm->b,1,MPI_INT,bufferSend,sizeSend,&positionSend,MPI_COMM_WORLD);
MPI_Pack(elm->c,200,MPI_INT,bufferSend,sizeSend,&positionSend,MPI_COMM_WORLD);
}
and the reception :
MPI_Allgather(bufferSend,1, MPI_PACKED, bufferRecv,1,MPI_PACKED, MPI_COMM_WORLD);
for(i=0;i<10*nbProc;i++){
struc_t* recvStruc=(struc_t*)malloc(sizeof(struc_t)+200*sizeof(int));
MPI_Unpack(bufferRecv, sizeRcv, &positionRcv,&recvStruc->a,1, MPI_FLOAT,MPI_COMM_WORLD);
MPI_Unpack(bufferRecv, sizeRcv, &positionRcv,&recvStruc->b,1, MPI_INT,MPI_COMM_WORLD);
MPI_Unpack(bufferRecv, sizeRcv, &positionRcv,recvStruc->c,200, MPI_INT,MPI_COMM_WORLD);
}
But the resultat of recvStruc is 0 :( where is the problem? If you help me, I call you god lol.
thx
Why pack your structs? It might make sense if they were variable length, but here you are transmitting the 200 integers anyway. A better solution is to just use the MPI datatypes. That way you have a chance of avoiding memory copies, and if the MPI library does need to pack your data behind the scenes, it can do it automatically.
Here's a working example:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
typedef struct{
float a;
int b;
int c[];
} struc_t;
int main (int argc, char **argv)
{
MPI_Init(&argc, &argv);
int nproc;
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
struc_t *test;
MPI_Aint struc_t_size;
MPI_Datatype struc_t_type;
{
int blocklen[] = {1, 1, 200};
MPI_Aint addr[4];
MPI_Address(test, &addr[0]);
MPI_Address(&test->a, &addr[1]);
MPI_Address(&test->b, &addr[2]);
MPI_Address(&test->c, &addr[3]);
MPI_Aint disp[] = { addr[1] - addr[0],
addr[2] - addr[0],
addr[3] - addr[0] };
MPI_Datatype types[] = {MPI_FLOAT, MPI_INT, MPI_INT};
MPI_Type_create_struct(3, blocklen, disp, types, &struc_t_type);
MPI_Type_commit(&struc_t_type);
}
MPI_Type_extent(struc_t_type, &struc_t_size);
test = malloc(struc_t_size);
// Put our rank in b to verify operation
MPI_Comm_rank(MPI_COMM_WORLD, &test->b);
void *buf = malloc(struc_t_size * nproc);
MPI_Allgather(test, 1, struc_t_type, buf, 1, struc_t_type, MPI_COMM_WORLD);
MPI_Type_free(&struc_t_type);
{
int i;
struc_t *p;
// Verify that everything was received correctly
for (i = 0; i < nproc; i++) {
p = buf + struc_t_size * i;
printf("%d %d\n", i, p->b);
}
}
MPI_Finalize();
return 0;
}