int MPI_Bcast(void *buf, int count, MPI_Datatype dtype,
int root, MPI_Comm comm)
{
int myrank;
MPI_Comm_rank(comm, &myrank);
/* global phase */
if (is_master(myrank, comm)) {
master_bcast(buf, count, dtype, root, comm);
}
/* local phase */
if (are_local(myrank, root, comm)) {
broadcast the data from the root to the local processes;
} else {
broadcast the data from the local master to the local processes;
}
return(MPI_SUCCESS);
}
int master_bcast(void *buf, int count, MPI_Datatype dtype,
int root, MPI_Comm comm)
{
MPI_Status status;
int myrank, nmasters, mynum, rootnum, vnum, dim, hibit;
int i, peer, mask;
MPI_Comm_rank(comm, &myrank);
nmasters = num_masters(comm);
if (nmasters <= MAXLINEARBCAST) {
/* linear broadcast between masters */
if (myrank == root) {
for (i = 0; i < nmasters; i++) {
if (i == local_master_num(root, comm)) continue;
MPI_Send(buf, count, dtype, master_rank(i, comm),
IMPI_BCAST_TAG, comm);
}
} else {
MPI_Recv(buf, count, dtype, root, IMPI_BCAST_TAG, comm, &status);
}
} else {
/* tree broadcast between masters */
mynum = master_num(myrank, comm);
rootnum = master_num(root, comm);
vnum = (mynum + nmasters - rootnum) % nmasters;
dim = cubedim(nmasters);
hibit = hibit(vnum, dim);
--dim;
/* receive data from parent in the tree */
if (vnum > 0) {
peer = ((vnum & ~(1 << hibit)) + rootnum) % nmasters;
MPI_Recv(buf, count, dtype, master_rank(peer, comm),
IMPI_BCAST_TAG, comm, &status);
}
/* send data to the children */
for (i = hibit + 1, mask = 1 << i; i <= dim; ++i, mask <<= 1) {
peer = vnum | mask;
if (peer < nmasters) {
peer = (peer + rootnum) % nmasters;
MPI_Send(buf, count, dtype, master_rank(peer, comm),
IMPI_BCAST_TAG, comm,);
}
}
}
return(MPI_SUCCESS);
}