Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/101 ibcast #108

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions include/boost/mpi/collectives/broadcast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <boost/mpi/exception.hpp>
#include <boost/mpi/datatype.hpp>
#include <boost/mpi/communicator.hpp>
#include <boost/mpi/detail/request_handlers.hpp>

namespace boost { namespace mpi {

Expand Down Expand Up @@ -133,6 +134,25 @@ namespace detail {
ia >> values[i];
}
}

#if BOOST_MPI_VERSION >= 3
// We're sending a type that has an associated MPI datatype, so
// we'll use MPI_Ibcast to do all of the work.
template<typename T>
request
ibroadcast_impl(const communicator& comm, T* values, int n, int root,
mpl::true_)
{
MPI_Request* c_ptr;
request req = request::make_trivial(c_ptr);
BOOST_MPI_CHECK_RESULT(MPI_Ibcast,
(values, n,
boost::mpi::get_mpi_datatype<T>(*values),
root, MPI_Comm(comm), c_ptr));
return req;
}
#endif

} // end namespace detail

template<typename T>
Expand All @@ -147,6 +167,19 @@ void broadcast(const communicator& comm, T* values, int n, int root)
detail::broadcast_impl(comm, values, n, root, is_mpi_datatype<T>());
}

#if BOOST_MPI_VERSION >= 3
template<typename T>
request ibroadcast(const communicator& comm, T& value, int root)
{
return detail::ibroadcast_impl(comm, &value, 1, root, is_mpi_datatype<T>());
}

template<typename T>
request ibroadcast(const communicator& comm, T* values, int n, int root)
{
return detail::ibroadcast_impl(comm, values, n, root, is_mpi_datatype<T>());
}
#endif
} } // end namespace boost::mpi

// If the user has already included skeleton_and_content.hpp, include
Expand Down
9 changes: 9 additions & 0 deletions include/boost/mpi/communicator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
2 changes: 1 addition & 1 deletion include/boost/mpi/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions include/boost/mpi/detail/request_handlers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down
7 changes: 7 additions & 0 deletions include/boost/mpi/request.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -150,7 +155,9 @@ class BOOST_MPI_DECL request
template<typename T, class A> class legacy_dynamic_primitive_array_handler;
#if BOOST_MPI_VERSION >= 3
template<class Data> class probe_handler;
friend class communicator;
#endif

private:
shared_ptr<handler> m_handler;
shared_ptr<void> m_preserved;
Expand Down
11 changes: 10 additions & 1 deletion src/communicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
7 changes: 7 additions & 0 deletions src/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ request::preserve(boost::shared_ptr<void> 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;
Expand Down
4 changes: 3 additions & 1 deletion test/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/Blockin/Blocking/

[ mpi-test ibarrier_test : : : 1 3 ]
;
}
80 changes: 53 additions & 27 deletions test/broadcast_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,45 +19,70 @@
#define BOOST_TEST_MODULE mpi_broadcast
#include <boost/test/included/unit_test.hpp>

using boost::mpi::communicator;

using boost::mpi::packed_skeleton_iarchive;
using boost::mpi::packed_skeleton_oarchive;
namespace mpi = boost::mpi;

template<typename T>
void
broadcast_test(const communicator& comm, const T& bc_value,
const char* kind, int root = -1)
broadcast_test(mpi::communicator const& comm, T const& bc_value,
char const* kind, int root = -1)
{
if (root == -1) {
for (root = 0; root < comm.size(); ++root)
broadcast_test(comm, bc_value, kind, root);
} else {
using boost::mpi::broadcast;
T value;
if (comm.rank() == root) {
value = bc_value;
std::cout << "Broadcasting " << kind << " from root " << root << "...";
std::cout.flush();
}

mpi::broadcast(comm, value, root);
BOOST_CHECK(value == bc_value);
if (comm.rank() == root && value == bc_value)
std::cout << "OK." << std::endl;
}

comm.barrier();
}

template<typename T>
void
ibroadcast_test(mpi::communicator const& comm, T const& bc_value,
char const* kind, int root = -1)
{
if (root == -1) {
for (root = 0; root < comm.size(); ++root)
ibroadcast_test(comm, bc_value, kind, root);
} else {
T value;
if (comm.rank() == root) {
value = bc_value;
std::cout << "Broadcasting " << kind << " from root " << root << "...";
std::cout.flush();
}

broadcast(comm, value, root);
mpi::request req = mpi::ibroadcast(comm, value, root);
std::ostringstream buf;
buf << "rk" << comm.rank() << ": Broadcasting " << value << " from " << root << "...";
if (!req.test()) {
buf << ".. not finished here. So we wait...";
req.wait();
buf << "done.\n";
} else {
buf << ".. which is already finished.\n";
}
std::cout << buf.str();
BOOST_CHECK(value == bc_value);
if (comm.rank() == root && value == bc_value)
std::cout << "OK." << std::endl;
}

(comm.barrier)();
}

void
test_skeleton_and_content(const communicator& comm, int root = 0)
test_skeleton_and_content(mpi::communicator const& comm, int root = 0)
{
using boost::mpi::content;
using boost::mpi::get_content;
using boost::make_counting_iterator;
using boost::mpi::broadcast;

int list_size = comm.size() + 7;
if (comm.rank() == root) {
Expand All @@ -67,21 +92,21 @@ test_skeleton_and_content(const communicator& comm, int root = 0)
original_list.push_back(i);

// Build up the skeleton
packed_skeleton_oarchive oa(comm);
mpi::packed_skeleton_oarchive oa(comm);
oa << original_list;

// Broadcast the skeleton
std::cout << "Broadcasting integer list skeleton from root " << root
<< "..." << std::flush;
broadcast(comm, oa, root);
mpi::broadcast(comm, oa, root);
std::cout << "OK." << std::endl;

// Broadcast the content
std::cout << "Broadcasting integer list content from root " << root
<< "..." << std::flush;
{
content c = get_content(original_list);
broadcast(comm, c, root);
mpi::content c = mpi::get_content(original_list);
mpi::broadcast(comm, c, root);
}
std::cout << "OK." << std::endl;

Expand All @@ -90,8 +115,8 @@ test_skeleton_and_content(const communicator& comm, int root = 0)
std::cout << "Broadcasting reversed integer list content from root "
<< root << "..." << std::flush;
{
content c = get_content(original_list);
broadcast(comm, c, root);
mpi::content c = mpi::get_content(original_list);
mpi::broadcast(comm, c, root);
}
std::cout << "OK." << std::endl;

Expand All @@ -101,24 +126,24 @@ test_skeleton_and_content(const communicator& comm, int root = 0)
std::list<int> junk_list(comm.rank() * 3 + 1, 17);

// Receive the skeleton
packed_skeleton_iarchive ia(comm);
broadcast(comm, ia, root);
mpi::packed_skeleton_iarchive ia(comm);
mpi::broadcast(comm, ia, root);

// Build up a list to match the skeleton, and make sure it has the
// right structure (we have no idea what the data will be).
std::list<int> transferred_list;
ia >> transferred_list;
BOOST_CHECK((int)transferred_list.size() == list_size);
BOOST_CHECK(int(transferred_list.size()) == list_size);

// Receive the content and check it
broadcast(comm, get_content(transferred_list), root);
mpi::broadcast(comm, mpi::get_content(transferred_list), root);
bool list_content_ok = std::equal(make_counting_iterator(0),
make_counting_iterator(list_size),
transferred_list.begin());
BOOST_CHECK(list_content_ok);

// Receive the reversed content and check it
broadcast(comm, get_content(transferred_list), root);
mpi::broadcast(comm, mpi::get_content(transferred_list), root);
bool rlist_content_ok = std::equal(make_counting_iterator(0),
make_counting_iterator(list_size),
transferred_list.rbegin());
Expand All @@ -132,18 +157,19 @@ test_skeleton_and_content(const communicator& comm, int root = 0)
}
}

(comm.barrier)();
comm.barrier();
}

BOOST_AUTO_TEST_CASE(broadcast_check)
{
boost::mpi::environment env;
communicator comm;
mpi::communicator comm;

BOOST_TEST_REQUIRE(comm.size() > 1);

// Check transfer of individual objects
broadcast_test(comm, 17, "integers");
ibroadcast_test(comm, 17, "integers");
broadcast_test(comm, gps_position(39,16,20.2799), "GPS positions");
broadcast_test(comm, gps_position(26,25,30.0), "GPS positions");
broadcast_test(comm, std::string("Rosie"), "string");
Expand Down
42 changes: 42 additions & 0 deletions test/ibarrier_test.cpp
Original file line number Diff line number Diff line change
@@ -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 <boost/mpi/communicator.hpp>
#include <boost/mpi/environment.hpp>


#define BOOST_TEST_MODULE mpi_ibarrier
#include <boost/test/included/unit_test.hpp>

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);
}
2 changes: 1 addition & 1 deletion test/sendrecv_test.cpp
Original file line number Diff line number Diff line change
@@ -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)
Expand Down