// 1) collect vector entries and create union
std::vector<T> result = vec;
- if (this_mpi_process(comm) == 0)
+ const unsigned int rank = this_mpi_process(comm);
+ const unsigned int nproc = n_mpi_processes(comm);
+
+ for (unsigned int stride = 1; stride < nproc; stride *= 2)
{
- for (unsigned int i = 1; i < n_mpi_processes(comm); i++)
+ const unsigned int rank_recv = (2 * stride) * (rank / (2 * stride));
+ const unsigned int rank_send = rank_recv + stride;
+
+ if (rank_send >= nproc) // nothing to do
+ continue;
+
+ if (rank_recv == rank) // process receives data
{
MPI_Status status;
- const auto ierr_1 = MPI_Probe(MPI_ANY_SOURCE,
+ const auto ierr_1 = MPI_Probe(rank_send,
internal::Tags::compute_union,
comm,
&status);
int amount;
const auto ierr_2 =
MPI_Get_count(&status,
- internal::mpi_type_id(vec.data()),
+ internal::mpi_type_id(result.data()),
&amount);
AssertThrowMPI(ierr_2);
const auto ierr_3 = MPI_Recv(result.data() + old_size,
amount,
- internal::mpi_type_id(vec.data()),
+ internal::mpi_type_id(result.data()),
status.MPI_SOURCE,
status.MPI_TAG,
comm,
result.erase(std::unique(result.begin(), result.end()),
result.end());
}
- }
- else
- {
- const auto ierr = MPI_Send(vec.data(),
- vec.size(),
- internal::mpi_type_id(vec.data()),
- 0,
- internal::Tags::compute_union,
- comm);
- AssertThrowMPI(ierr);
+ else if (rank_send == rank) // process sends data
+ {
+ const auto ierr = MPI_Send(result.data(),
+ result.size(),
+ internal::mpi_type_id(result.data()),
+ rank_recv,
+ internal::Tags::compute_union,
+ comm);
+ AssertThrowMPI(ierr);
+ }
}
// 2) broadcast result