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>
274 std::vector<unsigned int>
285 std::vector<unsigned int>
311 virtual std::vector<unsigned int>
313 const std::vector<unsigned int> & targets,
314 const std::function<RequestType(
const unsigned int)> &create_request,
315 const std::function<AnswerType(
const unsigned int,
316 const RequestType &)> &answer_request,
317 const std::function<
void(
const unsigned int,
const AnswerType &)>
356 template <
typename RequestType,
typename AnswerType>
391 virtual std::vector<unsigned int>
393 const std::vector<unsigned int> & targets,
394 const std::function<RequestType(
const unsigned int)> &create_request,
395 const std::function<AnswerType(
const unsigned int,
396 const RequestType &)> &answer_request,
397 const std::function<
void(
const unsigned int,
const AnswerType &)>
402#ifdef DEAL_II_WITH_MPI
448 const std::function<
void(
const unsigned int,
const AnswerType &)>
474 const std::function<AnswerType(
const unsigned int,
475 const RequestType &)> &answer_request,
484 const std::vector<unsigned int> & targets,
485 const std::function<RequestType(
const unsigned int)> &create_request,
541 template <
typename RequestType,
typename AnswerType>
542 std::vector<unsigned int>
543 nbx(
const std::vector<unsigned int> & targets,
544 const std::function<RequestType(
const unsigned int)> &create_request,
545 const std::function<AnswerType(
const unsigned int,
546 const RequestType &)> &answer_request,
547 const std::function<
void(
const unsigned int,
const AnswerType &)>
588 template <
typename RequestType>
589 std::vector<unsigned int>
590 nbx(
const std::vector<unsigned int> & targets,
591 const std::function<RequestType(
const unsigned int)> &create_request,
592 const std::function<
void(
const unsigned int,
const RequestType &)>
621 template <
typename RequestType,
typename AnswerType>
657 virtual std::vector<unsigned int>
659 const std::vector<unsigned int> & targets,
660 const std::function<RequestType(
const unsigned int)> &create_request,
661 const std::function<AnswerType(
const unsigned int,
662 const RequestType &)> &answer_request,
663 const std::function<
void(
const unsigned int,
const AnswerType &)>
668#ifdef DEAL_II_WITH_MPI
705 const std::vector<unsigned int> & targets,
706 const std::function<RequestType(
const unsigned int)> &create_request,
715 const unsigned int index,
716 const std::function<AnswerType(
const unsigned int,
717 const RequestType &)> &answer_request,
726 const unsigned int n_targets,
727 const std::function<
void(
const unsigned int,
const AnswerType &)>
797 template <
typename RequestType,
typename AnswerType>
798 std::vector<unsigned int>
799 pex(
const std::vector<unsigned int> & targets,
800 const std::function<RequestType(
const unsigned int)> &create_request,
801 const std::function<AnswerType(
const unsigned int,
802 const RequestType &)> &answer_request,
803 const std::function<
void(
const unsigned int,
const AnswerType &)>
844 template <
typename RequestType>
845 std::vector<unsigned int>
846 pex(
const std::vector<unsigned int> & targets,
847 const std::function<RequestType(
const unsigned int)> &create_request,
848 const std::function<
void(
const unsigned int,
const RequestType &)>
857 template <
typename RequestType,
typename AnswerType>
887 virtual std::vector<unsigned int>
889 const std::vector<unsigned int> & targets,
890 const std::function<RequestType(
const unsigned int)> &create_request,
891 const std::function<AnswerType(
const unsigned int,
892 const RequestType &)> &answer_request,
893 const std::function<
void(
const unsigned int,
const AnswerType &)>
932 template <
typename RequestType,
typename AnswerType>
933 std::vector<unsigned int>
935 const std::vector<unsigned int> & targets,
936 const std::function<RequestType(
const unsigned int)> &create_request,
937 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
939 const std::function<
void(
const unsigned int,
const AnswerType &)>
972 template <
typename RequestType>
973 std::vector<unsigned int>
975 const std::vector<unsigned int> & targets,
976 const std::function<RequestType(
const unsigned int)> &create_request,
977 const std::function<
void(
const unsigned int,
const RequestType &)>
995 template <
typename RequestType,
typename AnswerType>
1033 virtual std::vector<unsigned int>
1035 const std::vector<unsigned int> & targets,
1036 const std::function<RequestType(
const unsigned int)> &create_request,
1037 const std::function<AnswerType(
const unsigned int,
1038 const RequestType &)> &answer_request,
1039 const std::function<
void(
const unsigned int,
const AnswerType &)>
1094 template <
typename RequestType,
typename AnswerType>
1095 std::vector<unsigned int>
1097 const std::vector<unsigned int> & targets,
1098 const std::function<RequestType(
const unsigned int)> &create_request,
1099 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1101 const std::function<
void(
const unsigned int,
const AnswerType &)>
1142 template <
typename RequestType>
1143 std::vector<unsigned int>
1145 const std::vector<unsigned int> & targets,
1146 const std::function<RequestType(
const unsigned int)> &create_request,
1147 const std::function<
void(
const unsigned int,
const RequestType &)>
1158 template <
typename RequestType,
typename AnswerType>
1160 :
public Process<RequestType, AnswerType>
1173 const std::function<std::vector<unsigned int>()>
1174 &function_compute_targets,
1175 const std::function<
void(
const unsigned int, RequestType &)>
1176 & function_create_request = {},
1177 const std::function<void(
const unsigned int,
1178 const RequestType &,
1179 AnswerType &)> &function_answer_request = {},
1180 const std::function<void(
const unsigned int,
const AnswerType &)>
1181 &function_read_answer = {});
1186 std::vector<unsigned int>
1194 RequestType & send_buffer)
override;
1201 const RequestType &buffer_recv,
1202 AnswerType & request_buffer)
override;
1209 const AnswerType & recv_buffer)
override;
1212 const std::function<std::vector<unsigned int>()>
1214 const std::function<void(
const int, RequestType &)>
1216 const std::function<
1217 void(
const unsigned int,
const RequestType &, AnswerType &)>
1219 const std::function<void(
const int,
const AnswerType &)>
1227 template <
typename RequestType,
typename AnswerType>
1228 std::vector<unsigned int>
1229 nbx(
const std::vector<unsigned int> & targets,
1230 const std::function<RequestType(
const unsigned int)> &create_request,
1231 const std::function<AnswerType(
const unsigned int,
1232 const RequestType &)> &answer_request,
1233 const std::function<
void(
const unsigned int,
const AnswerType &)>
1238 targets, create_request, answer_request, process_answer,
comm);
1243 template <
typename RequestType>
1244 std::vector<unsigned int>
1245 nbx(
const std::vector<unsigned int> & targets,
1246 const std::function<RequestType(
const unsigned int)> &create_request,
1247 const std::function<
void(
const unsigned int,
const RequestType &)>
1256 using EmptyType = std::tuple<>;
1258 return nbx<RequestType, EmptyType>(
1262 [&process_request](
const unsigned int source_rank,
1263 const RequestType &request) -> EmptyType {
1264 process_request(source_rank, request);
1272 [](
const unsigned int ,
1273 const EmptyType & ) {},
1279 template <
typename RequestType,
typename AnswerType>
1280 std::vector<unsigned int>
1281 pex(
const std::vector<unsigned int> & targets,
1282 const std::function<RequestType(
const unsigned int)> &create_request,
1283 const std::function<AnswerType(
const unsigned int,
1284 const RequestType &)> &answer_request,
1285 const std::function<
void(
const unsigned int,
const AnswerType &)>
1289 return PEX<RequestType, AnswerType>().run(
1290 targets, create_request, answer_request, process_answer,
comm);
1295 template <
typename RequestType>
1296 std::vector<unsigned int>
1297 pex(
const std::vector<unsigned int> & targets,
1298 const std::function<RequestType(
const unsigned int)> &create_request,
1299 const std::function<
void(
const unsigned int,
const RequestType &)>
1308 using EmptyType = std::tuple<>;
1310 return pex<RequestType, EmptyType>(
1314 [&process_request](
const unsigned int source_rank,
1315 const RequestType &request) -> EmptyType {
1316 process_request(source_rank, request);
1324 [](
const unsigned int ,
1325 const EmptyType & ) {},
1331 template <
typename RequestType,
typename AnswerType>
1332 std::vector<unsigned int>
1334 const std::vector<unsigned int> & targets,
1335 const std::function<RequestType(
const unsigned int)> &create_request,
1336 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1338 const std::function<
void(
const unsigned int,
const AnswerType &)>
1342 return Serial<RequestType, AnswerType>().run(
1343 targets, create_request, answer_request, process_answer,
comm);
1348 template <
typename RequestType>
1349 std::vector<unsigned int>
1351 const std::vector<unsigned int> & targets,
1352 const std::function<RequestType(
const unsigned int)> &create_request,
1353 const std::function<
void(
const unsigned int,
const RequestType &)>
1362 using EmptyType = std::tuple<>;
1364 return serial<RequestType, EmptyType>(
1368 [&process_request](
const unsigned int source_rank,
1369 const RequestType &request) -> EmptyType {
1370 process_request(source_rank, request);
1378 [](
const unsigned int ,
1379 const EmptyType & ) {},
1385 template <
typename RequestType,
typename AnswerType>
1386 std::vector<unsigned int>
1388 const std::vector<unsigned int> & targets,
1389 const std::function<RequestType(
const unsigned int)> &create_request,
1390 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1392 const std::function<
void(
const unsigned int,
const AnswerType &)>
1396 return Selector<RequestType, AnswerType>().run(
1397 targets, create_request, answer_request, process_answer,
comm);
1402 template <
typename RequestType>
1403 std::vector<unsigned int>
1405 const std::vector<unsigned int> & targets,
1406 const std::function<RequestType(
const unsigned int)> &create_request,
1407 const std::function<
void(
const unsigned int,
const RequestType &)>
1416 using EmptyType = std::tuple<>;
1418 return selector<RequestType, EmptyType>(
1422 [&process_request](
const unsigned int source_rank,
1423 const RequestType &request) -> EmptyType {
1424 process_request(source_rank, request);
1432 [](
const unsigned int ,
1433 const EmptyType & ) {},
1439 template <
typename RequestType,
typename AnswerType>
1441 const std::function<std::vector<unsigned int>()>
1442 &function_compute_targets,
1443 const std::function<
void(
const unsigned int, RequestType &)>
1444 & function_create_request,
1445 const std::function<
void(
const unsigned int,
1446 const RequestType &,
1447 AnswerType &)> &function_answer_request,
1448 const std::function<
void(
const unsigned int,
const AnswerType &)>
1449 &function_read_answer)
1450 : function_compute_targets(function_compute_targets)
1451 , function_create_request(function_create_request)
1452 , function_answer_request(function_answer_request)
1453 , function_read_answer(function_read_answer)
1458 template <
typename RequestType,
typename AnswerType>
1459 std::vector<unsigned int>
1462 return function_compute_targets();
1467 template <
typename RequestType,
typename AnswerType>
1470 const unsigned int other_rank,
1471 RequestType & send_buffer)
1473 if (function_create_request)
1474 function_create_request(other_rank, send_buffer);
1479 template <
typename RequestType,
typename AnswerType>
1482 const unsigned int other_rank,
1483 const RequestType &buffer_recv,
1484 AnswerType & request_buffer)
1486 if (function_answer_request)
1487 function_answer_request(other_rank, buffer_recv, request_buffer);
1492 template <
typename RequestType,
typename AnswerType>
1495 const unsigned int other_rank,
1496 const AnswerType & recv_buffer)
1498 if (function_read_answer)
1499 function_read_answer(other_rank, recv_buffer);
1519 namespace ConsensusAlgorithms
1538# ifndef DEAL_II_MSVC
1542 has_unique_elements(
const std::vector<unsigned int> &targets)
1544 std::vector<unsigned int> my_destinations = targets;
1545 std::sort(my_destinations.begin(), my_destinations.end());
1546 return (std::adjacent_find(my_destinations.begin(),
1547 my_destinations.end()) ==
1548 my_destinations.end());
1557 handle_exception(std::exception_ptr &&exception,
const MPI_Comm comm)
1559# ifdef DEAL_II_WITH_MPI
1564 std::rethrow_exception(exception);
1572 <<
"----------------------------------------------------"
1577 <<
" on processing: " << std::endl
1578 << exc.
what() << std::endl
1579 <<
"Aborting!" << std::endl
1580 <<
"----------------------------------------------------"
1584 MPI_Abort(
comm, 255);
1586 catch (std::exception &exc)
1591 <<
"----------------------------------------------------"
1594 <<
"Exception within ConsensusAlgorithm"
1596 <<
" on processing: " << std::endl
1597 << exc.what() << std::endl
1598 <<
"Aborting!" << std::endl
1599 <<
"----------------------------------------------------"
1603 MPI_Abort(
comm, 255);
1610 <<
"----------------------------------------------------"
1613 <<
"Unknown exception within ConsensusAlgorithm!" << std::endl
1614 <<
"Aborting!" << std::endl
1615 <<
"----------------------------------------------------"
1619 MPI_Abort(
comm, 255);
1626 std::rethrow_exception(exception);
1633 template <
typename RequestType,
typename AnswerType>
1636 const RequestType &,
1644 template <
typename RequestType,
typename AnswerType>
1654 template <
typename RequestType,
typename AnswerType>
1664 template <
typename RequestType,
typename AnswerType>
1666 Process<RequestType, AnswerType> &process,
1674 template <
typename RequestType,
typename AnswerType>
1677 ,
comm(MPI_COMM_NULL)
1682 template <
typename RequestType,
typename AnswerType>
1683 std::vector<unsigned int>
1686 Assert(process !=
nullptr,
1687 ExcMessage(
"This function can only be called if the "
1688 "deprecated non-default constructor of this class "
1689 "has previously been called to set the Process "
1690 "object and a communicator."));
1696 template <
typename RequestType,
typename AnswerType>
1697 std::vector<unsigned int>
1699 Process<RequestType, AnswerType> &process,
1705 process.compute_targets(),
1707 [&process](
const unsigned int target) {
1708 RequestType request;
1709 process.create_request(target, request);
1713 [&process](
const unsigned int source,
const RequestType &request) {
1715 process.answer_request(source, request, answer);
1719 [&process](
const unsigned int target,
const AnswerType &answer) {
1720 process.read_answer(target, answer);
1727 template <
typename RequestType,
typename AnswerType>
1729 Process<RequestType, AnswerType> &process,
1731 : Interface<RequestType, AnswerType>(process,
comm)
1736 template <
typename RequestType,
typename AnswerType>
1737 std::vector<unsigned int>
1739 const std::vector<unsigned int> & targets,
1740 const std::function<RequestType(
const unsigned int)> &create_request,
1741 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1743 const std::function<
void(
const unsigned int,
const AnswerType &)>
1747 Assert(has_unique_elements(targets),
1748 ExcMessage(
"The consensus algorithms expect that each process "
1749 "only sends a single message to another process, "
1750 "but the targets provided include duplicates."));
1752 static CollectiveMutex mutex;
1753 CollectiveMutex::ScopedLock lock(mutex,
comm);
1759 start_communication(targets, create_request,
comm);
1775 while (all_locally_originated_receives_are_completed(process_answer,
1777 maybe_answer_one_request(answer_request,
comm);
1781 signal_finish(
comm);
1786 while (all_remotely_originated_receives_are_completed() ==
false)
1787 maybe_answer_one_request(answer_request,
comm);
1790 clean_up_and_end_communication(
comm);
1794 handle_exception(std::current_exception(),
comm);
1797 return std::vector<unsigned int>(requesting_processes.begin(),
1798 requesting_processes.end());
1803 template <
typename RequestType,
typename AnswerType>
1806 const std::vector<unsigned int> & targets,
1807 const std::function<RequestType(
const unsigned int)> &create_request,
1810# ifdef DEAL_II_WITH_MPI
1812 const auto n_targets = targets.size();
1818 send_requests.resize(n_targets);
1819 send_buffers.resize(n_targets);
1823 for (
unsigned int index = 0;
index < n_targets; ++
index)
1825 const unsigned int rank = targets[
index];
1828 auto &send_buffer = send_buffers[
index];
1831 std::vector<char>());
1834 auto ierr = MPI_Isend(send_buffer.data(),
1840 &send_requests[index]);
1846 n_outstanding_answers = n_targets;
1850 (void)create_request;
1857 template <
typename RequestType,
typename AnswerType>
1861 const std::function<
void(
const unsigned int,
const AnswerType &)>
1865# ifdef DEAL_II_WITH_MPI
1873 if (n_outstanding_answers == 0)
1880 int request_is_pending;
1882 const auto ierr = MPI_Iprobe(
1883 MPI_ANY_SOURCE, tag_deliver,
comm, &request_is_pending, &status);
1889 if (request_is_pending == 0)
1895 const auto target = status.MPI_SOURCE;
1902 MPI_Get_count(&status, MPI_CHAR, &message_size);
1905 std::vector<char> recv_buffer(message_size);
1911 const int ierr = MPI_Recv(recv_buffer.data(),
1922 process_answer(target,
1923 Utilities::unpack<AnswerType>(recv_buffer,
1928 --n_outstanding_answers;
1938 return (n_outstanding_answers == 0);
1943 (void)process_answer;
1952 template <
typename RequestType,
typename AnswerType>
1955 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1959# ifdef DEAL_II_WITH_MPI
1974 int request_is_pending;
1975 const auto ierr = MPI_Iprobe(
1976 MPI_ANY_SOURCE, tag_request,
comm, &request_is_pending, &status);
1979 if (request_is_pending != 0)
1983 const auto other_rank = status.MPI_SOURCE;
1985 Assert(requesting_processes.find(other_rank) ==
1986 requesting_processes.end(),
1987 ExcMessage(
"Process is requesting a second time!"));
1988 requesting_processes.insert(other_rank);
1992 auto ierr = MPI_Get_count(&status, MPI_CHAR, &number_amount);
1996 std::vector<char> buffer_recv(number_amount);
1997 ierr = MPI_Recv(buffer_recv.data(),
2008 request_buffers.emplace_back(std::make_unique<std::vector<char>>());
2009 auto &request_buffer = *request_buffers.back();
2013 Utilities::unpack<RequestType>(
2014 buffer_recv,
false)),
2018 request_requests.emplace_back(std::make_unique<MPI_Request>());
2019 ierr = MPI_Isend(request_buffer.data(),
2020 request_buffer.size(),
2025 request_requests.back().get());
2029 (void)answer_request;
2036 template <
typename RequestType,
typename AnswerType>
2040# ifdef DEAL_II_WITH_MPI
2041 const auto ierr = MPI_Ibarrier(
comm, &barrier_request);
2050 template <
typename RequestType,
typename AnswerType>
2053 AnswerType>::all_remotely_originated_receives_are_completed()
2055# ifdef DEAL_II_WITH_MPI
2056 int all_ranks_reached_barrier;
2057 const auto ierr = MPI_Test(&barrier_request,
2058 &all_ranks_reached_barrier,
2061 return all_ranks_reached_barrier != 0;
2069 template <
typename RequestType,
typename AnswerType>
2075# ifdef DEAL_II_WITH_MPI
2078 if (send_requests.size() > 0)
2080 const int ierr = MPI_Waitall(send_requests.size(),
2081 send_requests.data(),
2082 MPI_STATUSES_IGNORE);
2086 int ierr = MPI_Wait(&barrier_request, MPI_STATUS_IGNORE);
2089 for (
auto &i : request_requests)
2091 ierr = MPI_Wait(i.get(), MPI_STATUS_IGNORE);
2098 ierr = MPI_Barrier(
comm);
2107 template <
typename RequestType,
typename AnswerType>
2109 Process<RequestType, AnswerType> &process,
2111 : Interface<RequestType, AnswerType>(process,
comm)
2116 template <
typename RequestType,
typename AnswerType>
2117 std::vector<unsigned int>
2119 const std::vector<unsigned int> & targets,
2120 const std::function<RequestType(
const unsigned int)> &create_request,
2121 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
2123 const std::function<
void(
const unsigned int,
const AnswerType &)>
2127 Assert(has_unique_elements(targets),
2128 ExcMessage(
"The consensus algorithms expect that each process "
2129 "only sends a single message to another process, "
2130 "but the targets provided include duplicates."));
2132 static CollectiveMutex mutex;
2133 CollectiveMutex::ScopedLock lock(mutex,
comm);
2140 const unsigned int n_requests =
2141 start_communication(targets, create_request,
comm);
2144 for (
unsigned int request = 0; request < n_requests; ++request)
2145 answer_one_request(request, answer_request,
comm);
2148 process_incoming_answers(targets.size(), process_answer,
comm);
2151 clean_up_and_end_communication();
2155 handle_exception(std::current_exception(),
comm);
2158 return std::vector<unsigned int>(requesting_processes.begin(),
2159 requesting_processes.end());
2164 template <
typename RequestType,
typename AnswerType>
2167 const std::vector<unsigned int> & targets,
2168 const std::function<RequestType(
const unsigned int)> &create_request,
2171# ifdef DEAL_II_WITH_MPI
2177 const unsigned int n_targets = targets.size();
2180 const unsigned int n_sources =
2184 recv_buffers.resize(n_targets);
2185 send_buffers.resize(n_targets);
2186 send_request_requests.resize(n_targets);
2188 send_answer_requests.resize(n_sources);
2189 requests_buffers.resize(n_sources);
2192 for (
unsigned int i = 0; i < n_targets; ++i)
2194 const unsigned int rank = targets[i];
2198 auto &send_buffer = send_buffers[i];
2203 auto ierr = MPI_Isend(send_buffer.data(),
2209 &send_request_requests[i]);
2216 (void)create_request;
2224 template <
typename RequestType,
typename AnswerType>
2227 const unsigned int index,
2228 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
2232# ifdef DEAL_II_WITH_MPI
2241 int ierr = MPI_Probe(MPI_ANY_SOURCE, tag_request,
comm, &status);
2245 const unsigned int other_rank = status.MPI_SOURCE;
2247 Assert(requesting_processes.find(other_rank) ==
2248 requesting_processes.end(),
2250 "A process is sending a request after a request from "
2251 "the same process has previously already been "
2252 "received. This algorithm does not expect this to happen."));
2253 requesting_processes.insert(other_rank);
2257 ierr = MPI_Get_count(&status, MPI_CHAR, &number_amount);
2260 std::vector<char> buffer_recv(number_amount);
2261 ierr = MPI_Recv(buffer_recv.data(),
2272 auto &request_buffer = requests_buffers[
index];
2276 Utilities::unpack<RequestType>(
2277 buffer_recv,
false)),
2279 std::vector<char>());
2281 ierr = MPI_Isend(request_buffer.data(),
2282 request_buffer.size(),
2287 &send_answer_requests[index]);
2290 (void)answer_request;
2298 template <
typename RequestType,
typename AnswerType>
2301 const unsigned int n_targets,
2302 const std::function<
void(
const unsigned int,
const AnswerType &)>
2306# ifdef DEAL_II_WITH_MPI
2315 for (
unsigned int i = 0; i < n_targets; ++i)
2320 MPI_Probe(MPI_ANY_SOURCE, tag_deliver,
comm, &status);
2324 const auto other_rank = status.MPI_SOURCE;
2327 const int ierr = MPI_Get_count(&status, MPI_CHAR, &message_size);
2330 std::vector<char> recv_buffer(message_size);
2336 const int ierr = MPI_Recv(recv_buffer.data(),
2347 process_answer(other_rank,
2348 Utilities::unpack<AnswerType>(recv_buffer,
false));
2352 (void)process_answer;
2359 template <
typename RequestType,
typename AnswerType>
2363# ifdef DEAL_II_WITH_MPI
2366 if (send_request_requests.size() > 0)
2368 const int ierr = MPI_Waitall(send_request_requests.size(),
2369 send_request_requests.data(),
2370 MPI_STATUSES_IGNORE);
2375 if (send_answer_requests.size() > 0)
2377 const int ierr = MPI_Waitall(send_answer_requests.size(),
2378 send_answer_requests.data(),
2379 MPI_STATUSES_IGNORE);
2387 template <
typename RequestType,
typename AnswerType>
2389 Process<RequestType, AnswerType> &process,
2391 : Interface<RequestType, AnswerType>(process,
comm)
2396 template <
typename RequestType,
typename AnswerType>
2397 std::vector<unsigned int>
2399 const std::vector<unsigned int> & targets,
2400 const std::function<RequestType(
const unsigned int)> &create_request,
2401 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
2403 const std::function<
void(
const unsigned int,
const AnswerType &)>
2410 ExcMessage(
"You shouldn't use the 'Serial' class on "
2411 "communicators that have more than one process "
2412 "associated with it."));
2415 if (targets.size() != 0)
2417 Assert(targets.size() == 1,
2419 "On a single process, the only valid target "
2420 "is process zero (the process itself), which can only be "
2427 const RequestType request =
2428 (create_request ? create_request(0) : RequestType());
2429 const AnswerType answer =
2430 (answer_request ? answer_request(0, request) : AnswerType());
2433 process_answer(0, answer);
2441 template <
typename RequestType,
typename AnswerType>
2443 Process<RequestType, AnswerType> &process,
2445 : Interface<RequestType, AnswerType>(process,
comm)
2450 template <
typename RequestType,
typename AnswerType>
2451 std::vector<unsigned int>
2453 const std::vector<unsigned int> & targets,
2454 const std::function<RequestType(
const unsigned int)> &create_request,
2455 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
2457 const std::function<
void(
const unsigned int,
const AnswerType &)>
2470# ifdef DEAL_II_WITH_MPI
2476 consensus_algo.reset(
new NBX<RequestType, AnswerType>());
2480 consensus_algo.reset(
new PEX<RequestType, AnswerType>());
2482 consensus_algo.reset(
new Serial<RequestType, AnswerType>());
2484 return consensus_algo->run(
2485 targets, create_request, answer_request, process_answer,
comm);
const char * get_exc_name() const
virtual const char * what() const noexcept override
std::vector< unsigned int > compute_targets() override
const std::function< void(const unsigned int, const RequestType &, AnswerType &)> function_answer_request
const std::function< std::vector< unsigned int >()> function_compute_targets
void create_request(const unsigned int other_rank, RequestType &send_buffer) override
const std::function< void(const int, RequestType &)> function_create_request
void read_answer(const unsigned int other_rank, const AnswerType &recv_buffer) override
void answer_request(const unsigned int other_rank, const RequestType &buffer_recv, AnswerType &request_buffer) override
const std::function< void(const int, const AnswerType &)> function_read_answer
AnonymousProcess(const std::function< std::vector< unsigned int >()> &function_compute_targets, const std::function< void(const unsigned int, RequestType &)> &function_create_request={}, const std::function< void(const unsigned int, const RequestType &, AnswerType &)> &function_answer_request={}, const std::function< void(const unsigned int, const AnswerType &)> &function_read_answer={})
std::vector< unsigned int > run()
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
Interface(Process< RequestType, AnswerType > &process, const MPI_Comm comm)
Process< RequestType, AnswerType > * process
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)
NBX(Process< RequestType, AnswerType > &process, const MPI_Comm comm)
std::vector< std::unique_ptr< std::vector< char > > > request_buffers
std::set< unsigned int > requesting_processes
MPI_Request barrier_request
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
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
PEX(Process< RequestType, AnswerType > &process, const MPI_Comm comm)
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 std::vector< unsigned int > compute_targets()=0
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 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
Selector(Process< RequestType, AnswerType > &process, const MPI_Comm comm)
std::shared_ptr< Interface< RequestType, AnswerType > > consensus_algo
Serial(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) override
#define DEAL_II_DEPRECATED
#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 > 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 > 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 > 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)