Каждый должен договориться о «корне», прежде чем идти в коллектив, поэтому перед этим должно быть какое-то сотрудничество.Вот один простой подход - каждый отправляет флаг, указывающий, есть ли у него соответствующие данные, и тогда каждый может договориться, от кого получать.Это позволяет обрабатывать случаи, когда имеется несколько возможных отправителей или их нет.
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char **argv) {
int rank, size, ierr;
int bcaster;
int bcasterflag, *allflags;
int consensus;
int globaldata, mydata;
ierr = MPI_Init(&argc, &argv);
ierr|= MPI_Comm_size(MPI_COMM_WORLD,&size);
ierr|= MPI_Comm_rank(MPI_COMM_WORLD,&rank);
if (argc != 2) {
if (rank == 0) fprintf(stderr,"Usage: %s rank-to-broadcast\n",argv[0]);
MPI_Abort(MPI_COMM_WORLD,1);
}
bcaster = atoi(argv[1]);
if (bcaster < 0 ) bcaster = 0;
if (bcaster >= size) bcaster = size-1;
/* pretend the processes didn't all know the above and had to
* rely solely on local info to decide the broadcaster
*/
bcasterflag = 0; /* not the broadcaster yet */
mydata = rank*rank; /* the local data */
if (mydata == bcaster*bcaster) {
bcasterflag = 1;
globaldata = mydata;
}
/* collect these local decisions */
allflags = (int *)malloc(size * sizeof(int));
ierr = MPI_Allgather(&bcasterflag, 1, MPI_INT,
allflags, 1, MPI_INT, MPI_COMM_WORLD);
consensus = -1;
for (int i=0; i<size; i++)
if (allflags[i] != 0) consensus = i;
if (consensus == -1) {
if (rank == 0) {
fprintf(stderr,"Error: no one found to do the broadcast.\n");
}
} else {
ierr = MPI_Bcast(&globaldata, 1, MPI_INT, consensus, MPI_COMM_WORLD);
}
printf("%d: Received data %d from %d\n",
rank, globaldata, consensus);
return 0;
}