123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733 |
- #ifndef BOOST_MPI_NONBLOCKING_HPP
- #define BOOST_MPI_NONBLOCKING_HPP
- #include <boost/mpi/config.hpp>
- #include <vector>
- #include <iterator>
- #include <boost/optional.hpp>
- #include <utility>
- #include <algorithm>
- #include <boost/static_assert.hpp>
- #include <boost/mpi/request.hpp>
- #include <boost/mpi/status.hpp>
- #include <boost/mpi/exception.hpp>
- namespace boost { namespace mpi {
- template<typename ForwardIterator>
- std::pair<status, ForwardIterator>
- wait_any(ForwardIterator first, ForwardIterator last)
- {
- using std::advance;
- BOOST_ASSERT(first != last);
-
- typedef typename std::iterator_traits<ForwardIterator>::difference_type
- difference_type;
- bool all_trivial_requests = true;
- difference_type n = 0;
- ForwardIterator current = first;
- while (true) {
-
- if (current->active()) {
- optional<status> result = current->test();
- if (bool(result)) {
- return std::make_pair(*result, current);
- }
- }
-
-
-
-
-
-
-
- all_trivial_requests = all_trivial_requests && current->trivial();
-
- ++n;
- if (++current == last) {
-
-
-
- if (all_trivial_requests) {
- std::vector<MPI_Request> requests;
- requests.reserve(n);
- for (current = first; current != last; ++current) {
- requests.push_back(*current->trivial());
- }
-
- int index;
- status stat;
- BOOST_MPI_CHECK_RESULT(MPI_Waitany,
- (n, detail::c_data(requests), &index, &stat.m_status));
-
-
- if (index == MPI_UNDEFINED)
- boost::throw_exception(exception("MPI_Waitany", MPI_ERR_REQUEST));
-
- current = first;
- advance(current, index);
- *current->trivial() = requests[index];
- return std::make_pair(stat, current);
- }
-
-
- n = 0;
- current = first;
- all_trivial_requests = true;
- }
- }
-
- BOOST_ASSERT(false);
- }
- template<typename ForwardIterator>
- optional<std::pair<status, ForwardIterator> >
- test_any(ForwardIterator first, ForwardIterator last)
- {
- while (first != last) {
-
- if (optional<status> result = first->test()) {
- return std::make_pair(*result, first);
- }
- ++first;
- }
-
- return optional<std::pair<status, ForwardIterator> >();
- }
- template<typename ForwardIterator, typename OutputIterator>
- OutputIterator
- wait_all(ForwardIterator first, ForwardIterator last, OutputIterator out)
- {
- typedef typename std::iterator_traits<ForwardIterator>::difference_type
- difference_type;
- using std::distance;
- difference_type num_outstanding_requests = distance(first, last);
- std::vector<status> results(num_outstanding_requests);
- std::vector<bool> completed(num_outstanding_requests);
- while (num_outstanding_requests > 0) {
- bool all_trivial_requests = true;
- difference_type idx = 0;
- for (ForwardIterator current = first; current != last; ++current, ++idx) {
- if (!completed[idx]) {
- if (!current->active()) {
- completed[idx] = true;
- --num_outstanding_requests;
- } else if (optional<status> stat = current->test()) {
-
- results[idx] = *stat;
- completed[idx] = true;
- --num_outstanding_requests;
- all_trivial_requests = false;
- } else {
-
-
-
- all_trivial_requests = all_trivial_requests && current->trivial();
- }
- }
- }
-
-
-
- if (all_trivial_requests
- && num_outstanding_requests == (difference_type)results.size()) {
- std::vector<MPI_Request> requests;
- requests.reserve(num_outstanding_requests);
- for (ForwardIterator current = first; current != last; ++current)
- requests.push_back(*current->trivial());
-
- std::vector<MPI_Status> stats(num_outstanding_requests);
- BOOST_MPI_CHECK_RESULT(MPI_Waitall,
- (num_outstanding_requests, detail::c_data(requests),
- detail::c_data(stats)));
- for (std::vector<MPI_Status>::iterator i = stats.begin();
- i != stats.end(); ++i, ++out) {
- status stat;
- stat.m_status = *i;
- *out = stat;
- }
- return out;
- }
- all_trivial_requests = false;
- }
- return std::copy(results.begin(), results.end(), out);
- }
- template<typename ForwardIterator>
- void
- wait_all(ForwardIterator first, ForwardIterator last)
- {
- typedef typename std::iterator_traits<ForwardIterator>::difference_type
- difference_type;
- using std::distance;
- difference_type num_outstanding_requests = distance(first, last);
- std::vector<bool> completed(num_outstanding_requests, false);
- while (num_outstanding_requests > 0) {
- bool all_trivial_requests = true;
- difference_type idx = 0;
- for (ForwardIterator current = first; current != last; ++current, ++idx) {
- if (!completed[idx]) {
- if (!current->active()) {
- completed[idx] = true;
- --num_outstanding_requests;
- } else if (optional<status> stat = current->test()) {
-
- completed[idx] = true;
- --num_outstanding_requests;
- all_trivial_requests = false;
- } else {
-
-
-
- all_trivial_requests = all_trivial_requests && current->trivial();
- }
- }
- }
-
-
-
- if (all_trivial_requests
- && num_outstanding_requests == (difference_type)completed.size()) {
- std::vector<MPI_Request> requests;
- requests.reserve(num_outstanding_requests);
- for (ForwardIterator current = first; current != last; ++current)
- requests.push_back(*current->trivial());
-
- BOOST_MPI_CHECK_RESULT(MPI_Waitall,
- (num_outstanding_requests, detail::c_data(requests),
- MPI_STATUSES_IGNORE));
-
- num_outstanding_requests = 0;
- }
- }
- }
- template<typename ForwardIterator, typename OutputIterator>
- optional<OutputIterator>
- test_all(ForwardIterator first, ForwardIterator last, OutputIterator out)
- {
- std::vector<MPI_Request> requests;
- for (; first != last; ++first) {
-
-
- if (!first->trivial()) {
- return optional<OutputIterator>();
- }
- requests.push_back(*first->trivial());
- }
- int flag = 0;
- int n = requests.size();
- std::vector<MPI_Status> stats(n);
- BOOST_MPI_CHECK_RESULT(MPI_Testall, (n, detail::c_data(requests), &flag, detail::c_data(stats)));
- if (flag) {
- for (int i = 0; i < n; ++i, ++out) {
- status stat;
- stat.m_status = stats[i];
- *out = stat;
- }
- return out;
- } else {
- return optional<OutputIterator>();
- }
- }
- template<typename ForwardIterator>
- bool
- test_all(ForwardIterator first, ForwardIterator last)
- {
- std::vector<MPI_Request> requests;
- for (; first != last; ++first) {
-
-
- if (!first->trivial()) {
- return false;
- }
- requests.push_back(*first->trivial());
- }
- int flag = 0;
- int n = requests.size();
- BOOST_MPI_CHECK_RESULT(MPI_Testall,
- (n, detail::c_data(requests), &flag, MPI_STATUSES_IGNORE));
- return flag != 0;
- }
- template<typename BidirectionalIterator, typename OutputIterator>
- std::pair<OutputIterator, BidirectionalIterator>
- wait_some(BidirectionalIterator first, BidirectionalIterator last,
- OutputIterator out)
- {
- using std::advance;
- if (first == last)
- return std::make_pair(out, first);
-
- typedef typename std::iterator_traits<BidirectionalIterator>::difference_type
- difference_type;
- bool all_trivial_requests = true;
- difference_type n = 0;
- BidirectionalIterator current = first;
- BidirectionalIterator start_of_completed = last;
- while (true) {
-
- if (optional<status> result = current->test()) {
- using std::iter_swap;
-
- *out++ = *result;
-
- --start_of_completed;
- if (current == start_of_completed) {
-
-
-
-
- std::reverse(start_of_completed, last);
- return std::make_pair(out, start_of_completed);
- }
-
-
- iter_swap(current, start_of_completed);
- continue;
- }
-
-
-
- all_trivial_requests = all_trivial_requests && current->trivial();
-
- ++n;
- if (++current == start_of_completed) {
- if (start_of_completed != last) {
-
-
-
- std::reverse(start_of_completed, last);
- return std::make_pair(out, start_of_completed);
- }
-
-
-
- if (all_trivial_requests) {
- std::vector<MPI_Request> requests;
- std::vector<int> indices(n);
- std::vector<MPI_Status> stats(n);
- requests.reserve(n);
- for (current = first; current != last; ++current)
- requests.push_back(*current->trivial());
-
- int num_completed;
- BOOST_MPI_CHECK_RESULT(MPI_Waitsome,
- (n, detail::c_data(requests), &num_completed, detail::c_data(indices),
- detail::c_data(stats)));
-
-
- int current_offset = 0;
- current = first;
- for (int index = 0; index < num_completed; ++index, ++out) {
- using std::iter_swap;
-
- advance(current, indices[index] - current_offset);
- current_offset = indices[index];
-
- status stat;
- stat.m_status = stats[index];
- *out = stat;
-
-
- *current->trivial() = requests[indices[index]];
- --start_of_completed;
- iter_swap(current, start_of_completed);
- }
-
-
-
- std::reverse(start_of_completed, last);
- return std::make_pair(out, start_of_completed);
- }
-
-
- n = 0;
- current = first;
- }
- }
-
- BOOST_ASSERT(false);
- }
- template<typename BidirectionalIterator>
- BidirectionalIterator
- wait_some(BidirectionalIterator first, BidirectionalIterator last)
- {
- using std::advance;
- if (first == last)
- return first;
-
- typedef typename std::iterator_traits<BidirectionalIterator>::difference_type
- difference_type;
- bool all_trivial_requests = true;
- difference_type n = 0;
- BidirectionalIterator current = first;
- BidirectionalIterator start_of_completed = last;
- while (true) {
-
- if (optional<status> result = current->test()) {
- using std::iter_swap;
-
- --start_of_completed;
-
-
- if (current == start_of_completed)
- return start_of_completed;
-
-
- iter_swap(current, start_of_completed);
- continue;
- }
-
-
-
- all_trivial_requests = all_trivial_requests && current->trivial();
-
- ++n;
- if (++current == start_of_completed) {
-
- if (start_of_completed != last)
- return start_of_completed;
-
-
-
- if (all_trivial_requests) {
- std::vector<MPI_Request> requests;
- std::vector<int> indices(n);
- requests.reserve(n);
- for (current = first; current != last; ++current)
- requests.push_back(*current->trivial());
-
- int num_completed;
- BOOST_MPI_CHECK_RESULT(MPI_Waitsome,
- (n, detail::c_data(requests), &num_completed, detail::c_data(indices),
- MPI_STATUSES_IGNORE));
-
-
- int current_offset = 0;
- current = first;
- for (int index = 0; index < num_completed; ++index) {
- using std::iter_swap;
-
- advance(current, indices[index] - current_offset);
- current_offset = indices[index];
-
-
- *current->trivial() = requests[indices[index]];
- --start_of_completed;
- iter_swap(current, start_of_completed);
- }
-
- return start_of_completed;
- }
-
-
- n = 0;
- current = first;
- }
- }
-
- BOOST_ASSERT(false);
- }
- template<typename BidirectionalIterator, typename OutputIterator>
- std::pair<OutputIterator, BidirectionalIterator>
- test_some(BidirectionalIterator first, BidirectionalIterator last,
- OutputIterator out)
- {
- BidirectionalIterator current = first;
- BidirectionalIterator start_of_completed = last;
- while (current != start_of_completed) {
-
- if (optional<status> result = current->test()) {
- using std::iter_swap;
-
- *out++ = *result;
-
- --start_of_completed;
-
-
- iter_swap(current, start_of_completed);
- continue;
- }
-
- ++current;
- }
-
-
- std::reverse(start_of_completed, last);
- return std::make_pair(out, start_of_completed);
- }
- template<typename BidirectionalIterator>
- BidirectionalIterator
- test_some(BidirectionalIterator first, BidirectionalIterator last)
- {
- BidirectionalIterator current = first;
- BidirectionalIterator start_of_completed = last;
- while (current != start_of_completed) {
-
- if (optional<status> result = current->test()) {
- using std::iter_swap;
-
- --start_of_completed;
-
-
- iter_swap(current, start_of_completed);
- continue;
- }
-
- ++current;
- }
- return start_of_completed;
- }
- } }
- #endif
|