Allgather может немного запутать, когда вы впервые увидите это.Здесь происходит несколько вещей.
Во-первых, счетчики для всех сборщиков - количество отправленных сообщений и количество записей - это количество данных, отправляемых каждым процессом и получаемых от каждого процесса .
Во-вторых, принцип работы 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 <stdio.h>
#include <stdlib.h>
#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<size;i++){
printf("---\n");
printf("int array: ");
for (j=0; j<10; j++) printf("%3d ", recv[i].sendarray[j]);
printf("\nint: "); printf("%3d\n", recv[i].a);
printf("char array: ");
for (j=0; j<10; j++) printf("%3d ", (int)(recv[i].array2[j]));
printf("\n");
}
}
MPI_Finalize();
return 0;
}
Обратите внимание, что она собирает эти структуры в эквивалент массива этих структур.Работа с 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 <stdio.h>
#include <stdlib.h>
#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