diff --git a/include/boost/mpi/communicator.hpp b/include/boost/mpi/communicator.hpp index 8663ba3f..46349c57 100644 --- a/include/boost/mpi/communicator.hpp +++ b/include/boost/mpi/communicator.hpp @@ -775,6 +775,15 @@ class BOOST_MPI_DECL communicator void barrier() const; #endif +#if BOOST_MPI_VERSION >= 3 + /** + * @brief Non blocking version of barrier. + * + * This version will return immediatly. The request completes + * once all participants have reached the barrier. + */ + request ibarrier() const; +#endif /** @brief Determine if this communicator is valid for * communication. * diff --git a/include/boost/mpi/config.hpp b/include/boost/mpi/config.hpp index 1fd093bf..91ea093d 100644 --- a/include/boost/mpi/config.hpp +++ b/include/boost/mpi/config.hpp @@ -45,7 +45,7 @@ #endif #if defined MPI_SUBVERSION -/** @brief Major version of the underlying MPI implementation supproted standard. +/** @brief Major version of the underlying MPI implementation supported standard. * * If, for some reason, MPI_SUBVERSION is not supported, you should probably set that * according to your MPI documentation diff --git a/include/boost/mpi/detail/request_handlers.hpp b/include/boost/mpi/detail/request_handlers.hpp index 50a22ec3..2f14a24f 100644 --- a/include/boost/mpi/detail/request_handlers.hpp +++ b/include/boost/mpi/detail/request_handlers.hpp @@ -509,6 +509,9 @@ class BOOST_MPI_DECL request::trivial_handler : public request::handler { private: friend class request; +#if BOOST_MPI_VERSION >= 3 + friend class communicator; +#endif MPI_Request m_request; }; diff --git a/include/boost/mpi/request.hpp b/include/boost/mpi/request.hpp index 6edccc9b..6818b613 100644 --- a/include/boost/mpi/request.hpp +++ b/include/boost/mpi/request.hpp @@ -38,6 +38,11 @@ class BOOST_MPI_DECL request */ request(); + /** + * Just make a request from a C API request and provide its address + * for future assignement. + */ + static request make_trivial(MPI_Request*& r); /** * Send a known number of primitive objects in one MPI request. */ @@ -150,7 +155,9 @@ class BOOST_MPI_DECL request template class legacy_dynamic_primitive_array_handler; #if BOOST_MPI_VERSION >= 3 template class probe_handler; + friend class communicator; #endif + private: shared_ptr m_handler; shared_ptr m_preserved; diff --git a/src/communicator.cpp b/src/communicator.cpp index 016c6af4..07853857 100644 --- a/src/communicator.cpp +++ b/src/communicator.cpp @@ -131,7 +131,6 @@ void (communicator::barrier)() const BOOST_MPI_CHECK_RESULT(MPI_Barrier, (MPI_Comm(*this))); } - communicator::operator MPI_Comm() const { if (comm_ptr) return *comm_ptr; @@ -325,4 +324,14 @@ bool operator==(const communicator& comm1, const communicator& comm2) return result == MPI_IDENT; } +// Non blocking common +#if BOOST_MPI_VERSION >= 3 +request communicator::ibarrier() const +{ + request::trivial_handler* handler = new request::trivial_handler; + BOOST_MPI_CHECK_RESULT(MPI_Ibarrier, (*this, &handler->m_request)); + return request(handler); +} +#endif + } } // end namespace boost::mpi diff --git a/src/request.cpp b/src/request.cpp index 3ba5695a..b78951f8 100644 --- a/src/request.cpp +++ b/src/request.cpp @@ -26,6 +26,13 @@ request::preserve(boost::shared_ptr d) { } request request::make_dynamic() { return request(new dynamic_handler()); } +request request::make_trivial(MPI_Request*& r) { + trivial_handler *handler = new trivial_handler; + r = &(handler->m_request); + return request(handler); +} + + request request::make_bottom_send(communicator const& comm, int dest, int tag, MPI_Datatype tp) { trivial_handler* handler = new trivial_handler; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index ac9ac253..31883867 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -49,7 +49,9 @@ test-suite mpi [ mpi-test groups_test ] # tests that require -std=c++11 [ mpi-test sendrecv_vector : : : 2 ] - # Intel MPI 2018 and older are axtected to fail: + # Intel MPI 2018 and older are expected to fail: [ mpi-test non_blocking_any_source : : : 2 17 ] + # Non Blockin common (MPI 3 only) + [ mpi-test ibarrier_test : : : 1 3 ] ; } diff --git a/test/ibarrier_test.cpp b/test/ibarrier_test.cpp new file mode 100644 index 00000000..ac7a1923 --- /dev/null +++ b/test/ibarrier_test.cpp @@ -0,0 +1,42 @@ +// Copyright Alain Miniussi 2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// A test of the non blocking barrier operation. + +#include +#include + + +#define BOOST_TEST_MODULE mpi_ibarrier +#include + +namespace mpi = boost::mpi; + +BOOST_AUTO_TEST_CASE(ibarrier_check) +{ + mpi::environment env; + mpi::communicator world; + + std::ostringstream buf; + int rk = world.rank(); + buf << "rk" << rk << ": calling ibarrier.\n"; + std::cout << buf.str(); + mpi::request r = world.ibarrier(); + if (rk == 0) { + while (!r.test()) { + buf << "rk" << rk << ": not completed yet.\n"; + std::cout << buf.str(); + } + buf << "rk" << rk << ": completed.\n"; + std::cout << buf.str(); + } else { + buf << "rk" << rk << ": waiting..."; + std::cout << buf.str() << std::flush; + r.wait(); + buf << "rk" << rk << ": done.\n"; + std::cout << buf.str(); + } + BOOST_TEST(true); +} diff --git a/test/sendrecv_test.cpp b/test/sendrecv_test.cpp index 801b2629..a7fe3a3e 100644 --- a/test/sendrecv_test.cpp +++ b/test/sendrecv_test.cpp @@ -1,4 +1,4 @@ -// Copyright Alain Miniussi 20014. +// Copyright Alain Miniussi 2014. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt)