57 MPI_Request request{};
67 std::vector<future> root_futures;
70 MPI_Request req_ibcast_any{};
73 MPI_Request req_ibcast_all{};
76 MPI_Request req_isent{};
88 bool finalized =
false;
105 if (comm.
rank() == 0) {
106 root_futures.resize(c.size() - 1);
107 for (int rank = 1; rank < c.size(); ++rank) {
108 check_mpi_call(MPI_Irecv(&(root_futures[rank - 1].event), 1, MPI_INT, rank, rank, comm.get(), &(root_futures[rank - 1].request)),
112 check_mpi_call(MPI_Ibcast(&any_event, 1, MPI_INT, 0, comm.
get(), &req_ibcast_any),
"MPI_Ibcast");
113 check_mpi_call(MPI_Ibcast(&all_events, 1, MPI_INT, 0, comm.
get(), &req_ibcast_all),
"MPI_Ibcast");
139 if (local_event or finalized) {
return; }
143 if (comm.
rank() == 0) {
145 root_check_nodes_and_bcast();
148 check_mpi_call(MPI_Isend(&local_event, 1, MPI_INT, 0, comm.
rank(), comm.
get(), &req_isent),
"MPI_Isend");
169 if (finalized)
return any_event;
172 if (local_event)
return true;
176 if (comm.
rank() == 0) {
177 root_check_nodes_and_bcast();
184 int has_received = 0;
185 check_mpi_call(MPI_Test(&req_ibcast_any, &has_received, &status),
"MPI_Test");
186 return has_received and any_event;
205 if (finalized)
return all_events;
209 if (comm.
rank() == 0) {
210 root_check_nodes_and_bcast();
217 int has_received = 0;
218 check_mpi_call(MPI_Test(&req_ibcast_all, &has_received, &status),
"MPI_Test");
219 return has_received and all_events;
232 if (finalized)
return;
234 if (comm.
rank() == 0) {
236 while (root_check_nodes_and_bcast()) {
240 if (not any_event) {
check_mpi_call(MPI_Ibcast(&any_event, 1, MPI_INT, 0, comm.
get(), &req_ibcast_any),
"MPI_Ibcast"); }
241 if (not all_events) {
check_mpi_call(MPI_Ibcast(&all_events, 1, MPI_INT, 0, comm.
get(), &req_ibcast_all),
"MPI_Ibcast"); }
244 if (not local_event) {
check_mpi_call(MPI_Isend(&local_event, 1, MPI_INT, 0, comm.
rank(), comm.
get(), &req_isent),
"MPI_Isend"); }
248 MPI_Status status_any, status_all;
249 check_mpi_call(MPI_Wait(&req_ibcast_any, &status_any),
"MPI_Wait");
250 check_mpi_call(MPI_Wait(&req_ibcast_all, &status_all),
"MPI_Wait");
260 bool root_check_nodes_and_bcast() {
262 EXPECTS(comm.
rank() == 0);
265 bool finished =
true;
266 for (
auto &[request, rank_event] : root_futures) {
268 int rank_received = 0;
269 check_mpi_call(MPI_Test(&request, &rank_received, &status),
"MPI_Test");
270 any |= (rank_received and rank_event);
271 all &= (rank_received and rank_event);
272 finished &= rank_received;
274 if (not any_event and (any or local_event)) {
276 check_mpi_call(MPI_Ibcast(&any_event, 1, MPI_INT, 0, comm.
get(), &req_ibcast_any),
"MPI_Ibcast");
278 if (not all_events and all and local_event) {
280 check_mpi_call(MPI_Ibcast(&all_events, 1, MPI_INT, 0, comm.
get(), &req_ibcast_all),
"MPI_Ibcast");
C++ wrapper around MPI_Comm providing various convenience functions.
int rank() const
Get the rank of the calling process in the communicator.
void free()
Free the communicator.
MPI_Comm get() const noexcept
Get the wrapped MPI_Comm object.
Constructed on top of an MPI communicator, this class helps to monitor and communicate events across ...
void finalize_communications()
Finalize all pending communications.
monitor(mpi::communicator c)
Construct a monitor on top of a given mpi::communicator.
bool event_on_all_ranks()
Check if an event has occurred on all processes.
~monitor()
Destructor calls finalize_communications().
monitor & operator=(monitor const &)=delete
Deleted copy assignment operator.
void report_local_event()
Report a local event to the root process (rank == 0).
monitor(monitor const &)=delete
Deleted copy constructor.
bool event_on_any_rank()
Check if an event has occurred on any process.
Provides a C++ wrapper class for an MPI_Comm object.
void check_mpi_call(int errcode, const std::string &mpi_routine)
Check the success of an MPI call.
Macros used in the mpi library.
Provides general utilities related to MPI.