Arkerone
Arkerone

Reputation: 2026

Mpi_allgather and mpi_pack in C

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

Upvotes: 2

Views: 1953

Answers (1)

Greg Inozemtsev
Greg Inozemtsev

Reputation: 4671

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;
}

Upvotes: 3

Related Questions