我有一个关于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
答案 0 :(得分:3)
为什么打包你的结构?如果它们是可变长度可能有意义,但无论如何你在这里传输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;
}