From e30a6d88f62cdd07bf32a58d61ed1bfb2c632ea5 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Sun, 23 Jun 2019 11:22:06 -0500 Subject: [PATCH 01/11] Adding all_to_all facility - flyby: create new module for collectives, all_to_all is the first (and only) facility in this module - flyby: adding promise::get_shared_future to allow extracting a shared future from a promise without access to any (shared-)future that was extracted from this promise before - flyby: minor fixes to gather_here/gather_there This relies on #3902 being merged --- hpx/lcos/gather.hpp | 5 +- hpx/lcos/local/and_gate.hpp | 29 ++ hpx/lcos/local/promise.hpp | 112 +++- hpx/lcos/promise.hpp | 40 +- libs/CMakeLists.txt | 1 + libs/all_modules.rst | 1 + libs/collectives/CMakeLists.txt | 27 + libs/collectives/README.rst | 15 + libs/collectives/docs/index.rst | 12 + libs/collectives/examples/CMakeLists.txt | 10 + libs/collectives/include/hpx/collectives.hpp | 11 + .../include/hpx/collectives/all_to_all.hpp | 479 ++++++++++++++++++ libs/collectives/src/collectives.cpp | 9 + libs/collectives/tests/CMakeLists.txt | 37 ++ .../tests/performance/CMakeLists.txt | 4 + .../tests/regressions/CMakeLists.txt | 5 + libs/collectives/tests/unit/CMakeLists.txt | 40 ++ libs/collectives/tests/unit/all_to_all.cpp | 75 +++ 18 files changed, 875 insertions(+), 37 deletions(-) create mode 100644 libs/collectives/CMakeLists.txt create mode 100644 libs/collectives/README.rst create mode 100644 libs/collectives/docs/index.rst create mode 100644 libs/collectives/examples/CMakeLists.txt create mode 100644 libs/collectives/include/hpx/collectives.hpp create mode 100644 libs/collectives/include/hpx/collectives/all_to_all.hpp create mode 100644 libs/collectives/src/collectives.cpp create mode 100644 libs/collectives/tests/CMakeLists.txt create mode 100644 libs/collectives/tests/performance/CMakeLists.txt create mode 100644 libs/collectives/tests/regressions/CMakeLists.txt create mode 100644 libs/collectives/tests/unit/CMakeLists.txt create mode 100644 libs/collectives/tests/unit/all_to_all.cpp diff --git a/hpx/lcos/gather.hpp b/hpx/lcos/gather.hpp index 130051079934..d9bf83f803e1 100644 --- a/hpx/lcos/gather.hpp +++ b/hpx/lcos/gather.hpp @@ -191,9 +191,10 @@ namespace hpx { namespace lcos }} #else +#include + #if !defined(HPX_COMPUTE_DEVICE_CODE) -#include #include #include #include @@ -324,7 +325,7 @@ namespace hpx { namespace lcos { HPX_THROW_EXCEPTION(bad_parameter, "hpx::lcos::detail::register_gather_name", - "the given base name for gather opration was " + "the given base name for the gather operation was " "already registered: " + basename); } return target; diff --git a/hpx/lcos/local/and_gate.hpp b/hpx/lcos/local/and_gate.hpp index 62345793f838..171f8358c344 100644 --- a/hpx/lcos/local/and_gate.hpp +++ b/hpx/lcos/local/and_gate.hpp @@ -117,6 +117,35 @@ namespace hpx { namespace lcos { namespace local return hpx::future(); } + /// \brief get a shared future allowing to wait for the gate to fire + shared_future get_shared_future(std::size_t count = std::size_t(-1), + std::size_t* generation_value = nullptr, + error_code& ec = hpx::throws) + { + std::unique_lock l(mtx_); + + // by default we use as many segments as specified during construction + if (count == std::size_t(-1)) + count = received_segments_.size(); + HPX_ASSERT(count != 0); + + init_locked(l, count, ec); + if (!ec) { + HPX_ASSERT(generation_ != std::size_t(-1)); + +// FIXME: get_shared_future is called more than once for each generation +// ++generation_; + + trigger_conditions(ec); // re-check/trigger condition, if needed + if (!ec) { + if (generation_value) + *generation_value = generation_; + return promise_.get_shared_future(ec); + } + } + return hpx::future().share(); + } + /// \brief Set the data which has to go into the segment \a which. template bool set(std::size_t which, OuterLock & outer_lock, error_code& ec = throws) diff --git a/hpx/lcos/local/promise.hpp b/hpx/lcos/local/promise.hpp index d52cc528c67d..1e7ade02facc 100644 --- a/hpx/lcos/local/promise.hpp +++ b/hpx/lcos/local/promise.hpp @@ -37,12 +37,14 @@ namespace hpx { namespace lcos { namespace local promise_base() : shared_state_(new shared_state_type(init_no_addref{}), false) , future_retrieved_(false) + , shared_future_retrieved_(false) {} template promise_base(std::allocator_arg_t, Allocator const& a) : shared_state_() , future_retrieved_(false) + , shared_future_retrieved_(false) { typedef typename traits::detail::shared_state_allocator< SharedState, Allocator @@ -71,9 +73,11 @@ namespace hpx { namespace lcos { namespace local promise_base(promise_base&& other) noexcept : shared_state_(std::move(other.shared_state_)) , future_retrieved_(other.future_retrieved_) + , shared_future_retrieved_(other.shared_future_retrieved_) { other.shared_state_ = nullptr; other.future_retrieved_ = false; + other.shared_future_retrieved_ = false; } ~promise_base() @@ -91,9 +95,11 @@ namespace hpx { namespace lcos { namespace local shared_state_ = std::move(other.shared_state_); future_retrieved_ = other.future_retrieved_; + shared_future_retrieved_ = other.shared_future_retrieved_; other.shared_state_ = nullptr; other.future_retrieved_ = false; + other.shared_future_retrieved_ = false; } return *this; } @@ -102,6 +108,8 @@ namespace hpx { namespace lcos { namespace local { boost::swap(shared_state_, other.shared_state_); boost::swap(future_retrieved_, other.future_retrieved_); + boost::swap( + shared_future_retrieved_, other.shared_future_retrieved_); } bool valid() const noexcept @@ -111,7 +119,7 @@ namespace hpx { namespace lcos { namespace local future get_future(error_code& ec = throws) { - if (future_retrieved_) + if (future_retrieved_ || shared_future_retrieved_) { HPX_THROWS_IF(ec, future_already_retrieved, "local::detail::promise_base::get_future", @@ -131,6 +139,30 @@ namespace hpx { namespace lcos { namespace local return traits::future_access >::create(shared_state_); } + shared_future get_shared_future(error_code& ec = throws) + { + if (shared_future_retrieved_) + { + HPX_THROWS_IF(ec, future_already_retrieved, + "local::detail::promise_base::get_shared_future", + "shared future has already been retrieved from this " + "promise"); + return shared_future(); + } + + if (shared_state_ == nullptr) + { + HPX_THROWS_IF(ec, no_state, + "local::detail::promise_base::get_shared_future", + "this promise has no valid shared state"); + return shared_future(); + } + + shared_future_retrieved_ = true; + return traits::future_access>::create( + shared_state_); + } + template typename std::enable_if< std::is_constructible::value || @@ -182,7 +214,8 @@ namespace hpx { namespace lcos { namespace local protected: void check_abandon_shared_state(const char* fun) { - if (shared_state_ != nullptr && future_retrieved_ && + if (shared_state_ != nullptr && + (future_retrieved_ || shared_future_retrieved_) && !shared_state_->is_ready()) { shared_state_->set_error(broken_promise, fun, @@ -192,6 +225,7 @@ namespace hpx { namespace lcos { namespace local boost::intrusive_ptr shared_state_; bool future_retrieved_; + bool shared_future_retrieved_; }; } @@ -253,16 +287,24 @@ namespace hpx { namespace lcos { namespace local // Returns: A future object with the same shared state as *this. // Throws: future_error if *this has no shared state or if get_future - // has already been called on a promise with the same shared - // state as *this. + // or get_shared_future has already been called on a promise + // with the same shared state as *this. // Error conditions: - // - future_already_retrieved if get_future has already been called - // on a promise with the same shared state as *this. + // - future_already_retrieved if get_future or get_shared_future has + // already been called on a promise with the same shared state as + // *this. // - no_state if *this has no shared state. - future get_future(error_code& ec = throws) - { - return base_type::get_future(ec); - } + using base_type::get_future; + + // Returns: A shared_future object with the same shared state as *this. + // Throws: future_error if *this has no shared state or if + // get_shared_future has already been called on a promise + // with the same shared state as *this. + // Error conditions: + // - future_already_retrieved if get_shared_future has already been + // called on a promise with the same shared state as *this. + // - no_state if *this has no shared state. + using base_type::get_shared_future; // Effects: atomically stores the value r in the shared state and makes // that state ready (30.6.4). @@ -388,18 +430,26 @@ namespace hpx { namespace lcos { namespace local return base_type::valid(); } - // Returns: A future object with the same shared state as *this. + // Returns: A future object with the same shared state as *this. // Throws: future_error if *this has no shared state or if get_future - // has already been called on a promise with the same shared - // state as *this. + // or get_shared_future has already been called on a promise + // with the same shared state as *this. // Error conditions: - // - future_already_retrieved if get_future has already been called - // on a promise with the same shared state as *this. + // - future_already_retrieved if get_future or get_shared_future has + // already been called on a promise with the same shared state as + // *this. // - no_state if *this has no shared state. - future get_future(error_code& ec = throws) - { - return base_type::get_future(ec); - } + using base_type::get_future; + + // Returns: A shared_future object with the same shared state as *this. + // Throws: future_error if *this has no shared state or if + // get_shared_future has already been called on a promise + // with the same shared state as *this. + // Error conditions: + // - future_already_retrieved if get_shared_future has already been + // called on a promise with the same shared state as *this. + // - no_state if *this has no shared state. + using base_type::get_shared_future; // Effects: atomically stores the value r in the shared state and makes // that state ready (30.6.4). @@ -486,16 +536,24 @@ namespace hpx { namespace lcos { namespace local // Returns: A future object with the same shared state as *this. // Throws: future_error if *this has no shared state or if get_future - // has already been called on a promise with the same shared - // state as *this. + // or get_shared_future has already been called on a promise + // with the same shared state as *this. // Error conditions: - // - future_already_retrieved if get_future has already been called - // on a promise with the same shared state as *this. + // - future_already_retrieved if get_future or get_shared_future has + // already been called on a promise with the same shared state as + // *this. // - no_state if *this has no shared state. - future get_future(error_code& ec = throws) - { - return base_type::get_future(ec); - } + using base_type::get_future; + + // Returns: A shared_future object with the same shared state as *this. + // Throws: future_error if *this has no shared state or if + // get_shared_future has already been called on a promise + // with the same shared state as *this. + // Error conditions: + // - future_already_retrieved if get_shared_future has already been + // called on a promise with the same shared state as *this. + // - no_state if *this has no shared state. + using base_type::get_shared_future; // Effects: atomically stores the value r in the shared state and makes // that state ready (30.6.4). diff --git a/hpx/lcos/promise.hpp b/hpx/lcos/promise.hpp index 96fb485bec76..80e16cf0b439 100644 --- a/hpx/lcos/promise.hpp +++ b/hpx/lcos/promise.hpp @@ -115,14 +115,26 @@ namespace lcos { // Returns: A future object with the same shared state as *this. // Throws: future_error if *this has no shared state or if get_future - // has already been called on a promise with the same shared - // state as *this. + // or get_shared_future has already been called on a promise + // with the same shared state as *this. // Error conditions: - // - future_already_retrieved if get_future has already been called - // on a promise with the same shared state as *this. + // - future_already_retrieved if get_future or get_shared_future has + // already been called on a promise with the same shared state as + // *this. // - no_state if *this has no shared state. using base_type::get_future; + // Returns: A shared_future object with the same shared state + // as *this. + // Throws: future_error if *this has no shared state or if + // get_shared_future has already been called on a promise + // with the same shared state as *this. + // Error conditions: + // - future_already_retrieved if get_shared_future has already been + // called on a promise with the same shared state as *this. + // - no_state if *this has no shared state. + using base_type::get_shared_future; + // Effects: atomically stores the value r in the shared state and makes // that state ready (30.6.4). // Throws: @@ -202,14 +214,26 @@ namespace lcos { // Returns: A future object with the same shared state as *this. // Throws: future_error if *this has no shared state or if get_future - // has already been called on a promise with the same shared - // state as *this. + // or get_shared_future has already been called on a promise + // with the same shared state as *this. // Error conditions: - // - future_already_retrieved if get_future has already been called - // on a promise with the same shared state as *this. + // - future_already_retrieved if get_future or get_shared_future has + // already been called on a promise with the same shared state as + // *this. // - no_state if *this has no shared state. using base_type::get_future; + // Returns: A shared_future object with the same shared state + // as *this. + // Throws: future_error if *this has no shared state or if + // get_shared_future has already been called on a promise + // with the same shared state as *this. + // Error conditions: + // - future_already_retrieved if get_shared_future has already been + // called on a promise with the same shared state as *this. + // - no_state if *this has no shared state. + using base_type::get_shared_future; + // Effects: atomically stores the value r in the shared state and makes // that state ready (30.6.4). // Throws: diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 53267e318670..1dc491d713b5 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -9,6 +9,7 @@ include(HPX_Message) set(HPX_LIBS cache + collectives config preprocessor CACHE INTERNAL "" FORCE diff --git a/libs/all_modules.rst b/libs/all_modules.rst index 7267313cd64e..3c126cc7ab46 100644 --- a/libs/all_modules.rst +++ b/libs/all_modules.rst @@ -15,5 +15,6 @@ All modules /libs/_example/docs/index.rst /libs/cache/docs/index.rst + /libs/collectives/docs/index.rst /libs/config/docs/index.rst /libs/preprocessor/docs/index.rst diff --git a/libs/collectives/CMakeLists.txt b/libs/collectives/CMakeLists.txt new file mode 100644 index 000000000000..0170bf7295f5 --- /dev/null +++ b/libs/collectives/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (c) 2019 The STE||AR-Group +# +# 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) + +cmake_minimum_required(VERSION 3.3.2 FATAL_ERROR) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +# Default location is $HPX_ROOT/libs/collectives/include +set(collectives_headers + hpx/collectives/all_to_all.hpp +) + +# Default location is $HPX_ROOT/libs/collectives/src +set(collectives_sources + collectives.cpp +) + +include(HPX_AddModule) +add_hpx_module(collectives + DEPRECATION_WARNINGS + SOURCES ${collectives_sources} + HEADERS ${collectives_headers} + DEPENDENCIES hpx_config + CMAKE_SUBDIRS examples tests +) diff --git a/libs/collectives/README.rst b/libs/collectives/README.rst new file mode 100644 index 000000000000..db288af5a063 --- /dev/null +++ b/libs/collectives/README.rst @@ -0,0 +1,15 @@ + +.. + Copyright (c) 2019 The STE||AR-Group + + 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) + +=== +Collectives +=== + +This library is part of HPX. + +Documentation can be found `here +`__. diff --git a/libs/collectives/docs/index.rst b/libs/collectives/docs/index.rst new file mode 100644 index 000000000000..c922b45f513c --- /dev/null +++ b/libs/collectives/docs/index.rst @@ -0,0 +1,12 @@ +.. + Copyright (c) 2019 The STE||AR-Group + + 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) + +.. _libs_collectives: + +===== +collectives +===== + diff --git a/libs/collectives/examples/CMakeLists.txt b/libs/collectives/examples/CMakeLists.txt new file mode 100644 index 000000000000..d150fd0dbaae --- /dev/null +++ b/libs/collectives/examples/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2019 The STE||AR-Group +# +# 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) + +if (HPX_WITH_TESTS AND HPX_WITH_TESTS_EXAMPLES) + add_hpx_pseudo_target(tests.examples.collectives) + add_hpx_pseudo_dependencies(tests.examples tests.examples.collectives) +endif() + diff --git a/libs/collectives/include/hpx/collectives.hpp b/libs/collectives/include/hpx/collectives.hpp new file mode 100644 index 000000000000..4c1e1dbab8bb --- /dev/null +++ b/libs/collectives/include/hpx/collectives.hpp @@ -0,0 +1,11 @@ +// Copyright (c) 2019 Hartmut Kaiser +// +// 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) + +#if !defined(HPX_COLLECTIVES_HPP) +#define HPX_COLLECTIVES_HPP + +#include + +#endif diff --git a/libs/collectives/include/hpx/collectives/all_to_all.hpp b/libs/collectives/include/hpx/collectives/all_to_all.hpp new file mode 100644 index 000000000000..7096a2225ad4 --- /dev/null +++ b/libs/collectives/include/hpx/collectives/all_to_all.hpp @@ -0,0 +1,479 @@ +// Copyright (c) 2019 Hartmut Kaiser +// +// 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) + +/// \file all_to_all.hpp + +#if !defined(HPX_COLLECTIVES_ALL_TO_ALL_JUN_23_2019_0900AM) +#define HPX_COLLECTIVES_ALL_TO_ALL_JUN_23_2019_0900AM + +#if defined(DOXYGEN) +namespace hpx { namespace lcos +{ + /// AllToAll a set of values from different call sites + /// + /// This function receives a set of values from all call sites operating on + /// the given base name. + /// + /// \param basename The base name identifying the all_to_all operation + /// \param local_result A future referring to the value to transmit to all + /// participating sites from this call site. + /// \param num_sites The number of participating sites (default: all + /// localities). + /// \param generation The generational counter identifying the sequence + /// number of the all_to_all operation performed on the + /// given base name. This is optional and needs to be + /// supplied only if the all_to_all operation on the + /// given base name has to be performed more than once. + /// \param this_site The sequence number of this invocation (usually + /// the locality id). This value is optional and + /// defaults to whatever hpx::get_locality_id() returns. + /// \params root_site The site that is responsible for creating the + /// all_to_all support object. This value is optional + /// and defaults to '0' (zero). + /// + /// \note Each all_to_all operation has to be accompanied with a unique + /// usage of the \a HPX_REGISTER_ALLTOALL macro to define the + /// necessary internal facilities used by \a all_to_all. + /// + /// \returns This function returns a future holding a vector with all + /// values send by all participating sites. It will become + /// ready once the all_to_all operation has been completed. + /// + template + hpx::future > + all_to_all(char const* basename, hpx::future result, + std::size_t num_sites = std::size_t(-1), + std::size_t generation = std::size_t(-1), + std::size_t this_site = std::size_t(-1), + std::size_t root_sire = 0); + + /// AllToAll a set of values from different call sites + /// + /// This function receives a set of values from all call sites operating on + /// the given base name. + /// + /// \param basename The base name identifying the all_to_all operation + /// \param local_result The value to transmit to all + /// participating sites from this call site. + /// \param num_sites The number of participating sites (default: all + /// localities). + /// \param generation The generational counter identifying the sequence + /// number of the all_to_all operation performed on the + /// given base name. This is optional and needs to be + /// supplied only if the all_to_all operation on the + /// given base name has to be performed more than once. + /// \param this_site The sequence number of this invocation (usually + /// the locality id). This value is optional and + /// defaults to whatever hpx::get_locality_id() returns. + /// \params root_site The site that is responsible for creating the + /// all_to_all support object. This value is optional + /// and defaults to '0' (zero). + /// + /// \note Each all_to_all operation has to be accompanied with a unique + /// usage of the \a HPX_REGISTER_ALLTOALL macro to define the + /// necessary internal facilities used by \a all_to_all. + /// + /// \returns This function returns a future holding a vector with all + /// values send by all participating sites. It will become + /// ready once the all_to_all operation has been completed. + /// + template + hpx::future::type> > + all_to_all(char const* basename, T && result, + std::size_t num_sites = std::size_t(-1), + std::size_t generation = std::size_t(-1), + std::size_t this_site = std::size_t(-1), + std::size_t root_sire = 0); + + /// \def HPX_REGISTER_ALLTOALL_DECLARATION(type, name) + /// + /// \brief Declare a all_to_all object named \a name for a given data type \a type. + /// + /// The macro \a HPX_REGISTER_ALLTOALL_DECLARATION can be used to declare + /// all facilities necessary for a (possibly remote) all_to_all operation. + /// + /// The parameter \a type specifies for which data type the all_to_all + /// operations should be enabled. + /// + /// The (optional) parameter \a name should be a unique C-style identifier + /// that will be internally used to identify a particular all_to_all operation. + /// If this defaults to \a \_all_to_all if not specified. + /// + /// \note The macro \a HPX_REGISTER_ALLTOALL_DECLARATION can be used with 1 + /// or 2 arguments. The second argument is optional and defaults to + /// \a \_all_to_all. + /// + #define HPX_REGISTER_ALLTOALL_DECLARATION(type, name) + + /// \def HPX_REGISTER_ALLTOALL(type, name) + /// + /// \brief Define a all_to_all object named \a name for a given data type \a type. + /// + /// The macro \a HPX_REGISTER_ALLTOALL can be used to define + /// all facilities necessary for a (possibly remote) all_to_all operation. + /// + /// The parameter \a type specifies for which data type the all_to_all + /// operations should be enabled. + /// + /// The (optional) parameter \a name should be a unique C-style identifier + /// that will be internally used to identify a particular all_to_all operation. + /// If this defaults to \a \_all_to_all if not specified. + /// + /// \note The macro \a HPX_REGISTER_ALLTOALL can be used with 1 + /// or 2 arguments. The second argument is optional and defaults to + /// \a \_all_to_all. + /// + #define HPX_REGISTER_ALLTOALL(type, name) +}} +#else + +#include + +#if !defined(HPX_COMPUTE_DEVICE_CODE) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace hpx { namespace lcos +{ + namespace detail + { + /////////////////////////////////////////////////////////////////////// + template + class all_to_all_server + : public hpx::components::component_base > + { + using mutex_type = lcos::local::spinlock; + + std::vector on_ready(shared_future&& f) + { + f.get(); // propagate any exceptions + + std::vector data(num_sites_); + + { + std::unique_lock l(mtx_); + std::swap(data, data_); + } + + return data; + } + + public: + all_to_all_server() //-V730 + { + HPX_ASSERT(false); // shouldn't ever be called + } + + all_to_all_server(std::size_t num_sites, std::string const& name, + std::size_t site) + : num_sites_(num_sites) + , data_(num_sites) + , gate_(num_sites) + , name_(name) + , site_(site) + {} + + ~all_to_all_server() + { + hpx::unregister_with_basename(name_, site_); + } + + hpx::future > get_result(std::size_t which, T&& t) + { + std::unique_lock l(mtx_); + + hpx::future> f = + gate_.get_shared_future().then(hpx::launch::async, + util::bind_front(&all_to_all_server::on_ready, this)); + + gate_.synchronize(1, l); + data_[which] = std::move(t); + gate_.set(which, l); + + return f; + } + + HPX_DEFINE_COMPONENT_ACTION( + all_to_all_server, get_result, get_result_action); + + private: + mutex_type mtx_; + std::size_t num_sites_; + std::vector data_; + lcos::local::and_gate gate_; + std::string name_; + std::size_t site_; + }; + + /////////////////////////////////////////////////////////////////////// + inline hpx::future register_all_to_all_name( + hpx::future&& f, std::string basename, + std::size_t site) + { + hpx::id_type target = f.get(); + + // Register unmanaged id to avoid cyclic dependencies, unregister + // is done in the destructor of the component above. + hpx::future result = hpx::register_with_basename( + basename, hpx::unmanaged(target), site); + + return result.then( + hpx::launch::sync, + [HPX_CAPTURE_MOVE(target), HPX_CAPTURE_MOVE(basename)]( + hpx::future&& f) + -> hpx::id_type + { + bool result = f.get(); + if (!result) + { + HPX_THROW_EXCEPTION(bad_parameter, + "hpx::lcos::detail::register_gather_name", + "the given base name for the all_to_all operation " + "was already registered: " + basename); + } + return target; + }); + } + + /////////////////////////////////////////////////////////////////////// + template + hpx::future > + all_to_all_data(hpx::future&& f, + hpx::future&& local_result, std::size_t site) + { + using action_type = typename all_to_all_server::get_result_action; + + // make sure id is kept alive as long as the returned future + hpx::id_type id = f.get(); + return async(action_type(), id, site, local_result.get()).then( + hpx::launch::sync, + [HPX_CAPTURE_MOVE(id)](hpx::future> && f) + -> std::vector + { + HPX_UNUSED(id); + return f.get(); + }); + } + + template + hpx::future > + all_to_all_data_direct(hpx::future&& f, T&& local_result, + std::size_t site) + { + using action_type = typename all_to_all_server::get_result_action; + + // make sure id is kept alive as long as the returned future + hpx::id_type id = f.get(); + return async(action_type(), id, site, std::forward(local_result)) + .then(hpx::launch::sync, + [HPX_CAPTURE_MOVE(id)](hpx::future> && f) + -> std::vector + { + HPX_UNUSED(id); + return f.get(); + }); + } + } + + /////////////////////////////////////////////////////////////////////////// + template + hpx::future + create_all_to_all(char const* basename, + std::size_t num_sites = std::size_t(-1), + std::size_t generation = std::size_t(-1), + std::size_t this_site = std::size_t(-1)) + { + if (num_sites == std::size_t(-1)) + num_sites = hpx::get_num_localities(hpx::launch::sync); + if (this_site == std::size_t(-1)) + this_site = static_cast(hpx::get_locality_id()); + + std::string name(basename); + if (generation != std::size_t(-1)) + name += std::to_string(generation) + "/"; + + // create a new all_to_all_server + using result_type = typename util::decay::type; + hpx::future id = + hpx::new_ >( + hpx::find_here(), num_sites, name, this_site); + + // register the all_to_all's id using the given basename + return id.then(hpx::launch::sync, util::bind_back( + &detail::register_all_to_all_name, std::move(name), this_site)); + } + + /////////////////////////////////////////////////////////////////////////// + // destination site needs to be handled differently + template + hpx::future> + all_to_all(hpx::future&& f, hpx::future&& local_result, + std::size_t this_site = std::size_t(-1)) + { + if (this_site == std::size_t(-1)) + this_site = static_cast(hpx::get_locality_id()); + + return dataflow(hpx::launch::sync, + util::bind_back(&detail::all_to_all_data, this_site), + std::move(f), std::move(local_result)); + } + + template + hpx::future > + all_to_all(char const* basename, hpx::future&& local_result, + std::size_t num_sites = std::size_t(-1), + std::size_t generation = std::size_t(-1), + std::size_t this_site = std::size_t(-1), + std::size_t root_site = 0) + { + if (num_sites == std::size_t(-1)) + num_sites = hpx::get_num_localities(hpx::launch::sync); + if (this_site == std::size_t(-1)) + this_site = static_cast(hpx::get_locality_id()); + + if (this_site == 0) + { + return all_to_all( + create_all_to_all(basename, num_sites, generation, root_site), + std::move(local_result), this_site); + } + + std::string name(basename); + if (generation != std::size_t(-1)) + name += std::to_string(generation) + "/"; + + return all_to_all( + hpx::find_from_basename(std::move(name), root_site), + std::move(local_result), this_site); + } + + /////////////////////////////////////////////////////////////////////////// + // all_to_all plain values + template + hpx::future::type> > + all_to_all(hpx::future&& f, T&& local_result, + std::size_t this_site = std::size_t(-1)) + { + if (this_site == std::size_t(-1)) + this_site = static_cast(hpx::get_locality_id()); + + using result_type = typename util::decay::type; + return dataflow(hpx::launch::sync, + util::bind_back( + &detail::all_to_all_data_direct, this_site), + std::move(f), std::forward(local_result)); + } + + template + hpx::future::type> > + all_to_all(char const* basename, T&& local_result, + std::size_t num_sites = std::size_t(-1), + std::size_t generation = std::size_t(-1), + std::size_t this_site = std::size_t(-1), + std::size_t root_site = 0) + { + if (num_sites == std::size_t(-1)) + num_sites = hpx::get_num_localities(hpx::launch::sync); + if (this_site == std::size_t(-1)) + this_site = static_cast(hpx::get_locality_id()); + + if (this_site == root_site) + { + return all_to_all( + create_all_to_all(basename, num_sites, generation, root_site), + std::forward(local_result), this_site); + } + + std::string name(basename); + if (generation != std::size_t(-1)) + name += std::to_string(generation) + "/"; + + return all_to_all( + hpx::find_from_basename(std::move(name), root_site), + std::move(local_result), this_site); + } +}} + +//////////////////////////////////////////////////////////////////////////////// +namespace hpx +{ + using lcos::create_all_to_all; + using lcos::all_to_all; +} + +//////////////////////////////////////////////////////////////////////////////// +#define HPX_REGISTER_ALLTOALL_DECLARATION(...) \ + HPX_REGISTER_ALLTOALL_DECLARATION_(__VA_ARGS__) \ + /**/ + +#define HPX_REGISTER_ALLTOALL_DECLARATION_(...) \ + HPX_PP_EXPAND(HPX_PP_CAT( \ + HPX_REGISTER_ALLTOALL_DECLARATION_, HPX_PP_NARGS(__VA_ARGS__) \ + )(__VA_ARGS__)) \ + /**/ + +#define HPX_REGISTER_ALLTOALL_DECLARATION_1(type) \ + HPX_REGISTER_ALLTOALL_DECLARATION_2(type, HPX_PP_CAT(type, _all_to_all)) \ + /**/ + +#define HPX_REGISTER_ALLTOALL_DECLARATION_2(type, name) \ + HPX_REGISTER_ACTION_DECLARATION( \ + hpx::lcos::detail::all_to_all_server::get_result_action, \ + HPX_PP_CAT(gather_get_result_action_, name)); \ + /**/ + +//////////////////////////////////////////////////////////////////////////////// +#define HPX_REGISTER_ALLTOALL(...) \ + HPX_REGISTER_ALLTOALL_(__VA_ARGS__) \ + /**/ + +#define HPX_REGISTER_ALLTOALL_(...) \ + HPX_PP_EXPAND(HPX_PP_CAT( \ + HPX_REGISTER_ALLTOALL_, HPX_PP_NARGS(__VA_ARGS__) \ + )(__VA_ARGS__)) \ + /**/ + +#define HPX_REGISTER_ALLTOALL_1(type) \ + HPX_REGISTER_ALLTOALL_2(type, HPX_PP_CAT(type, _all_to_all)) \ + /**/ + +#define HPX_REGISTER_ALLTOALL_2(type, name) \ + HPX_REGISTER_ACTION( \ + hpx::lcos::detail::all_to_all_server::get_result_action, \ + HPX_PP_CAT(gather_get_result_action_, name)); \ + typedef hpx::components::component< \ + hpx::lcos::detail::all_to_all_server \ + > HPX_PP_CAT(all_to_all_, name); \ + HPX_REGISTER_COMPONENT(HPX_PP_CAT(all_to_all_, name)) \ + /**/ + +#endif // COMPUTE_HOST_CODE +#endif // DOXYGEN +#endif diff --git a/libs/collectives/src/collectives.cpp b/libs/collectives/src/collectives.cpp new file mode 100644 index 000000000000..fd2b4d41ab57 --- /dev/null +++ b/libs/collectives/src/collectives.cpp @@ -0,0 +1,9 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2019 STE||AR Group +// +// 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) +//////////////////////////////////////////////////////////////////////////////// + +// This file was intentionally left empty. It is used as a dummy to force cmake +// into generating a separate Visual Studio project for this module. diff --git a/libs/collectives/tests/CMakeLists.txt b/libs/collectives/tests/CMakeLists.txt new file mode 100644 index 000000000000..87ea2d1590f2 --- /dev/null +++ b/libs/collectives/tests/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (c) 2019 The STE||AR-Group +# +# 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(HPX_Option) + +if (NOT HPX_WITH_TESTS AND HPX_TOP_LEVEL) + hpx_set_option(HPX_COLLECTIVES_WITH_TESTS VALUE OFF FORCE) + return() +endif() +if (NOT HPX_COLLECTIVES_WITH_TESTS) + message(STATUS "Tests for collectives disabled") + return() +endif() + +if (HPX_WITH_TESTS_UNIT) + add_hpx_pseudo_target(tests.unit.collectives) + add_hpx_pseudo_dependencies(tests.unit tests.unit.collectives) + add_subdirectory(unit) +endif() + +if (HPX_WITH_TESTS_REGRESSIONS) + add_hpx_pseudo_target(tests.regressions.collectives) + add_hpx_pseudo_dependencies(tests.regressions tests.regressions.collectives) + add_subdirectory(regressions) +endif() + +if (HPX_WITH_TESTS_BENCHMARKS) + add_hpx_pseudo_target(tests.performance.collectives) + add_hpx_pseudo_dependencies(tests.performance tests.performance.collectives) + add_subdirectory(performance) +endif() + +if (HPX_WITH_TESTS_HEADERS) + add_hpx_lib_header_tests(collectives) +endif() diff --git a/libs/collectives/tests/performance/CMakeLists.txt b/libs/collectives/tests/performance/CMakeLists.txt new file mode 100644 index 000000000000..8e44d2f9364c --- /dev/null +++ b/libs/collectives/tests/performance/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2019 The STE||AR-Group +# +# 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) diff --git a/libs/collectives/tests/regressions/CMakeLists.txt b/libs/collectives/tests/regressions/CMakeLists.txt new file mode 100644 index 000000000000..bfca91199899 --- /dev/null +++ b/libs/collectives/tests/regressions/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2019 The STE||AR-Group +# +# 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) + diff --git a/libs/collectives/tests/unit/CMakeLists.txt b/libs/collectives/tests/unit/CMakeLists.txt new file mode 100644 index 000000000000..24bbd0e3bb00 --- /dev/null +++ b/libs/collectives/tests/unit/CMakeLists.txt @@ -0,0 +1,40 @@ +# Copyright (c) 2019 Hartmut Kaiser +# +# 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) + +set(tests + all_to_all + ) + +set(all_to_all_PARAMETERS LOCALITIES 2) + +foreach(test ${tests}) + set(sources + ${test}.cpp) + + source_group("Source Files" FILES ${sources}) + + # add example executable + add_hpx_executable(${test}_test + SOURCES ${sources} + ${${test}_FLAGS} + EXCLUDE_FROM_ALL + HPX_PREFIX ${HPX_BUILD_PREFIX} + FOLDER "Tests/Modules/Unit/Collectives") + + add_hpx_unit_test("collectives" ${test} ${${test}_PARAMETERS}) + + # add a custom target for this test + add_hpx_pseudo_target(tests.unit.collectives.${test}) + + # make pseudo-targets depend on master pseudo-target + add_hpx_pseudo_dependencies(tests.unit.collectives + tests.unit.collectives.${test}) + + # add dependencies to pseudo-target + add_hpx_pseudo_dependencies(tests.unit.collectives.${test} + ${test}_test) +endforeach() + + diff --git a/libs/collectives/tests/unit/all_to_all.cpp b/libs/collectives/tests/unit/all_to_all.cpp new file mode 100644 index 000000000000..cacc6a5f6d65 --- /dev/null +++ b/libs/collectives/tests/unit/all_to_all.cpp @@ -0,0 +1,75 @@ +// Copyright (c) 2019 Hartmut Kaiser +// +// 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 + +#include +#include +#include +#include +#include +#include + +char const* all_to_all_basename = "/test/all_to_all/"; +char const* all_to_all_direct_basename = "/test/all_to_all_direct/"; + +HPX_REGISTER_ALLTOALL(std::uint32_t, test_all_to_all); + +int hpx_main(int argc, char* argv[]) +{ + std::uint32_t num_localities = hpx::get_num_localities(hpx::launch::sync); + + // test functionality based on future<> of local result + for (int i = 0; i != 10; ++i) + { + hpx::future value = + hpx::make_ready_future(hpx::get_locality_id()); + + hpx::future > overall_result = + hpx::all_to_all(all_to_all_basename, std::move(value), + num_localities, i); + + std::vector r = overall_result.get(); + HPX_TEST_EQ(r.size(), num_localities); + + for (std::size_t j = 0; j != r.size(); ++j) + { + HPX_TEST_EQ(r[j], j); + } + } + + // test functionality based on immediate local result value + for (int i = 0; i != 10; ++i) + { + std::uint32_t value = hpx::get_locality_id(); + + hpx::future > overall_result = + hpx::all_to_all(all_to_all_direct_basename, value, + num_localities, i); + + std::vector r = overall_result.get(); + HPX_TEST_EQ(r.size(), num_localities); + + for (std::size_t j = 0; j != r.size(); ++j) + { + HPX_TEST_EQ(r[j], j); + } + } + + return hpx::finalize(); +} + +int main(int argc, char* argv[]) +{ + std::vector const cfg = { + "hpx.run_hpx_main!=1" + }; + + HPX_TEST_EQ(hpx::init(argc, argv, cfg), 0); + return hpx::util::report_errors(); +} From 0908dff482315ec223412cba781420fe3403b941 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Sun, 23 Jun 2019 14:39:16 -0500 Subject: [PATCH 02/11] Adding collectives tests to circleci - flyby: remove superfluous file, properly install generated files - flyby: fix unregistration for all_to_all server component --- .circleci/config.yml | 72 ++++++++++--------- cmake/HPX_AddCompileTest.cmake | 29 ++++---- cmake/HPX_AddModule.cmake | 1 + libs/CMakeLists.txt | 16 +++++ libs/_example/tests/CMakeLists.txt | 17 +++-- libs/cache/tests/CMakeLists.txt | 14 ++-- libs/cache/tests/unit/CMakeLists.txt | 10 +-- libs/collectives/CMakeLists.txt | 3 +- libs/collectives/include/hpx/collectives.hpp | 11 --- .../include/hpx/collectives/all_to_all.hpp | 11 ++- libs/collectives/tests/CMakeLists.txt | 14 ++-- libs/collectives/tests/unit/CMakeLists.txt | 10 +-- libs/config/tests/CMakeLists.txt | 14 ++-- libs/preprocessor/tests/CMakeLists.txt | 14 ++-- tests/headers/CMakeLists.txt | 2 +- 15 files changed, 130 insertions(+), 108 deletions(-) delete mode 100644 libs/collectives/include/hpx/collectives.hpp diff --git a/.circleci/config.yml b/.circleci/config.yml index 41b68d65c5fe..98e4985a7e16 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -804,25 +804,27 @@ jobs: - store_artifacts: path: tests.unit.util - tests.unit.libs: + tests.unit.modules: <<: *defaults steps: - attach_workspace: at: /hpx - run: - name: Building Unit Tests + name: Building Module Unit Tests command: | - ninja -j2 -k 0 tests.unit.cache - ninja -j2 -k 0 tests.unit.config - ninja -j2 -k 0 tests.unit.preprocessor + ninja -j2 -k 0 tests.unit.modules.cache + ninja -j2 -k 0 tests.unit.modules.collectives + ninja -j2 -k 0 tests.unit.modules.config + ninja -j2 -k 0 tests.unit.modules.preprocessor - run: name: Running Unit Tests when: always command: | ulimit -c unlimited - ctest -T test --no-compress-output --output-on-failure -R tests.unit.cache - ctest -T test --no-compress-output --output-on-failure -R tests.unit.config - ctest -T test --no-compress-output --output-on-failure -R tests.unit.preprocessor + ctest -T test --no-compress-output --output-on-failure -R tests.unit.modules.cache + ctest -T test --no-compress-output --output-on-failure -R tests.unit.modules.collectives + ctest -T test --no-compress-output --output-on-failure -R tests.unit.modules.config + ctest -T test --no-compress-output --output-on-failure -R tests.unit.modules.preprocessor - run: <<: *convert_xml - run: @@ -830,9 +832,10 @@ jobs: - run: <<: *move_debug_log - store_test_results: - path: tests.unit.libs + path: tests.unit.modules - store_artifacts: - path: tests.unit.libs + path: tests.unit.modules + tests.regressions: <<: *defaults steps: @@ -866,7 +869,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.compat + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.compat - run: <<: *convert_xml - store_test_results: @@ -882,7 +885,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.components + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.components - run: <<: *convert_xml - store_test_results: @@ -898,7 +901,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.compute + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.compute - run: <<: *convert_xml - store_test_results: @@ -914,7 +917,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.config + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.config - run: <<: *convert_xml - store_test_results: @@ -930,7 +933,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.include + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.include - run: <<: *convert_xml - store_test_results: @@ -946,7 +949,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.lcos + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.lcos - run: <<: *convert_xml - store_test_results: @@ -962,7 +965,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.parallel + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.parallel - run: <<: *convert_xml - store_test_results: @@ -978,7 +981,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.performance_counters + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.performance_counters - run: <<: *convert_xml - store_test_results: @@ -994,7 +997,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.plugins + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.plugins - run: <<: *convert_xml - store_test_results: @@ -1010,7 +1013,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.runtime + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.runtime - run: <<: *convert_xml - store_test_results: @@ -1026,7 +1029,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.traits + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.traits - run: <<: *convert_xml - store_test_results: @@ -1042,7 +1045,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.util + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.util - run: <<: *convert_xml - store_test_results: @@ -1050,23 +1053,24 @@ jobs: - store_artifacts: path: tests.headers.util - tests.headers.libs: + tests.headers.modules: <<: *defaults steps: - attach_workspace: at: /hpx - run: - name: Building Header Tests + name: Building Modules Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.cache - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.config - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.preprocessor + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.modules.cache + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.modules.collectives + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.modules.config + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.modules.preprocessor - run: <<: *convert_xml - store_test_results: - path: tests.headers.libs + path: tests.headers.modules - store_artifacts: - path: tests.headers.libs + path: tests.headers.modules tests.performance: <<: *defaults @@ -1135,7 +1139,7 @@ jobs: docker create -v /hpx --name sources stellargroup/hpx:dev /bin/true docker cp ./source/examples/quickstart/hello_world_distributed.cpp sources:/hpx docker run --volumes-from sources -w /hpx ${TARGET_IMAGE_NAME} \ - hpxcxx --exe=hello_world_distributed_test_build \ + hpxcxx --exe=hello_world_distributed_test_build \ hello_world_distributed.cpp -g -lhpx_iostreamsd docker run --volumes-from sources -w /hpx ${TARGET_IMAGE_NAME} \ ./hello_world_distributed_test_build --hpx:bind=none @@ -1244,7 +1248,7 @@ workflows: <<: *core_dependency - tests.unit.util: <<: *core_dependency - - tests.unit.libs: + - tests.unit.modules: <<: *core_dependency - tests.regressions: <<: *core_dependency @@ -1274,7 +1278,7 @@ workflows: <<: *core_dependency - tests.headers.util: <<: *core_dependency - - tests.headers.libs: + - tests.headers.modules: <<: *core_dependency - examples: <<: *core_dependency @@ -1311,7 +1315,7 @@ workflows: - tests.unit.topology - tests.unit.traits - tests.unit.util - - tests.unit.libs + - tests.unit.modules - tests.headers.compat - tests.headers.components - tests.headers.compute @@ -1324,7 +1328,7 @@ workflows: - tests.headers.runtime - tests.headers.traits - tests.headers.util - - tests.headers.libs + - tests.headers.modules - tests.performance - tests.regressions - examples diff --git a/cmake/HPX_AddCompileTest.cmake b/cmake/HPX_AddCompileTest.cmake index 19d3d5d040eb..307bcb529c79 100644 --- a/cmake/HPX_AddCompileTest.cmake +++ b/cmake/HPX_AddCompileTest.cmake @@ -51,10 +51,13 @@ function(add_hpx_headers_compile_test category name) endfunction() function(add_hpx_lib_header_tests lib) - file(GLOB_RECURSE headers ${DO_CONFIGURE_DEPENDS} "${PROJECT_SOURCE_DIR}/include/hpx/*hpp") + file(GLOB_RECURSE headers ${DO_CONFIGURE_DEPENDS} + "${PROJECT_SOURCE_DIR}/include/hpx/*hpp") + set(all_headers) - add_custom_target(tests.headers.${lib}) - add_dependencies(tests.headers tests.headers.${lib}) + add_custom_target(tests.headers.modules.${lib}) + add_dependencies(tests.headers.modules tests.headers.modules.${lib}) + foreach(header ${headers}) # skip all headers in directories containing 'detail' @@ -80,14 +83,14 @@ function(add_hpx_lib_header_tests lib) set(all_headers ${all_headers} "#include \n") - add_library(tests.headers.${lib}.${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${full_test_file}) - target_link_libraries(tests.headers.${lib}.${test_name} hpx_${lib}) - add_dependencies(tests.headers.${lib} tests.headers.${lib}.${test_name}) + add_library(tests.headers.modules.${lib}.${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${full_test_file}) + target_link_libraries(tests.headers.modules.${lib}.${test_name} hpx_${lib}) + add_dependencies(tests.headers.modules.${lib} tests.headers.modules.${lib}.${test_name}) - add_test(NAME "tests.headers.${lib}.${test_name}" + add_test(NAME "tests.headers.modules.${lib}.${test_name}" COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} - --target tests.headers.${lib}.${test_name} + --target tests.headers.modules.${lib}.${test_name} --config $ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) endif() @@ -101,14 +104,14 @@ function(add_hpx_lib_header_tests lib) "int main(int argc, char** argv) { return 0; }\n" "#endif\n") - add_library(tests.headers.${lib}.${test_name} "${CMAKE_CURRENT_BINARY_DIR}/${test_name}.cpp") - target_link_libraries(tests.headers.${lib}.${test_name} hpx_${lib}) - add_dependencies(tests.headers.${lib} tests.headers.${lib}.${test_name}) + add_library(tests.headers.modules.${lib}.${test_name} "${CMAKE_CURRENT_BINARY_DIR}/${test_name}.cpp") + target_link_libraries(tests.headers.modules.${lib}.${test_name} hpx_${lib}) + add_dependencies(tests.headers.modules.${lib} tests.headers.modules.${lib}.${test_name}) - add_test(NAME "tests.headers.${lib}.${test_name}" + add_test(NAME "tests.headers.modules.${lib}.${test_name}" COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} - --target tests.headers.${lib}.${test_name} + --target tests.headers.modules.${lib}.${test_name} --config $ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) endfunction() diff --git a/cmake/HPX_AddModule.cmake b/cmake/HPX_AddModule.cmake index 120a7d1c66aa..f735011adc6b 100644 --- a/cmake/HPX_AddModule.cmake +++ b/cmake/HPX_AddModule.cmake @@ -17,6 +17,7 @@ function(add_hpx_module name) hpx_info(" ${name}") + # Global headers should be always generated except if explicitly disabled if ("${${name}_GLOBAL_HEADER_GEN}" STREQUAL "") set(${name}_GLOBAL_HEADER_GEN ON) endif() diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 1dc491d713b5..f148a4247085 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -15,6 +15,22 @@ set(HPX_LIBS CACHE INTERNAL "" FORCE ) +if (HPX_WITH_TESTS_UNIT) + add_hpx_pseudo_target(tests.unit.modules) +endif() + +if (HPX_WITH_TESTS_REGRESSIONS) + add_hpx_pseudo_target(tests.regressions.modules) +endif() + +if (HPX_WITH_TESTS_BENCHMARKS) + add_hpx_pseudo_target(tests.performance.modules) +endif() + +if (HPX_WITH_TESTS_HEADERS) + add_custom_target(tests.headers.modules) +endif() + hpx_info("Configuring modules:") foreach(lib ${HPX_LIBS}) diff --git a/libs/_example/tests/CMakeLists.txt b/libs/_example/tests/CMakeLists.txt index fd430c629248..3a720ce52653 100644 --- a/libs/_example/tests/CMakeLists.txt +++ b/libs/_example/tests/CMakeLists.txt @@ -4,28 +4,31 @@ # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) if (NOT HPX_WITH_TESTS) + hpx_set_option(HPX__EXAMPLE_WITH_TESTS VALUE OFF FORCE) return() endif() if (NOT HPX__EXAMPLE_WITH_TESTS) - message(STATUS "Tests for example disabled") + message(STATUS "Tests for _example disabled") return() endif() if (HPX_WITH_TESTS_UNIT) - add_hpx_pseudo_target(tests.unit.example) - add_hpx_pseudo_dependencies(tests.unit tests.unit.example) + add_hpx_pseudo_target(tests.unit.modules.example) + add_hpx_pseudo_dependencies(tests.unit.modules tests.unit.modules.example) add_subdirectory(unit) endif() if (HPX_WITH_TESTS_REGRESSIONS) - add_hpx_pseudo_target(tests.regressions.example) - add_hpx_pseudo_dependencies(tests.regressions tests.regressions.example) + add_hpx_pseudo_target(tests.regressions.modules.example) + add_hpx_pseudo_dependencies(tests.regressions.modules + tests.regressions.modules.example) add_subdirectory(regressions) endif() if (HPX_WITH_TESTS_BENCHMARKS) - add_hpx_pseudo_target(tests.performance.example) - add_hpx_pseudo_dependencies(tests.performance tests.performance.example) + add_hpx_pseudo_target(tests.performance.modules.example) + add_hpx_pseudo_dependencies(tests.performance.modules + tests.performance.modules.example) add_subdirectory(performance) endif() diff --git a/libs/cache/tests/CMakeLists.txt b/libs/cache/tests/CMakeLists.txt index a87bc18d9845..7bbf30a8d1c6 100644 --- a/libs/cache/tests/CMakeLists.txt +++ b/libs/cache/tests/CMakeLists.txt @@ -15,20 +15,22 @@ if (NOT HPX_CACHE_WITH_TESTS) endif() if (HPX_WITH_TESTS_UNIT) - add_hpx_pseudo_target(tests.unit.cache) - add_hpx_pseudo_dependencies(tests.unit tests.unit.cache) + add_hpx_pseudo_target(tests.unit.modules.cache) + add_hpx_pseudo_dependencies(tests.unit.modules tests.unit.modules.cache) add_subdirectory(unit) endif() if (HPX_WITH_TESTS_REGRESSIONS) - add_hpx_pseudo_target(tests.regressions.cache) - add_hpx_pseudo_dependencies(tests.regressions tests.regressions.cache) + add_hpx_pseudo_target(tests.regressions.modules.cache) + add_hpx_pseudo_dependencies(tests.regressions.modules + tests.regressions.modules.cache) add_subdirectory(regressions) endif() if (HPX_WITH_TESTS_BENCHMARKS) - add_hpx_pseudo_target(tests.performance.cache) - add_hpx_pseudo_dependencies(tests.performance tests.performance.cache) + add_hpx_pseudo_target(tests.performance.modules.cache) + add_hpx_pseudo_dependencies(tests.performance.modules + tests.performance.modules.cache) add_subdirectory(performance) endif() diff --git a/libs/cache/tests/unit/CMakeLists.txt b/libs/cache/tests/unit/CMakeLists.txt index 2138dc6261ab..b93b5c0a8a5f 100644 --- a/libs/cache/tests/unit/CMakeLists.txt +++ b/libs/cache/tests/unit/CMakeLists.txt @@ -23,17 +23,17 @@ foreach(test ${tests}) HPX_PREFIX ${HPX_BUILD_PREFIX} FOLDER "Tests/Modules/Unit/Cache") - add_hpx_unit_test("cache" ${test} ${${test}_PARAMETERS}) + add_hpx_test("tests.unit.modules.cache" ${test} ${${test}_PARAMETERS}) # add a custom target for this example - add_hpx_pseudo_target(tests.unit.cache.${test}) + add_hpx_pseudo_target(tests.unit.modules.cache.${test}) # make pseudo-targets depend on master pseudo-target - add_hpx_pseudo_dependencies(tests.unit.cache - tests.unit.cache.${test}) + add_hpx_pseudo_dependencies(tests.unit.modules.cache + tests.unit.modules.cache.${test}) # add dependencies to pseudo-target - add_hpx_pseudo_dependencies(tests.unit.cache.${test} + add_hpx_pseudo_dependencies(tests.unit.modules.cache.${test} ${test}_test) endforeach() diff --git a/libs/collectives/CMakeLists.txt b/libs/collectives/CMakeLists.txt index 0170bf7295f5..84d74440b033 100644 --- a/libs/collectives/CMakeLists.txt +++ b/libs/collectives/CMakeLists.txt @@ -19,9 +19,8 @@ set(collectives_sources include(HPX_AddModule) add_hpx_module(collectives - DEPRECATION_WARNINGS SOURCES ${collectives_sources} HEADERS ${collectives_headers} - DEPENDENCIES hpx_config + DEPENDENCIES hpx_config hpx_preprocessor CMAKE_SUBDIRS examples tests ) diff --git a/libs/collectives/include/hpx/collectives.hpp b/libs/collectives/include/hpx/collectives.hpp deleted file mode 100644 index 4c1e1dbab8bb..000000000000 --- a/libs/collectives/include/hpx/collectives.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2019 Hartmut Kaiser -// -// 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) - -#if !defined(HPX_COLLECTIVES_HPP) -#define HPX_COLLECTIVES_HPP - -#include - -#endif diff --git a/libs/collectives/include/hpx/collectives/all_to_all.hpp b/libs/collectives/include/hpx/collectives/all_to_all.hpp index 7096a2225ad4..f9bf46d0b6bf 100644 --- a/libs/collectives/include/hpx/collectives/all_to_all.hpp +++ b/libs/collectives/include/hpx/collectives/all_to_all.hpp @@ -182,6 +182,10 @@ namespace hpx { namespace lcos std::swap(data, data_); } + // this is a one-shot object (generations counters are not + // supported), unregister ourselves + hpx::unregister_with_basename(name_, site_); + return data; } @@ -200,11 +204,6 @@ namespace hpx { namespace lcos , site_(site) {} - ~all_to_all_server() - { - hpx::unregister_with_basename(name_, site_); - } - hpx::future > get_result(std::size_t which, T&& t) { std::unique_lock l(mtx_); @@ -240,7 +239,7 @@ namespace hpx { namespace lcos hpx::id_type target = f.get(); // Register unmanaged id to avoid cyclic dependencies, unregister - // is done in the destructor of the component above. + // is done after all data has been collected in the component above. hpx::future result = hpx::register_with_basename( basename, hpx::unmanaged(target), site); diff --git a/libs/collectives/tests/CMakeLists.txt b/libs/collectives/tests/CMakeLists.txt index 87ea2d1590f2..79acdbafee22 100644 --- a/libs/collectives/tests/CMakeLists.txt +++ b/libs/collectives/tests/CMakeLists.txt @@ -15,20 +15,22 @@ if (NOT HPX_COLLECTIVES_WITH_TESTS) endif() if (HPX_WITH_TESTS_UNIT) - add_hpx_pseudo_target(tests.unit.collectives) - add_hpx_pseudo_dependencies(tests.unit tests.unit.collectives) + add_hpx_pseudo_target(tests.unit.modules.collectives) + add_hpx_pseudo_dependencies(tests.unit.modules tests.unit.modules.collectives) add_subdirectory(unit) endif() if (HPX_WITH_TESTS_REGRESSIONS) - add_hpx_pseudo_target(tests.regressions.collectives) - add_hpx_pseudo_dependencies(tests.regressions tests.regressions.collectives) + add_hpx_pseudo_target(tests.regressions.modules.collectives) + add_hpx_pseudo_dependencies(tests.regressions.modules + tests.regressions.modules.collectives) add_subdirectory(regressions) endif() if (HPX_WITH_TESTS_BENCHMARKS) - add_hpx_pseudo_target(tests.performance.collectives) - add_hpx_pseudo_dependencies(tests.performance tests.performance.collectives) + add_hpx_pseudo_target(tests.performance.modules.collectives) + add_hpx_pseudo_dependencies(tests.performance.modules + tests.performance.modules.collectives) add_subdirectory(performance) endif() diff --git a/libs/collectives/tests/unit/CMakeLists.txt b/libs/collectives/tests/unit/CMakeLists.txt index 24bbd0e3bb00..d5d199d0792c 100644 --- a/libs/collectives/tests/unit/CMakeLists.txt +++ b/libs/collectives/tests/unit/CMakeLists.txt @@ -23,17 +23,17 @@ foreach(test ${tests}) HPX_PREFIX ${HPX_BUILD_PREFIX} FOLDER "Tests/Modules/Unit/Collectives") - add_hpx_unit_test("collectives" ${test} ${${test}_PARAMETERS}) + add_hpx_test("tests.unit.modules.collectives" ${test} ${${test}_PARAMETERS}) # add a custom target for this test - add_hpx_pseudo_target(tests.unit.collectives.${test}) + add_hpx_pseudo_target(tests.unit.modules.collectives.${test}) # make pseudo-targets depend on master pseudo-target - add_hpx_pseudo_dependencies(tests.unit.collectives - tests.unit.collectives.${test}) + add_hpx_pseudo_dependencies(tests.unit.modules.collectives + tests.unit.modules.collectives.${test}) # add dependencies to pseudo-target - add_hpx_pseudo_dependencies(tests.unit.collectives.${test} + add_hpx_pseudo_dependencies(tests.unit.modules.collectives.${test} ${test}_test) endforeach() diff --git a/libs/config/tests/CMakeLists.txt b/libs/config/tests/CMakeLists.txt index 980c827bb2f1..4d96d23fb2c8 100644 --- a/libs/config/tests/CMakeLists.txt +++ b/libs/config/tests/CMakeLists.txt @@ -15,20 +15,22 @@ if (NOT HPX_CONFIG_WITH_TESTS) endif() if (HPX_WITH_TESTS_UNIT) - add_hpx_pseudo_target(tests.unit.config) - add_hpx_pseudo_dependencies(tests.unit tests.unit.config) + add_hpx_pseudo_target(tests.unit.modules.config) + add_hpx_pseudo_dependencies(tests.unit.modules tests.unit.modules.config) add_subdirectory(unit) endif() if (HPX_WITH_TESTS_REGRESSIONS) - add_hpx_pseudo_target(tests.regressions.config) - add_hpx_pseudo_dependencies(tests.regressions tests.regressions.config) + add_hpx_pseudo_target(tests.regressions.modules.config) + add_hpx_pseudo_dependencies(tests.regressions.modules + tests.regressions.modules.config) add_subdirectory(regressions) endif() if (HPX_WITH_TESTS_BENCHMARKS) - add_hpx_pseudo_target(tests.performance.config) - add_hpx_pseudo_dependencies(tests.performance tests.performance.config) + add_hpx_pseudo_target(tests.performance.modules.config) + add_hpx_pseudo_dependencies(tests.performance.modules + tests.performance.modules.config) add_subdirectory(performance) endif() diff --git a/libs/preprocessor/tests/CMakeLists.txt b/libs/preprocessor/tests/CMakeLists.txt index bae9e72b6b4e..e3c64100d080 100644 --- a/libs/preprocessor/tests/CMakeLists.txt +++ b/libs/preprocessor/tests/CMakeLists.txt @@ -13,20 +13,22 @@ if (NOT HPX_PREPROCESSOR_WITH_TESTS) endif() if (HPX_WITH_TESTS_UNIT) - add_hpx_pseudo_target(tests.unit.preprocessor) - add_hpx_pseudo_dependencies(tests.unit tests.unit.preprocessor) + add_hpx_pseudo_target(tests.unit.modules.preprocessor) + add_hpx_pseudo_dependencies(tests.unit.modules tests.unit.modules.preprocessor) add_subdirectory(unit) endif() if (HPX_WITH_TESTS_REGRESSIONS) - add_hpx_pseudo_target(tests.regressions.preprocessor) - add_hpx_pseudo_dependencies(tests.regressions tests.regressions.preprocessor) + add_hpx_pseudo_target(tests.regressions.modules.preprocessor) + add_hpx_pseudo_dependencies(tests.regressions.modules + tests.regressions.modules.preprocessor) add_subdirectory(regressions) endif() if (HPX_WITH_TESTS_BENCHMARKS) - add_hpx_pseudo_target(tests.performance.preprocessor) - add_hpx_pseudo_dependencies(tests.performance tests.performance.preprocessor) + add_hpx_pseudo_target(tests.performance.modules.preprocessor) + add_hpx_pseudo_dependencies(tests.performance.modules + tests.performance.modules.preprocessor) add_subdirectory(performance) endif() diff --git a/tests/headers/CMakeLists.txt b/tests/headers/CMakeLists.txt index 12b7943663f3..ad2fc70da3d4 100644 --- a/tests/headers/CMakeLists.txt +++ b/tests/headers/CMakeLists.txt @@ -4,7 +4,7 @@ # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # collect a list of all header files in the source tree -file(GLOB_RECURSE headers "${PROJECT_SOURCE_DIR}/hpx/*hpp") +file(GLOB_RECURSE headers ${DO_CONFIGURE_DEPENDS} "${PROJECT_SOURCE_DIR}/hpx/*hpp") set(all_headers) From d9be48bc02d6cbc8b302a77f9db8d47a4067e9db Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Sun, 23 Jun 2019 15:28:16 -0500 Subject: [PATCH 03/11] Fixing and_gate when used with shared_future --- hpx/lcos/gather.hpp | 2 +- hpx/lcos/local/and_gate.hpp | 101 ++++++++++++++---- hpx/lcos/local/promise.hpp | 8 +- .../include/hpx/collectives/all_to_all.hpp | 15 ++- tests/performance/network/osu/broadcast.hpp | 2 +- 5 files changed, 95 insertions(+), 33 deletions(-) diff --git a/hpx/lcos/gather.hpp b/hpx/lcos/gather.hpp index d9bf83f803e1..0e2e10ef022a 100644 --- a/hpx/lcos/gather.hpp +++ b/hpx/lcos/gather.hpp @@ -268,7 +268,7 @@ namespace hpx { namespace lcos { std::unique_lock l(mtx_); - hpx::future > f = gate_.get_future().then( + hpx::future > f = gate_.get_future(l).then( util::bind_front(&gather_server::on_ready, this)); set_result_locked(which, std::move(t), l); diff --git a/hpx/lcos/local/and_gate.hpp b/hpx/lcos/local/and_gate.hpp index 171f8358c344..d8363221cb33 100644 --- a/hpx/lcos/local/and_gate.hpp +++ b/hpx/lcos/local/and_gate.hpp @@ -89,9 +89,11 @@ namespace hpx { namespace lcos { namespace local return triggered; } - public: + protected: /// \brief get a future allowing to wait for the gate to fire - future get_future(std::size_t count = std::size_t(-1), + template + future get_future(OuterLock& outer_lock, + std::size_t count = std::size_t(-1), std::size_t* generation_value = nullptr, error_code& ec = hpx::throws) { @@ -102,7 +104,7 @@ namespace hpx { namespace lcos { namespace local count = received_segments_.size(); HPX_ASSERT(count != 0); - init_locked(l, count, ec); + init_locked(outer_lock, l, count, ec); if (!ec) { HPX_ASSERT(generation_ != std::size_t(-1)); ++generation_; @@ -117,8 +119,21 @@ namespace hpx { namespace lcos { namespace local return hpx::future(); } + public: + future get_future(std::size_t count = std::size_t(-1), + std::size_t* generation_value = nullptr, + error_code& ec = hpx::throws) + { + no_mutex mtx; + std::unique_lock lk(mtx); + return get_future(lk, count, generation_value, ec); + } + + protected: /// \brief get a shared future allowing to wait for the gate to fire - shared_future get_shared_future(std::size_t count = std::size_t(-1), + template + shared_future get_shared_future(OuterLock& outer_lock, + std::size_t count = std::size_t(-1), std::size_t* generation_value = nullptr, error_code& ec = hpx::throws) { @@ -128,14 +143,15 @@ namespace hpx { namespace lcos { namespace local if (count == std::size_t(-1)) count = received_segments_.size(); HPX_ASSERT(count != 0); + HPX_ASSERT(generation_ != std::size_t(-1)); - init_locked(l, count, ec); - if (!ec) { - HPX_ASSERT(generation_ != std::size_t(-1)); - -// FIXME: get_shared_future is called more than once for each generation -// ++generation_; + if (generation_ == 0) + { + init_locked(outer_lock, l, count, ec); + generation_ = 1; + } + if (!ec) { trigger_conditions(ec); // re-check/trigger condition, if needed if (!ec) { if (generation_value) @@ -146,6 +162,17 @@ namespace hpx { namespace lcos { namespace local return hpx::future().share(); } + public: + shared_future get_shared_future(std::size_t count = std::size_t(-1), + std::size_t* generation_value = nullptr, + error_code& ec = hpx::throws) + { + no_mutex mtx; + std::unique_lock lk(mtx); + return get_shared_future(lk, count, generation_value, ec); + } + + protected: /// \brief Set the data which has to go into the segment \a which. template bool set(std::size_t which, OuterLock & outer_lock, error_code& ec = throws) @@ -155,6 +182,7 @@ namespace hpx { namespace lcos { namespace local { // out of bounds index l.unlock(); + outer_lock.unlock(); HPX_THROWS_IF(ec, bad_parameter, "base_and_gate<>::set", "index is out of range for this base_and_gate"); return false; @@ -163,6 +191,7 @@ namespace hpx { namespace lcos { namespace local { // segment already filled, logic error l.unlock(); + outer_lock.unlock(); HPX_THROWS_IF(ec, bad_parameter, "base_and_gate<>::set", "input with the given index has already been triggered"); return false; @@ -180,19 +209,20 @@ namespace hpx { namespace lcos { namespace local promise p; std::swap(p, promise_); received_segments_.reset(); // reset data store - { - // Unlock the lock to avoid locking problems - // when triggering the promise - l.unlock(); - outer_lock.unlock(); - p.set_value(); // fire event - return true; - } + + // Unlock the lock to avoid locking problems when triggering + // the promise + l.unlock(); + outer_lock.unlock(); + p.set_value(); // fire event + + return true; } return false; } + public: bool set(std::size_t which, error_code& ec = throws) { no_mutex mtx; @@ -222,7 +252,7 @@ namespace hpx { namespace lcos { namespace local } template - future get_future(Condition&& func, + future get_future(Condition&& func, error_code& ec = hpx::throws) { return (*it_)->get_future(std::forward(func), ec); @@ -297,13 +327,15 @@ namespace hpx { namespace lcos { namespace local } protected: - template - void init_locked(Lock& l, std::size_t count, error_code& ec = throws) + template + void init_locked(OuterLock& outer_lock, Lock& l, std::size_t count, + error_code& ec = throws) { if (0 != received_segments_.count()) { // reset happens while part of the slots are filled l.unlock(); + outer_lock.unlock(); HPX_THROWS_IF(ec, bad_parameter, "base_and_gate<>::init", "initializing this base_and_gate while slots are filled"); return; @@ -353,10 +385,35 @@ namespace hpx { namespace lcos { namespace local return *this; } + template + future get_future(Lock& l, + std::size_t count = std::size_t(-1), + std::size_t* generation_value = nullptr, + error_code& ec = hpx::throws) + { + return this->base_type::get_future(l, count, generation_value, ec); + } + + template + shared_future get_shared_future(Lock& l, + std::size_t count = std::size_t(-1), + std::size_t* generation_value = nullptr, + error_code& ec = hpx::throws) + { + return this->base_type::get_shared_future( + l, count, generation_value, ec); + } + + template + bool set(std::size_t which, Lock& l, error_code& ec = throws) + { + return this->base_type::set(which, l, ec); + } + template void synchronize(std::size_t generation_value, Lock& l, char const* function_name = "and_gate::synchronize", - error_code& ec= throws) + error_code& ec = throws) { this->base_type::synchronize(generation_value, l, function_name, ec); } diff --git a/hpx/lcos/local/promise.hpp b/hpx/lcos/local/promise.hpp index 1e7ade02facc..f062c34114b8 100644 --- a/hpx/lcos/local/promise.hpp +++ b/hpx/lcos/local/promise.hpp @@ -123,7 +123,8 @@ namespace hpx { namespace lcos { namespace local { HPX_THROWS_IF(ec, future_already_retrieved, "local::detail::promise_base::get_future", - "future has already been retrieved from this promise"); + "future or shared future has already been retrieved " + "from this promise"); return future(); } @@ -141,12 +142,11 @@ namespace hpx { namespace lcos { namespace local shared_future get_shared_future(error_code& ec = throws) { - if (shared_future_retrieved_) + if (future_retrieved_) { HPX_THROWS_IF(ec, future_already_retrieved, "local::detail::promise_base::get_shared_future", - "shared future has already been retrieved from this " - "promise"); + "future has already been retrieved from this promise"); return shared_future(); } diff --git a/libs/collectives/include/hpx/collectives/all_to_all.hpp b/libs/collectives/include/hpx/collectives/all_to_all.hpp index f9bf46d0b6bf..756e368c9b87 100644 --- a/libs/collectives/include/hpx/collectives/all_to_all.hpp +++ b/libs/collectives/include/hpx/collectives/all_to_all.hpp @@ -175,16 +175,21 @@ namespace hpx { namespace lcos { f.get(); // propagate any exceptions - std::vector data(num_sites_); + std::vector data; + std::string name; { std::unique_lock l(mtx_); - std::swap(data, data_); + data = data_; + std::swap(name, name_); } // this is a one-shot object (generations counters are not - // supported), unregister ourselves - hpx::unregister_with_basename(name_, site_); + // supported), unregister ourselves (but only once) + if (!name.empty()) + { + hpx::unregister_with_basename(name, site_); + } return data; } @@ -209,7 +214,7 @@ namespace hpx { namespace lcos std::unique_lock l(mtx_); hpx::future> f = - gate_.get_shared_future().then(hpx::launch::async, + gate_.get_shared_future(l).then(hpx::launch::async, util::bind_front(&all_to_all_server::on_ready, this)); gate_.synchronize(1, l); diff --git a/tests/performance/network/osu/broadcast.hpp b/tests/performance/network/osu/broadcast.hpp index 981732589288..e90c13d14182 100644 --- a/tests/performance/network/osu/broadcast.hpp +++ b/tests/performance/network/osu/broadcast.hpp @@ -91,7 +91,7 @@ namespace hpx { namespace lcos { { std::lock_guard lk(mtx); - bcast_future = bcast_gate.get_future(1); + bcast_future = bcast_gate.get_future(lk, 1); ready_promise.set_value(); ready_promise = hpx::lcos::local::promise(); From 24fbe1d003f04b5ac6bc579e288ca5f697bed401 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Wed, 26 Jun 2019 10:53:53 -0500 Subject: [PATCH 04/11] Adding INSTALL_BINARIES=OFF to CMakeLists.txt --- libs/collectives/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/collectives/CMakeLists.txt b/libs/collectives/CMakeLists.txt index 84d74440b033..eed10ae3f4ea 100644 --- a/libs/collectives/CMakeLists.txt +++ b/libs/collectives/CMakeLists.txt @@ -22,5 +22,6 @@ add_hpx_module(collectives SOURCES ${collectives_sources} HEADERS ${collectives_headers} DEPENDENCIES hpx_config hpx_preprocessor + INSTALL_BINARIES OFF CMAKE_SUBDIRS examples tests ) From f444ef5c46c279baba0058d375e9020b9077b3d1 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Thu, 27 Jun 2019 09:00:49 -0500 Subject: [PATCH 05/11] Addressing review comments - adding minimal docs - fixing pseudo target names - updating create_library_skeleton.py --- CMakeLists.txt | 7 ++- cmake/HPX_AddCompileTest.cmake | 2 +- libs/CMakeLists.txt | 46 ++++++++++++------ libs/_example/tests/CMakeLists.txt | 2 +- libs/cache/examples/CMakeLists.txt | 4 +- libs/cache/tests/CMakeLists.txt | 2 +- libs/collectives/README.rst | 4 +- libs/collectives/docs/index.rst | 11 ++++- libs/collectives/examples/CMakeLists.txt | 5 +- libs/collectives/tests/CMakeLists.txt | 2 +- libs/config/examples/CMakeLists.txt | 4 +- libs/config/tests/CMakeLists.txt | 2 +- libs/create_library_skeleton.py | 59 ++++++++++++++++++++---- libs/preprocessor/tests/CMakeLists.txt | 2 +- 14 files changed, 111 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28b40f8a04a4..7bbfab76159c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1830,7 +1830,7 @@ if (HPX_WITH_TESTS) add_hpx_pseudo_target(tests.headers) add_hpx_pseudo_dependencies(tests tests.headers) endif() - if (HPX_WITH_TESTS_EXAMPLES) + if (HPX_WITH_EXAMPLES AND HPX_WITH_TESTS_EXAMPLES) add_hpx_pseudo_target(tests.examples) add_hpx_pseudo_dependencies(tests tests.examples) endif() @@ -1839,6 +1839,10 @@ if (HPX_WITH_TESTS) include(CTest) endif() +if(HPX_WITH_EXAMPLES) + add_hpx_pseudo_target(examples) +endif() + ################################################################################ # Debug library postfix ################################################################################ @@ -1901,7 +1905,6 @@ if(HPX_WITH_TESTS) endif() if(HPX_WITH_EXAMPLES) - add_hpx_pseudo_target(examples) include_directories(examples) add_subdirectory(examples) endif() diff --git a/cmake/HPX_AddCompileTest.cmake b/cmake/HPX_AddCompileTest.cmake index 307bcb529c79..a059462579e5 100644 --- a/cmake/HPX_AddCompileTest.cmake +++ b/cmake/HPX_AddCompileTest.cmake @@ -50,7 +50,7 @@ function(add_hpx_headers_compile_test category name) add_hpx_compile_test("tests.headers.${category}" ${name} ${ARGN}) endfunction() -function(add_hpx_lib_header_tests lib) +function(add_hpx_module_header_tests lib) file(GLOB_RECURSE headers ${DO_CONFIGURE_DEPENDS} "${PROJECT_SOURCE_DIR}/include/hpx/*hpp") diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index f148a4247085..63f09bf0358a 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -6,29 +6,49 @@ # This file is auto generated. Please do not edit manually. include(HPX_Message) +include(HPX_AddPseudoDependencies) +include(HPX_AddPseudoTarget) set(HPX_LIBS cache collectives config preprocessor - CACHE INTERNAL "" FORCE + CACHE INTERNAL "list of HPX modules" FORCE ) -if (HPX_WITH_TESTS_UNIT) - add_hpx_pseudo_target(tests.unit.modules) +# add example pseudo targets needed for modules +if(HPX_WITH_EXAMPLES) + add_hpx_pseudo_target(examples.modules) + add_hpx_pseudo_dependencies(examples examples.modules) endif() -if (HPX_WITH_TESTS_REGRESSIONS) - add_hpx_pseudo_target(tests.regressions.modules) -endif() - -if (HPX_WITH_TESTS_BENCHMARKS) - add_hpx_pseudo_target(tests.performance.modules) -endif() - -if (HPX_WITH_TESTS_HEADERS) - add_custom_target(tests.headers.modules) +# add test pseudo targets needed for modules +if(HPX_WITH_TESTS) + if (HPX_WITH_TESTS_UNIT) + add_hpx_pseudo_target(tests.unit.modules) + add_hpx_pseudo_dependencies(tests.unit tests.unit.modules) + endif() + + if (HPX_WITH_EXAMPLES AND HPX_WITH_TESTS_EXAMPLES) + add_hpx_pseudo_target(tests.examples.modules) + add_hpx_pseudo_dependencies(tests.examples tests.examples.modules) + endif() + + if (HPX_WITH_TESTS_REGRESSIONS) + add_hpx_pseudo_target(tests.regressions.modules) + add_hpx_pseudo_dependencies(tests.regressions tests.regressions.modules) + endif() + + if (HPX_WITH_TESTS_BENCHMARKS) + add_hpx_pseudo_target(tests.performance.modules) + add_hpx_pseudo_dependencies(tests.performance tests.performance.modules) + endif() + + if (HPX_WITH_TESTS_HEADERS) + add_custom_target(tests.headers.modules) + add_hpx_pseudo_dependencies(tests.headers tests.headers.modules) + endif() endif() hpx_info("Configuring modules:") diff --git a/libs/_example/tests/CMakeLists.txt b/libs/_example/tests/CMakeLists.txt index 3a720ce52653..75a01361c0bf 100644 --- a/libs/_example/tests/CMakeLists.txt +++ b/libs/_example/tests/CMakeLists.txt @@ -33,5 +33,5 @@ if (HPX_WITH_TESTS_BENCHMARKS) endif() if (HPX_WITH_TESTS_HEADERS) - add_hpx_lib_header_tests(example) + add_hpx_module_header_tests(example) endif() diff --git a/libs/cache/examples/CMakeLists.txt b/libs/cache/examples/CMakeLists.txt index 46d5af511d3b..f733835b9954 100644 --- a/libs/cache/examples/CMakeLists.txt +++ b/libs/cache/examples/CMakeLists.txt @@ -4,7 +4,7 @@ # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) if (HPX_WITH_TESTS AND HPX_WITH_TESTS_EXAMPLES) - add_hpx_pseudo_target(tests.examples.cache) - add_hpx_pseudo_dependencies(tests.examples tests.examples.cache) + add_hpx_pseudo_target(tests.examples.modules.cache) + add_hpx_pseudo_dependencies(tests.examples.modules tests.examples.modules.cache) endif() diff --git a/libs/cache/tests/CMakeLists.txt b/libs/cache/tests/CMakeLists.txt index 7bbf30a8d1c6..197219734fcb 100644 --- a/libs/cache/tests/CMakeLists.txt +++ b/libs/cache/tests/CMakeLists.txt @@ -35,5 +35,5 @@ if (HPX_WITH_TESTS_BENCHMARKS) endif() if (HPX_WITH_TESTS_HEADERS) - add_hpx_lib_header_tests(cache) + add_hpx_module_header_tests(cache) endif() diff --git a/libs/collectives/README.rst b/libs/collectives/README.rst index db288af5a063..15ba9cba2078 100644 --- a/libs/collectives/README.rst +++ b/libs/collectives/README.rst @@ -5,9 +5,9 @@ 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) -=== +=========== Collectives -=== +=========== This library is part of HPX. diff --git a/libs/collectives/docs/index.rst b/libs/collectives/docs/index.rst index c922b45f513c..311108588fc8 100644 --- a/libs/collectives/docs/index.rst +++ b/libs/collectives/docs/index.rst @@ -6,7 +6,14 @@ .. _libs_collectives: -===== +=========== collectives -===== +=========== + +The collectives module exposes a set of distributed collective operations. Those +can be used to exchange data between participating sites in a coordinated way. +At this point the module exposes the following collective primitives: + +* ``all_to_all``: each participating site provides its element of the data to + collect while all participating sites receive the data from every other site. diff --git a/libs/collectives/examples/CMakeLists.txt b/libs/collectives/examples/CMakeLists.txt index d150fd0dbaae..63290275aab2 100644 --- a/libs/collectives/examples/CMakeLists.txt +++ b/libs/collectives/examples/CMakeLists.txt @@ -4,7 +4,8 @@ # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) if (HPX_WITH_TESTS AND HPX_WITH_TESTS_EXAMPLES) - add_hpx_pseudo_target(tests.examples.collectives) - add_hpx_pseudo_dependencies(tests.examples tests.examples.collectives) + add_hpx_pseudo_target(tests.examples.modules.collectives) + add_hpx_pseudo_dependencies(tests.examples.modules + tests.examples.modules.collectives) endif() diff --git a/libs/collectives/tests/CMakeLists.txt b/libs/collectives/tests/CMakeLists.txt index 79acdbafee22..4b73d79294c0 100644 --- a/libs/collectives/tests/CMakeLists.txt +++ b/libs/collectives/tests/CMakeLists.txt @@ -35,5 +35,5 @@ if (HPX_WITH_TESTS_BENCHMARKS) endif() if (HPX_WITH_TESTS_HEADERS) - add_hpx_lib_header_tests(collectives) + add_hpx_module_header_tests(collectives) endif() diff --git a/libs/config/examples/CMakeLists.txt b/libs/config/examples/CMakeLists.txt index 44a2387ec517..81c71437ad1c 100644 --- a/libs/config/examples/CMakeLists.txt +++ b/libs/config/examples/CMakeLists.txt @@ -4,7 +4,7 @@ # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) if (HPX_WITH_TESTS AND HPX_WITH_TESTS_EXAMPLES) - add_hpx_pseudo_target(tests.examples.config) - add_hpx_pseudo_dependencies(tests.examples tests.examples.config) + add_hpx_pseudo_target(tests.examples.modules.config) + add_hpx_pseudo_dependencies(tests.examples.modules tests.examples.modules.config) endif() diff --git a/libs/config/tests/CMakeLists.txt b/libs/config/tests/CMakeLists.txt index 4d96d23fb2c8..50f69a2cac84 100644 --- a/libs/config/tests/CMakeLists.txt +++ b/libs/config/tests/CMakeLists.txt @@ -35,5 +35,5 @@ if (HPX_WITH_TESTS_BENCHMARKS) endif() if (HPX_WITH_TESTS_HEADERS) - add_hpx_lib_header_tests(config) + add_hpx_module_header_tests(config) endif() diff --git a/libs/create_library_skeleton.py b/libs/create_library_skeleton.py index 099220e3040a..17e0c0d2ef04 100755 --- a/libs/create_library_skeleton.py +++ b/libs/create_library_skeleton.py @@ -86,8 +86,8 @@ examples_cmakelists_template = cmake_header + f''' if (HPX_WITH_TESTS AND HPX_WITH_TESTS_EXAMPLES) - add_hpx_pseudo_target(tests.examples.{lib_name}) - add_hpx_pseudo_dependencies(tests.examples tests.examples.{lib_name}) + add_hpx_pseudo_target(tests.examples.module.{lib_name}) + add_hpx_pseudo_dependencies(tests.examples.module tests.examples.module.{lib_name}) endif() ''' @@ -105,25 +105,25 @@ endif() if (HPX_WITH_TESTS_UNIT) - add_hpx_pseudo_target(tests.unit.{lib_name}) - add_hpx_pseudo_dependencies(tests.unit tests.unit.{lib_name}) + add_hpx_pseudo_target(tests.unit.module.{lib_name}) + add_hpx_pseudo_dependencies(tests.unit.module tests.unit.module.{lib_name}) add_subdirectory(unit) endif() if (HPX_WITH_TESTS_REGRESSIONS) - add_hpx_pseudo_target(tests.regressions.{lib_name}) - add_hpx_pseudo_dependencies(tests.regressions tests.regressions.{lib_name}) + add_hpx_pseudo_target(tests.regressions.module.{lib_name}) + add_hpx_pseudo_dependencies(tests.regressions.module tests.regressions.module.{lib_name}) add_subdirectory(regressions) endif() if (HPX_WITH_TESTS_BENCHMARKS) - add_hpx_pseudo_target(tests.performance.{lib_name}) - add_hpx_pseudo_dependencies(tests.performance tests.performance.{lib_name}) + add_hpx_pseudo_target(tests.performance.module.{lib_name}) + add_hpx_pseudo_dependencies(tests.performance.module tests.performance.module.{lib_name}) add_subdirectory(performance) endif() if (HPX_WITH_TESTS_HEADERS) - add_hpx_lib_header_tests({lib_name}) + add_hpx_module_header_tests({lib_name}) endif() ''' @@ -208,13 +208,52 @@ def mkdir(path): libs_cmakelists += ''' include(HPX_Message) +include(HPX_AddPseudoDependencies) +include(HPX_AddPseudoTarget) set(HPX_LIBS ''' for lib in libs: if not lib.startswith('_'): libs_cmakelists += f' {lib}\n' -libs_cmakelists += ' CACHE INTERNAL "" FORCE\n)\n' +libs_cmakelists += ' CACHE INTERNAL "list of HPX modules" FORCE\n)\n\n' + +libs_cmakelists += ''' +# add example pseudo targets needed for modules +if(HPX_WITH_EXAMPLES) + add_hpx_pseudo_target(examples.modules) + add_hpx_pseudo_dependencies(examples examples.modules) +endif() + +# add test pseudo targets needed for modules +if(HPX_WITH_TESTS) + if (HPX_WITH_TESTS_UNIT) + add_hpx_pseudo_target(tests.unit.modules) + add_hpx_pseudo_dependencies(tests.unit tests.unit.modules) + endif() + + if (HPX_WITH_EXAMPLES AND HPX_WITH_TESTS_EXAMPLES) + add_hpx_pseudo_target(tests.examples.modules) + add_hpx_pseudo_dependencies(tests.examples tests.examples.modules) + endif() + + if (HPX_WITH_TESTS_REGRESSIONS) + add_hpx_pseudo_target(tests.regressions.modules) + add_hpx_pseudo_dependencies(tests.regressions tests.regressions.modules) + endif() + + if (HPX_WITH_TESTS_BENCHMARKS) + add_hpx_pseudo_target(tests.performance.modules) + add_hpx_pseudo_dependencies(tests.performance tests.performance.modules) + endif() + + if (HPX_WITH_TESTS_HEADERS) + add_custom_target(tests.headers.modules) + add_hpx_pseudo_dependencies(tests.headers tests.headers.modules) + endif() +endif() + +''' libs_cmakelists += ''' hpx_info("Configuring modules:") diff --git a/libs/preprocessor/tests/CMakeLists.txt b/libs/preprocessor/tests/CMakeLists.txt index e3c64100d080..131e07ada1dc 100644 --- a/libs/preprocessor/tests/CMakeLists.txt +++ b/libs/preprocessor/tests/CMakeLists.txt @@ -33,5 +33,5 @@ if (HPX_WITH_TESTS_BENCHMARKS) endif() if (HPX_WITH_TESTS_HEADERS) - add_hpx_lib_header_tests(preprocessor) + add_hpx_module_header_tests(preprocessor) endif() From ca57c84c03459ce4e9756d687d409e0cb9ce8646 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 28 Jun 2019 11:35:15 +0200 Subject: [PATCH 06/11] Generate force_linking.hpp header for modules --- cmake/HPX_AddModule.cmake | 20 ++++++++++++++++--- libs/cache/CMakeLists.txt | 1 - .../cache/include/hpx/cache/force_linking.hpp | 10 ---------- libs/config/CMakeLists.txt | 1 - .../include/hpx/config/force_linking.hpp | 10 ---------- libs/preprocessor/CMakeLists.txt | 1 - .../hpx/preprocessor/force_linking.hpp | 10 ---------- 7 files changed, 17 insertions(+), 36 deletions(-) delete mode 100644 libs/cache/include/hpx/cache/force_linking.hpp delete mode 100644 libs/config/include/hpx/config/force_linking.hpp delete mode 100644 libs/preprocessor/include/hpx/preprocessor/force_linking.hpp diff --git a/cmake/HPX_AddModule.cmake b/cmake/HPX_AddModule.cmake index f735011adc6b..8f48aae8093d 100644 --- a/cmake/HPX_AddModule.cmake +++ b/cmake/HPX_AddModule.cmake @@ -100,12 +100,26 @@ function(add_hpx_module name) ) endif() + set(force_linking_header "${CMAKE_BINARY_DIR}/hpx/${name}/force_linking.hpp") + # Add a header to force linking of modules on Windows + FILE(WRITE ${force_linking_header} + "// Copyright (c) 2019 The STE||AR GROUP\n" + "//\n" + "// Distributed under the Boost Software License, Version 1.0. (See accompanying\n" + "// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" + "\n" + "namespace hpx { namespace config\n" + "{\n" + " void force_linking();\n" + "}}\n" + ) + foreach(header_file ${headers}) hpx_debug(${header_file}) endforeach(header_file) add_library(hpx_${name} STATIC ${sources} ${headers} ${global_header} ${compat_headers}) - + target_link_libraries(hpx_${name} ${${name}_DEPENDENCIES}) target_include_directories(hpx_${name} PUBLIC $ @@ -173,7 +187,7 @@ function(add_hpx_module name) COMPONENT ${name} ) endif() - + write_config_defines_file( NAMESPACE ${name_upper} FILENAME "${CMAKE_BINARY_DIR}/hpx/${name}/config/defines.hpp") @@ -185,5 +199,5 @@ function(add_hpx_module name) foreach(dir ${${name}_CMAKE_SUBDIRS}) add_subdirectory(${dir}) endforeach(dir) - + endfunction(add_hpx_module) diff --git a/libs/cache/CMakeLists.txt b/libs/cache/CMakeLists.txt index 3c8025d843a6..cb4b7224da6d 100644 --- a/libs/cache/CMakeLists.txt +++ b/libs/cache/CMakeLists.txt @@ -9,7 +9,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Default location is $HPX_ROOT/libs/cache/include set(cache_headers - hpx/cache/force_linking.hpp hpx/cache/local_cache.hpp hpx/cache/lru_cache.hpp hpx/cache/entries/entry.hpp diff --git a/libs/cache/include/hpx/cache/force_linking.hpp b/libs/cache/include/hpx/cache/force_linking.hpp deleted file mode 100644 index 3712a699a2d7..000000000000 --- a/libs/cache/include/hpx/cache/force_linking.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2019 Hartmut Kaiser -// -// 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) - -/////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace cache -{ - void force_linking(); -}} diff --git a/libs/config/CMakeLists.txt b/libs/config/CMakeLists.txt index 5134a263ba80..cb01563148b0 100644 --- a/libs/config/CMakeLists.txt +++ b/libs/config/CMakeLists.txt @@ -22,7 +22,6 @@ set(config_headers hpx/config/emulate_deleted.hpp hpx/config/export_definitions.hpp hpx/config/forceinline.hpp - hpx/config/force_linking.hpp hpx/config/lambda_capture.hpp hpx/config/manual_profiling.hpp hpx/config/threads_stack.hpp diff --git a/libs/config/include/hpx/config/force_linking.hpp b/libs/config/include/hpx/config/force_linking.hpp deleted file mode 100644 index 76a349617989..000000000000 --- a/libs/config/include/hpx/config/force_linking.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2019 Hartmut Kaiser -// -// 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) - -/////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace config -{ - void force_linking(); -}} diff --git a/libs/preprocessor/CMakeLists.txt b/libs/preprocessor/CMakeLists.txt index 4db15f74ca20..e0c00c6f9717 100644 --- a/libs/preprocessor/CMakeLists.txt +++ b/libs/preprocessor/CMakeLists.txt @@ -12,7 +12,6 @@ set(preprocessor_headers hpx/preprocessor/cat.hpp hpx/preprocessor/config.hpp hpx/preprocessor/expand.hpp - hpx/preprocessor/force_linking.hpp hpx/preprocessor/nargs.hpp hpx/preprocessor/stringize.hpp hpx/preprocessor/strip_parens.hpp diff --git a/libs/preprocessor/include/hpx/preprocessor/force_linking.hpp b/libs/preprocessor/include/hpx/preprocessor/force_linking.hpp deleted file mode 100644 index a3f17b54f9ee..000000000000 --- a/libs/preprocessor/include/hpx/preprocessor/force_linking.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2019 Hartmut Kaiser -// -// 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) - -/////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace preprocessor -{ - void force_linking(); -}} From d2d63b5b062053799eabe5aab57b84f840f3812b Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Fri, 28 Jun 2019 07:26:33 -0500 Subject: [PATCH 07/11] Touching up on HPX_AddModule cmake script - Generating force_linking source files - remove unneeded source files (those are being generated now) - add missing source groups - export modules as targets only if those are installed --- cmake/HPX_AddModule.cmake | 86 +++++++++++++++++++------- libs/cache/CMakeLists.txt | 2 +- libs/cache/src/cache.cpp | 12 ---- libs/collectives/CMakeLists.txt | 2 +- libs/collectives/src/collectives.cpp | 9 --- libs/config/CMakeLists.txt | 1 + libs/preprocessor/CMakeLists.txt | 4 +- libs/preprocessor/src/CMakeLists.txt | 16 ----- libs/preprocessor/src/preprocessor.cpp | 12 ---- 9 files changed, 70 insertions(+), 74 deletions(-) delete mode 100644 libs/cache/src/cache.cpp delete mode 100644 libs/collectives/src/collectives.cpp delete mode 100644 libs/preprocessor/src/CMakeLists.txt delete mode 100644 libs/preprocessor/src/preprocessor.cpp diff --git a/cmake/HPX_AddModule.cmake b/cmake/HPX_AddModule.cmake index 8f48aae8093d..24a8ec44df32 100644 --- a/cmake/HPX_AddModule.cmake +++ b/cmake/HPX_AddModule.cmake @@ -6,7 +6,7 @@ function(add_hpx_module name) # Retrieve arguments set(options DEPRECATION_WARNINGS) - set(one_value_args COMPATIBILITY_HEADERS GLOBAL_HEADER_GEN INSTALL_BINARIES) + set(one_value_args COMPATIBILITY_HEADERS GLOBAL_HEADER_GEN FORCE_LINKING_GEN INSTALL_BINARIES) set(multi_value_args SOURCES HEADERS COMPAT_HEADERS DEPENDENCIES CMAKE_SUBDIRS) cmake_parse_arguments(${name} "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) @@ -77,16 +77,21 @@ function(add_hpx_module name) prepend(compat_headers ${COMPAT_HEADER_ROOT} ${${name}_COMPAT_HEADERS}) endif() + set(copyright + "// Copyright (c) 2019 The STE||AR GROUP\n" + "//\n" + "// Distributed under the Boost Software License, Version 1.0. (See accompanying\n" + "// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" + "\n" + ) + # This header generation is disabled for config module specific generated # headers are included if (${name}_GLOBAL_HEADER_GEN) set(global_header "${CMAKE_BINARY_DIR}/hpx/${name}.hpp") # Add a global include file that include all module headers FILE(WRITE ${global_header} - "// Copyright (c) 2019 The STE||AR GROUP\n" - "//\n" - "// Distributed under the Boost Software License, Version 1.0. (See accompanying\n" - "// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n\n" + ${copyright} "#ifndef HPX_${name_upper}_HPP\n" "#define HPX_${name_upper}_HPP\n\n" ) @@ -96,29 +101,48 @@ function(add_hpx_module name) ) endforeach(header_file) FILE(APPEND ${global_header} - "\n#endif" + "\n#endif\n" ) endif() - set(force_linking_header "${CMAKE_BINARY_DIR}/hpx/${name}/force_linking.hpp") - # Add a header to force linking of modules on Windows - FILE(WRITE ${force_linking_header} - "// Copyright (c) 2019 The STE||AR GROUP\n" - "//\n" - "// Distributed under the Boost Software License, Version 1.0. (See accompanying\n" - "// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" - "\n" - "namespace hpx { namespace config\n" - "{\n" - " void force_linking();\n" - "}}\n" - ) + if(${name}_FORCE_LINKING_GEN) + # Add a header to force linking of modules on Windows + set(force_linking_header "${CMAKE_BINARY_DIR}/hpx/${name}/force_linking.hpp") + FILE(WRITE ${force_linking_header} + ${copyright} + "#if !defined(HPX_${name_upper}_FORCE_LINKING_HPP)\n" + "#define HPX_${name_upper}_FORCE_LINKING_HPP\n" + "\n" + "namespace hpx { namespace ${name}\n" + "{\n" + " void force_linking();\n" + "}}\n" + "\n" + "#endif\n" + ) + + # Add a source file implementing the above function + set(force_linking_source "${CMAKE_BINARY_DIR}/libs/${name}/force_linking.cpp") + FILE(WRITE ${force_linking_source} + ${copyright} + "#include \n" + "\n" + "namespace hpx { namespace ${name}\n" + "{\n" + " void force_linking() {}\n" + "}}\n" + "\n" + ) + endif() foreach(header_file ${headers}) hpx_debug(${header_file}) endforeach(header_file) - add_library(hpx_${name} STATIC ${sources} ${headers} ${global_header} ${compat_headers}) + add_library(hpx_${name} STATIC + ${sources} ${force_linking_source} + ${headers} ${global_header} ${compat_headers} + ${force_linking_header}) target_link_libraries(hpx_${name} ${${name}_DEPENDENCIES}) target_include_directories(hpx_${name} PUBLIC @@ -154,6 +178,26 @@ function(add_hpx_module name) TARGETS ${compat_headers}) endif() + if (${name}_GLOBAL_HEADER_GEN) + add_hpx_source_group( + NAME hpx_{name} + ROOT ${CMAKE_BINARY_DIR}/hpx + CLASS "Generated Files" + TARGETS ${global_header}) + endif() + if (${name}_FORCE_LINKING_GEN) + add_hpx_source_group( + NAME hpx_{name} + ROOT ${CMAKE_BINARY_DIR}/hpx + CLASS "Generated Files" + TARGETS ${force_linking_header}) + add_hpx_source_group( + NAME hpx_{name} + ROOT ${CMAKE_BINARY_DIR}/libs + CLASS "Generated Files" + TARGETS ${force_linking_source}) + endif() + set_target_properties(hpx_${name} PROPERTIES FOLDER "Core/Modules") @@ -164,8 +208,8 @@ function(add_hpx_module name) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${name} ) + hpx_export_targets(hpx_${name}) endif() - hpx_export_targets(hpx_${name}) install( DIRECTORY include/hpx diff --git a/libs/cache/CMakeLists.txt b/libs/cache/CMakeLists.txt index cb4b7224da6d..2cabf175fb9f 100644 --- a/libs/cache/CMakeLists.txt +++ b/libs/cache/CMakeLists.txt @@ -39,7 +39,6 @@ set(cache_compat_headers # Default location is $HPX_ROOT/libs/cache/src set(cache_sources - cache.cpp ) include(HPX_AddModule) @@ -47,6 +46,7 @@ add_hpx_module(cache DEPRECATION_WARNINGS COMPATIBILITY_HEADERS ON # Added in 1.4.0 INSTALL_BINARIES OFF + FORCE_LINKING_GEN ON SOURCES ${cache_sources} HEADERS ${cache_headers} COMPAT_HEADERS ${cache_compat_headers} diff --git a/libs/cache/src/cache.cpp b/libs/cache/src/cache.cpp deleted file mode 100644 index 7fa4ffe764f4..000000000000 --- a/libs/cache/src/cache.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2019 STE||AR Group -// -// 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 - -/////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace cache -{ - void force_linking() {} -}} diff --git a/libs/collectives/CMakeLists.txt b/libs/collectives/CMakeLists.txt index eed10ae3f4ea..db9f904ac14f 100644 --- a/libs/collectives/CMakeLists.txt +++ b/libs/collectives/CMakeLists.txt @@ -14,7 +14,6 @@ set(collectives_headers # Default location is $HPX_ROOT/libs/collectives/src set(collectives_sources - collectives.cpp ) include(HPX_AddModule) @@ -22,6 +21,7 @@ add_hpx_module(collectives SOURCES ${collectives_sources} HEADERS ${collectives_headers} DEPENDENCIES hpx_config hpx_preprocessor + FORCE_LINKING_GEN ON INSTALL_BINARIES OFF CMAKE_SUBDIRS examples tests ) diff --git a/libs/collectives/src/collectives.cpp b/libs/collectives/src/collectives.cpp deleted file mode 100644 index fd2b4d41ab57..000000000000 --- a/libs/collectives/src/collectives.cpp +++ /dev/null @@ -1,9 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright (c) 2019 STE||AR Group -// -// 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) -//////////////////////////////////////////////////////////////////////////////// - -// This file was intentionally left empty. It is used as a dummy to force cmake -// into generating a separate Visual Studio project for this module. diff --git a/libs/config/CMakeLists.txt b/libs/config/CMakeLists.txt index cb01563148b0..a0c0d4ed8130 100644 --- a/libs/config/CMakeLists.txt +++ b/libs/config/CMakeLists.txt @@ -40,6 +40,7 @@ add_hpx_module(config COMPATIBILITY_HEADERS OFF GLOBAL_HEADER_GEN OFF INSTALL_BINARIES OFF + FORCE_LINKING_GEN OFF SOURCES ${config_sources} HEADERS ${config_headers} DEPENDENCIES hpx_preprocessor diff --git a/libs/preprocessor/CMakeLists.txt b/libs/preprocessor/CMakeLists.txt index e0c00c6f9717..6fd82fdf7882 100644 --- a/libs/preprocessor/CMakeLists.txt +++ b/libs/preprocessor/CMakeLists.txt @@ -29,7 +29,6 @@ set(preprocessor_compat_headers # Default location is $HPX_ROOT/libs/preprocessor/src set(preprocessor_sources - preprocessor.cpp ) include(HPX_AddModule) @@ -37,9 +36,10 @@ add_hpx_module(preprocessor DEPRECATION_WARNINGS COMPATIBILITY_HEADERS OFF INSTALL_BINARIES OFF + FORCE_LINKING_GEN ON SOURCES ${preprocessor_sources} HEADERS ${preprocessor_headers} COMPAT_HEADERS ${preprocessor_compat_headers} DEPENDENCIES hpx_config - CMAKE_SUBDIRS src tests + CMAKE_SUBDIRS tests ) diff --git a/libs/preprocessor/src/CMakeLists.txt b/libs/preprocessor/src/CMakeLists.txt deleted file mode 100644 index 8de4dc0436d2..000000000000 --- a/libs/preprocessor/src/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2019 The STE||AR-Group -# -# 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) - -# cmake will not create a separate VS project without any source files, thus -# this adds a dummy (empty) source file to the target -set(sources ${CMAKE_CURRENT_SOURCE_DIR}/preprocessor.cpp) - -target_sources(hpx_preprocessor PRIVATE ${sources}) - -add_hpx_source_group( - NAME hpx_preprocessor - ROOT ${CMAKE_CURRENT_SOURCE_DIR} - CLASS "Source Files" - TARGETS ${sources}) diff --git a/libs/preprocessor/src/preprocessor.cpp b/libs/preprocessor/src/preprocessor.cpp deleted file mode 100644 index 9c40fbce587b..000000000000 --- a/libs/preprocessor/src/preprocessor.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2019 STE||AR Group -// -// 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 - -/////////////////////////////////////////////////////////////////////////////// -namespace hpx { namespace preprocessor -{ - void force_linking() {} -}} From ba255de2859437c5ac91d2fbc7e20f7aae4a4f66 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 28 Jun 2019 15:00:37 +0200 Subject: [PATCH 08/11] Change header test names back to tests.headers.headers in CircleCI config --- .circleci/config.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 98e4985a7e16..360163a6973c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -869,7 +869,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.compat + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.compat - run: <<: *convert_xml - store_test_results: @@ -885,7 +885,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.components + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.components - run: <<: *convert_xml - store_test_results: @@ -901,7 +901,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.compute + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.compute - run: <<: *convert_xml - store_test_results: @@ -917,7 +917,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.config + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.config - run: <<: *convert_xml - store_test_results: @@ -933,7 +933,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.include + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.include - run: <<: *convert_xml - store_test_results: @@ -949,7 +949,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.lcos + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.lcos - run: <<: *convert_xml - store_test_results: @@ -965,7 +965,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.parallel + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.parallel - run: <<: *convert_xml - store_test_results: @@ -981,7 +981,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.performance_counters + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.performance_counters - run: <<: *convert_xml - store_test_results: @@ -997,7 +997,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.plugins + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.plugins - run: <<: *convert_xml - store_test_results: @@ -1013,7 +1013,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.runtime + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.runtime - run: <<: *convert_xml - store_test_results: @@ -1029,7 +1029,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.traits + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.traits - run: <<: *convert_xml - store_test_results: @@ -1045,7 +1045,7 @@ jobs: - run: name: Building Header Tests command: | - ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.util + ctest -j2 -T test --no-compress-output --output-on-failure -R tests.headers.headers.util - run: <<: *convert_xml - store_test_results: From d767b6a97bfe79df68e540dff2d99ea997ee70db Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 28 Jun 2019 17:39:31 +0200 Subject: [PATCH 09/11] Add missing force_linking.hpp header to config module --- libs/config/CMakeLists.txt | 1 + libs/config/include/hpx/config/force_linking.hpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 libs/config/include/hpx/config/force_linking.hpp diff --git a/libs/config/CMakeLists.txt b/libs/config/CMakeLists.txt index a0c0d4ed8130..70ad7a369a2e 100644 --- a/libs/config/CMakeLists.txt +++ b/libs/config/CMakeLists.txt @@ -21,6 +21,7 @@ set(config_headers hpx/config/debug.hpp hpx/config/emulate_deleted.hpp hpx/config/export_definitions.hpp + hpx/config/force_linking.hpp hpx/config/forceinline.hpp hpx/config/lambda_capture.hpp hpx/config/manual_profiling.hpp diff --git a/libs/config/include/hpx/config/force_linking.hpp b/libs/config/include/hpx/config/force_linking.hpp new file mode 100644 index 000000000000..21125c1072f2 --- /dev/null +++ b/libs/config/include/hpx/config/force_linking.hpp @@ -0,0 +1,14 @@ +// Copyright (c) 2019 The STE||AR GROUP +// +// 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) + +#if !defined(HPX_CONFIG_FORCE_LINKING_HPP) +#define HPX_CONFIG_FORCE_LINKING_HPP + +namespace hpx { namespace config +{ + void force_linking(); +}} + +#endif From 0187188b77358f8c444b1ab516c8e35e7de18859 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Fri, 28 Jun 2019 10:51:13 -0500 Subject: [PATCH 10/11] Explicitly reference symbols to re-export --- libs/config/CMakeLists.txt | 1 + .../include/hpx/config/force_linking.hpp | 8 +++++++- libs/config/src/force_linking.cpp | 20 +++++++++++++++++++ libs/config/src/version.cpp | 6 ------ 4 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 libs/config/src/force_linking.cpp diff --git a/libs/config/CMakeLists.txt b/libs/config/CMakeLists.txt index 70ad7a369a2e..93926595f9f5 100644 --- a/libs/config/CMakeLists.txt +++ b/libs/config/CMakeLists.txt @@ -33,6 +33,7 @@ set(config_headers # Default location is $HPX_ROOT/libs/config/src set(config_sources + force_linking.cpp version.cpp ) diff --git a/libs/config/include/hpx/config/force_linking.hpp b/libs/config/include/hpx/config/force_linking.hpp index 21125c1072f2..3580fb02c895 100644 --- a/libs/config/include/hpx/config/force_linking.hpp +++ b/libs/config/include/hpx/config/force_linking.hpp @@ -8,7 +8,13 @@ namespace hpx { namespace config { - void force_linking(); + struct force_linking_helper + { + const char* const hpx_version; + const char* const boost_version; + }; + + force_linking_helper& force_linking(); }} #endif diff --git a/libs/config/src/force_linking.cpp b/libs/config/src/force_linking.cpp new file mode 100644 index 000000000000..86ef2c2dc7ac --- /dev/null +++ b/libs/config/src/force_linking.cpp @@ -0,0 +1,20 @@ +// Copyright (c) 2019 The STE||AR GROUP +// +// 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 + +namespace hpx { namespace config +{ + // reference all symbols that have to be explicitly linked with the core + // library + force_linking_helper& force_linking() + { + static force_linking_helper helper{ + hpx::HPX_CHECK_VERSION, hpx::HPX_CHECK_BOOST_VERSION}; + return helper; + } +}} + diff --git a/libs/config/src/version.cpp b/libs/config/src/version.cpp index e0f8fba3981d..54a0ab2d62c6 100644 --- a/libs/config/src/version.cpp +++ b/libs/config/src/version.cpp @@ -7,7 +7,6 @@ //////////////////////////////////////////////////////////////////////////////// #include -#include #include #include @@ -18,9 +17,4 @@ namespace hpx HPX_PP_STRINGIZE(HPX_CHECK_VERSION); HPX_EXPORT char const HPX_CHECK_BOOST_VERSION[] = HPX_PP_STRINGIZE(HPX_CHECK_BOOST_VERSION); - - namespace config - { - void force_linking() {} - } } From b8e4d91d1650aced889128c8f26892b8f01f68b7 Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser Date: Fri, 28 Jun 2019 12:29:00 -0500 Subject: [PATCH 11/11] Setting POSITION_INDEPENDENT_CODE=ON for all modules --- cmake/HPX_AddModule.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/HPX_AddModule.cmake b/cmake/HPX_AddModule.cmake index 24a8ec44df32..6cd4861f6874 100644 --- a/cmake/HPX_AddModule.cmake +++ b/cmake/HPX_AddModule.cmake @@ -199,7 +199,8 @@ function(add_hpx_module name) endif() set_target_properties(hpx_${name} PROPERTIES - FOLDER "Core/Modules") + FOLDER "Core/Modules" + POSITION_INDEPENDENT_CODE ON) if(${name}_INSTALL_BINARIES) install(TARGETS hpx_${name} EXPORT HPXTargets