使用MPI_Allgather分发结构

我必须使用MPI_Allgather()将结构发送到所有进程。 我似乎没有任何明显的错误,但代码不起作用。 当我检查我是否在recv[]收到任何值时,它都没有显示。 如果我只使用类似的代码发送单个变量而不是结构,那么这是有效的,所以我不确定发生了什么。 该结构具有静态数组,因此内存应该是连续的,或者我应该使用MPI_Pack还是其他东西? 这是代码:

 #include  #include  #include "mpi.h" #define NUMEL 21 struct mystruct{ int sendarray[10]; int a; char array2[10]; }; typedef struct mystruct struct_t; int main (int argc, char ** argv) { MPI_Status status; int rank, size; char *recv; int i, j; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); // init struct_t * fd = (struct_t*)malloc(sizeof(*fd));; for (i=0;isendarray[i] = 0; fd->array2[i] = 0; } recv = (char *) malloc ( size*NUMEL); // put some stuff in your array for (i=0;isendarray[i] = i *10; fd->array2[i] = i *20; fd->a = rank; } if(fd->sendarray[i] != 0) printf("My rank is %d, fd->sendarray[%d] is %d\n", rank, i, fd->sendarray[i]); } // gather data from all now.. MPI_Allgather (fd, NUMEL, MPI_BYTE, recv, NUMEL * size, MPI_INT, MPI_COMM_WORLD); // check if correct data has been received for (i=0;i<size*NUMEL;i++){ if(recv[i] != 0) printf("My rank is %d and recv[i]=%d and i is %d\n", rank, recv[i],i); } MPI_Finalize(); } 

Allgather在您第一次看到它时会有点混乱。 这里发生了一些事情。

首先,allgather的计数 – 发送计数和recv计数 – 是每个进程发送的数据量,并从每个进程收到。

其次,allgather的工作方式是连接发送的数据。 所以,如果你有

 int send[3]; int recv[9]; 

每个进程上的发送数组看起来像这样:

 send: +---+---+---+ | 0 | 0 | 0 | rank 0 +---+---+---+ +---+---+---+ | 1 | 1 | 1 | rank 1 +---+---+---+ +---+---+---+ | 2 | 2 | 2 | rank 2 +---+---+---+ 

然后打电话给

 MPI_Allgather(send, 3, MPI_INT, recv, 3, MPI_INT, MPI_COMM_WORLD); 

会导致:

 recv: +---+---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | 1 | 1 | 1 | 2 | 2 | 2 | +---+---+---+---+---+---+---+---+---+ 

因此,提取正确数据的代码版本是:

 #include  #include  #include "mpi.h" struct mystruct{ int sendarray[10]; int a; char array2[10]; }; typedef struct mystruct struct_t; int main (int argc, char ** argv) { int rank, size; struct_t *recv; int i, j; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); // init struct_t * fd = (struct_t*)malloc(sizeof(*fd)); for (i=0;i<10;i++){ fd->sendarray[i] = 0; fd->array2[i] = 0; } recv = malloc ( size * sizeof(*fd) ); // put some stuff in your array fd->sendarray[rank] = rank*10; fd->array2[rank] = rank*20; fd->a = rank; printf("My rank is %d, fd->sendarray[%d] is %d\n", rank, i, fd->sendarray[i]); // gather data from all now.. MPI_Allgather (fd, sizeof(*fd), MPI_BYTE, recv, sizeof(*fd), MPI_BYTE, MPI_COMM_WORLD); // check if correct data has been received if (rank == 0) { printf("Received:\n"); for (i=0;i 

请注意,它将这些结构收集到这些结构的数组中。 运行4个处理器给出:

 My rank is 0, fd->sendarray[10] is 0 My rank is 1, fd->sendarray[10] is 1 My rank is 2, fd->sendarray[10] is 2 My rank is 3, fd->sendarray[10] is 3 Received: --- int array: 0 0 0 0 0 0 0 0 0 0 int: 0 char array: 0 0 0 0 0 0 0 0 0 0 --- int array: 0 10 0 0 0 0 0 0 0 0 int: 1 char array: 0 20 0 0 0 0 0 0 0 0 --- int array: 0 0 20 0 0 0 0 0 0 0 int: 2 char array: 0 0 40 0 0 0 0 0 0 0 --- int array: 0 0 0 30 0 0 0 0 0 0 int: 3 char array: 0 0 0 60 0 0 0 0 0 0 

如果您真的只想收集相应的元素,那么您只需从结构中的特定位置发送一个int / char:

 #include  #include  #include "mpi.h" struct mystruct{ int sendarray[10]; int a; char array2[10]; }; typedef struct mystruct struct_t; int main (int argc, char ** argv) { int rank, size; struct_t fd; struct_t recv; int i, j; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); // init for (i=0;i<10;i++){ fd.sendarray[i] = 0; fd.array2[i] = 0; recv.sendarray[i] =999; recv.array2[i] = 99; } recv.a =999; // put some stuff in your array fd.sendarray[rank] = rank*10; fd.array2[rank] = (char)(rank*20); fd.a = rank; printf("My rank is %d, fd.sendarray[%d] is %d\n", rank, rank, fd.sendarray[rank]); // gather data from all now.. send the int: MPI_Allgather (&(fd.sendarray[rank]), 1, MPI_INT, recv.sendarray, 1, MPI_INT, MPI_COMM_WORLD); // then the char MPI_Allgather (&(fd.array2[rank]), 1, MPI_CHAR, recv.array2, 1, MPI_CHAR, MPI_COMM_WORLD); // check if correct data has been received if (rank == 0) { printf("Received:\n"); printf("---\n"); printf("int array: "); for (j=0; j<10; j++) printf("%3d ", recv.sendarray[j]); printf("\nint: "); printf("%3d\n", recv.a); printf("char array: "); for (j=0; j<10; j++) printf("%3d ", (int)(recv.array2[j])); printf("\n"); } MPI_Finalize(); return 0; } 

如果我们用4个进程运行它,我们得到:

 My rank is 0, fd.sendarray[0] is 0 My rank is 1, fd.sendarray[1] is 10 My rank is 2, fd.sendarray[2] is 20 My rank is 3, fd.sendarray[3] is 30 Received: --- int array: 0 10 20 30 999 999 999 999 999 999 int: 999 char array: 0 20 40 60 99 99 99 99 99 99