From e2ebac2b4d27dbe02db1e2fce181a0a4a5c09e54 Mon Sep 17 00:00:00 2001 From: "K. Noel Belcourt" Date: Fri, 22 Jul 2016 12:14:58 -0600 Subject: [PATCH] Add allocator support to vector send recv api. Added test case to send recv a vector of udt with an overload of get_mpi_datatype. Added test to Jamfile for nightly testing. --- include/boost/mpi/communicator.hpp | 68 ++++++++++++----------- test/Jamfile.v2 | 1 + test/sendrecv_vector.cpp | 86 ++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 32 deletions(-) create mode 100644 test/sendrecv_vector.cpp diff --git a/include/boost/mpi/communicator.hpp b/include/boost/mpi/communicator.hpp index af616a3..a491086 100644 --- a/include/boost/mpi/communicator.hpp +++ b/include/boost/mpi/communicator.hpp @@ -1,4 +1,5 @@ // Copyright (C) 2005, 2006 Douglas Gregor . +// Copyright (C) 2016 K. Noel Belcourt . // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -23,6 +24,7 @@ #include #include #include // for std::range_error +#include // For (de-)serializing sends and receives #include @@ -272,14 +274,16 @@ class BOOST_MPI_DECL communicator template void send(int dest, int tag, const T& value) const; - template - void send(int dest, int tag, const std::vector& value) const; + template + void send(int dest, int tag, const std::vector& value) const; - template - void send_vector(int dest, int tag, const std::vector& value, mpl::true_) const; + template + void send_vector(int dest, int tag, const std::vector& value, + mpl::true_) const; - template - void send_vector(int dest, int tag, const std::vector& value, mpl::false_) const; + template + void send_vector(int dest, int tag, const std::vector& value, + mpl::false_) const; /** * @brief Send the skeleton of an object. @@ -393,16 +397,16 @@ class BOOST_MPI_DECL communicator template status recv(int source, int tag, T& value) const; - template - status recv(int source, int tag, std::vector& value) const; + template + status recv(int source, int tag, std::vector& value) const; - template - status recv_vector(int source, int tag, std::vector& value - , mpl::true_) const; + template + status recv_vector(int source, int tag, std::vector& value, + mpl::true_) const; - template - status recv_vector(int source, int tag, std::vector& value - , mpl::false_) const; + template + status recv_vector(int source, int tag, std::vector& value, + mpl::false_) const; /** * @brief Receive a skeleton from a remote process. @@ -1207,26 +1211,26 @@ communicator::array_send_impl(int dest, int tag, const T* values, int n, send(dest, tag, oa); } -template -void communicator::send_vector(int dest, int tag, const std::vector& value - , mpl::true_ true_type) const +template +void communicator::send_vector(int dest, int tag, + const std::vector& value, mpl::true_ true_type) const { // send the vector size - typename std::vector::size_type size = value.size(); + typename std::vector::size_type size = value.size(); send(dest, tag, size); // send the data this->array_send_impl(dest, tag, value.data(), size, true_type); } -template -void communicator::send_vector(int dest, int tag, const std::vector& value - , mpl::false_ false_type) const +template +void communicator::send_vector(int dest, int tag, + const std::vector& value, mpl::false_ false_type) const { this->send_impl(dest, tag, value, false_type); } -template -void communicator::send(int dest, int tag, const std::vector& value) const +template +void communicator::send(int dest, int tag, const std::vector& value) const { send_vector(dest, tag, value, is_mpi_datatype()); } @@ -1313,12 +1317,12 @@ communicator::array_recv_impl(int source, int tag, T* values, int n, return stat; } -template -status communicator::recv_vector(int source, int tag, std::vector& value - , mpl::true_ true_type) const +template +status communicator::recv_vector(int source, int tag, + std::vector& value, mpl::true_ true_type) const { // receive the vector size - typename std::vector::size_type size = 0; + typename std::vector::size_type size = 0; recv(source, tag, size); // size the vector value.resize(size); @@ -1326,15 +1330,15 @@ status communicator::recv_vector(int source, int tag, std::vector& value return this->array_recv_impl(source, tag, value.data(), size, true_type); } -template -status communicator::recv_vector(int source, int tag, std::vector& value - , mpl::false_ false_type) const +template +status communicator::recv_vector(int source, int tag, + std::vector& value, mpl::false_ false_type) const { return this->recv_impl(source, tag, value, false_type); } -template -status communicator::recv(int source, int tag, std::vector& value) const +template +status communicator::recv(int source, int tag, std::vector& value) const { return recv_vector(source, tag, value, is_mpi_datatype()); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 6c31448..5973eb2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -41,5 +41,6 @@ test-suite mpi [ mpi-test graph_topology_test : : : 2 7 13 ] [ mpi-test pointer_test : : : 2 ] [ mpi-test groups_test ] + [ mpi-test sendrecv_vector : : : 2 ] ; } diff --git a/test/sendrecv_vector.cpp b/test/sendrecv_vector.cpp new file mode 100644 index 0000000..0d032e9 --- /dev/null +++ b/test/sendrecv_vector.cpp @@ -0,0 +1,86 @@ +// Author: K. Noel Belcourt + +// 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) + +#include +#include +#include + +#include "boost/mpi/environment.hpp" +#include "boost/mpi/communicator.hpp" + +using std::array; +using std::vector; + +namespace mpi = boost::mpi; + +struct blob : array, array, array { +}; + +template <> +struct mpi::is_mpi_datatype : mpl::true_ { +}; + +template <> +MPI_Datatype +mpi::get_mpi_datatype(const blob& b) +{ + const array block_lengths{ + { 9, 3, 5 } + }; + + const array displacements{ + { 0, 40, 64 } + }; + + const array datatypes{ + { MPI_INT, MPI_DOUBLE, MPI_CHAR } + }; + + MPI_Datatype blob_type; + MPI_Type_create_struct(block_lengths.size() + , (const int *)block_lengths.data(), displacements.data(), + datatypes.data(), &blob_type); + + MPI_Type_commit(&blob_type); + return blob_type; + +} + +int main(int argc, char* argv[]) { + mpi::environment env(argc, argv); + mpi::communicator world; + + vector data; + + if (world.rank() == 0) { + int size = 10000000; + data.resize(size); + // initialize data at vector ends + blob& b1= data[0]; + array& i = b1; + i[0] = -1; +#if 0 + blob& b2= data[size-1]; + array& c = b2; + c[4] = 'a'; +#endif + world.send(1, 0, data); + } + else { + world.recv(0, 0, data); + // check data at vector ends + blob& b1 = data[0]; + array& i = b1; + assert(i[0] == -1); +#if 0 + blob& b2 = data[data.size()-1]; + array& c = b2; + assert(c[4] == 'a'); +#endif + } + + return 0; +}