16 #ifndef dealii_mpi_consensus_algorithm_h
17 #define dealii_mpi_consensus_algorithm_h
22 #include <deal.II/base/mpi.templates.h>
132 namespace ConsensusAlgorithms
158 template <
typename RequestType,
typename AnswerType>
174 virtual std::vector<unsigned int>
203 const RequestType &buffer_recv,
204 AnswerType &request_buffer);
215 const AnswerType &recv_buffer);
233 template <
typename RequestType,
typename AnswerType>
256 std::vector<unsigned int>
282 virtual std::vector<unsigned int>
284 const std::vector<unsigned int> &targets,
285 const std::function<RequestType(
const unsigned int)> &create_request,
286 const std::function<AnswerType(
const unsigned int,
287 const RequestType &)> &answer_request,
288 const std::function<
void(
const unsigned int,
const AnswerType &)>
290 const MPI_Comm
comm) = 0;
307 template <
typename RequestType,
typename AnswerType>
327 virtual std::vector<unsigned int>
329 const std::vector<unsigned int> &targets,
330 const std::function<RequestType(
const unsigned int)> &create_request,
331 const std::function<AnswerType(
const unsigned int,
332 const RequestType &)> &answer_request,
333 const std::function<
void(
const unsigned int,
const AnswerType &)>
335 const MPI_Comm
comm)
override;
338 #ifdef DEAL_II_WITH_MPI
384 const std::function<
void(
const unsigned int,
const AnswerType &)>
386 const MPI_Comm
comm);
410 const std::function<AnswerType(
const unsigned int,
411 const RequestType &)> &answer_request,
412 const MPI_Comm
comm);
420 const std::vector<unsigned int> &targets,
421 const std::function<RequestType(
const unsigned int)> &create_request,
422 const MPI_Comm
comm);
477 template <
typename RequestType,
typename AnswerType>
478 std::vector<unsigned int>
479 nbx(
const std::vector<unsigned int> &targets,
480 const std::function<RequestType(
const unsigned int)> &create_request,
481 const std::function<AnswerType(
const unsigned int,
482 const RequestType &)> &answer_request,
483 const std::function<
void(
const unsigned int,
const AnswerType &)>
485 const MPI_Comm
comm);
524 template <
typename RequestType>
525 std::vector<unsigned int>
526 nbx(
const std::vector<unsigned int> &targets,
527 const std::function<RequestType(
const unsigned int)> &create_request,
528 const std::function<
void(
const unsigned int,
const RequestType &)>
530 const MPI_Comm
comm);
557 template <
typename RequestType,
typename AnswerType>
577 virtual std::vector<unsigned int>
579 const std::vector<unsigned int> &targets,
580 const std::function<RequestType(
const unsigned int)> &create_request,
581 const std::function<AnswerType(
const unsigned int,
582 const RequestType &)> &answer_request,
583 const std::function<
void(
const unsigned int,
const AnswerType &)>
585 const MPI_Comm
comm)
override;
588 #ifdef DEAL_II_WITH_MPI
625 const std::vector<unsigned int> &targets,
626 const std::function<RequestType(
const unsigned int)> &create_request,
627 const MPI_Comm
comm);
635 const unsigned int index,
636 const std::function<AnswerType(
const unsigned int,
637 const RequestType &)> &answer_request,
638 const MPI_Comm
comm);
646 const unsigned int n_targets,
647 const std::function<
void(
const unsigned int,
const AnswerType &)>
649 const MPI_Comm
comm);
717 template <
typename RequestType,
typename AnswerType>
718 std::vector<unsigned int>
719 pex(
const std::vector<unsigned int> &targets,
720 const std::function<RequestType(
const unsigned int)> &create_request,
721 const std::function<AnswerType(
const unsigned int,
722 const RequestType &)> &answer_request,
723 const std::function<
void(
const unsigned int,
const AnswerType &)>
725 const MPI_Comm
comm);
764 template <
typename RequestType>
765 std::vector<unsigned int>
766 pex(
const std::vector<unsigned int> &targets,
767 const std::function<RequestType(
const unsigned int)> &create_request,
768 const std::function<
void(
const unsigned int,
const RequestType &)>
770 const MPI_Comm
comm);
777 template <
typename RequestType,
typename AnswerType>
792 virtual std::vector<unsigned int>
794 const std::vector<unsigned int> &targets,
795 const std::function<RequestType(
const unsigned int)> &create_request,
796 const std::function<AnswerType(
const unsigned int,
797 const RequestType &)> &answer_request,
798 const std::function<
void(
const unsigned int,
const AnswerType &)>
800 const MPI_Comm
comm)
override;
837 template <
typename RequestType,
typename AnswerType>
838 std::vector<unsigned int>
840 const std::vector<unsigned int> &targets,
841 const std::function<RequestType(
const unsigned int)> &create_request,
842 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
844 const std::function<
void(
const unsigned int,
const AnswerType &)>
846 const MPI_Comm
comm);
877 template <
typename RequestType>
878 std::vector<unsigned int>
880 const std::vector<unsigned int> &targets,
881 const std::function<RequestType(
const unsigned int)> &create_request,
882 const std::function<
void(
const unsigned int,
const RequestType &)>
884 const MPI_Comm
comm);
900 template <
typename RequestType,
typename AnswerType>
922 virtual std::vector<unsigned int>
924 const std::vector<unsigned int> &targets,
925 const std::function<RequestType(
const unsigned int)> &create_request,
926 const std::function<AnswerType(
const unsigned int,
927 const RequestType &)> &answer_request,
928 const std::function<
void(
const unsigned int,
const AnswerType &)>
930 const MPI_Comm
comm)
override;
983 template <
typename RequestType,
typename AnswerType>
984 std::vector<unsigned int>
986 const std::vector<unsigned int> &targets,
987 const std::function<RequestType(
const unsigned int)> &create_request,
988 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
990 const std::function<
void(
const unsigned int,
const AnswerType &)>
992 const MPI_Comm
comm);
1031 template <
typename RequestType>
1032 std::vector<unsigned int>
1034 const std::vector<unsigned int> &targets,
1035 const std::function<RequestType(
const unsigned int)> &create_request,
1036 const std::function<
void(
const unsigned int,
const RequestType &)>
1038 const MPI_Comm
comm);
1045 template <
typename RequestType,
typename AnswerType>
1046 std::vector<unsigned int>
1047 nbx(
const std::vector<unsigned int> &targets,
1048 const std::function<RequestType(
const unsigned int)> &create_request,
1049 const std::function<AnswerType(
const unsigned int,
1050 const RequestType &)> &answer_request,
1051 const std::function<
void(
const unsigned int,
const AnswerType &)>
1053 const MPI_Comm
comm)
1056 targets, create_request, answer_request, process_answer,
comm);
1061 template <
typename RequestType>
1062 std::vector<unsigned int>
1063 nbx(
const std::vector<unsigned int> &targets,
1064 const std::function<RequestType(
const unsigned int)> &create_request,
1065 const std::function<
void(
const unsigned int,
const RequestType &)>
1067 const MPI_Comm
comm)
1074 using EmptyType = std::tuple<>;
1076 return nbx<RequestType, EmptyType>(
1080 [&process_request](
const unsigned int source_rank,
1081 const RequestType &request) -> EmptyType {
1082 process_request(source_rank, request);
1090 [](
const unsigned int ,
1091 const EmptyType & ) {},
1097 template <
typename RequestType,
typename AnswerType>
1098 std::vector<unsigned int>
1099 pex(
const std::vector<unsigned int> &targets,
1100 const std::function<RequestType(
const unsigned int)> &create_request,
1101 const std::function<AnswerType(
const unsigned int,
1102 const RequestType &)> &answer_request,
1103 const std::function<
void(
const unsigned int,
const AnswerType &)>
1105 const MPI_Comm
comm)
1107 return PEX<RequestType, AnswerType>().run(
1108 targets, create_request, answer_request, process_answer,
comm);
1113 template <
typename RequestType>
1114 std::vector<unsigned int>
1115 pex(
const std::vector<unsigned int> &targets,
1116 const std::function<RequestType(
const unsigned int)> &create_request,
1117 const std::function<
void(
const unsigned int,
const RequestType &)>
1119 const MPI_Comm
comm)
1126 using EmptyType = std::tuple<>;
1128 return pex<RequestType, EmptyType>(
1132 [&process_request](
const unsigned int source_rank,
1133 const RequestType &request) -> EmptyType {
1134 process_request(source_rank, request);
1142 [](
const unsigned int ,
1143 const EmptyType & ) {},
1149 template <
typename RequestType,
typename AnswerType>
1150 std::vector<unsigned int>
1152 const std::vector<unsigned int> &targets,
1153 const std::function<RequestType(
const unsigned int)> &create_request,
1154 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1156 const std::function<
void(
const unsigned int,
const AnswerType &)>
1158 const MPI_Comm
comm)
1160 return Serial<RequestType, AnswerType>().run(
1161 targets, create_request, answer_request, process_answer,
comm);
1166 template <
typename RequestType>
1167 std::vector<unsigned int>
1169 const std::vector<unsigned int> &targets,
1170 const std::function<RequestType(
const unsigned int)> &create_request,
1171 const std::function<
void(
const unsigned int,
const RequestType &)>
1173 const MPI_Comm
comm)
1180 using EmptyType = std::tuple<>;
1182 return serial<RequestType, EmptyType>(
1186 [&process_request](
const unsigned int source_rank,
1187 const RequestType &request) -> EmptyType {
1188 process_request(source_rank, request);
1196 [](
const unsigned int ,
1197 const EmptyType & ) {},
1203 template <
typename RequestType,
typename AnswerType>
1204 std::vector<unsigned int>
1206 const std::vector<unsigned int> &targets,
1207 const std::function<RequestType(
const unsigned int)> &create_request,
1208 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1210 const std::function<
void(
const unsigned int,
const AnswerType &)>
1212 const MPI_Comm
comm)
1214 return Selector<RequestType, AnswerType>().run(
1215 targets, create_request, answer_request, process_answer,
comm);
1220 template <
typename RequestType>
1221 std::vector<unsigned int>
1223 const std::vector<unsigned int> &targets,
1224 const std::function<RequestType(
const unsigned int)> &create_request,
1225 const std::function<
void(
const unsigned int,
const RequestType &)>
1227 const MPI_Comm
comm)
1234 using EmptyType = std::tuple<>;
1236 return selector<RequestType, EmptyType>(
1240 [&process_request](
const unsigned int source_rank,
1241 const RequestType &request) -> EmptyType {
1242 process_request(source_rank, request);
1250 [](
const unsigned int ,
1251 const EmptyType & ) {},
1272 namespace ConsensusAlgorithms
1291 # ifndef DEAL_II_MSVC
1295 has_unique_elements(
const std::vector<unsigned int> &targets)
1297 std::vector<unsigned int> my_destinations = targets;
1298 std::sort(my_destinations.begin(), my_destinations.end());
1299 return (std::adjacent_find(my_destinations.begin(),
1300 my_destinations.end()) ==
1301 my_destinations.end());
1310 handle_exception(std::exception_ptr &&exception,
const MPI_Comm
comm)
1312 # ifdef DEAL_II_WITH_MPI
1317 std::rethrow_exception(exception);
1325 <<
"----------------------------------------------------"
1330 <<
" on processing: " << std::endl
1331 << exc.
what() << std::endl
1332 <<
"Aborting!" << std::endl
1333 <<
"----------------------------------------------------"
1337 MPI_Abort(
comm, 255);
1339 catch (std::exception &exc)
1344 <<
"----------------------------------------------------"
1347 <<
"Exception within ConsensusAlgorithm"
1349 <<
" on processing: " << std::endl
1350 << exc.what() << std::endl
1351 <<
"Aborting!" << std::endl
1352 <<
"----------------------------------------------------"
1356 MPI_Abort(
comm, 255);
1363 <<
"----------------------------------------------------"
1366 <<
"Unknown exception within ConsensusAlgorithm!" << std::endl
1367 <<
"Aborting!" << std::endl
1368 <<
"----------------------------------------------------"
1372 MPI_Abort(
comm, 255);
1379 std::rethrow_exception(exception);
1386 template <
typename RequestType,
typename AnswerType>
1389 const RequestType &,
1397 template <
typename RequestType,
typename AnswerType>
1407 template <
typename RequestType,
typename AnswerType>
1417 template <
typename RequestType,
typename AnswerType>
1418 std::vector<unsigned int>
1420 Process<RequestType, AnswerType> &process,
1421 const MPI_Comm
comm)
1426 process.compute_targets(),
1428 [&process](
const unsigned int target) {
1429 RequestType request;
1430 process.create_request(target, request);
1434 [&process](
const unsigned int source,
const RequestType &request) {
1436 process.answer_request(source, request, answer);
1440 [&process](
const unsigned int target,
const AnswerType &answer) {
1441 process.read_answer(target, answer);
1448 template <
typename RequestType,
typename AnswerType>
1449 std::vector<unsigned int>
1451 const std::vector<unsigned int> &targets,
1452 const std::function<RequestType(
const unsigned int)> &create_request,
1453 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1455 const std::function<
void(
const unsigned int,
const AnswerType &)>
1457 const MPI_Comm
comm)
1459 Assert(has_unique_elements(targets),
1460 ExcMessage(
"The consensus algorithms expect that each process "
1461 "only sends a single message to another process, "
1462 "but the targets provided include duplicates."));
1464 static CollectiveMutex mutex;
1465 CollectiveMutex::ScopedLock lock(mutex,
comm);
1471 start_communication(targets, create_request,
comm);
1487 while (all_locally_originated_receives_are_completed(process_answer,
1489 maybe_answer_one_request(answer_request,
comm);
1493 signal_finish(
comm);
1498 while (all_remotely_originated_receives_are_completed() ==
false)
1499 maybe_answer_one_request(answer_request,
comm);
1502 clean_up_and_end_communication(
comm);
1506 handle_exception(std::current_exception(),
comm);
1509 return std::vector<unsigned int>(requesting_processes.begin(),
1510 requesting_processes.end());
1515 template <
typename RequestType,
typename AnswerType>
1518 const std::vector<unsigned int> &targets,
1519 const std::function<RequestType(
const unsigned int)> &create_request,
1520 const MPI_Comm
comm)
1522 # ifdef DEAL_II_WITH_MPI
1524 const auto n_targets = targets.size();
1530 send_requests.resize(n_targets);
1531 send_buffers.resize(n_targets);
1535 for (
unsigned int index = 0;
index < n_targets; ++
index)
1537 const unsigned int rank = targets[
index];
1540 auto &send_buffer = send_buffers[
index];
1543 std::vector<char>());
1546 auto ierr = MPI_Isend(send_buffer.data(),
1552 &send_requests[index]);
1558 n_outstanding_answers = n_targets;
1562 (void)create_request;
1569 template <
typename RequestType,
typename AnswerType>
1573 const std::function<
void(
const unsigned int,
const AnswerType &)>
1575 const MPI_Comm
comm)
1577 # ifdef DEAL_II_WITH_MPI
1585 if (n_outstanding_answers == 0)
1592 int request_is_pending;
1594 const auto ierr = MPI_Iprobe(
1595 MPI_ANY_SOURCE, tag_deliver,
comm, &request_is_pending, &status);
1601 if (request_is_pending == 0)
1607 const auto target = status.MPI_SOURCE;
1614 MPI_Get_count(&status, MPI_CHAR, &message_size);
1617 std::vector<char> recv_buffer(message_size);
1623 const int ierr = MPI_Recv(recv_buffer.data(),
1634 process_answer(target,
1635 Utilities::unpack<AnswerType>(recv_buffer,
1640 --n_outstanding_answers;
1650 return (n_outstanding_answers == 0);
1655 (void)process_answer;
1664 template <
typename RequestType,
typename AnswerType>
1667 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1669 const MPI_Comm
comm)
1671 # ifdef DEAL_II_WITH_MPI
1686 int request_is_pending;
1687 const auto ierr = MPI_Iprobe(
1688 MPI_ANY_SOURCE, tag_request,
comm, &request_is_pending, &status);
1691 if (request_is_pending != 0)
1695 const auto other_rank = status.MPI_SOURCE;
1697 Assert(requesting_processes.find(other_rank) ==
1698 requesting_processes.end(),
1699 ExcMessage(
"Process is requesting a second time!"));
1700 requesting_processes.insert(other_rank);
1704 auto ierr = MPI_Get_count(&status, MPI_CHAR, &number_amount);
1708 std::vector<char> buffer_recv(number_amount);
1709 ierr = MPI_Recv(buffer_recv.data(),
1720 request_buffers.emplace_back(std::make_unique<std::vector<char>>());
1721 auto &request_buffer = *request_buffers.back();
1725 Utilities::unpack<RequestType>(
1726 buffer_recv,
false)),
1730 request_requests.emplace_back(std::make_unique<MPI_Request>());
1731 ierr = MPI_Isend(request_buffer.data(),
1732 request_buffer.size(),
1737 request_requests.back().get());
1741 (void)answer_request;
1748 template <
typename RequestType,
typename AnswerType>
1752 # ifdef DEAL_II_WITH_MPI
1753 const auto ierr = MPI_Ibarrier(
comm, &barrier_request);
1762 template <
typename RequestType,
typename AnswerType>
1765 AnswerType>::all_remotely_originated_receives_are_completed()
1767 # ifdef DEAL_II_WITH_MPI
1768 int all_ranks_reached_barrier;
1769 const auto ierr = MPI_Test(&barrier_request,
1770 &all_ranks_reached_barrier,
1773 return all_ranks_reached_barrier != 0;
1781 template <
typename RequestType,
typename AnswerType>
1784 const MPI_Comm
comm)
1787 # ifdef DEAL_II_WITH_MPI
1790 if (send_requests.size() > 0)
1792 const int ierr = MPI_Waitall(send_requests.size(),
1793 send_requests.data(),
1794 MPI_STATUSES_IGNORE);
1798 int ierr = MPI_Wait(&barrier_request, MPI_STATUS_IGNORE);
1801 for (
auto &i : request_requests)
1803 ierr = MPI_Wait(i.get(), MPI_STATUS_IGNORE);
1810 ierr = MPI_Barrier(
comm);
1819 template <
typename RequestType,
typename AnswerType>
1820 std::vector<unsigned int>
1822 const std::vector<unsigned int> &targets,
1823 const std::function<RequestType(
const unsigned int)> &create_request,
1824 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1826 const std::function<
void(
const unsigned int,
const AnswerType &)>
1828 const MPI_Comm
comm)
1830 Assert(has_unique_elements(targets),
1831 ExcMessage(
"The consensus algorithms expect that each process "
1832 "only sends a single message to another process, "
1833 "but the targets provided include duplicates."));
1835 static CollectiveMutex mutex;
1836 CollectiveMutex::ScopedLock lock(mutex,
comm);
1843 const unsigned int n_requests =
1844 start_communication(targets, create_request,
comm);
1847 for (
unsigned int request = 0; request < n_requests; ++request)
1848 answer_one_request(request, answer_request,
comm);
1851 process_incoming_answers(targets.size(), process_answer,
comm);
1854 clean_up_and_end_communication();
1858 handle_exception(std::current_exception(),
comm);
1861 return std::vector<unsigned int>(requesting_processes.begin(),
1862 requesting_processes.end());
1867 template <
typename RequestType,
typename AnswerType>
1870 const std::vector<unsigned int> &targets,
1871 const std::function<RequestType(
const unsigned int)> &create_request,
1872 const MPI_Comm
comm)
1874 # ifdef DEAL_II_WITH_MPI
1880 const unsigned int n_targets = targets.size();
1883 const unsigned int n_sources =
1887 recv_buffers.resize(n_targets);
1888 send_buffers.resize(n_targets);
1889 send_request_requests.resize(n_targets);
1891 send_answer_requests.resize(n_sources);
1892 requests_buffers.resize(n_sources);
1895 for (
unsigned int i = 0; i < n_targets; ++i)
1897 const unsigned int rank = targets[i];
1901 auto &send_buffer = send_buffers[i];
1906 auto ierr = MPI_Isend(send_buffer.data(),
1912 &send_request_requests[i]);
1919 (void)create_request;
1927 template <
typename RequestType,
typename AnswerType>
1930 const unsigned int index,
1931 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1933 const MPI_Comm
comm)
1935 # ifdef DEAL_II_WITH_MPI
1944 int ierr = MPI_Probe(MPI_ANY_SOURCE, tag_request,
comm, &status);
1948 const unsigned int other_rank = status.MPI_SOURCE;
1950 Assert(requesting_processes.find(other_rank) ==
1951 requesting_processes.end(),
1953 "A process is sending a request after a request from "
1954 "the same process has previously already been "
1955 "received. This algorithm does not expect this to happen."));
1956 requesting_processes.insert(other_rank);
1960 ierr = MPI_Get_count(&status, MPI_CHAR, &number_amount);
1963 std::vector<char> buffer_recv(number_amount);
1964 ierr = MPI_Recv(buffer_recv.data(),
1975 auto &request_buffer = requests_buffers[
index];
1979 Utilities::unpack<RequestType>(
1980 buffer_recv,
false)),
1982 std::vector<char>());
1984 ierr = MPI_Isend(request_buffer.data(),
1985 request_buffer.size(),
1990 &send_answer_requests[index]);
1993 (void)answer_request;
2001 template <
typename RequestType,
typename AnswerType>
2004 const unsigned int n_targets,
2005 const std::function<
void(
const unsigned int,
const AnswerType &)>
2007 const MPI_Comm
comm)
2009 # ifdef DEAL_II_WITH_MPI
2018 for (
unsigned int i = 0; i < n_targets; ++i)
2023 MPI_Probe(MPI_ANY_SOURCE, tag_deliver,
comm, &status);
2027 const auto other_rank = status.MPI_SOURCE;
2030 const int ierr = MPI_Get_count(&status, MPI_CHAR, &message_size);
2033 std::vector<char> recv_buffer(message_size);
2039 const int ierr = MPI_Recv(recv_buffer.data(),
2050 process_answer(other_rank,
2051 Utilities::unpack<AnswerType>(recv_buffer,
false));
2055 (void)process_answer;
2062 template <
typename RequestType,
typename AnswerType>
2066 # ifdef DEAL_II_WITH_MPI
2069 if (send_request_requests.size() > 0)
2071 const int ierr = MPI_Waitall(send_request_requests.size(),
2072 send_request_requests.data(),
2073 MPI_STATUSES_IGNORE);
2078 if (send_answer_requests.size() > 0)
2080 const int ierr = MPI_Waitall(send_answer_requests.size(),
2081 send_answer_requests.data(),
2082 MPI_STATUSES_IGNORE);
2090 template <
typename RequestType,
typename AnswerType>
2091 std::vector<unsigned int>
2093 const std::vector<unsigned int> &targets,
2094 const std::function<RequestType(
const unsigned int)> &create_request,
2095 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
2097 const std::function<
void(
const unsigned int,
const AnswerType &)>
2099 const MPI_Comm
comm)
2103 ExcMessage(
"You shouldn't use the 'Serial' class on "
2104 "communicators that have more than one process "
2105 "associated with it."));
2108 if (targets.size() != 0)
2110 Assert(targets.size() == 1,
2112 "On a single process, the only valid target "
2113 "is process zero (the process itself), which can only be "
2120 const RequestType request =
2121 (create_request ? create_request(0) : RequestType());
2122 const AnswerType answer =
2123 (answer_request ? answer_request(0, request) : AnswerType());
2126 process_answer(0, answer);
2134 template <
typename RequestType,
typename AnswerType>
2135 std::vector<unsigned int>
2137 const std::vector<unsigned int> &targets,
2138 const std::function<RequestType(
const unsigned int)> &create_request,
2139 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
2141 const std::function<
void(
const unsigned int,
const AnswerType &)>
2143 const MPI_Comm
comm)
2154 # ifdef DEAL_II_WITH_MPI
2160 consensus_algo.reset(
new NBX<RequestType, AnswerType>());
2164 consensus_algo.reset(
new PEX<RequestType, AnswerType>());
2166 consensus_algo.reset(
new Serial<RequestType, AnswerType>());
2168 return consensus_algo->run(
2169 targets, create_request, answer_request, process_answer,
comm);
const char * get_exc_name() const
virtual const char * what() const noexcept override
virtual ~Interface()=default
std::vector< unsigned int > run(Process< RequestType, AnswerType > &process, const MPI_Comm comm)
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)=0
void start_communication(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const MPI_Comm comm)
void maybe_answer_one_request(const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const MPI_Comm comm)
std::vector< std::unique_ptr< std::vector< char > > > request_buffers
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm) override
std::set< unsigned int > requesting_processes
MPI_Request barrier_request
void clean_up_and_end_communication(const MPI_Comm comm)
bool all_locally_originated_receives_are_completed(const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
std::vector< std::unique_ptr< MPI_Request > > request_requests
std::vector< std::vector< char > > send_buffers
void signal_finish(const MPI_Comm comm)
bool all_remotely_originated_receives_are_completed()
unsigned int n_outstanding_answers
std::vector< MPI_Request > send_requests
void clean_up_and_end_communication()
std::vector< MPI_Request > send_answer_requests
std::vector< MPI_Request > send_request_requests
unsigned int start_communication(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const MPI_Comm comm)
std::vector< std::vector< char > > requests_buffers
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm) override
std::vector< std::vector< char > > send_buffers
void answer_one_request(const unsigned int index, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const MPI_Comm comm)
std::set< unsigned int > requesting_processes
std::vector< std::vector< char > > recv_buffers
void process_incoming_answers(const unsigned int n_targets, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
virtual ~Process()=default
virtual void answer_request(const unsigned int other_rank, const RequestType &buffer_recv, AnswerType &request_buffer)
virtual void read_answer(const unsigned int other_rank, const AnswerType &recv_buffer)
virtual std::vector< unsigned int > compute_targets()=0
virtual void create_request(const unsigned int other_rank, RequestType &send_buffer)
virtual ~Selector()=default
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm) override
std::shared_ptr< Interface< RequestType, AnswerType > > consensus_algo
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm) override
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< unsigned int > serial(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
std::vector< unsigned int > nbx(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
std::vector< unsigned int > selector(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
std::vector< unsigned int > pex(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
unsigned int compute_n_point_to_point_communications(const MPI_Comm mpi_comm, const std::vector< unsigned int > &destinations)
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
void run(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)