diff --git a/include/boost/mpi/collectives/all_gather.hpp b/include/boost/mpi/collectives/all_gather.hpp index d44ea42..da665e9 100644 --- a/include/boost/mpi/collectives/all_gather.hpp +++ b/include/boost/mpi/collectives/all_gather.hpp @@ -27,7 +27,7 @@ namespace detail { all_gather_impl(const communicator& comm, const T* in_values, int n, T* out_values, mpl::true_) { - MPI_Datatype type = boost::mpi::get_mpi_datatype(); + MPI_Datatype type = boost::mpi::get_mpi_datatype(*in_values); BOOST_MPI_CHECK_RESULT(MPI_Allgather, (const_cast(in_values), n, type, out_values, n, type, comm)); diff --git a/include/boost/mpi/collectives/all_reduce.hpp b/include/boost/mpi/collectives/all_reduce.hpp index 41acdb9..fbb4090 100644 --- a/include/boost/mpi/collectives/all_reduce.hpp +++ b/include/boost/mpi/collectives/all_reduce.hpp @@ -32,7 +32,7 @@ namespace detail { { BOOST_MPI_CHECK_RESULT(MPI_Allreduce, (const_cast(in_values), out_values, n, - boost::mpi::get_mpi_datatype(), + boost::mpi::get_mpi_datatype(*in_values), is_mpi_op::op(), comm)); } @@ -51,7 +51,7 @@ namespace detail { user_op mpi_op(op); BOOST_MPI_CHECK_RESULT(MPI_Allreduce, (const_cast(in_values), out_values, n, - boost::mpi::get_mpi_datatype(), + boost::mpi::get_mpi_datatype(*in_values), mpi_op.get_mpi_op(), comm)); } diff --git a/include/boost/mpi/collectives/all_to_all.hpp b/include/boost/mpi/collectives/all_to_all.hpp index 61f512b..8c33c2a 100644 --- a/include/boost/mpi/collectives/all_to_all.hpp +++ b/include/boost/mpi/collectives/all_to_all.hpp @@ -30,7 +30,7 @@ namespace detail { all_to_all_impl(const communicator& comm, const T* in_values, int n, T* out_values, mpl::true_) { - MPI_Datatype type = get_mpi_datatype(); + MPI_Datatype type = get_mpi_datatype(*in_values); BOOST_MPI_CHECK_RESULT(MPI_Alltoall, (const_cast(in_values), n, type, out_values, n, type, comm)); @@ -87,6 +87,10 @@ namespace detail { } std::vector > incoming(sum > 0? sum : 1); + // Make sure we don't try to reference an empty vector + if (outgoing.empty()) + outgoing.push_back(0); + // Transmit the actual data BOOST_MPI_CHECK_RESULT(MPI_Alltoallv, (&outgoing[0], &send_sizes[0], diff --git a/include/boost/mpi/collectives/broadcast.hpp b/include/boost/mpi/collectives/broadcast.hpp index 7a8ce83..a615cc2 100644 --- a/include/boost/mpi/collectives/broadcast.hpp +++ b/include/boost/mpi/collectives/broadcast.hpp @@ -95,7 +95,7 @@ namespace detail { { BOOST_MPI_CHECK_RESULT(MPI_Bcast, (values, n, - boost::mpi::get_mpi_datatype(), + boost::mpi::get_mpi_datatype(*values), root, MPI_Comm(comm))); } diff --git a/include/boost/mpi/collectives/gather.hpp b/include/boost/mpi/collectives/gather.hpp index ab104bd..5c605a8 100644 --- a/include/boost/mpi/collectives/gather.hpp +++ b/include/boost/mpi/collectives/gather.hpp @@ -28,7 +28,7 @@ namespace detail { gather_impl(const communicator& comm, const T* in_values, int n, T* out_values, int root, mpl::true_) { - MPI_Datatype type = get_mpi_datatype(); + MPI_Datatype type = get_mpi_datatype(*in_values); BOOST_MPI_CHECK_RESULT(MPI_Gather, (const_cast(in_values), n, type, out_values, n, type, root, comm)); @@ -41,7 +41,7 @@ namespace detail { gather_impl(const communicator& comm, const T* in_values, int n, int root, mpl::true_) { - MPI_Datatype type = get_mpi_datatype(); + MPI_Datatype type = get_mpi_datatype(*in_values); BOOST_MPI_CHECK_RESULT(MPI_Gather, (const_cast(in_values), n, type, 0, n, type, root, comm)); @@ -99,10 +99,12 @@ void gather(const communicator& comm, const T& in_value, std::vector& out_values, int root) { - if (comm.rank() == root) + if (comm.rank() == root) { out_values.resize(comm.size()); - - ::boost::mpi::gather(comm, in_value, &out_values[0], root); + ::boost::mpi::gather(comm, in_value, &out_values[0], root); + } else { + ::boost::mpi::gather(comm, in_value, root); + } } template diff --git a/include/boost/mpi/collectives/reduce.hpp b/include/boost/mpi/collectives/reduce.hpp index 39c18de..6ea8279 100644 --- a/include/boost/mpi/collectives/reduce.hpp +++ b/include/boost/mpi/collectives/reduce.hpp @@ -51,7 +51,7 @@ namespace detail { { BOOST_MPI_CHECK_RESULT(MPI_Reduce, (const_cast(in_values), out_values, n, - boost::mpi::get_mpi_datatype(), + boost::mpi::get_mpi_datatype(*in_values), is_mpi_op::op(), root, comm)); } @@ -64,7 +64,7 @@ namespace detail { { BOOST_MPI_CHECK_RESULT(MPI_Reduce, (const_cast(in_values), 0, n, - boost::mpi::get_mpi_datatype(), + boost::mpi::get_mpi_datatype(*in_values), is_mpi_op::op(), root, comm)); } @@ -84,7 +84,7 @@ namespace detail { user_op mpi_op(op); BOOST_MPI_CHECK_RESULT(MPI_Reduce, (const_cast(in_values), out_values, n, - boost::mpi::get_mpi_datatype(), + boost::mpi::get_mpi_datatype(*in_values), mpi_op.get_mpi_op(), root, comm)); } @@ -99,7 +99,7 @@ namespace detail { user_op mpi_op(op); BOOST_MPI_CHECK_RESULT(MPI_Reduce, (const_cast(in_values), 0, n, - boost::mpi::get_mpi_datatype(), + boost::mpi::get_mpi_datatype(*in_values), mpi_op.get_mpi_op(), root, comm)); } diff --git a/include/boost/mpi/collectives/scan.hpp b/include/boost/mpi/collectives/scan.hpp index e01359a..83dc8ca 100644 --- a/include/boost/mpi/collectives/scan.hpp +++ b/include/boost/mpi/collectives/scan.hpp @@ -51,7 +51,7 @@ namespace detail { { BOOST_MPI_CHECK_RESULT(MPI_Scan, (const_cast(in_values), out_values, n, - boost::mpi::get_mpi_datatype(), + boost::mpi::get_mpi_datatype(*in_values), is_mpi_op::op(), comm)); } @@ -70,7 +70,7 @@ namespace detail { user_op mpi_op(op); BOOST_MPI_CHECK_RESULT(MPI_Scan, (const_cast(in_values), out_values, n, - boost::mpi::get_mpi_datatype(), + boost::mpi::get_mpi_datatype(*in_values), mpi_op.get_mpi_op(), comm)); } diff --git a/include/boost/mpi/collectives/scatter.hpp b/include/boost/mpi/collectives/scatter.hpp index 125d001..4d9ed8e 100644 --- a/include/boost/mpi/collectives/scatter.hpp +++ b/include/boost/mpi/collectives/scatter.hpp @@ -28,7 +28,7 @@ namespace detail { scatter_impl(const communicator& comm, const T* in_values, T* out_values, int n, int root, mpl::true_) { - MPI_Datatype type = get_mpi_datatype(); + MPI_Datatype type = get_mpi_datatype(*in_values); BOOST_MPI_CHECK_RESULT(MPI_Scatter, (const_cast(in_values), n, type, out_values, n, type, root, comm)); @@ -41,7 +41,7 @@ namespace detail { scatter_impl(const communicator& comm, T* out_values, int n, int root, mpl::true_) { - MPI_Datatype type = get_mpi_datatype(); + MPI_Datatype type = get_mpi_datatype(*out_values); BOOST_MPI_CHECK_RESULT(MPI_Scatter, (0, n, type, out_values, n, type, @@ -112,10 +112,10 @@ scatter(const communicator& comm, const std::vector& in_values, T& out_value, int root) { if (comm.rank() == root) - ::boost::mpi::scatter(comm, &in_values[0], out_value, root); + ::boost::mpi::scatter(comm, &in_values[0], out_value, root); else - ::boost::mpi::scatter(comm, static_cast(0), out_value, - root); + ::boost::mpi::scatter(comm, static_cast(0), out_value, + root); } template diff --git a/include/boost/mpi/communicator.hpp b/include/boost/mpi/communicator.hpp index 9362ec9..d0bf763 100644 --- a/include/boost/mpi/communicator.hpp +++ b/include/boost/mpi/communicator.hpp @@ -35,6 +35,11 @@ #include #include +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4800) // forcing to bool 'true' or 'false' +#endif + namespace boost { namespace mpi { /** @@ -955,7 +960,7 @@ optional status::count_impl(mpl::true_) int return_value; BOOST_MPI_CHECK_RESULT(MPI_Get_count, - (&m_status, get_mpi_datatype(), &return_value)); + (&m_status, get_mpi_datatype(T()), &return_value)); if (return_value == MPI_UNDEFINED) return optional(); else @@ -979,7 +984,7 @@ void communicator::send_impl(int dest, int tag, const T& value, mpl::true_) const { BOOST_MPI_CHECK_RESULT(MPI_Send, - (const_cast(&value), 1, get_mpi_datatype(), + (const_cast(&value), 1, get_mpi_datatype(value), dest, tag, MPI_Comm(*this))); } @@ -1011,7 +1016,8 @@ communicator::array_send_impl(int dest, int tag, const T* values, int n, mpl::true_) const { BOOST_MPI_CHECK_RESULT(MPI_Send, - (const_cast(values), n, get_mpi_datatype(), + (const_cast(values), n, + get_mpi_datatype(*values), dest, tag, MPI_Comm(*this))); } @@ -1043,7 +1049,8 @@ status communicator::recv_impl(int source, int tag, T& value, mpl::true_) const status stat; BOOST_MPI_CHECK_RESULT(MPI_Recv, - (const_cast(&value), 1, get_mpi_datatype(), + (const_cast(&value), 1, + get_mpi_datatype(value), source, tag, MPI_Comm(*this), &stat.m_status)); return stat; } @@ -1077,7 +1084,8 @@ communicator::array_recv_impl(int source, int tag, T* values, int n, { status stat; BOOST_MPI_CHECK_RESULT(MPI_Recv, - (const_cast(values), n, get_mpi_datatype(), + (const_cast(values), n, + get_mpi_datatype(*values), source, tag, MPI_Comm(*this), &stat.m_status)); return stat; } @@ -1123,7 +1131,8 @@ communicator::isend_impl(int dest, int tag, const T& value, mpl::true_) const { request req; BOOST_MPI_CHECK_RESULT(MPI_Isend, - (const_cast(&value), 1, get_mpi_datatype(), + (const_cast(&value), 1, + get_mpi_datatype(value), dest, tag, MPI_Comm(*this), &req.m_requests[0])); return req; } @@ -1157,7 +1166,8 @@ communicator::array_isend_impl(int dest, int tag, const T* values, int n, { request req; BOOST_MPI_CHECK_RESULT(MPI_Isend, - (const_cast(values), n, get_mpi_datatype(), + (const_cast(values), n, + get_mpi_datatype(*values), dest, tag, MPI_Comm(*this), &req.m_requests[0])); return req; } @@ -1396,7 +1406,8 @@ communicator::irecv_impl(int source, int tag, T& value, mpl::true_) const { request req; BOOST_MPI_CHECK_RESULT(MPI_Irecv, - (const_cast(&value), 1, get_mpi_datatype(), + (const_cast(&value), 1, + get_mpi_datatype(value), source, tag, MPI_Comm(*this), &req.m_requests[0])); return req; } @@ -1412,7 +1423,8 @@ communicator::irecv_impl(int source, int tag, T& value, mpl::false_) const req.m_handler = request::handle_serialized_irecv; BOOST_MPI_CHECK_RESULT(MPI_Irecv, - (&data->count, 1, get_mpi_datatype(), + (&data->count, 1, + get_mpi_datatype(data->count), source, tag, MPI_Comm(*this), &req.m_requests[0])); return req; @@ -1432,7 +1444,8 @@ communicator::array_irecv_impl(int source, int tag, T* values, int n, { request req; BOOST_MPI_CHECK_RESULT(MPI_Irecv, - (const_cast(values), n, get_mpi_datatype(), + (const_cast(values), n, + get_mpi_datatype(*values), source, tag, MPI_Comm(*this), &req.m_requests[0])); return req; } @@ -1449,7 +1462,8 @@ communicator::array_irecv_impl(int source, int tag, T* values, int n, req.m_handler = request::handle_serialized_array_irecv; BOOST_MPI_CHECK_RESULT(MPI_Irecv, - (&data->count, 1, get_mpi_datatype(), + (&data->count, 1, + get_mpi_datatype(data->count), source, tag, MPI_Comm(*this), &req.m_requests[0])); return req; @@ -1580,4 +1594,8 @@ communicator::irecv(int source, int tag, # include #endif +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + #endif // BOOST_MPI_COMMUNICATOR_HPP diff --git a/include/boost/mpi/config.hpp b/include/boost/mpi/config.hpp index 5bcc271..92c2c83 100644 --- a/include/boost/mpi/config.hpp +++ b/include/boost/mpi/config.hpp @@ -39,6 +39,22 @@ # define BOOST_MPI_HAS_NOARG_INITIALIZATION #endif +#if defined(MPIAPI) +# define BOOST_MPI_CALLING_CONVENTION MPIAPI +#else +/** @brief Specifies the calling convention that will be used for callbacks + * from the underlying C MPI. + * + * This is a Windows-specific macro, which will be used internally to state + * the calling convention of any function that is to be used as a callback + * from MPI. For example, the internally-defined functions that are used in + * a call to @c MPI_Op_create. This macro is likely only to be useful to + * users that wish to bypass Boost.MPI, registering their own callbacks in + * certain cases, e.g., through @c MPI_Op_create. + */ +# define BOOST_MPI_CALLING_CONVENTION +#endif + #if defined(LAM_MPI) // Configuration for LAM/MPI # define BOOST_MPI_HAS_MEMORY_ALLOCATION diff --git a/include/boost/mpi/detail/mpi_datatype_cache.hpp b/include/boost/mpi/detail/mpi_datatype_cache.hpp index dc98911..4f19970 100644 --- a/include/boost/mpi/detail/mpi_datatype_cache.hpp +++ b/include/boost/mpi/detail/mpi_datatype_cache.hpp @@ -18,6 +18,15 @@ #include #include +// The std::type_info::before function in Visual C++ 8.0 (and probably earlier) +// incorrectly returns an "int" instead of a "bool". Then the compiler has the +// audacity to complain when that "int" is converted to a "bool". Silence +// this warning. +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4800) +#endif + namespace boost { namespace mpi { namespace detail { /// @brief comparison function object for two std::type_info pointers @@ -55,13 +64,13 @@ public: } template - MPI_Datatype datatype(const T& = T(), typename boost::enable_if >::type* =0) + MPI_Datatype datatype(const T& x = T(), typename boost::enable_if >::type* =0) { - return get_mpi_datatype(); + return get_mpi_datatype(x); } template - MPI_Datatype datatype(const T& x=T(), typename boost::disable_if >::type* =0 ) + MPI_Datatype datatype(const T& x =T(), typename boost::disable_if >::type* =0 ) { BOOST_MPL_ASSERT((is_mpi_datatype)); @@ -94,5 +103,8 @@ extern mpi_datatype_map mpi_datatype_cache; } } } // end namespace boost::mpi::detail +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif #endif // BOOST_MPI_DETAIL_TYPE_MPI_DATATYPE_CACHE_HPP diff --git a/include/boost/mpi/detail/packed_oprimitive.hpp b/include/boost/mpi/detail/packed_oprimitive.hpp index 9cae7fa..b752cf0 100644 --- a/include/boost/mpi/detail/packed_oprimitive.hpp +++ b/include/boost/mpi/detail/packed_oprimitive.hpp @@ -74,7 +74,7 @@ public: template void save(const T & t) { - save_impl(&t, get_mpi_datatype(), 1); + save_impl(&t, get_mpi_datatype(t), 1); } void save(const std::string &s) diff --git a/include/boost/mpi/operations.hpp b/include/boost/mpi/operations.hpp index edb326c..c1189e4 100644 --- a/include/boost/mpi/operations.hpp +++ b/include/boost/mpi/operations.hpp @@ -18,7 +18,7 @@ #ifndef BOOST_MPI_IS_MPI_OP_HPP #define BOOST_MPI_IS_MPI_OP_HPP -#include +#include #include #include #include @@ -305,7 +305,7 @@ namespace detail { MPI_Op mpi_op; static Op* op_ptr; - static void perform(void* vinvec, void* voutvec, int* plen, MPI_Datatype*) + static void BOOST_MPI_CALLING_CONVENTION perform(void* vinvec, void* voutvec, int* plen, MPI_Datatype*) { T* invec = static_cast(vinvec); T* outvec = static_cast(voutvec);