Showing with 3,880 additions and 13 deletions.
  1. +3 −0 .gitignore
  2. +86 −0 CMakeLists.txt
  3. +1 −0 build/Jamfile.v2
  4. +49 −0 include/boost/mpi/collectives.hpp
  5. +2 −1 include/boost/mpi/datatype.hpp
  6. +1 −1 include/boost/mpi/detail/binary_buffer_iprimitive.hpp
  7. +1 −1 include/boost/mpi/detail/binary_buffer_oprimitive.hpp
  8. +2 −1 include/boost/mpi/detail/ignore_skeleton_oarchive.hpp
  9. +1 −1 include/boost/mpi/detail/offsets.hpp
  10. +15 −4 include/boost/mpi/environment.hpp
  11. +2 −1 meta/libraries.json
  12. +55 −3 src/environment.cpp
  13. +56 −0 test/CMakeLists.txt
  14. +52 −0 test/mpi_test_utils.hpp
  15. +153 −0 test/test_all_gather.cpp
  16. +317 −0 test/test_all_reduce.cpp
  17. +115 −0 test/test_all_to_all.cpp
  18. +101 −0 test/test_block_nonblock.cpp
  19. +166 −0 test/test_broadcast.cpp
  20. +78 −0 test/test_broadcast_stl.cpp
  21. +211 −0 test/test_cartesian_topology.cpp
  22. +88 −0 test/test_cartesian_topology_init.cpp
  23. +170 −0 test/test_gather.cpp
  24. +142 −0 test/test_graph_topology.cpp
  25. +63 −0 test/test_groups.cpp
  26. +33 −0 test/test_is_mpi_op.cpp
  27. +40 −0 test/test_mt_init.cpp
  28. +115 −0 test/test_mt_level.cpp
  29. +64 −0 test/test_non_blocking_any_source.cpp
  30. +252 −0 test/test_nonblocking.cpp
  31. +42 −0 test/test_pointer.cpp
  32. +240 −0 test/test_reduce.cpp
  33. +130 −0 test/test_ring.cpp
  34. +231 −0 test/test_scan.cpp
  35. +236 −0 test/test_scatter.cpp
  36. +66 −0 test/test_sendrecv.cpp
  37. +95 −0 test/test_sendrecv_vector.cpp
  38. +206 −0 test/test_skeleton_content.cpp
  39. +67 −0 test/test_version.cpp
  40. +17 −0 test/test_wait_all_on_null.cpp
  41. +46 −0 test/test_wait_all_vector.cpp
  42. +64 −0 test/test_wait_any.cpp
  43. +6 −0 test/version_test.cpp
3 changes: 3 additions & 0 deletions .gitignore
@@ -0,0 +1,3 @@
**~
*.pyc
TAGS
86 changes: 86 additions & 0 deletions CMakeLists.txt
@@ -0,0 +1,86 @@
# Generated by `boostdep --cmake mpi`
# Copyright 2020 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt

cmake_minimum_required(VERSION 3.5...3.20)

project(boost_mpi VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)

add_library(boost_mpi
src/broadcast.cpp
src/cartesian_communicator.cpp
src/communicator.cpp
src/computation_tree.cpp
src/content_oarchive.cpp
src/environment.cpp
src/error_string.cpp
src/exception.cpp
src/graph_communicator.cpp
src/group.cpp
src/intercommunicator.cpp
src/mpi_datatype_cache.cpp
src/mpi_datatype_oarchive.cpp
src/offsets.cpp
src/packed_iarchive.cpp
src/packed_oarchive.cpp
src/packed_skeleton_iarchive.cpp
src/packed_skeleton_oarchive.cpp
src/point_to_point.cpp
src/request.cpp
src/status.cpp
src/text_skeleton_oarchive.cpp
src/timer.cpp
)

add_library(Boost::mpi ALIAS boost_mpi)

target_include_directories(boost_mpi PUBLIC include)

target_link_libraries(boost_mpi
PUBLIC
Boost::assert
Boost::config
Boost::core
Boost::foreach
Boost::function
Boost::graph
Boost::integer
Boost::iterator
Boost::mpl
Boost::optional
Boost::serialization
Boost::smart_ptr
Boost::static_assert
Boost::throw_exception
Boost::type_traits

PRIVATE
Boost::lexical_cast
Boost::utility
)

if(BOOST_ENABLE_MPI)

find_package(MPI REQUIRED COMPONENTS CXX)
target_link_libraries(boost_mpi PUBLIC MPI::MPI_CXX)

endif()

target_compile_definitions(boost_mpi
PUBLIC BOOST_MPI_NO_LIB
PRIVATE BOOST_MPI_SOURCE
)

if(BUILD_SHARED_LIBS)
target_compile_definitions(boost_mpi PUBLIC BOOST_MPI_DYN_LINK)
else()
target_compile_definitions(boost_mpi PUBLIC BOOST_MPI_STATIC_LINK)
endif()

if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")

add_subdirectory(test)

endif()

1 change: 1 addition & 0 deletions build/Jamfile.v2
Expand Up @@ -77,6 +77,7 @@ lib boost_mpi
: # Requirements : # Requirements
<library>boost_mpi <library>boost_mpi
<library>/mpi//mpi [ mpi.extra-requirements ] <library>/mpi//mpi [ mpi.extra-requirements ]
<library>/python//python_for_extensions
<library>/boost/python//boost_python <library>/boost/python//boost_python
<link>shared:<define>BOOST_MPI_DYN_LINK=1 <link>shared:<define>BOOST_MPI_DYN_LINK=1
<link>shared:<define>BOOST_MPI_PYTHON_DYN_LINK=1 <link>shared:<define>BOOST_MPI_PYTHON_DYN_LINK=1
Expand Down
49 changes: 49 additions & 0 deletions include/boost/mpi/collectives.hpp
Expand Up @@ -74,6 +74,54 @@ template<typename T>
void void
all_gather(const communicator& comm, const T* in_values, int n, T* out_values); all_gather(const communicator& comm, const T* in_values, int n, T* out_values);


/**
* \overload
*/
template<typename T>
void
all_gatherv(const communicator& comm, const T& in_value, T* out_values,
const std::vector<int>& sizes);

/**
* \overload
*/
template<typename T>
void
all_gatherv(const communicator& comm, const T* in_values, T* out_values,
const std::vector<int>& sizes);

/**
* \overload
*/
template<typename T>
void
all_gatherv(const communicator& comm, std::vector<T> const& in_values, std::vector<T>& out_values,
const std::vector<int>& sizes);

/**
* \overload
*/
template<typename T>
void
all_gatherv(const communicator& comm, const T& in_value, T* out_values,
const std::vector<int>& sizes, const std::vector<int>& displs);

/**
* \overload
*/
template<typename T>
void
all_gatherv(const communicator& comm, const T* in_values, T* out_values,
const std::vector<int>& sizes, const std::vector<int>& displs);

/**
* \overload
*/
template<typename T>
void
all_gatherv(const communicator& comm, std::vector<T> const& in_values, std::vector<T>& out_values,
const std::vector<int>& sizes, const std::vector<int>& displs);

/** /**
* @brief Combine the values stored by each process into a single * @brief Combine the values stored by each process into a single
* value available to all processes. * value available to all processes.
Expand Down Expand Up @@ -684,6 +732,7 @@ scan(const communicator& comm, const T* in_values, int n, T* out_values, Op op);
#ifndef BOOST_MPI_COLLECTIVES_FORWARD_ONLY #ifndef BOOST_MPI_COLLECTIVES_FORWARD_ONLY
// Include implementations of each of the collectives // Include implementations of each of the collectives
# include <boost/mpi/collectives/all_gather.hpp> # include <boost/mpi/collectives/all_gather.hpp>
# include <boost/mpi/collectives/all_gatherv.hpp>
# include <boost/mpi/collectives/all_reduce.hpp> # include <boost/mpi/collectives/all_reduce.hpp>
# include <boost/mpi/collectives/all_to_all.hpp> # include <boost/mpi/collectives/all_to_all.hpp>
# include <boost/mpi/collectives/broadcast.hpp> # include <boost/mpi/collectives/broadcast.hpp>
Expand Down
3 changes: 2 additions & 1 deletion include/boost/mpi/datatype.hpp
Expand Up @@ -27,6 +27,7 @@
#include <boost/mpi/detail/mpi_datatype_cache.hpp> #include <boost/mpi/detail/mpi_datatype_cache.hpp>
#include <boost/mpl/assert.hpp> #include <boost/mpl/assert.hpp>
#include <boost/archive/basic_archive.hpp> #include <boost/archive/basic_archive.hpp>
#include <boost/serialization/library_version_type.hpp>
#include <boost/serialization/item_version_type.hpp> #include <boost/serialization/item_version_type.hpp>
#include <utility> // for std::pair #include <utility> // for std::pair


Expand Down Expand Up @@ -344,7 +345,7 @@ struct is_mpi_datatype<bool>


#ifndef BOOST_MPI_DOXYGEN #ifndef BOOST_MPI_DOXYGEN
// direct support for special primitive data types of the serialization library // direct support for special primitive data types of the serialization library
BOOST_MPI_DATATYPE(boost::archive::library_version_type, get_mpi_datatype(uint_least16_t()), integer); BOOST_MPI_DATATYPE(boost::serialization::library_version_type, get_mpi_datatype(uint_least16_t()), integer);
BOOST_MPI_DATATYPE(boost::archive::version_type, get_mpi_datatype(uint_least8_t()), integer); BOOST_MPI_DATATYPE(boost::archive::version_type, get_mpi_datatype(uint_least8_t()), integer);
BOOST_MPI_DATATYPE(boost::archive::class_id_type, get_mpi_datatype(int_least16_t()), integer); BOOST_MPI_DATATYPE(boost::archive::class_id_type, get_mpi_datatype(int_least16_t()), integer);
BOOST_MPI_DATATYPE(boost::archive::class_id_reference_type, get_mpi_datatype(int_least16_t()), integer); BOOST_MPI_DATATYPE(boost::archive::class_id_reference_type, get_mpi_datatype(int_least16_t()), integer);
Expand Down
2 changes: 1 addition & 1 deletion include/boost/mpi/detail/binary_buffer_iprimitive.hpp
Expand Up @@ -100,7 +100,7 @@ class BOOST_MPI_DECL binary_buffer_iprimitive
#endif #endif
s.resize(l); s.resize(l);
// note breaking a rule here - could be a problem on some platform // note breaking a rule here - could be a problem on some platform
load_impl(const_cast<char *>(s.data()),l); load_impl(const_cast<CharType *>(s.data()), l*sizeof(CharType));
} }


private: private:
Expand Down
2 changes: 1 addition & 1 deletion include/boost/mpi/detail/binary_buffer_oprimitive.hpp
Expand Up @@ -89,7 +89,7 @@ class BOOST_MPI_DECL binary_buffer_oprimitive
{ {
unsigned int l = static_cast<unsigned int>(s.size()); unsigned int l = static_cast<unsigned int>(s.size());
save(l); save(l);
save_impl(s.data(),s.size()); save_impl(s.data(),s.size()*sizeof(CharType));
} }


private: private:
Expand Down
3 changes: 2 additions & 1 deletion include/boost/mpi/detail/ignore_skeleton_oarchive.hpp
Expand Up @@ -15,6 +15,7 @@
#include <boost/archive/detail/oserializer.hpp> #include <boost/archive/detail/oserializer.hpp>
#include <boost/serialization/collection_size_type.hpp> #include <boost/serialization/collection_size_type.hpp>
#include <boost/serialization/array.hpp> #include <boost/serialization/array.hpp>
#include <boost/serialization/library_version_type.hpp>
#include <boost/serialization/item_version_type.hpp> #include <boost/serialization/item_version_type.hpp>


namespace boost { namespace mpi { namespace detail { namespace boost { namespace mpi { namespace detail {
Expand Down Expand Up @@ -48,14 +49,14 @@ class ignore_skeleton_oarchive


BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::class_id_optional_type) BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::class_id_optional_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::version_type) BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::version_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::library_version_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::class_id_type) BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::class_id_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::class_id_reference_type) BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::class_id_reference_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::object_id_type) BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::object_id_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::object_reference_type) BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::object_reference_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::tracking_type) BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::tracking_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::class_name_type) BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(archive::class_name_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(serialization::collection_size_type) BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(serialization::collection_size_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(serialization::library_version_type)
BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(serialization::item_version_type) BOOST_ARCHIVE_IGNORE_IMPLEMENTATION(serialization::item_version_type)


void save_override(std::string const & s) void save_override(std::string const & s)
Expand Down
2 changes: 1 addition & 1 deletion include/boost/mpi/detail/offsets.hpp
Expand Up @@ -33,7 +33,7 @@ void offsets2skipped(int const* sizes, int const* offsets, int* skipped, int n);
// displs are not already provided. // displs are not already provided.
// If memory was allocated, returns a pointer to it // If memory was allocated, returns a pointer to it
// otherwise null. // otherwise null.
int* make_offsets(communicator const& comm, int const* sizes, int const* displs, int root = -1); int* BOOST_MPI_DECL make_offsets(communicator const& comm, int const* sizes, int const* displs, int root = -1);


// Reconstruct skip slots from sizes and offsets. // Reconstruct skip slots from sizes and offsets.
// Only takes place if on the root process and if // Only takes place if on the root process and if
Expand Down
19 changes: 15 additions & 4 deletions include/boost/mpi/environment.hpp
Expand Up @@ -28,27 +28,27 @@ namespace threading {
enum level { enum level {
/** Only one thread will execute. /** Only one thread will execute.
*/ */
single = MPI_THREAD_SINGLE, single,
/** Only main thread will do MPI calls. /** Only main thread will do MPI calls.
* *
* The process may be multi-threaded, but only the main * The process may be multi-threaded, but only the main
* thread will make MPI calls (all MPI calls are ``funneled'' * thread will make MPI calls (all MPI calls are ``funneled''
* to the main thread). * to the main thread).
*/ */
funneled = MPI_THREAD_FUNNELED, funneled,
/** Only one thread at the time do MPI calls. /** Only one thread at the time do MPI calls.
* *
* The process may be multi-threaded, and multiple * The process may be multi-threaded, and multiple
* threads may make MPI calls, but only one at a time: * threads may make MPI calls, but only one at a time:
* MPI calls are not made concurrently from two distinct * MPI calls are not made concurrently from two distinct
* threads (all MPI calls are ``serialized''). * threads (all MPI calls are ``serialized'').
*/ */
serialized = MPI_THREAD_SERIALIZED, serialized,
/** Multiple thread may do MPI calls. /** Multiple thread may do MPI calls.
* *
* Multiple threads may call MPI, with no restrictions. * Multiple threads may call MPI, with no restrictions.
*/ */
multiple = MPI_THREAD_MULTIPLE multiple
}; };


/** Formated output for threading level. */ /** Formated output for threading level. */
Expand Down Expand Up @@ -271,6 +271,17 @@ class BOOST_MPI_DECL environment : noncopyable {
*/ */
static std::pair<int, int> version(); static std::pair<int, int> version();


/** @brief MPI library implementation version string.
*
* This routine returns a string with an additional library version
* information. The actual form of this version string is unspecified,
* but may be documented by the underlying MPI implementation.
* This routine is implemented as a call to @c MPI_Get_library_version,
* which is available from MPI-3. On older implementations the empty
* string will be returned.
*/
static std::string library_version();

private: private:
/// Whether this environment object called MPI_Init /// Whether this environment object called MPI_Init
bool i_initialized; bool i_initialized;
Expand Down
3 changes: 2 additions & 1 deletion meta/libraries.json
Expand Up @@ -12,5 +12,6 @@
"maintainers": [ "maintainers": [
"K. Noel Belcourt <kbelco -at- sandia.gov>", "K. Noel Belcourt <kbelco -at- sandia.gov>",
"Alain Miniussi <alain.miniussi -at- oca.eu>" "Alain Miniussi <alain.miniussi -at- oca.eu>"
] ],
"cxxstd": "03"
} }
58 changes: 55 additions & 3 deletions src/environment.cpp
Expand Up @@ -16,7 +16,47 @@
#include <ostream> #include <ostream>


namespace boost { namespace mpi { namespace boost { namespace mpi {
namespace detail {

int level2int(threading::level l)
{
using namespace threading;

switch(l) {
case single:
return MPI_THREAD_SINGLE;
case funneled:
return MPI_THREAD_FUNNELED;
case serialized:
return MPI_THREAD_SERIALIZED;
case multiple:
return MPI_THREAD_MULTIPLE;
default:
environment::abort(70); // EX_SOFTWARE
}
}

threading::level int2level(int mpi_level)
{
using namespace threading;

switch(mpi_level) {
case MPI_THREAD_SINGLE:
return single;
case MPI_THREAD_FUNNELED:
return funneled;
case MPI_THREAD_SERIALIZED:
return serialized;
case MPI_THREAD_MULTIPLE:
return multiple;
default:
environment::abort(70); // EX_SOFTWARE
}
}
} // namespace detail

namespace threading { namespace threading {

std::istream& operator>>(std::istream& in, level& l) std::istream& operator>>(std::istream& in, level& l)
{ {
std::string tk; std::string tk;
Expand Down Expand Up @@ -87,7 +127,7 @@ environment::environment(threading::level mt_level, bool abrt)
int dummy_thread_level = 0; int dummy_thread_level = 0;
if (!initialized()) { if (!initialized()) {
BOOST_MPI_CHECK_RESULT(MPI_Init_thread, BOOST_MPI_CHECK_RESULT(MPI_Init_thread,
(0, 0, int(mt_level), &dummy_thread_level )); (0, 0, detail::level2int(mt_level), &dummy_thread_level ));
i_initialized = true; i_initialized = true;
} }


Expand Down Expand Up @@ -124,7 +164,7 @@ environment::environment(int& argc, char** &argv, threading::level mt_level,
int dummy_thread_level = 0; int dummy_thread_level = 0;
if (!initialized()) { if (!initialized()) {
BOOST_MPI_CHECK_RESULT(MPI_Init_thread, BOOST_MPI_CHECK_RESULT(MPI_Init_thread,
(&argc, &argv, int(mt_level), &dummy_thread_level)); (&argc, &argv, detail::level2int(mt_level), &dummy_thread_level));
i_initialized = true; i_initialized = true;
} }


Expand Down Expand Up @@ -237,7 +277,7 @@ threading::level environment::thread_level()
int level; int level;


BOOST_MPI_CHECK_RESULT(MPI_Query_thread, (&level)); BOOST_MPI_CHECK_RESULT(MPI_Query_thread, (&level));
return static_cast<threading::level>(level); return detail::int2level(level);
} }


bool environment::is_main_thread() bool environment::is_main_thread()
Expand All @@ -255,4 +295,16 @@ std::pair<int, int> environment::version()
return std::make_pair(major, minor); return std::make_pair(major, minor);
} }


std::string environment::library_version()
{
#if (3 <= MPI_VERSION)
char lib_version[MPI_MAX_LIBRARY_VERSION_STRING];
int len = 0;
BOOST_MPI_CHECK_RESULT(MPI_Get_library_version, (lib_version, &len));
return std::string(lib_version, len);
#else
return "";
#endif
}

} } // end namespace boost::mpi } } // end namespace boost::mpi