Mpi_allgather и mpi_pack в C - PullRequest
       29

Mpi_allgather и mpi_pack в C

2 голосов
/ 27 марта 2012

у меня есть проблема с mpi и MPI_Allgather и MPI_pack.У меня есть структура:

typedef struct{
    float a;
    int b;
    int c[];
}struc_t;

Я инициализирую свою структуру:

  struc_t* test=(struc_t*)malloc(sizeof(struc_t)+200*sizeof(int));

И я хотел бы отправить массив моей структуры с 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;

код 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);

Я создаю свой пакет:

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

и получаю:

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

Но результат recvStruc равен 0 :( гдев чем проблема? Если вы мне поможете, я назову вас богом, лол.

thx

1 Ответ

3 голосов
/ 27 марта 2012

Зачем собирать свои структуры? Это могло бы иметь смысл, если бы они были переменной длины, но здесь вы все равно передаете 200 целых чисел. Лучшее решение - просто использовать типы данных MPI. Таким образом, у вас есть шанс избежать копий памяти, и если библиотеке MPI действительно нужно упаковать ваши данные за кулисы, она может сделать это автоматически.

Вот рабочий пример:

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