From 56fd46be77bc2164b603bd9e300655a1e391759a Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser <hartmut.kaiser@gmail.com> Date: Sat, 5 Oct 2024 15:09:15 -0500 Subject: [PATCH] Enable variable partition sizes for partitioned_vector --- .github/CONTRIBUTING.md | 10 +- cmake/HPX_SetupNanobench.cmake | 6 + .../partitioned_vector/CMakeLists.txt | 2 +- .../partitioned_vector_component_decl.hpp | 72 ++++- .../partitioned_vector_component_impl.hpp | 105 +++++-- .../partitioned_vector_decl.hpp | 297 +++++++++++++----- .../partitioned_vector_impl.hpp | 153 +++++---- .../partitioned_vector_predef.hpp | 29 +- .../partitioned_vector_segmented_iterator.hpp | 284 ++++++++++------- .../serialization/partitioned_vector.hpp | 119 +++++++ .../hpx/include/partitioned_vector.hpp | 4 +- .../hpx/include/partitioned_vector_predef.hpp | 6 +- .../serialization/partitioned_vector.hpp | 39 --- .../partitioned_vector_component_double.cpp | 7 + .../src/partitioned_vector_component_int.cpp | 13 + ...artitioned_vector_component_std_string.cpp | 7 + .../unit/serialization_partitioned_vector.cpp | 25 +- .../containers/unordered/unordered_map.hpp | 4 +- .../hpx/datastructures/member_pack.hpp | 2 +- libs/core/functional/CMakeLists.txt | 1 + .../hpx/functional/reference_wrapper.hpp | 60 ++++ .../hpx/iterator_support/iterator_facade.hpp | 34 +- libs/core/testing/src/performance.cpp | 4 +- .../hpx/actions_base/component_action.hpp | 3 +- .../traits/is_distribution_policy.hpp | 32 ++ .../transfer_continuation_action.hpp | 12 +- .../host/target_distribution_policy.hpp | 7 +- .../full/distribution_policies/CMakeLists.txt | 1 + .../binpacking_distribution_policy.hpp | 14 +- .../colocating_distribution_policy.hpp | 67 +++- .../container_distribution_policy.hpp | 90 ++++-- .../default_distribution_policy.hpp | 46 +-- ...explicit_container_distribution_policy.hpp | 160 ++++++++++ .../target_distribution_policy.hpp | 4 +- libs/full/naming/src/credit_handling.cpp | 10 +- .../create_component_helpers.hpp | 23 +- .../include/hpx/runtime_components/new.hpp | 4 +- .../runtime_distributed/runtime_support.hpp | 36 +-- .../server/runtime_support.hpp | 57 ++-- .../stubs/runtime_support.hpp | 18 +- .../segmented_algorithms/all_any_none.hpp | 9 +- .../segmented_algorithms/for_each.hpp | 64 ++-- .../unit/partitioned_vector_for_each.cpp | 88 ++++-- .../partitioned_vector_inclusive_scan.cpp | 9 +- 44 files changed, 1454 insertions(+), 583 deletions(-) create mode 100644 components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp delete mode 100644 components/containers/partitioned_vector/include/hpx/runtime/serialization/partitioned_vector.hpp create mode 100644 libs/core/functional/include/hpx/functional/reference_wrapper.hpp create mode 100644 libs/full/distribution_policies/include/hpx/distribution_policies/explicit_container_distribution_policy.hpp diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 6278ac283b68..244715d3c14a 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,4 +1,4 @@ -<!-- Copyright (c) 2014-2022 Hartmut Kaiser --> +<!-- Copyright (c) 2014-2024 Hartmut Kaiser --> <!-- --> <!-- SPDX-License-Identifier: BSL-1.0 --> <!-- Distributed under the Boost Software License, Version 1.0. (See accompanying --> @@ -19,10 +19,10 @@ i.e. pull requests. The easiest ways to get in contact with us are listed here: -* Mailing list: [hpx-users@stellar-group.org](email:hpx-users@stellar-group.org), [hpx-devel@stellar-group.org](email:hpx-devel@stellar-group.org) -* IRC channel: #ste||ar on Libra.Chat -* Blog: [hpx.stellar-group.org](hpx.stellar-group.org) -* More options: See our [support page](https://github.com/STEllAR-GROUP/hpx/blob/master/.github/SUPPORT.md) +* Mailing list: [hpx-users@stellar-group.org](email:hpx-users@stellar-group.org), [hpx-devel@stellar-group.org](email:hpx-devel@stellar-group.org) +* Discord server: [#ste||ar](https://discord.gg/Tn9QuzVjvy) +* Blog: [hpx.stellar-group.org](hpx.stellar-group.org) +* More options: See our [support page](https://github.com/STEllAR-GROUP/hpx/blob/master/.github/SUPPORT.md) The basic approach is to find something fun you want to fix, hack it up, and send a `git diff` as a mail attachment to [hpx-devel@stellar-group.org](email:hpx-devel@stellar-group.org) diff --git a/cmake/HPX_SetupNanobench.cmake b/cmake/HPX_SetupNanobench.cmake index 14ba9880a209..431e0ea9bf18 100644 --- a/cmake/HPX_SetupNanobench.cmake +++ b/cmake/HPX_SetupNanobench.cmake @@ -1,3 +1,9 @@ +# Copyright (c) 2024 Hartmut Kaiser +# +# SPDX-License-Identifier: BSL-1.0 +# 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(FetchContent) fetchcontent_declare( diff --git a/components/containers/partitioned_vector/CMakeLists.txt b/components/containers/partitioned_vector/CMakeLists.txt index c0aa1f2433fc..2a4e8a5da088 100644 --- a/components/containers/partitioned_vector/CMakeLists.txt +++ b/components/containers/partitioned_vector/CMakeLists.txt @@ -30,10 +30,10 @@ set(partitioned_vector_headers hpx/components/containers/partitioned_vector/partitioned_vector_segmented_iterator.hpp hpx/components/containers/partitioned_vector/partitioned_vector_view.hpp hpx/components/containers/partitioned_vector/partitioned_vector_view_iterator.hpp + hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp hpx/include/partitioned_vector.hpp hpx/include/partitioned_vector_predef.hpp hpx/include/partitioned_vector_view.hpp - hpx/runtime/serialization/partitioned_vector.hpp ) set(partitioned_vector_sources diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp index 9d3f7ea7daf5..785ef1076d20 100644 --- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp @@ -24,6 +24,7 @@ #include <hpx/components/client_base.hpp> #include <hpx/components_base/server/component_base.hpp> #include <hpx/components_base/server/locking_hook.hpp> +#include <hpx/functional/invoke_result.hpp> #include <hpx/preprocessor/cat.hpp> #include <hpx/preprocessor/expand.hpp> #include <hpx/preprocessor/nargs.hpp> @@ -39,11 +40,33 @@ #include <hpx/config/warnings_prefix.hpp> +namespace hpx::detail { + + HPX_HAS_XXX_TRAIT_DEF(allocator_type); + + template <typename T, typename Data, typename Enable = void> + struct extract_allocator_type + { + using type = std::allocator<T>; + }; + + template <typename T, typename Data> + struct extract_allocator_type<T, Data, + std::enable_if_t<has_allocator_type_v<Data>>> + { + using type = typename Data::allocator_type; + }; + + template <typename T, typename Data> + using extract_allocator_type_t = + typename extract_allocator_type<T, Data>::type; +} // namespace hpx::detail + namespace hpx::server { /// \brief This is the basic wrapper class for stl vector. /// - /// This contains the implementation of the partitioned_vector_partition's + /// This contains the implementation of the partitioned_vector partition's /// component functionality. template <typename T, typename Data> class partitioned_vector @@ -53,7 +76,7 @@ namespace hpx::server { public: using data_type = Data; - using allocator_type = typename data_type::allocator_type; + using allocator_type = hpx::detail::extract_allocator_type_t<T, Data>; using size_type = typename data_type::size_type; using iterator_type = typename data_type::iterator; using const_iterator_type = typename data_type::const_iterator; @@ -71,7 +94,9 @@ namespace hpx::server { /// size 0. partitioned_vector(); - explicit partitioned_vector(size_type partition_size); + explicit partitioned_vector(std::size_t partnum, + std::vector<size_type> const& partition_sizes, + traits::create_mode = traits::create_mode::resize); /// Constructor which create and initialize partitioned_vector_partition /// with all elements as \a val. @@ -79,9 +104,11 @@ namespace hpx::server { /// param partition_size The size of vector /// param val Default value for the elements in partitioned_vector_partition /// - partitioned_vector(size_type partition_size, T const& val); + partitioned_vector(std::size_t partnum, + std::vector<size_type> const& partition_sizes, T const& val); - partitioned_vector(size_type partition_size, T const& val, + partitioned_vector(std::size_t partnum, + std::vector<size_type> const& partition_sizes, T const& val, allocator_type const& alloc); // support components::copy @@ -274,13 +301,31 @@ namespace hpx::server { // HPX_DEFINE_COMPONENT_ACTION(partitioned_vector_partition, clear) HPX_DEFINE_COMPONENT_DIRECT_ACTION(partitioned_vector, get_copied_data) HPX_DEFINE_COMPONENT_DIRECT_ACTION(partitioned_vector, set_data) + + /// Invoke given function on given element + /// + /// \return This returns whatever the given function invocation returns + template <typename F, typename... Ts> + util::invoke_result_t<F, T, Ts...> apply( + std::size_t pos, F f, Ts... ts); + + template <typename F, typename... Ts> + struct apply_action + : hpx::actions::make_action_t< + decltype(&partitioned_vector::apply<F, Ts...>), + &partitioned_vector::apply<F, Ts...>, apply_action<F, Ts...>> + { + }; }; } // namespace hpx::server /////////////////////////////////////////////////////////////////////////////// +#if 0 +#define HPX_REGISTER_PARTITIONED_VECTOR_DECLARATION(...) +#else #define HPX_REGISTER_PARTITIONED_VECTOR_DECLARATION(...) \ HPX_REGISTER_VECTOR_DECLARATION_(__VA_ARGS__) \ -/**/ + /**/ #define HPX_REGISTER_VECTOR_DECLARATION_(...) \ HPX_PP_EXPAND(HPX_PP_CAT(HPX_REGISTER_VECTOR_DECLARATION_, \ HPX_PP_NARGS(__VA_ARGS__))(__VA_ARGS__)) \ @@ -307,16 +352,17 @@ namespace hpx::server { #define HPX_REGISTER_VECTOR_DECLARATION_1(type) \ HPX_REGISTER_VECTOR_DECLARATION_2(type, std::vector<type>) \ -/**/ + /**/ #define HPX_REGISTER_VECTOR_DECLARATION_2(type, data) \ HPX_REGISTER_VECTOR_DECLARATION_3(type, data, type) \ -/**/ + /**/ #define HPX_REGISTER_VECTOR_DECLARATION_3(type, data, name) \ typedef ::hpx::server::partitioned_vector<type, data> HPX_PP_CAT( \ __partitioned_vector_, HPX_PP_CAT(type, name)); \ HPX_REGISTER_VECTOR_DECLARATION_IMPL( \ HPX_PP_CAT(__partitioned_vector_, HPX_PP_CAT(type, name)), name) \ /**/ +#endif namespace hpx { @@ -559,8 +605,7 @@ namespace hpx { /// hpx::future<typename server_type::data_type> get_copied_data() const; - /// Updates the data owned by the partition_vector - /// component. + /// Updates the data owned by the partition_vector component. /// /// \return This returns the data of the partition_vector /// @@ -574,6 +619,13 @@ namespace hpx { /// hpx::future<void> set_data( typename server_type::data_type&& other) const; + + /// Invoke given function on given element + /// + /// \return This returns whatever the given function invocation returns + template <typename F, typename... Ts> + hpx::future<util::invoke_result_t<F, T, Ts...>> apply( + std::size_t pos, F&& f, Ts&&... ts); }; } // namespace hpx diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_impl.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_impl.hpp index dd011ba4738f..4ff99e4f6ce2 100644 --- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_impl.hpp +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_component_impl.hpp @@ -37,24 +37,33 @@ namespace hpx::server { template <typename T, typename Data> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT - partitioned_vector<T, Data>::partitioned_vector(size_type partition_size) - : partitioned_vector_partition_(partition_size) + partitioned_vector<T, Data>::partitioned_vector(std::size_t partnum, + std::vector<size_type> const& partition_sizes, traits::create_mode mode) { + if (mode == traits::create_mode::resize) + { + partitioned_vector_partition_.resize(partition_sizes[partnum]); + } + else + { + partitioned_vector_partition_.reserve(partition_sizes[partnum]); + } } template <typename T, typename Data> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT - partitioned_vector<T, Data>::partitioned_vector( - size_type partition_size, T const& val) - : partitioned_vector_partition_(partition_size, val) + partitioned_vector<T, Data>::partitioned_vector(std::size_t partnum, + std::vector<size_type> const& partition_sizes, T const& val) + : partitioned_vector_partition_(partition_sizes[partnum], val) { } template <typename T, typename Data> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT - partitioned_vector<T, Data>::partitioned_vector( - size_type partition_size, T const& val, allocator_type const& alloc) - : partitioned_vector_partition_(partition_size, val, alloc) + partitioned_vector<T, Data>::partitioned_vector(std::size_t partnum, + std::vector<size_type> const& partition_sizes, T const& val, + allocator_type const& alloc) + : partitioned_vector_partition_(partition_sizes[partnum], val, alloc) { } @@ -266,12 +275,20 @@ namespace hpx::server { { partitioned_vector_partition_.clear(); } + + template <typename T, typename Data> + template <typename F, typename... Ts> + HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT + util::invoke_result_t<F, T, Ts...> + partitioned_vector<T, Data>::apply(std::size_t pos, F f, Ts... ts) + { + return HPX_INVOKE( + HPX_MOVE(f), partitioned_vector_partition_[pos], HPX_MOVE(ts)...); + } } // namespace hpx::server /////////////////////////////////////////////////////////////////////////////// -#define HPX_REGISTER_PARTITIONED_VECTOR(...) \ - HPX_REGISTER_VECTOR_(__VA_ARGS__) \ -/**/ +#define HPX_REGISTER_PARTITIONED_VECTOR(...) HPX_REGISTER_VECTOR_(__VA_ARGS__) #define HPX_REGISTER_VECTOR_(...) \ HPX_PP_EXPAND(HPX_PP_CAT(HPX_REGISTER_VECTOR_, HPX_PP_NARGS(__VA_ARGS__))( \ __VA_ARGS__)) \ @@ -294,6 +311,9 @@ namespace hpx::server { HPX_PP_CAT(__vector_get_copied_data_action_, name)) \ HPX_REGISTER_ACTION( \ type::set_data_action, HPX_PP_CAT(__vector_set_data_action_, name)) \ + /**/ + +#define HPX_REGISTER_VECTOR_COMPONENT_IMPL(type, name) \ typedef ::hpx::components::component<type> HPX_PP_CAT(__vector_, name); \ HPX_REGISTER_COMPONENT(HPX_PP_CAT(__vector_, name)) \ /**/ @@ -301,16 +321,28 @@ namespace hpx::server { #define HPX_REGISTER_VECTOR_1(type) \ HPX_REGISTER_VECTOR_3( \ type, std::vector<type>, HPX_PP_CAT(std_vector_, type)) \ -/**/ + /**/ #define HPX_REGISTER_VECTOR_2(type, data) \ HPX_REGISTER_VECTOR_3(type, data, HPX_PP_CAT(type, data)) \ -/**/ + /**/ + +#if 0 +#define HPX_REGISTER_VECTOR_3(type, data, name) \ + typedef ::hpx::server::partitioned_vector<type, data> HPX_PP_CAT( \ + __partitioned_vector_, HPX_PP_CAT(type, name)); \ + HPX_REGISTER_VECTOR_COMPONENT_IMPL( \ + HPX_PP_CAT(__partitioned_vector_, HPX_PP_CAT(type, name)), name) \ + /**/ +#else #define HPX_REGISTER_VECTOR_3(type, data, name) \ typedef ::hpx::server::partitioned_vector<type, data> HPX_PP_CAT( \ __partitioned_vector_, HPX_PP_CAT(type, name)); \ HPX_REGISTER_VECTOR_IMPL( \ HPX_PP_CAT(__partitioned_vector_, HPX_PP_CAT(type, name)), name) \ + HPX_REGISTER_VECTOR_COMPONENT_IMPL( \ + HPX_PP_CAT(__partitioned_vector_, HPX_PP_CAT(type, name)), name) \ /**/ +#endif namespace hpx { @@ -346,7 +378,7 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async<typename server_type::size_action>(this->get_id()); + return hpx::async(typename server_type::size_action(), this->get_id()); #else HPX_ASSERT(false); return hpx::make_ready_future(std::size_t{}); @@ -375,8 +407,8 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async<typename server_type::resize_action>( - this->get_id(), n, val); + return hpx::async( + typename server_type::resize_action(), this->get_id(), n, val); #else HPX_ASSERT(false); return hpx::make_ready_future(); @@ -398,8 +430,8 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async<typename server_type::get_value_action>( - this->get_id(), pos); + return hpx::async( + typename server_type::get_value_action(), this->get_id(), pos); #else HPX_ASSERT(false); return hpx::future<T>{}; @@ -421,8 +453,8 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async<typename server_type::get_values_action>( - this->get_id(), pos); + return hpx::async( + typename server_type::get_values_action(), this->get_id(), pos); #else HPX_ASSERT(false); return hpx::make_ready_future(std::vector<T>{}); @@ -452,7 +484,7 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async<typename server_type::set_value_action>( + return hpx::async(typename server_type::set_value_action(), this->get_id(), pos, HPX_MOVE(val)); #else HPX_ASSERT(false); @@ -467,8 +499,8 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async<typename server_type::set_value_action>( - this->get_id(), pos, val); + return hpx::async( + typename server_type::set_value_action(), this->get_id(), pos, val); #else HPX_ASSERT(false); return hpx::make_ready_future(); @@ -491,7 +523,7 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async<typename server_type::set_values_action>( + return hpx::async(typename server_type::set_values_action(), this->get_id(), pos, val); #else HPX_ASSERT(false); @@ -515,8 +547,8 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async<typename server_type::get_copied_data_action>( - this->get_id()); + return hpx::async( + typename server_type::get_copied_data_action(), this->get_id()); #else HPX_ASSERT(false); return hpx::make_ready_future(typename partitioned_vector_partition<T, @@ -539,11 +571,30 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async<typename server_type::set_data_action>( + return hpx::async(typename server_type::set_data_action(), this->get_id(), HPX_MOVE(other)); #else HPX_ASSERT(false); return hpx::make_ready_future(); +#endif + } + + template <typename T, typename Data /*= std::vector<T> */> + template <typename F, typename... Ts> + HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT + hpx::future<util::invoke_result_t<F, T, Ts...>> + partitioned_vector_partition<T, Data>::apply( + [[maybe_unused]] std::size_t pos, [[maybe_unused]] F&& f, + [[maybe_unused]] Ts&&... ts) + { +#if !defined(HPX_COMPUTE_DEVICE_CODE) + HPX_ASSERT(this->get_id()); + return hpx::async( + typename server_type::template apply_action<F, Ts...>(), + this->get_id(), pos, HPX_FORWARD(F, f), HPX_FORWARD(Ts, ts)...); +#else + HPX_ASSERT(false); + return hpx::make_ready_future(util::invoke_result_t<F&&, Ts&&...>()); #endif } } // namespace hpx diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp index c4e582c086c4..c645ac2801b3 100644 --- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp @@ -16,10 +16,12 @@ #include <hpx/async_combinators/when_all.hpp> #include <hpx/components/client_base.hpp> #include <hpx/distribution_policies/container_distribution_policy.hpp> -#include <hpx/modules/errors.hpp> +#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp> +#include <hpx/functional/reference_wrapper.hpp> #include <hpx/runtime_components/distributed_metadata_base.hpp> #include <hpx/runtime_components/new.hpp> #include <hpx/runtime_distributed/copy_component.hpp> +#include <hpx/type_support/identity.hpp> #include <hpx/components/containers/partitioned_vector/export_definitions.hpp> #include <hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp> @@ -50,9 +52,10 @@ namespace hpx::server { { partition_data() = default; - partition_data(id_type const& part, std::size_t size, - std::uint32_t locality_id) + partition_data(id_type const& part, std::size_t first, + std::size_t size, std::uint32_t locality_id) : partition_(part) + , first_(first) , size_(size) , locality_id_(locality_id) { @@ -64,6 +67,7 @@ namespace hpx::server { } hpx::id_type partition_; + std::size_t first_ = 0; std::size_t size_ = 0; std::uint32_t locality_id_ = naming::invalid_locality_id; @@ -73,7 +77,9 @@ namespace hpx::server { template <typename Archive> void serialize(Archive& ar, unsigned) { - ar & partition_ & size_ & locality_id_; + // clang-format off + ar & partition_ & first_ & size_ & locality_id_; + // clang-format on } }; @@ -107,6 +113,7 @@ HPX_DISTRIBUTED_METADATA_DECLARATION( /// \endcond namespace hpx { + /// hpx::partitioned_vector is a sequence container that encapsulates /// dynamic size arrays. /// @@ -145,7 +152,7 @@ namespace hpx { server::partitioned_vector_config_data>> { public: - using allocator_type = typename Data::allocator_type; + using allocator_type = detail::extract_allocator_type_t<T, Data>; using size_type = typename Data::size_type; using difference_type = typename Data::difference_type; @@ -155,8 +162,8 @@ namespace hpx { using const_reference = T const; #if defined(HPX_NATIVE_MIC) - typedef T* pointer; - typedef T const* const_pointer; + using pointer = T*; + using const_pointer = T const*; #else using pointer = typename std::allocator_traits<allocator_type>::pointer; using const_pointer = @@ -173,6 +180,8 @@ namespace hpx { using partitioned_vector_partition_client = hpx::partitioned_vector_partition<T, Data>; + using create_mode = traits::create_mode; + struct partition_data : server::partitioned_vector_config_data::partition_data { @@ -181,9 +190,9 @@ namespace hpx { partition_data() = default; - partition_data(id_type const& part, std::size_t size, - std::uint32_t locality_id) - : base_type(part, size, locality_id) + partition_data(id_type const& part, std::size_t first, + std::size_t size, std::uint32_t locality_id) + : base_type(part, first, size, locality_id) { } @@ -200,8 +209,7 @@ namespace hpx { // size, and locality id. using partitions_vector_type = std::vector<partition_data>; - size_type size_; // overall size of the vector - size_type partition_size_; // cached partition size + size_type size_; // overall size of the vector // This is the vector representing the base_index and corresponding // global ID's of the underlying partitioned_vector_partitions. @@ -230,6 +238,8 @@ namespace hpx { segmented::local_segment_vector_iterator<T, Data, typename partitions_vector_type::const_iterator>; + using partition_data_type = partition_data; + private: friend class segmented::vector_iterator<T, Data>; friend class segmented::const_vector_iterator<T, Data>; @@ -239,15 +249,15 @@ namespace hpx { friend class segmented::const_segment_vector_iterator<T, Data, typename partitions_vector_type::const_iterator>; - std::size_t get_partition_size() const; - std::size_t get_global_index(std::size_t segment, std::size_t part_size, - size_type local_index) const; + std::size_t get_partition_size(std::size_t partnum) const; + std::size_t get_global_index_part( + std::size_t partnum, size_type local_index) const; /////////////////////////////////////////////////////////////////////// // Connect this vector to the existing vector using the given symbolic // name. void get_data_helper( - id_type id, server::partitioned_vector_config_data data); + id_type id, server::partitioned_vector_config_data&& data); // this will be called by the base class once the registered id becomes // available @@ -266,13 +276,13 @@ namespace hpx { partitioned_vector(future<id_type>&& f); public: - // Return the sequence number of the segment corresponding to the - // given global index + // Return the sequence number of the segment corresponding to the given + // global index std::size_t get_partition(size_type global_index) const; - // Return the local index inside the segment corresponding to the - // given global index - std::size_t get_local_index(size_type global_index) const; + // Return the local index inside the given segment + std::size_t get_local_index( + size_type partnum, size_type global_index) const; // Return the local indices inside the segment corresponding to the // given global indices @@ -285,15 +295,8 @@ namespace hpx { std::size_t get_global_index( SegmentIter const& it, size_type local_index) const { - std::size_t part_size = partition_size_; - if (part_size == static_cast<std::size_t>(-1) || part_size == 0) - return size_; - - std::size_t segment = it.base() - partitions_.cbegin(); - if (segment == partitions_.size()) - return size_; - - return get_global_index(segment, part_size, local_index); + return get_global_index_part( + it.base() - partitions_.cbegin(), local_index); } template <typename SegmentIter> @@ -308,8 +311,8 @@ namespace hpx { const_local_iterator get_const_local_iterator( size_type global_index) const; - // Return the segment iterator referencing a segment based on the - // given global index. + // Return the segment iterator referencing a segment based on the given + // global index. segment_iterator get_segment_iterator(size_type global_index); const_segment_iterator get_const_segment_iterator( size_type global_index) const; @@ -322,19 +325,21 @@ namespace hpx { template <typename DistPolicy> static hpx::future<std::vector<bulk_locality_result>> create_helper1( - DistPolicy const& policy, std::size_t count, std::size_t size); + DistPolicy const& policy, std::size_t count, + std::vector<std::size_t> const& sizes, create_mode mode); template <typename DistPolicy> static hpx::future<std::vector<bulk_locality_result>> create_helper2( - DistPolicy const& policy, std::size_t count, std::size_t size, - T const& val); + DistPolicy const& policy, std::size_t count, + std::vector<std::size_t> const& sizes, T const& val); struct get_ptr_helper; // This function is called when we are creating the vector. It // initializes the partitions based on the give parameters. template <typename DistPolicy, typename Create> - void create(DistPolicy const& policy, Create&& creator); + void create(DistPolicy const& policy, Create&& creator, + create_mode mode = create_mode::resize); template <typename DistPolicy> void create(DistPolicy const& policy); @@ -345,21 +350,46 @@ namespace hpx { // Perform a deep copy from the given vector void copy_from(partitioned_vector const& rhs); + enum class take_ref + { + yes = 0 + }; + + partitioned_vector(partitioned_vector const& rhs, take_ref) + : base_type(rhs.get_id()) + , size_(rhs.size_) + { + } + + explicit partitioned_vector(hpx::id_type id, std::size_t size, + partitions_vector_type&& partitions) + : base_type(HPX_MOVE(id)) + , size_(size) + , partitions_(partitions) + { + } + public: - /// Default Constructor which create hpx::partitioned_vector with + static partitioned_vector create_from(hpx::id_type id, std::size_t size, + partitions_vector_type&& partitions) + { + return partitioned_vector(HPX_MOVE(id), size, HPX_MOVE(partitions)); + } + + /// Default Constructor which creates hpx::partitioned_vector with /// \a num_partitions = 0 and \a partition_size = 0. Hence, the overall /// size of the vector is 0. /// partitioned_vector(); - /// Constructor which create hpx::partitioned_vector with the given + /// Constructor which creates hpx::partitioned_vector with the given /// overall \a size /// /// \param size The overall size of the vector /// explicit partitioned_vector(size_type size); - /// Constructor which create and initialize vector with the given + /// Constructor which creates and initializes vector with the given /// \a where all elements are initialized with \a val. /// /// \param size The overall size of the vector @@ -369,8 +399,20 @@ namespace hpx { /// partitioned_vector(size_type size, T const& val); - /// Constructor which create and initialize vector of \a size using the - /// given distribution policy. + /// Constructor which creates vector of \a size using the given + /// distribution policy. + /// + /// \param policy The distribution policy to use + /// \param symbolic_name The (optional) name to register the newly + /// created vector + /// + template <typename DistPolicy> + explicit partitioned_vector(DistPolicy const& policy, + std::enable_if_t<traits::is_distribution_policy_v<DistPolicy>>* = + nullptr); + + /// Constructor which creates and initializes vector of \a size using + /// the given distribution policy. /// /// \param size The overall size of the vector /// \param policy The distribution policy to use @@ -379,12 +421,12 @@ namespace hpx { /// template <typename DistPolicy> partitioned_vector(size_type size, DistPolicy const& policy, - std::enable_if_t< - traits::is_distribution_policy<DistPolicy>::value>* = nullptr); + std::enable_if_t<traits::is_distribution_policy_v<DistPolicy>>* = + nullptr); - /// Constructor which create and initialize vector with the - /// given \a where all elements are initialized with \a val and - /// using the given distribution policy. + /// Constructor which creates and initializes vector of \a size, where + /// all elements are initialized with \a val and using the given + /// distribution policy. /// /// \param size The overall size of the vector /// \param val Default value for the elements in vector @@ -395,8 +437,8 @@ namespace hpx { template <typename DistPolicy> partitioned_vector(size_type size, T const& val, DistPolicy const& policy, - std::enable_if_t< - traits::is_distribution_policy<DistPolicy>::value>* = nullptr); + std::enable_if_t<traits::is_distribution_policy_v<DistPolicy>>* = + nullptr); /// Copy construction performs a deep copy of the right hand side /// vector. @@ -411,11 +453,9 @@ namespace hpx { partitioned_vector(partitioned_vector&& rhs) noexcept : base_type(HPX_MOVE(rhs)) , size_(rhs.size_) - , partition_size_(rhs.partition_size_) , partitions_(HPX_MOVE(rhs.partitions_)) { rhs.size_ = 0; - rhs.partition_size_ = static_cast<std::size_t>(-1); } public: @@ -469,15 +509,19 @@ namespace hpx { this->base_type::operator=(static_cast<base_type&&>(rhs)); size_ = rhs.size_; - partition_size_ = rhs.partition_size_; partitions_ = HPX_MOVE(rhs.partitions_); rhs.size_ = 0; - rhs.partition_size_ = static_cast<std::size_t>(-1); } return *this; } + // Create reference to rhs partitioned vector + partitioned_vector ref() const + { + return partitioned_vector(*this, take_ref::yes); + } + /////////////////////////////////////////////////////////////////////// // Capacity related APIs in vector class @@ -490,6 +534,15 @@ namespace hpx { return size_; } + /// \brief Compute the information about the underlying partitions. + /// + /// \return Return the partitions + /// + partitions_vector_type partitions() const + { + return partitions_; + } + // // Element access APIs in vector class // @@ -503,8 +556,8 @@ namespace hpx { /// T get_value(launch::sync_policy, size_type pos) const { - return get_value( - launch::sync, get_partition(pos), get_local_index(pos)); + auto part = get_partition(pos); + return get_value(launch::sync, part, get_local_index(part, pos)); } /// Returns the element at position \a pos in the vector container. @@ -519,7 +572,9 @@ namespace hpx { { partition_data const& part_data = partitions_[part]; if (part_data.local_data_) + { return part_data.local_data_->get_value(pos); + } return partitioned_vector_partition_client(part_data.partition_) .get_value(launch::sync, pos); @@ -535,7 +590,8 @@ namespace hpx { /// future<T> get_value(size_type pos) const { - return get_value(get_partition(pos), get_local_index(pos)); + auto part = get_partition(pos); + return get_value(part, get_local_index(part, pos)); } /// Returns the element at position \a pos in the given partition in @@ -837,8 +893,9 @@ namespace hpx { template <typename T_> void set_value(launch::sync_policy, size_type pos, T_&& val) { - return set_value(launch::sync, get_partition(pos), - get_local_index(pos), HPX_FORWARD(T_, val)); + auto part = get_partition(pos); + return set_value(launch::sync, part, get_local_index(part, pos), + HPX_FORWARD(T_, val)); } /// Copy the value of \a val in the element at position \a pos in @@ -876,8 +933,9 @@ namespace hpx { template <typename T_> future<void> set_value(size_type pos, T_&& val) { + auto part = get_partition(pos); return set_value( - get_partition(pos), get_local_index(pos), HPX_FORWARD(T_, val)); + part, get_local_index(part, pos), HPX_FORWARD(T_, val)); } /// Asynchronously set the element at position \a pos in @@ -990,21 +1048,19 @@ namespace hpx { // if the partition of the current position is NOT the same // as the positions before the block ends here - else - { - // this is the end of a block containing indexes ('pos') - // of the same partition ('part'). - // set asynchronous values for this block - part_futures.push_back(set_values(part_cur, - get_local_indices( - std::vector<size_type>(pos_block_begin, pos_it)), - std::vector<T>(val_block_begin, val_it))); - - // reset block variables to start a new one from here - part_cur = part; - pos_block_begin = pos_it; - val_block_begin = val_it; - } + + // this is the end of a block containing indexes ('pos') + // of the same partition ('part'). + // set asynchronous values for this block + part_futures.push_back(set_values(part_cur, + get_local_indices( + std::vector<size_type>(pos_block_begin, pos_it)), + std::vector<T>(val_block_begin, val_it))); + + // reset block variables to start a new one from here + part_cur = part; + pos_block_begin = pos_it; + val_block_begin = val_it; } // the end of the vector is also an end of a block @@ -1023,6 +1079,38 @@ namespace hpx { return set_values(pos, val).get(); } + template <typename F, typename... Ts> + future<util::invoke_result_t<F, T, Ts...>> apply_on( + size_type part, size_type pos, F f, Ts... ts) const + { + if (partitions_[part].local_data_) + { + return make_ready_future(partitions_[part].local_data_->apply( + pos, HPX_FORWARD(F, f), HPX_FORWARD(Ts, ts)...)); + } + + return partitioned_vector_partition_client( + partitions_[part].partition_) + .apply(pos, HPX_FORWARD(F, f), HPX_FORWARD(Ts, ts)...); + } + + template <typename F, typename... Ts> + auto apply(std::size_t pos, F f, Ts... ts) + { + auto part = get_partition(pos); + return apply_on(part, get_local_index(part, pos), HPX_FORWARD(F, f), + HPX_FORWARD(Ts, ts)...); + } + + template <typename F, typename... Ts> + auto apply(launch::sync_policy, std::size_t pos, F f, Ts... ts) + { + auto part = get_partition(pos); + return apply_on(part, get_local_index(part, pos), HPX_FORWARD(F, f), + HPX_FORWARD(Ts, ts)...) + .get(); + } + // //CLEAR // // TODO if number of partitions is kept constant every time then // // clear should modify (clear each partitioned_vector_partition @@ -1281,4 +1369,67 @@ namespace hpx { return segment_cend(naming::get_locality_id_from_id(id)); } }; + + /////////////////////////////////////////////////////////////////////////// + template <typename T, typename Data> + struct reference_wrapper<partitioned_vector<T, Data>> + { + using wrapped_type = partitioned_vector<T, Data>; + + // we define a default constructor to support serialization + reference_wrapper() = default; + + // clang-format off + template <typename U, + typename Enable = std::enable_if_t< + !std::is_same_v<std::decay<U>, reference_wrapper>>> + // clang-format on + constexpr reference_wrapper(U&& val) noexcept + : ptr(val.ref()) + { + } + + reference_wrapper(reference_wrapper const& rhs) + : ptr(rhs.get().ref()) + { + } + reference_wrapper(reference_wrapper&& rhs) = default; + + reference_wrapper& operator=(reference_wrapper const& rhs) + { + ptr = rhs.get().ref(); + return *this; + } + reference_wrapper& operator=(reference_wrapper&& rhs) = default; + + constexpr operator wrapped_type&() noexcept + { + return ptr; + } + + constexpr operator wrapped_type const&() const noexcept + { + return ptr; + } + + [[nodiscard]] constexpr wrapped_type& get() noexcept + { + return ptr; + } + + [[nodiscard]] constexpr wrapped_type const& get() const noexcept + { + return ptr; + } + + private: + partitioned_vector<T, Data> ptr{}; + }; + + template <typename T, typename Data> + reference_wrapper<partitioned_vector<T, Data>> ref( + partitioned_vector<T, Data>&& val) noexcept + { + return reference_wrapper<partitioned_vector<T, Data>>(HPX_MOVE(val)); + } } // namespace hpx diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp index 74eea0a28318..69204f366b8d 100644 --- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_impl.hpp @@ -14,7 +14,7 @@ #include <hpx/async_combinators/wait_all.hpp> #include <hpx/components/get_ptr.hpp> #include <hpx/distribution_policies/container_distribution_policy.hpp> -#include <hpx/functional/bind_back.hpp> +#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp> #include <hpx/modules/async_distributed.hpp> #include <hpx/modules/errors.hpp> #include <hpx/modules/execution.hpp> @@ -42,24 +42,34 @@ namespace hpx { template <typename T, typename Data /*= std::vector<T> */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t - partitioned_vector<T, Data>::get_partition_size() const + partitioned_vector<T, Data>::get_partition_size(std::size_t partnum) const { - std::size_t num_parts = partitions_.size(); - return num_parts ? ((size_ + num_parts - 1) / num_parts) : 0; + std::size_t size = partitions_.size(); + if (partnum == size) + { + return 0; + } + return size == 0 ? 0 : partitions_[partnum].size_; } template <typename T, typename Data /*= std::vector<T> */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t - partitioned_vector<T, Data>::get_global_index( - std::size_t segment, std::size_t part_size, size_type local_index) const + partitioned_vector<T, Data>::get_global_index_part( + std::size_t partnum, size_type local_index) const { - return segment * part_size + local_index; + std::size_t size = partitions_.size(); + if (partnum == size) + { + return size_; + } + return size == 0 ? local_index : + partitions_[partnum].first_ + local_index; } template <typename T, typename Data /*= std::vector<T> */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void partitioned_vector<T, Data>::get_data_helper( - id_type id, server::partitioned_vector_config_data data) + id_type id, server::partitioned_vector_config_data&& data) { partitions_.clear(); partitions_.reserve(data.partitions_.size()); @@ -72,11 +82,9 @@ namespace hpx { std::vector<future<void>> ptrs; ptrs.reserve(partitions_.size()); - using const_iterator = typename partitions_vector_type::const_iterator; - std::size_t l = 0; - const_iterator end = partitions_.cend(); - for (const_iterator it = partitions_.cbegin(); it != end; ++it, ++l) + auto end = partitions_.cend(); + for (auto it = partitions_.cbegin(); it != end; ++it, ++l) { if (it->locality_id_ == this_locality) { @@ -87,7 +95,6 @@ namespace hpx { } hpx::wait_all(ptrs); - partition_size_ = get_partition_size(); this->base_type::reset(HPX_MOVE(id)); } @@ -175,29 +182,35 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t partitioned_vector<T, Data>::get_partition(size_type global_index) const { + if (global_index == 0) + { + return 0; + } if (global_index == size_) + { return partitions_.size(); + } - std::size_t part_size = partition_size_; - if (part_size != 0) - return (part_size != size_) ? (global_index / part_size) : 0; + // find partition that holds the global index + for (std::size_t part = 0; part != partitions_.size(); ++part) + { + auto const& partition = partitions_[part]; + if (partition.first_ <= global_index && + global_index < partition.first_ + partition.size_) + { + return part; + } + } return partitions_.size(); } template <typename T, typename Data /*= std::vector<T> */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t - partitioned_vector<T, Data>::get_local_index(size_type global_index) const + partitioned_vector<T, Data>::get_local_index( + size_type partnum, size_type global_index) const { - if (global_index == size_ || - partition_size_ == static_cast<std::size_t>(-1) || - partition_size_ == 0) - { - return static_cast<std::size_t>(-1); - } - - return (partition_size_ != size_) ? (global_index % partition_size_) : - global_index; + return global_index - partitions_[partnum].first_; } template <typename T, typename Data /*= std::vector<T> */> @@ -207,7 +220,9 @@ namespace hpx { std::vector<size_type> indices) const { for (size_type& index : indices) - index = get_local_index(index); + { + index = get_local_index(get_partition(index), index); + } return indices; } @@ -228,7 +243,7 @@ namespace hpx { back.partition_, back.size_, back.local_data_); } - std::size_t local_index = get_local_index(global_index); + std::size_t local_index = get_local_index(part, global_index); HPX_ASSERT(local_index != static_cast<std::size_t>(-1)); return local_iterator(partitions_[part].partition_, local_index, @@ -252,7 +267,7 @@ namespace hpx { back.partition_, back.size_, back.local_data_); } - std::size_t local_index = get_local_index(global_index); + std::size_t local_index = get_local_index(part, global_index); HPX_ASSERT(local_index != static_cast<std::size_t>(-1)); return const_local_iterator(partitions_[part].partition_, local_index, @@ -290,13 +305,15 @@ namespace hpx { template <typename DistPolicy> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT hpx::future< std::vector<typename partitioned_vector<T, Data>::bulk_locality_result>> - partitioned_vector<T, Data>::create_helper1( - DistPolicy const& policy, std::size_t count, std::size_t size) + partitioned_vector<T, Data>::create_helper1(DistPolicy const& policy, + std::size_t count, std::vector<std::size_t> const& sizes, + create_mode mode) { using component_type = typename partitioned_vector_partition_client::server_component_type; - return policy.template bulk_create<component_type>(count, size); + return policy.template bulk_create<true, component_type>( + count, sizes, mode); } template <typename T, typename Data /*= std::vector<T> */> @@ -304,12 +321,13 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT hpx::future< std::vector<typename partitioned_vector<T, Data>::bulk_locality_result>> partitioned_vector<T, Data>::create_helper2(DistPolicy const& policy, - std::size_t count, std::size_t size, T const& val) + std::size_t count, std::vector<std::size_t> const& sizes, T const& val) { using component_type = typename partitioned_vector_partition_client::server_component_type; - return policy.template bulk_create<component_type>(count, size, val); + return policy.template bulk_create<true, component_type>( + count, sizes, val); } template <typename T, typename Data /*= std::vector<T> */> @@ -329,18 +347,19 @@ namespace hpx { template <typename T, typename Data /*= std::vector<T> */> template <typename DistPolicy, typename Create> void partitioned_vector<T, Data>::create( - DistPolicy const& policy, Create&& creator) + DistPolicy const& policy, Create&& creator, create_mode mode) { std::size_t num_parts = traits::num_container_partitions<DistPolicy>::call(policy); - std::size_t part_size = (size_ + num_parts - 1) / num_parts; + std::vector<std::size_t> part_sizes = + traits::container_partition_sizes<DistPolicy>::call(policy, size_); // create as many partitions as required hpx::future<std::vector<bulk_locality_result>> f = - creator(policy, num_parts, part_size); + HPX_FORWARD(Create, creator)(policy, num_parts, part_sizes, mode); // now initialize our data structures - std::uint32_t this_locality = get_locality_id(); + std::uint32_t const this_locality = get_locality_id(); std::vector<future<void>> ptrs; ptrs.reserve(num_parts); @@ -360,8 +379,9 @@ namespace hpx { for (hpx::id_type const& id : r.second) { std::size_t size = - (std::min)(part_size, size_ - allocated_size); - partitions_[l] = partition_data(id, size, locality); + (std::min)(part_sizes[l], size_ - allocated_size); + partitions_[l] = + partition_data(id, allocated_size, size, locality); if (locality == this_locality) { @@ -377,7 +397,7 @@ namespace hpx { HPX_ASSERT(allocated_size == size_); // shrink last partition, if appropriate - if (size != part_size) + if (size != part_sizes.back()) { partitioned_vector_partition_client( partitions_[l - 1].partition_) @@ -385,19 +405,14 @@ namespace hpx { } break; } - else - { - HPX_ASSERT(size == part_size); - } + + HPX_ASSERT(size == part_sizes[l - 1]); HPX_ASSERT(l < num_parts); } } HPX_ASSERT(l == num_parts); hpx::wait_all(ptrs); - - // cache our partition size - partition_size_ = get_partition_size(); } template <typename T, typename Data /*= std::vector<T> */> @@ -405,7 +420,8 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void partitioned_vector<T, Data>::create(DistPolicy const& policy) { - create(policy, &partitioned_vector::create_helper1<DistPolicy>); + create(policy, &partitioned_vector::create_helper1<DistPolicy>, + traits::allocation_mode<DistPolicy>::call(policy)); } template <typename T, typename Data /*= std::vector<T> */> @@ -414,19 +430,21 @@ namespace hpx { partitioned_vector<T, Data>::create(T const& val, DistPolicy const& policy) { create(policy, - hpx::bind_back(&partitioned_vector::create_helper2<DistPolicy>, - std::ref(val))); + [&val](DistPolicy const& policy, std::size_t num_parts, + std::vector<std::size_t> const& part_sizes, create_mode) { + return create_helper2(policy, num_parts, part_sizes, val); + }); } template <typename T, typename Data /*= std::vector<T> */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void partitioned_vector<T, Data>::copy_from(partitioned_vector const& rhs) { - using const_iterator = typename partitions_vector_type::const_iterator; - std::vector<future<id_type>> objs; - const_iterator end = rhs.partitions_.end(); - for (const_iterator it = rhs.partitions_.begin(); it != end; ++it) + objs.reserve(rhs.partitions_.size()); + + auto end = rhs.partitions_.end(); + for (auto it = rhs.partitions_.begin(); it != end; ++it) { using component_type = typename partitioned_vector_partition_client:: @@ -445,12 +463,13 @@ namespace hpx { // to set the local partition data partitions_vector_type partitions; partitions.resize(rhs.partitions_.size()); + for (std::size_t i = 0; i != rhs.partitions_.size(); ++i) { std::uint32_t locality = rhs.partitions_[i].locality_id_; - partitions[i] = partition_data( - objs[i].get(), rhs.partitions_[i].size_, locality); + partitions[i] = partition_data(objs[i].get(), + rhs.partitions_[i].first_, rhs.partitions_[i].size_, locality); if (locality == this_locality) { @@ -463,7 +482,6 @@ namespace hpx { hpx::wait_all(ptrs); size_ = rhs.size_; - partition_size_ = rhs.partition_size_; std::swap(partitions_, partitions); } @@ -472,7 +490,6 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT partitioned_vector<T, Data>::partitioned_vector() : size_(0) - , partition_size_(static_cast<std::size_t>(-1)) { } @@ -480,7 +497,6 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT partitioned_vector<T, Data>::partitioned_vector(size_type size) : size_(size) - , partition_size_(static_cast<std::size_t>(-1)) { if (size != 0) create(hpx::container_layout); @@ -491,7 +507,6 @@ namespace hpx { partitioned_vector<T, Data>::partitioned_vector( size_type size, T const& val) : size_(size) - , partition_size_(static_cast<std::size_t>(-1)) { if (size != 0) create(val, hpx::container_layout); @@ -502,23 +517,31 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT partitioned_vector<T, Data>::partitioned_vector(size_type size, DistPolicy const& policy, - std::enable_if_t<traits::is_distribution_policy<DistPolicy>::value>*) + std::enable_if_t<traits::is_distribution_policy_v<DistPolicy>>*) : size_(size) - , partition_size_(static_cast<std::size_t>(-1)) { if (size != 0) create(policy); } + template <typename T, typename Data /*= std::vector<T> */> + template <typename DistPolicy> + HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT + partitioned_vector<T, Data>::partitioned_vector(DistPolicy const& policy, + std::enable_if_t<traits::is_distribution_policy_v<DistPolicy>>*) + : size_(0) + { + reserve(policy); + } + template <typename T, typename Data /*= std::vector<T> */> template <typename DistPolicy> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT partitioned_vector<T, Data>::partitioned_vector(size_type size, T const& val, DistPolicy const& policy, std::enable_if_t< - traits::is_distribution_policy<DistPolicy>::value>* /*= nullptr*/) + traits::is_distribution_policy_v<DistPolicy>>* /*= nullptr*/) : size_(size) - , partition_size_(static_cast<std::size_t>(-1)) { if (size != 0) create(val, policy); diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_predef.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_predef.hpp index 7a821d7d777d..a6e12f45278b 100644 --- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_predef.hpp +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_predef.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 Anuj R. Sharma -// Copyright (c) 2014-2016 Hartmut Kaiser +// Copyright (c) 2014-2024 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -8,6 +8,7 @@ #pragma once #include <hpx/distribution_policies/container_distribution_policy.hpp> +#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp> #include <hpx/components/containers/partitioned_vector/export_definitions.hpp> #include <hpx/components/containers/partitioned_vector/partitioned_vector_component_decl.hpp> @@ -36,6 +37,12 @@ extern template hpx::partitioned_vector<double, extern template hpx::partitioned_vector<double, std::vector<double>>::partitioned_vector(size_type, double const&, hpx::container_distribution_policy const&, void*); +extern template hpx::partitioned_vector<double, + std::vector<double>>::partitioned_vector(size_type, + hpx::explicit_container_distribution_policy const&, void*); +extern template hpx::partitioned_vector<double, + std::vector<double>>::partitioned_vector(size_type, double const&, + hpx::explicit_container_distribution_policy const&, void*); // partitioned_vector<int> HPX_REGISTER_PARTITIONED_VECTOR_DECLARATION(int) @@ -49,9 +56,15 @@ extern template hpx::partitioned_vector<int, extern template hpx::partitioned_vector<int, std::vector<int>>::partitioned_vector(size_type, int const&, hpx::container_distribution_policy const&, void*); +extern template hpx::partitioned_vector<int, + std::vector<int>>::partitioned_vector(size_type, + hpx::explicit_container_distribution_policy const&, void*); +extern template hpx::partitioned_vector<int, + std::vector<int>>::partitioned_vector(size_type, int const&, + hpx::explicit_container_distribution_policy const&, void*); // partitioned_vector<long long> -typedef long long long_long; +using long_long = long long; HPX_REGISTER_PARTITIONED_VECTOR_DECLARATION(long_long) extern template class hpx::server::partitioned_vector<long long, @@ -66,6 +79,12 @@ extern template hpx::partitioned_vector<long long, extern template hpx::partitioned_vector<long long, std::vector<long long>>::partitioned_vector(size_type, long long const&, hpx::container_distribution_policy const&, void*); +extern template hpx::partitioned_vector<long long, + std::vector<long long>>::partitioned_vector(size_type, + hpx::explicit_container_distribution_policy const&, void*); +extern template hpx::partitioned_vector<long long, + std::vector<long long>>::partitioned_vector(size_type, long long const&, + hpx::explicit_container_distribution_policy const&, void*); // partitioned_vector<std::string> using partitioned_vector_std_string_argument = std::string; @@ -85,5 +104,11 @@ extern template hpx::partitioned_vector<std::string, extern template hpx::partitioned_vector<std::string, std::vector<std::string>>::partitioned_vector(size_type, std::string const&, hpx::container_distribution_policy const&, void*); +extern template hpx::partitioned_vector<std::string, + std::vector<std::string>>::partitioned_vector(size_type, + hpx::explicit_container_distribution_policy const&, void*); +extern template hpx::partitioned_vector<std::string, + std::vector<std::string>>::partitioned_vector(size_type, std::string const&, + hpx::explicit_container_distribution_policy const&, void*); #endif diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_segmented_iterator.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_segmented_iterator.hpp index d9b192f48c04..00b7d7915842 100644 --- a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_segmented_iterator.hpp +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/partitioned_vector_segmented_iterator.hpp @@ -54,9 +54,9 @@ namespace hpx::segmented { local_raw_vector_iterator() = default; local_raw_vector_iterator(base_iterator const& it, - std::shared_ptr<server::partitioned_vector<T, Data>> const& data) + std::shared_ptr<server::partitioned_vector<T, Data>> data) : base_type(it) - , data_(data) + , data_(HPX_MOVE(data)) { } @@ -102,9 +102,9 @@ namespace hpx::segmented { const_local_raw_vector_iterator() = default; const_local_raw_vector_iterator(base_iterator const& it, - std::shared_ptr<server::partitioned_vector<T, Data>> const& data) + std::shared_ptr<server::partitioned_vector<T, Data>> data) : base_type(it) - , data_(data) + , data_(HPX_MOVE(data)) { } @@ -144,6 +144,16 @@ namespace hpx::segmented { { } + local_vector_value_proxy(local_vector_value_proxy const&) = default; + local_vector_value_proxy(local_vector_value_proxy&&) = default; + + local_vector_value_proxy& operator=( + local_vector_value_proxy const&) = default; + local_vector_value_proxy& operator=( + local_vector_value_proxy&&) = default; + + ~local_vector_value_proxy() = default; + operator T() const { if (!it_.get_data()) @@ -172,6 +182,7 @@ namespace hpx::segmented { return *this; } + private: local_vector_iterator<T, Data> const& it_; }; @@ -184,6 +195,18 @@ namespace hpx::segmented { { } + const_local_vector_value_proxy( + const_local_vector_value_proxy const&) = default; + const_local_vector_value_proxy( + const_local_vector_value_proxy&&) = default; + + const_local_vector_value_proxy& operator=( + const_local_vector_value_proxy const&) = default; + const_local_vector_value_proxy& operator=( + const_local_vector_value_proxy&&) = default; + + ~const_local_vector_value_proxy() = default; + operator T() const { if (!it_.get_data()) @@ -194,6 +217,7 @@ namespace hpx::segmented { return *it_.local(); } + private: const_local_vector_iterator<T, Data> const& it_; }; @@ -202,15 +226,23 @@ namespace hpx::segmented { struct vector_value_proxy { explicit vector_value_proxy( - hpx::partitioned_vector<T, Data>& v, std::size_t index) - : v_(v) + hpx::partitioned_vector<T, Data>& v, std::size_t const index) + : v_(&v) , index_(index) { } + vector_value_proxy(vector_value_proxy const&) = default; + vector_value_proxy(vector_value_proxy&&) = default; + + vector_value_proxy& operator=(vector_value_proxy const&) = default; + vector_value_proxy& operator=(vector_value_proxy&&) = default; + + ~vector_value_proxy() = default; + operator T() const { - return v_.get_value(launch::sync, index_); + return v_->get_value(launch::sync, index_); } template <typename T_, @@ -218,11 +250,12 @@ namespace hpx::segmented { !std::is_same_v<std::decay_t<T_>, vector_value_proxy>>> vector_value_proxy& operator=(T_&& value) { - v_.set_value(launch::sync, index_, HPX_FORWARD(T_, value)); + v_->set_value(launch::sync, index_, HPX_FORWARD(T_, value)); return *this; } - partitioned_vector<T, Data>& v_; + private: + partitioned_vector<T, Data>* v_; std::size_t index_; }; } // namespace detail @@ -246,27 +279,24 @@ namespace hpx::segmented { using size_type = std::size_t; // constructors - local_vector_iterator() - : partition_() - , local_index_(static_cast<size_type>(-1)) - { - } + local_vector_iterator() = default; - local_vector_iterator(hpx::id_type const& partition, - size_type local_index, - std::shared_ptr<server::partitioned_vector<T, Data>> const& data) - : partition_(partitioned_vector_partition<T, Data>(partition)) + local_vector_iterator(hpx::id_type partition, + size_type const local_index, + std::shared_ptr<server::partitioned_vector<T, Data>> data) + : partition_( + partitioned_vector_partition<T, Data>(HPX_MOVE(partition))) , local_index_(local_index) - , data_(data) + , data_(HPX_MOVE(data)) { } local_vector_iterator(partitioned_vector_partition<T, Data> partition, - size_type local_index, - std::shared_ptr<server::partitioned_vector<T, Data>> const& data) - : partition_(partition) + size_type const local_index, + std::shared_ptr<server::partitioned_vector<T, Data>> data) noexcept + : partition_(HPX_MOVE(partition)) , local_index_(local_index) - , data_(data) + , data_(HPX_MOVE(data)) { } @@ -280,14 +310,18 @@ namespace hpx::segmented { local_raw_iterator local() { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return local_raw_iterator( data_->begin() + local_index_, data_); //-V522 } local_raw_const_iterator local() const { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return local_raw_iterator( data_->cbegin() + local_index_, data_); //-V522 } @@ -296,18 +330,11 @@ namespace hpx::segmented { friend class hpx::serialization::access; template <typename Archive> - void load(Archive& ar, unsigned /* version */) - { - ar & partition_ & local_index_; - } - template <typename Archive> - void save(Archive& ar, unsigned /* version */) const + void serialize(Archive& ar, unsigned /* version */) { ar & partition_ & local_index_; } - HPX_SERIALIZATION_SPLIT_MEMBER() - protected: friend class hpx::util::iterator_core_access; @@ -322,38 +349,39 @@ namespace hpx::segmented { return segmented::detail::local_vector_value_proxy<T, Data>(*this); } - void increment() + void increment() noexcept { ++local_index_; } - void decrement() + void decrement() noexcept { --local_index_; } - void advance(std::ptrdiff_t n) + void advance(std::ptrdiff_t const n) noexcept { local_index_ += n; } - std::ptrdiff_t distance_to(local_vector_iterator const& other) const + std::ptrdiff_t distance_to( + local_vector_iterator const& other) const noexcept { HPX_ASSERT(partition_ == other.partition_); return other.local_index_ - local_index_; } public: - partitioned_vector_partition<T, Data>& get_partition() + partitioned_vector_partition<T, Data>& get_partition() noexcept { return partition_; } - partitioned_vector_partition<T, Data> get_partition() const + partitioned_vector_partition<T, Data> get_partition() const noexcept { return partition_; } - size_type get_local_index() const + [[nodiscard]] size_type get_local_index() const noexcept { return local_index_; } @@ -361,26 +389,30 @@ namespace hpx::segmented { std::shared_ptr<server::partitioned_vector<T, Data>>& get_data() { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return data_; } std::shared_ptr<server::partitioned_vector<T, Data>> const& get_data() const { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return data_; } protected: // refer to a partition of the vector - partitioned_vector_partition<T, Data> partition_; + partitioned_vector_partition<T, Data> partition_{}; // local position in the referenced partition - size_type local_index_; + size_type local_index_ = static_cast<size_type>(-1); // caching address of component - mutable std::shared_ptr<server::partitioned_vector<T, Data>> data_; + mutable std::shared_ptr<server::partitioned_vector<T, Data>> data_{}; }; template <typename T, typename Data> @@ -389,7 +421,6 @@ namespace hpx::segmented { T const, std::random_access_iterator_tag, segmented::detail::const_local_vector_value_proxy<T, Data>> { - private: using base_type = hpx::util::iterator_facade<const_local_vector_iterator<T, Data>, T const, std::random_access_iterator_tag, @@ -399,28 +430,25 @@ namespace hpx::segmented { using size_type = std::size_t; // constructors - const_local_vector_iterator() - : partition_() - , local_index_(static_cast<size_type>(-1)) - { - } + const_local_vector_iterator() = default; - const_local_vector_iterator(hpx::id_type const& partition, - size_type local_index, - std::shared_ptr<server::partitioned_vector<T, Data>> const& data) - : partition_(partitioned_vector_partition<T, Data>(partition)) + const_local_vector_iterator(hpx::id_type partition, + size_type const local_index, + std::shared_ptr<server::partitioned_vector<T, Data>> data) + : partition_( + partitioned_vector_partition<T, Data>(HPX_MOVE(partition))) , local_index_(local_index) - , data_(data) + , data_(HPX_MOVE(data)) { } const_local_vector_iterator( partitioned_vector_partition<T, Data> partition, - size_type local_index, - std::shared_ptr<server::partitioned_vector<T, Data>> const& data) - : partition_(partition) + size_type const local_index, + std::shared_ptr<server::partitioned_vector<T, Data>> data) noexcept + : partition_(HPX_MOVE(partition)) , local_index_(local_index) - , data_(data) + , data_(HPX_MOVE(data)) { } @@ -439,14 +467,18 @@ namespace hpx::segmented { local_raw_iterator local() { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return local_raw_iterator( data_->cbegin() + local_index_, data_); //-V522 } local_raw_const_iterator local() const { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return local_raw_const_iterator( data_->cbegin() + local_index_, data_); //-V522 } @@ -455,17 +487,10 @@ namespace hpx::segmented { friend class hpx::serialization::access; template <typename Archive> - void load(Archive& ar, unsigned /* version */) + void serialize(Archive& ar, unsigned /* version */) { ar & partition_ & local_index_; } - template <typename Archive> - void save(Archive& ar, unsigned /* version */) const - { - ar & partition_ & local_index_; - } - - HPX_SERIALIZATION_SPLIT_MEMBER() protected: friend class hpx::util::iterator_core_access; @@ -482,34 +507,34 @@ namespace hpx::segmented { *this); } - void increment() + void increment() noexcept { ++local_index_; } - void decrement() + void decrement() noexcept { --local_index_; } - void advance(std::ptrdiff_t n) + void advance(std::ptrdiff_t const n) noexcept { local_index_ += n; } std::ptrdiff_t distance_to( - const_local_vector_iterator const& other) const + const_local_vector_iterator const& other) const noexcept { HPX_ASSERT(partition_ == other.partition_); return other.local_index_ - local_index_; } public: - partitioned_vector_partition<T, Data> const& get_partition() const + partitioned_vector_partition<T, Data> get_partition() const { return partition_; } - size_type get_local_index() const + [[nodiscard]] size_type get_local_index() const noexcept { return local_index_; } @@ -517,26 +542,30 @@ namespace hpx::segmented { std::shared_ptr<server::partitioned_vector<T, Data>>& get_data() { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return data_; } std::shared_ptr<server::partitioned_vector<T, Data>> const& get_data() const { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return data_; } protected: // refer to a partition of the vector - partitioned_vector_partition<T, Data> partition_; + partitioned_vector_partition<T, Data> partition_{}; // local position in the referenced partition - size_type local_index_; + size_type local_index_ = static_cast<size_type>(-1); // caching address of component - mutable std::shared_ptr<server::partitioned_vector<T, Data>> data_; + mutable std::shared_ptr<server::partitioned_vector<T, Data>> data_{}; }; /////////////////////////////////////////////////////////////////////////// @@ -552,10 +581,7 @@ namespace hpx::segmented { segment_vector_iterator<T, Data, BaseIter>, BaseIter>; public: - segment_vector_iterator() - : data_(nullptr) - { - } + segment_vector_iterator() = default; explicit segment_vector_iterator( BaseIter const& it, partitioned_vector<T, Data>* data = nullptr) @@ -564,11 +590,12 @@ namespace hpx::segmented { { } - partitioned_vector<T, Data>* get_data() + [[nodiscard]] partitioned_vector<T, Data>* get_data() noexcept { return data_; } - partitioned_vector<T, Data> const* get_data() const + [[nodiscard]] partitioned_vector<T, Data> const* get_data() + const noexcept { return data_; } @@ -580,7 +607,7 @@ namespace hpx::segmented { } private: - partitioned_vector<T, Data>* data_; + partitioned_vector<T, Data>* data_ = nullptr; }; template <typename T, typename Data, typename BaseIter> @@ -593,10 +620,7 @@ namespace hpx::segmented { const_segment_vector_iterator<T, Data, BaseIter>, BaseIter>; public: - const_segment_vector_iterator() - : data_(nullptr) - { - } + const_segment_vector_iterator() = default; template <typename RightBaseIter> explicit const_segment_vector_iterator( @@ -613,7 +637,8 @@ namespace hpx::segmented { { } - partitioned_vector<T, Data> const* get_data() const + [[nodiscard]] partitioned_vector<T, Data> const* get_data() + const noexcept { return data_; } @@ -625,11 +650,12 @@ namespace hpx::segmented { } private: - partitioned_vector<T, Data> const* data_; + partitioned_vector<T, Data> const* data_ = nullptr; }; /////////////////////////////////////////////////////////////////////////// namespace detail { + template <typename BaseIterator> struct is_requested_locality { @@ -637,12 +663,12 @@ namespace hpx::segmented { typename std::iterator_traits<BaseIterator>::reference; explicit is_requested_locality( - std::uint32_t locality_id = naming::invalid_locality_id) + std::uint32_t const locality_id = naming::invalid_locality_id) : locality_id_(locality_id) { } - bool operator()(reference val) const + constexpr bool operator()(reference val) const { return locality_id_ == naming::invalid_locality_id || locality_id_ == val.locality_id_; @@ -694,12 +720,18 @@ namespace hpx::segmented { void unsatisfy_predicate() { while (this->base() != end_ && predicate_(*this->base())) + { ++(this->base_reference()); + } if (this->base() != end_) + { data_ = this->base()->local_data_; + } else + { data_.reset(); + } } private: @@ -716,9 +748,13 @@ namespace hpx::segmented { ++(this->base_reference()); if (this->base() != end_) + { data_ = this->base()->local_data_; + } else + { data_.reset(); + } } void satisfy_predicate() @@ -727,9 +763,13 @@ namespace hpx::segmented { ++(this->base_reference()); if (this->base() != end_) + { data_ = this->base()->local_data_; + } else + { data_.reset(); + } } std::shared_ptr<server::partitioned_vector<T, Data>> data_; @@ -759,30 +799,30 @@ namespace hpx::segmented { using local_iterator = typename partitioned_vector<T, Data>::local_iterator; + // disable use of brackets_proxy in iterator_facade + using use_brackets_proxy = std::false_type; + // constructors - vector_iterator() - : data_(nullptr) - , global_index_(static_cast<size_type>(-1)) - { - } + vector_iterator() = default; - vector_iterator( - partitioned_vector<T, Data>* data, size_type global_index) + vector_iterator(partitioned_vector<T, Data>* data, + size_type const global_index) noexcept : data_(data) , global_index_(global_index) { } - partitioned_vector<T, Data>* get_data() + [[nodiscard]] partitioned_vector<T, Data>* get_data() noexcept { return data_; } - partitioned_vector<T, Data> const* get_data() const + [[nodiscard]] partitioned_vector<T, Data> const* get_data() + const noexcept { return data_; } - size_type get_global_index() const + [[nodiscard]] size_type get_global_index() const noexcept { return global_index_; } @@ -802,25 +842,25 @@ namespace hpx::segmented { *data_, global_index_); } - void increment() + void increment() noexcept { HPX_ASSERT(data_); ++global_index_; } - void decrement() + void decrement() noexcept { HPX_ASSERT(data_); --global_index_; } - void advance(std::ptrdiff_t n) + void advance(std::ptrdiff_t const n) noexcept { HPX_ASSERT(data_); global_index_ += n; } - std::ptrdiff_t distance_to(vector_iterator const& other) const + std::ptrdiff_t distance_to(vector_iterator const& other) const noexcept { HPX_ASSERT(data_ && other.data_); HPX_ASSERT(data_ == other.data_); @@ -828,10 +868,10 @@ namespace hpx::segmented { } // refer to the vector - partitioned_vector<T, Data>* data_; + partitioned_vector<T, Data>* data_ = nullptr; // global position in the referenced vector - size_type global_index_; + size_type global_index_ = static_cast<size_type>(-1); }; /////////////////////////////////////////////////////////////////////////// @@ -853,25 +893,24 @@ namespace hpx::segmented { using local_iterator = typename partitioned_vector<T, Data>::const_local_iterator; + // disable use of brackets_proxy in iterator_facade + using use_brackets_proxy = std::false_type; + // constructors - const_vector_iterator() - : data_(nullptr) - , global_index_(static_cast<size_type>(-1)) - { - } + const_vector_iterator() = default; - const_vector_iterator( - partitioned_vector<T, Data> const* data, size_type global_index) + const_vector_iterator(partitioned_vector<T, Data> const* data, + size_type const global_index) noexcept : data_(data) , global_index_(global_index) { } - partitioned_vector<T, Data> const* get_data() const + partitioned_vector<T, Data> const* get_data() const noexcept { return data_; } - size_type get_global_index() const + [[nodiscard]] size_type get_global_index() const noexcept { return global_index_; } @@ -879,7 +918,7 @@ namespace hpx::segmented { protected: friend class hpx::util::iterator_core_access; - bool equal(const_vector_iterator const& other) const + bool equal(const_vector_iterator const& other) const noexcept { return data_ == other.data_ && global_index_ == other.global_index_; } @@ -890,25 +929,26 @@ namespace hpx::segmented { return data_->get_value(launch::sync, global_index_); } - void increment() + void increment() noexcept { HPX_ASSERT(data_); ++global_index_; } - void decrement() + void decrement() noexcept { HPX_ASSERT(data_); --global_index_; } - void advance(std::ptrdiff_t n) + void advance(std::ptrdiff_t const n) { HPX_ASSERT(data_); global_index_ += n; } - std::ptrdiff_t distance_to(const_vector_iterator const& other) const + std::ptrdiff_t distance_to( + const_vector_iterator const& other) const noexcept { HPX_ASSERT(data_ && other.data_); HPX_ASSERT(data_ == other.data_); @@ -916,10 +956,10 @@ namespace hpx::segmented { } // refer to the vector - partitioned_vector<T, Data> const* data_; + partitioned_vector<T, Data> const* data_ = nullptr; // global position in the referenced vector - size_type global_index_; + size_type global_index_ = static_cast<size_type>(-1); }; } // namespace hpx::segmented @@ -985,7 +1025,9 @@ namespace hpx::traits { static local_iterator end(segment_iterator seg_iter) { if (seg_iter.is_at_end()) + { --seg_iter; // return iterator to the end of last segment + } auto& base = seg_iter.base(); return local_iterator( @@ -1076,7 +1118,9 @@ namespace hpx::traits { static local_iterator end(segment_iterator seg_iter) { if (seg_iter.is_at_end()) + { --seg_iter; // return iterator to the end of last segment + } auto& base = seg_iter.base(); return local_iterator( diff --git a/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp new file mode 100644 index 000000000000..1aa5cadb44fc --- /dev/null +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp @@ -0,0 +1,119 @@ +// Copyright (c) 2017 Christopher Taylor +// Copyright (c) 2024 Hartmut Kaiser +// +// SPDX-License-Identifier: BSL-1.0 +// 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) + +#pragma once + +#include <hpx/config.hpp> +#include <hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp> +#include <hpx/serialization/serialize.hpp> + +#include <cstddef> +#include <string> +#include <vector> + +namespace hpx::serialization { + + template <typename T, typename Data> + void serialize( + input_archive& ar, hpx::partitioned_vector<T, Data>& v, unsigned) + { + using partitioned_vector = hpx::partitioned_vector<T, Data>; + bool has_id = false; + ar >> has_id; + if (has_id) + { + hpx::id_type id; + std::size_t size; + std::vector<typename partitioned_vector::partition_data_type> + partitions; + + ar >> id >> size >> partitions; + v = partitioned_vector::create_from( + HPX_MOVE(id), size, HPX_MOVE(partitions)); + } + else + { + std::string registered_name; + ar >> registered_name; + v.connect_to(registered_name).get(); + } + } + + template <typename T, typename Data> + void serialize( + output_archive& ar, hpx::partitioned_vector<T, Data> const& v, unsigned) + { + bool has_id = v.valid(); + ar << has_id; + if (has_id) + { + ar << v.get_id() << v.size() << v.partitions(); + } + else + { + std::string const registered_name = v.registered_name(); + if (registered_name.empty()) + { + HPX_THROW_EXCEPTION(hpx::error::invalid_status, + "hpx::serialization::serialize", + "partitioned_vector is not registered"); + } + ar << registered_name; + } + } + + template <typename T, typename Data> + void serialize(input_archive& ar, + hpx::reference_wrapper<hpx::partitioned_vector<T, Data>>& v, unsigned) + { + using partitioned_vector = hpx::partitioned_vector<T, Data>; + + bool has_id = false; + ar >> has_id; + if (has_id) + { + hpx::id_type id; + std::size_t size; + std::vector<typename partitioned_vector::partition_data_type> + partitions; + + ar >> id >> size >> partitions; + v = hpx::ref(partitioned_vector::create_from( + HPX_MOVE(id), size, HPX_MOVE(partitions))); + } + else + { + std::string registered_name; + ar >> registered_name; + v.get().connect_to(registered_name).get(); + } + } + + template <typename T, typename Data> + void serialize(output_archive& ar, + hpx::reference_wrapper<hpx::partitioned_vector<T, Data>> const& v, + unsigned) + { + bool has_id = v.get().valid(); + ar << has_id; + if (has_id) + { + ar << v.get().get_id() << v.get().size() << v.get().partitions(); + } + else + { + std::string const registered_name = v.get().registered_name(); + if (registered_name.empty()) + { + HPX_THROW_EXCEPTION(hpx::error::invalid_status, + "hpx::serialization::serialize", + "partitioned_vector is not registered"); + } + ar << registered_name; + } + } +} // namespace hpx::serialization diff --git a/components/containers/partitioned_vector/include/hpx/include/partitioned_vector.hpp b/components/containers/partitioned_vector/include/hpx/include/partitioned_vector.hpp index 4796f62341cd..674202b95962 100644 --- a/components/containers/partitioned_vector/include/hpx/include/partitioned_vector.hpp +++ b/components/containers/partitioned_vector/include/hpx/include/partitioned_vector.hpp @@ -7,6 +7,4 @@ #pragma once #include <hpx/components/containers/partitioned_vector/partitioned_vector.hpp> - - - +#include <hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp> diff --git a/components/containers/partitioned_vector/include/hpx/include/partitioned_vector_predef.hpp b/components/containers/partitioned_vector/include/hpx/include/partitioned_vector_predef.hpp index a56793514efc..069f15fbc40c 100644 --- a/components/containers/partitioned_vector/include/hpx/include/partitioned_vector_predef.hpp +++ b/components/containers/partitioned_vector/include/hpx/include/partitioned_vector_predef.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Hartmut Kaiser +// Copyright (C) 2017-2024 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -7,6 +7,4 @@ #pragma once #include <hpx/components/containers/partitioned_vector/partitioned_vector_predef.hpp> - - - +#include <hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp> diff --git a/components/containers/partitioned_vector/include/hpx/runtime/serialization/partitioned_vector.hpp b/components/containers/partitioned_vector/include/hpx/runtime/serialization/partitioned_vector.hpp deleted file mode 100644 index 0e940b5ec974..000000000000 --- a/components/containers/partitioned_vector/include/hpx/runtime/serialization/partitioned_vector.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2017 Christopher Taylor -// -// SPDX-License-Identifier: BSL-1.0 -// 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) - -#pragma once - -#include <hpx/config.hpp> -#include <hpx/components/containers/partitioned_vector/partitioned_vector_decl.hpp> -#include <hpx/modules/errors.hpp> -#include <hpx/serialization/serialize.hpp> - -#include <string> - -namespace hpx::serialization { - - template <typename T> - void serialize(input_archive& ar, hpx::partitioned_vector<T>& v, unsigned) - { - std::string pvec_registered_name; - ar >> pvec_registered_name; - v.connect_to(pvec_registered_name).get(); - } - - template <typename T> - void serialize( - output_archive& ar, const hpx::partitioned_vector<T>& v, unsigned) - { - std::string pvec_registered_name = v.registered_name(); - if (pvec_registered_name.empty()) - { - HPX_THROW_EXCEPTION(hpx::error::invalid_status, - "hpx::serialization::serialize", - "partitioned_vector is not registered"); - } - ar << pvec_registered_name; - } -} // namespace hpx::serialization diff --git a/components/containers/partitioned_vector/src/partitioned_vector_component_double.cpp b/components/containers/partitioned_vector/src/partitioned_vector_component_double.cpp index b08b3882435b..a52c32f359d4 100644 --- a/components/containers/partitioned_vector/src/partitioned_vector_component_double.cpp +++ b/components/containers/partitioned_vector/src/partitioned_vector_component_double.cpp @@ -8,6 +8,7 @@ #if !defined(HPX_HAVE_STATIC_LINKING) #include <hpx/distribution_policies/container_distribution_policy.hpp> +#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp> #include <hpx/components/containers/partitioned_vector/export_definitions.hpp> #include <hpx/components/containers/partitioned_vector/partitioned_vector.hpp> @@ -36,6 +37,12 @@ hpx::partitioned_vector<double, std::vector<double>>::partitioned_vector( template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<double, std::vector<double>>::partitioned_vector( size_type, double const&, hpx::container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT +hpx::partitioned_vector<double, std::vector<double>>::partitioned_vector( + size_type, hpx::explicit_container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<double, + std::vector<double>>::partitioned_vector(size_type, double const&, + hpx::explicit_container_distribution_policy const&, void*); #if defined(HPX_MSVC) #pragma warning(pop) diff --git a/components/containers/partitioned_vector/src/partitioned_vector_component_int.cpp b/components/containers/partitioned_vector/src/partitioned_vector_component_int.cpp index 1dc775086ee3..1d47be48a633 100644 --- a/components/containers/partitioned_vector/src/partitioned_vector_component_int.cpp +++ b/components/containers/partitioned_vector/src/partitioned_vector_component_int.cpp @@ -8,6 +8,7 @@ #if !defined(HPX_HAVE_STATIC_LINKING) #include <hpx/distribution_policies/container_distribution_policy.hpp> +#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp> #include <hpx/components/containers/partitioned_vector/export_definitions.hpp> #include <hpx/components/containers/partitioned_vector/partitioned_vector.hpp> @@ -38,6 +39,12 @@ hpx::partitioned_vector<int, std::vector<int>>::partitioned_vector( template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<int, std::vector<int>>::partitioned_vector( size_type, int const&, hpx::container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT +hpx::partitioned_vector<int, std::vector<int>>::partitioned_vector( + size_type, hpx::explicit_container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT +hpx::partitioned_vector<int, std::vector<int>>::partitioned_vector( + size_type, int const&, hpx::explicit_container_distribution_policy const&, void*); template class HPX_PARTITIONED_VECTOR_EXPORT hpx::server::partitioned_vector<long long, std::vector<long long>>; @@ -51,6 +58,12 @@ hpx::partitioned_vector<long long, std::vector<long long>>::partitioned_vector( template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<long long, std::vector<long long>>::partitioned_vector(size_type, long long const&, hpx::container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT +hpx::partitioned_vector<long long, std::vector<long long>>::partitioned_vector( + size_type, hpx::explicit_container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<long long, + std::vector<long long>>::partitioned_vector(size_type, long long const&, + hpx::explicit_container_distribution_policy const&, void*); #if defined(HPX_MSVC) #pragma warning(pop) diff --git a/components/containers/partitioned_vector/src/partitioned_vector_component_std_string.cpp b/components/containers/partitioned_vector/src/partitioned_vector_component_std_string.cpp index 8c32b90404e9..d74d531fd58b 100644 --- a/components/containers/partitioned_vector/src/partitioned_vector_component_std_string.cpp +++ b/components/containers/partitioned_vector/src/partitioned_vector_component_std_string.cpp @@ -8,6 +8,7 @@ #if !defined(HPX_HAVE_STATIC_LINKING) #include <hpx/distribution_policies/container_distribution_policy.hpp> +#include <hpx/distribution_policies/explicit_container_distribution_policy.hpp> #include <hpx/components/containers/partitioned_vector/export_definitions.hpp> #include <hpx/components/containers/partitioned_vector/partitioned_vector.hpp> @@ -39,6 +40,12 @@ template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<std::string, template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<std::string, std::vector<std::string>>::partitioned_vector(size_type, std::string const&, hpx::container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<std::string, + std::vector<std::string>>::partitioned_vector(size_type, + hpx::explicit_container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector<std::string, + std::vector<std::string>>::partitioned_vector(size_type, std::string const&, + hpx::explicit_container_distribution_policy const&, void*); #if defined(HPX_MSVC) #pragma warning(pop) diff --git a/components/containers/partitioned_vector/tests/unit/serialization_partitioned_vector.cpp b/components/containers/partitioned_vector/tests/unit/serialization_partitioned_vector.cpp index 2723a8c4d5af..66d5ba705eb4 100644 --- a/components/containers/partitioned_vector/tests/unit/serialization_partitioned_vector.cpp +++ b/components/containers/partitioned_vector/tests/unit/serialization_partitioned_vector.cpp @@ -10,9 +10,10 @@ #include <hpx/include/parallel_fill.hpp> #include <hpx/include/partitioned_vector.hpp> -#include <hpx/runtime/serialization/partitioned_vector.hpp> #include <hpx/modules/testing.hpp> +#include <hpx/naming/detail/preprocess_gid_types.hpp> +#include <hpx/serialization/detail/preprocess_container.hpp> #include <cstddef> #include <numeric> @@ -24,7 +25,7 @@ HPX_REGISTER_PARTITIONED_VECTOR(double) #endif -typedef unsigned long ulong; +using ulong = unsigned long; HPX_REGISTER_PARTITIONED_VECTOR(ulong) HPX_REGISTER_PARTITIONED_VECTOR(long) @@ -36,15 +37,28 @@ void test(T minval, T maxval) { std::vector<char> buffer; - hpx::serialization::output_archive oarchive( - buffer, hpx::serialization::archive_flags::disable_data_chunking); - std::size_t sz = static_cast<std::size_t>(maxval - minval); hpx::partitioned_vector<T> os(sz); os.register_as("test_vector"); hpx::fill(hpx::execution::par, std::begin(os), std::end(os), 42); + hpx::serialization::detail::preprocess_container gather_size; + hpx::serialization::output_archive archive(gather_size, + hpx::serialization::archive_flags::disable_data_chunking); + + auto& split_gids = archive.get_extra_data< + hpx::serialization::detail::preprocess_gid_types>(); + + archive << os; + + hpx::serialization::output_archive oarchive( + buffer, hpx::serialization::archive_flags::disable_data_chunking); + + auto& osplit_gids = oarchive.get_extra_data< + hpx::serialization::detail::preprocess_gid_types>(); + osplit_gids.set_split_gids(split_gids.move_split_gids()); + oarchive << os; hpx::serialization::input_archive iarchive(buffer); @@ -88,4 +102,5 @@ int main() return hpx::util::report_errors(); } + #endif diff --git a/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp b/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp index 03f4b4753489..a37ccfd26f54 100644 --- a/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp +++ b/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp @@ -435,7 +435,7 @@ namespace hpx { // create as many partitions as required hpx::future<std::vector<bulk_locality_result>> f = - policy.template bulk_create<component_type>(num_parts); + policy.template bulk_create<false, component_type>(num_parts); // now initialize our data structures init(f.get()); @@ -454,7 +454,7 @@ namespace hpx { // create as many partitions as required hpx::future<std::vector<bulk_locality_result>> f = - policy.template bulk_create<component_type>( + policy.template bulk_create<false, component_type>( num_parts, bucket_count, hash, equal); // now initialize our data structures diff --git a/libs/core/datastructures/include/hpx/datastructures/member_pack.hpp b/libs/core/datastructures/include/hpx/datastructures/member_pack.hpp index b74cb60e8469..22ae32c6345c 100644 --- a/libs/core/datastructures/include/hpx/datastructures/member_pack.hpp +++ b/libs/core/datastructures/include/hpx/datastructures/member_pack.hpp @@ -50,7 +50,7 @@ namespace hpx::util { } #else template <std::size_t I, typename T, - bool Empty = std::is_empty<T>::value && !std::is_final<T>::value> + bool Empty = std::is_empty_v<T> && !std::is_final_v<T>> struct member_leaf { T member; diff --git a/libs/core/functional/CMakeLists.txt b/libs/core/functional/CMakeLists.txt index c37d19e05e8c..e10b492a16b9 100644 --- a/libs/core/functional/CMakeLists.txt +++ b/libs/core/functional/CMakeLists.txt @@ -33,6 +33,7 @@ set(functional_headers hpx/functional/experimental/scope_exit.hpp hpx/functional/experimental/scope_fail.hpp hpx/functional/experimental/scope_success.hpp + hpx/functional/reference_wrapper.hpp hpx/functional/serialization/detail/serializable_basic_function.hpp hpx/functional/serialization/detail/vtable/serializable_function_vtable.hpp hpx/functional/serialization/detail/vtable/serializable_vtable.hpp diff --git a/libs/core/functional/include/hpx/functional/reference_wrapper.hpp b/libs/core/functional/include/hpx/functional/reference_wrapper.hpp new file mode 100644 index 000000000000..e10a150dd66a --- /dev/null +++ b/libs/core/functional/include/hpx/functional/reference_wrapper.hpp @@ -0,0 +1,60 @@ +// Copyright (c) 2024 Hartmut Kaiser +// +// SPDX-License-Identifier: BSL-1.0 +// 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 reference_wrapper.hpp +/// \page hpx::reference_wrapper, hpx::ref, hpx::cref +/// \headerfile hpx/functional.hpp + +#pragma once + +#include <hpx/config.hpp> + +#include <functional> + +namespace hpx { + + /////////////////////////////////////////////////////////////////////////// + template <typename T> + struct reference_wrapper : std::reference_wrapper<T> + { + reference_wrapper() = delete; + + using std::reference_wrapper<T>::referrence_wrapper; + }; + + template <typename T> + [[nodiscard]] constexpr reference_wrapper<T> ref(T& val) noexcept + { + return reference_wrapper<T>(val); + } + + template <typename T> + void ref(T const&&) = delete; + + template <typename T> + [[nodiscard]] constexpr reference_wrapper<T> ref( + reference_wrapper<T> val) noexcept + { + return val; + } + + template <typename T> + [[nodiscard]] constexpr reference_wrapper<T const> cref( + T const& val) noexcept + { + return reference_wrapper<T const>(val); + } + + template <typename T> + void cref(T const&&) = delete; + + template <typename T> + [[nodiscard]] constexpr reference_wrapper<T const> cref( + reference_wrapper<T> val) noexcept + { + return val; + } +} // namespace hpx diff --git a/libs/core/iterator_support/include/hpx/iterator_support/iterator_facade.hpp b/libs/core/iterator_support/include/hpx/iterator_support/iterator_facade.hpp index 2769e209c3a0..a60c1c71070a 100644 --- a/libs/core/iterator_support/include/hpx/iterator_support/iterator_facade.hpp +++ b/libs/core/iterator_support/include/hpx/iterator_support/iterator_facade.hpp @@ -14,6 +14,8 @@ #pragma once #include <hpx/config.hpp> + +#include <hpx/concepts/has_xxx.hpp> #include <hpx/iterator_support/traits/is_iterator.hpp> #include <hpx/type_support/equality.hpp> @@ -233,7 +235,7 @@ namespace hpx::util { // Implementation for random access iterators // A proxy return type for operator[], needed to deal with iterators - // that may invalidate referents upon destruction. Consider the + // that may invalidate references upon destruction. Consider the // temporary iterator in *(a + n) template <typename Iterator> class operator_brackets_proxy @@ -267,22 +269,34 @@ namespace hpx::util { Iterator iter_; }; + // We can force (not) using the operator_brackets_proxy by adding an + // embedded type use_brackets_proxy to the iterator that evaluates to + // either std::true_type of std::false_type. + HPX_HAS_XXX_TRAIT_DEF(use_brackets_proxy) + // A meta-function that determines whether operator[] must return a // proxy, or whether it can simply return a copy of the value_type. - template <typename ValueType> + template <typename Iterator, typename Value, typename Enable = void> struct use_operator_brackets_proxy : std::integral_constant<bool, - !(std::is_copy_constructible_v<ValueType> && - std::is_const_v<ValueType>)> + !(std::is_copy_constructible_v<Value> && + std::is_const_v<Value>)> + { + }; + + template <typename Iterator, typename Value> + struct use_operator_brackets_proxy<Iterator, Value, + std::enable_if_t<has_use_brackets_proxy_v<Iterator>>> + : Iterator::use_brackets_proxy { }; template <typename Iterator, typename Value> struct operator_brackets_result { - using type = - std::conditional_t<use_operator_brackets_proxy<Value>::value, - operator_brackets_proxy<Iterator>, Value>; + using type = std::conditional_t< + use_operator_brackets_proxy<Iterator, Value>::value, + operator_brackets_proxy<Iterator>, Value>; }; template <typename Iterator> @@ -319,11 +333,9 @@ namespace hpx::util { HPX_HOST_DEVICE iterator_facade_base() = default; - HPX_HOST_DEVICE constexpr - typename operator_brackets_result<Derived, T>::type - operator[](difference_type n) const + HPX_HOST_DEVICE constexpr auto operator[](difference_type n) const { - using use_proxy = use_operator_brackets_proxy<T>; + using use_proxy = use_operator_brackets_proxy<Derived, T>; return make_operator_brackets_result<Derived>( this->derived() + n, use_proxy{}); diff --git a/libs/core/testing/src/performance.cpp b/libs/core/testing/src/performance.cpp index 0227a776785a..6b2369157844 100644 --- a/libs/core/testing/src/performance.cpp +++ b/libs/core/testing/src/performance.cpp @@ -46,7 +46,7 @@ namespace hpx::util { char const* nanobench_hpx_simple_template() noexcept { return R"DELIM(Results: -{{#result}} +{{#result}} name: {{name}}, executor: {{context(executor)}}, average: {{average(elapsed)}}{{^-last}} @@ -238,7 +238,7 @@ average: {{average(elapsed)}}{{^-last}} using timer = std::chrono::high_resolution_clock; for (std::size_t i = 0; i != steps; ++i) { - // For now we don't flush the cache + // For now, we don't flush the cache //flush_cache(); timer::time_point start = timer::now(); test(); diff --git a/libs/full/actions_base/include/hpx/actions_base/component_action.hpp b/libs/full/actions_base/include/hpx/actions_base/component_action.hpp index 1680bc423b79..66530481847b 100644 --- a/libs/full/actions_base/include/hpx/actions_base/component_action.hpp +++ b/libs/full/actions_base/include/hpx/actions_base/component_action.hpp @@ -297,7 +297,8 @@ namespace hpx::actions { : hpx::actions::make_direct_action_t<decltype(&component::func), \ &component::func, name> \ { \ - }; /**/ + }; \ + /**/ #define HPX_DEFINE_COMPONENT_DIRECT_ACTION_2(component, func) \ HPX_DEFINE_COMPONENT_DIRECT_ACTION_3( \ diff --git a/libs/full/actions_base/include/hpx/actions_base/traits/is_distribution_policy.hpp b/libs/full/actions_base/include/hpx/actions_base/traits/is_distribution_policy.hpp index d6b96358a7b0..73f989755c54 100644 --- a/libs/full/actions_base/include/hpx/actions_base/traits/is_distribution_policy.hpp +++ b/libs/full/actions_base/include/hpx/actions_base/traits/is_distribution_policy.hpp @@ -9,6 +9,7 @@ #include <cstddef> #include <type_traits> +#include <vector> namespace hpx::traits { @@ -31,4 +32,35 @@ namespace hpx::traits { return policy.get_num_localities(); } }; + + // By default, the sizes of the partitions are equal across the localities + // represented by the given distribution policy. + template <typename Policy, typename Enable = void> + struct container_partition_sizes + { + static std::vector<std::size_t> call( + Policy const& policy, std::size_t const size) + { + std::size_t const num_parts = policy.get_num_partitions(); + return std::vector<std::size_t>( + num_parts, (size + num_parts - 1) / num_parts); + } + }; + + // By default, the container distribution policy resizes the underlying + // vectors. + enum class create_mode + { + resize = 0, + reserve = 1 + }; + + template <typename Policy, typename Enable = void> + struct allocation_mode + { + static create_mode call(Policy const&) + { + return create_mode::resize; + } + }; } // namespace hpx::traits diff --git a/libs/full/async_distributed/include/hpx/async_distributed/transfer_continuation_action.hpp b/libs/full/async_distributed/include/hpx/async_distributed/transfer_continuation_action.hpp index 7cd7ed742ad3..32c7af2067bb 100644 --- a/libs/full/async_distributed/include/hpx/async_distributed/transfer_continuation_action.hpp +++ b/libs/full/async_distributed/include/hpx/async_distributed/transfer_continuation_action.hpp @@ -257,16 +257,14 @@ namespace hpx::actions { { // If this is a direct action and deferred schedule was requested, // i.e. if we are not the last parcel, return immediately - if (base_type::direct_execution::value) + if constexpr (base_type::direct_execution::value) { return; } - else - { - // If this is not a direct action, we can safely set deferred_schedule - // to false - deferred_schedule = false; - } + + // If this is not a direct action, we can safely set + // deferred_schedule to false + deferred_schedule = false; } schedule_thread(HPX_MOVE(target), lva, comptype, num_thread); diff --git a/libs/full/compute/include/hpx/compute/host/target_distribution_policy.hpp b/libs/full/compute/include/hpx/compute/host/target_distribution_policy.hpp index 8537fc4ac8b6..f3f7842f3398 100644 --- a/libs/full/compute/include/hpx/compute/host/target_distribution_policy.hpp +++ b/libs/full/compute/include/hpx/compute/host/target_distribution_policy.hpp @@ -142,7 +142,7 @@ namespace hpx::compute::host { /// \returns A future holding the list of global addresses which /// represent the newly created objects /// - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> hpx::future<std::vector<bulk_locality_result>> bulk_create( [[maybe_unused]] std::size_t count, [[maybe_unused]] Ts&&... ts) const @@ -183,8 +183,9 @@ namespace hpx::compute::host { } objs.push_back( - components::bulk_create_async<Component>(localities.back(), - num_partitions, ts..., HPX_MOVE(local_targets))); + components::bulk_create_async<WithCount, Component>( + localities.back(), num_partitions, ts..., + HPX_MOVE(local_targets))); } return hpx::dataflow( diff --git a/libs/full/distribution_policies/CMakeLists.txt b/libs/full/distribution_policies/CMakeLists.txt index d681132a6cb5..72812cd1bd40 100644 --- a/libs/full/distribution_policies/CMakeLists.txt +++ b/libs/full/distribution_policies/CMakeLists.txt @@ -15,6 +15,7 @@ set(distribution_policies_headers hpx/distribution_policies/colocating_distribution_policy.hpp hpx/distribution_policies/container_distribution_policy.hpp hpx/distribution_policies/default_distribution_policy.hpp + hpx/distribution_policies/explicit_container_distribution_policy.hpp hpx/distribution_policies/target_distribution_policy.hpp hpx/distribution_policies/unwrapping_result_policy.hpp ) diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/binpacking_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/binpacking_distribution_policy.hpp index 1f76904a3771..d0a8025ff8f8 100644 --- a/libs/full/distribution_policies/include/hpx/distribution_policies/binpacking_distribution_policy.hpp +++ b/libs/full/distribution_policies/include/hpx/distribution_policies/binpacking_distribution_policy.hpp @@ -79,7 +79,7 @@ namespace hpx::components { std::vector<hpx::id_type> const& localities_; }; - template <typename Component> + template <bool WithCount, typename Component> struct create_bulk_helper { typedef std::pair<hpx::id_type, std::vector<hpx::id_type>> @@ -104,7 +104,7 @@ namespace hpx::components { for (std::size_t i = 0; i != to_create.size(); ++i) { - objs.emplace_back(bulk_create_async<Component>( + objs.emplace_back(bulk_create_async<WithCount, Component>( localities_[i], to_create[i], vs...)); } @@ -269,7 +269,7 @@ namespace hpx::components { /// \returns A future holding the list of global addresses which /// represent the newly created objects /// - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> hpx::future<std::vector<bulk_locality_result>> bulk_create( std::size_t count, Ts&&... vs) const { @@ -281,8 +281,9 @@ namespace hpx::components { counter_name_, localities_); return values.then(hpx::bind_back( - detail::create_bulk_helper<Component>(localities_), count, - HPX_FORWARD(Ts, vs)...)); + detail::create_bulk_helper<WithCount, Component>( + localities_), + count, HPX_FORWARD(Ts, vs)...)); } // handle special cases @@ -291,7 +292,8 @@ namespace hpx::components { localities_.front(); hpx::future<std::vector<hpx::id_type>> f = - bulk_create_async<Component>(id, count, HPX_FORWARD(Ts, vs)...); + bulk_create_async<WithCount, Component>( + id, count, HPX_FORWARD(Ts, vs)...); return f.then(hpx::launch::sync, [id = HPX_MOVE(id)](hpx::future<std::vector<hpx::id_type>>&& f) diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/colocating_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/colocating_distribution_policy.hpp index ec526faca6a6..12ff0dea6a30 100644 --- a/libs/full/distribution_policies/include/hpx/distribution_policies/colocating_distribution_policy.hpp +++ b/libs/full/distribution_policies/include/hpx/distribution_policies/colocating_distribution_policy.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2023 Hartmut Kaiser +// Copyright (c) 2014-2024 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -39,7 +39,6 @@ namespace hpx::components { /// object is currently placed. struct colocating_distribution_policy { - public: /// Default-construct a new instance of a \a colocating_distribution_policy. /// This policy will represent the local locality. constexpr colocating_distribution_policy() = default; @@ -89,6 +88,13 @@ namespace hpx::components { naming::get_id_from_locality_id(agas::get_locality_id()), HPX_FORWARD(Ts, vs)...); } + if (!naming::detail::is_migratable(id_.get_gid())) + { + return create_async<Component>( + naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)), + HPX_FORWARD(Ts, vs)...); + } return create_colocated_async<Component>( id_, HPX_FORWARD(Ts, vs)...); } @@ -111,7 +117,7 @@ namespace hpx::components { /// \returns A future holding the list of global addresses which /// represent the newly created objects /// - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> hpx::future<std::vector<bulk_locality_result>> bulk_create( std::size_t count, Ts&&... vs) const { @@ -120,13 +126,20 @@ namespace hpx::components { if (!id_) { id = naming::get_id_from_locality_id(agas::get_locality_id()); - f = bulk_create_async<Component>( + f = bulk_create_async<WithCount, Component>( + id, count, HPX_FORWARD(Ts, vs)...); + } + else if (!naming::detail::is_migratable(id_.get_gid())) + { + id = naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)); + f = bulk_create_async<WithCount, Component>( id, count, HPX_FORWARD(Ts, vs)...); } else { id = id_; - f = bulk_create_colocated_async<Component>( + f = bulk_create_colocated_async<WithCount, Component>( id, count, HPX_FORWARD(Ts, vs)...); } @@ -160,6 +173,13 @@ namespace hpx::components { naming::get_id_from_locality_id(agas::get_locality_id()), HPX_FORWARD(Ts, vs)...); } + if (!naming::detail::is_migratable(id_.get_gid())) + { + return hpx::detail::async_impl<Action>(policy, + naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)), + HPX_FORWARD(Ts, vs)...); + } return hpx::detail::async_colocated<Action>( id_, HPX_FORWARD(Ts, vs)...); } @@ -177,6 +197,13 @@ namespace hpx::components { naming::get_id_from_locality_id(agas::get_locality_id()), HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...); } + if (!naming::detail::is_migratable(id_.get_gid())) + { + return hpx::detail::async_cb_impl<Action>(policy, + naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)), + HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...); + } return hpx::detail::async_colocated_cb<Action>( id_, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...); } @@ -194,6 +221,14 @@ namespace hpx::components { naming::get_id_from_locality_id(agas::get_locality_id()), policy, HPX_FORWARD(Ts, vs)...); } + if (!naming::detail::is_migratable(id_.get_gid())) + { + return hpx::detail::post_impl<Action>( + HPX_FORWARD(Continuation, c), + naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)), + policy, HPX_FORWARD(Ts, vs)...); + } return hpx::detail::post_colocated<Action>( HPX_FORWARD(Continuation, c), id_, HPX_FORWARD(Ts, vs)...); } @@ -207,6 +242,13 @@ namespace hpx::components { naming::get_id_from_locality_id(agas::get_locality_id()), policy, HPX_FORWARD(Ts, vs)...); } + if (!naming::detail::is_migratable(id_.get_gid())) + { + return hpx::detail::post_impl<Action>( + naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)), + policy, HPX_FORWARD(Ts, vs)...); + } return hpx::detail::post_colocated<Action>( id_, HPX_FORWARD(Ts, vs)...); } @@ -226,6 +268,14 @@ namespace hpx::components { naming::get_id_from_locality_id(agas::get_locality_id()), policy, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...); } + if (!naming::detail::is_migratable(id_.get_gid())) + { + return hpx::detail::post_cb_impl<Action>( + HPX_FORWARD(Continuation, c), + naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)), + policy, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...); + } return hpx::detail::post_colocated_cb<Action>( HPX_FORWARD(Continuation, c), id_, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...); @@ -240,6 +290,13 @@ namespace hpx::components { naming::get_id_from_locality_id(agas::get_locality_id()), policy, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...); } + if (!naming::detail::is_migratable(id_.get_gid())) + { + return hpx::detail::post_cb_impl<Action>( + naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)), + policy, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...); + } return hpx::detail::post_colocated_cb<Action>( id_, HPX_FORWARD(Callback, cb), HPX_FORWARD(Ts, vs)...); } diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/container_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/container_distribution_policy.hpp index a0bde52afafa..2e2e3e118dc8 100644 --- a/libs/full/distribution_policies/include/hpx/distribution_policies/container_distribution_policy.hpp +++ b/libs/full/distribution_policies/include/hpx/distribution_policies/container_distribution_policy.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 Bibek Ghimire -// Copyright (c) 2014-2023 Hartmut Kaiser +// Copyright (c) 2014-2024 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -31,56 +31,59 @@ namespace hpx { struct container_distribution_policy : components::default_distribution_policy { - public: - constexpr container_distribution_policy() = default; + container_distribution_policy() = default; - container_distribution_policy operator()( - std::size_t num_partitions) const + container_distribution_policy operator()(std::size_t num_partitions, + traits::create_mode mode = traits::create_mode::resize) const { - return container_distribution_policy( - num_partitions, get_localities()); + return {num_partitions, get_localities(), mode}; } - container_distribution_policy operator()( - hpx::id_type const& locality) const + container_distribution_policy operator()(traits::create_mode mode) const + { + return container_distribution_policy(mode); + } + + container_distribution_policy operator()(hpx::id_type const& locality, + traits::create_mode mode = traits::create_mode::resize) const { - return container_distribution_policy(locality); + return {locality, mode}; } container_distribution_policy operator()( - std::vector<id_type> const& localities) const + std::vector<id_type> const& localities, + traits::create_mode mode = traits::create_mode::resize) const { if (num_partitions_ != static_cast<std::size_t>(-1)) { - return container_distribution_policy( - num_partitions_, localities); + return {num_partitions_, localities, mode}; } - return container_distribution_policy(localities.size(), localities); + return {localities.size(), localities, mode}; } container_distribution_policy operator()( - std::vector<id_type>&& localities) const + std::vector<id_type>&& localities, + traits::create_mode mode = traits::create_mode::resize) const { if (num_partitions_ != static_cast<std::size_t>(-1)) { - return container_distribution_policy( - num_partitions_, HPX_MOVE(localities)); + return {num_partitions_, HPX_MOVE(localities), mode}; } - return container_distribution_policy( - localities.size(), HPX_MOVE(localities)); + return {localities.size(), HPX_MOVE(localities), mode}; } container_distribution_policy operator()(std::size_t num_partitions, - std::vector<id_type> const& localities) const + std::vector<id_type> const& localities, + traits::create_mode mode = traits::create_mode::resize) const { - return container_distribution_policy(num_partitions, localities); + return {num_partitions, localities, mode}; } - container_distribution_policy operator()( - std::size_t num_partitions, std::vector<id_type>&& localities) const + container_distribution_policy operator()(std::size_t num_partitions, + std::vector<id_type>&& localities, + traits::create_mode mode = traits::create_mode::resize) const { - return container_distribution_policy( - num_partitions, HPX_MOVE(localities)); + return {num_partitions, HPX_MOVE(localities), mode}; } /////////////////////////////////////////////////////////////////////// @@ -110,6 +113,11 @@ namespace hpx { return *localities_; } + [[nodiscard]] constexpr traits::create_mode get_create_mode() const + { + return mode_; + } + private: friend class hpx::serialization::access; @@ -117,32 +125,41 @@ namespace hpx { void serialize(Archive& ar, const unsigned int /* version */) { // clang-format off - ar & localities_ & num_partitions_; + ar & localities_ & num_partitions_ & mode_; // clang-format on } - container_distribution_policy( - std::size_t num_partitions, std::vector<id_type> const& localities) + container_distribution_policy(std::size_t num_partitions, + std::vector<id_type> const& localities, traits::create_mode mode) : components::default_distribution_policy(localities) , num_partitions_(num_partitions) + , mode_(mode) { } - container_distribution_policy( - std::size_t num_partitions, std::vector<id_type>&& localities) + container_distribution_policy(std::size_t num_partitions, + std::vector<id_type>&& localities, traits::create_mode mode) : components::default_distribution_policy(HPX_MOVE(localities)) , num_partitions_(num_partitions) + , mode_(mode) { } - explicit container_distribution_policy(hpx::id_type const& locality) + container_distribution_policy( + hpx::id_type const& locality, traits::create_mode mode) : components::default_distribution_policy(locality) + , mode_(mode) + { + } + + explicit container_distribution_policy(traits::create_mode mode) + : mode_(mode) { } - private: // number of chunks to create std::size_t num_partitions_ = static_cast<std::size_t>(-1); + traits::create_mode mode_ = traits::create_mode::resize; }; static container_distribution_policy const container_layout{}; @@ -164,5 +181,14 @@ namespace hpx { return policy.get_num_partitions(); } }; + + template <> + struct allocation_mode<container_distribution_policy> + { + static create_mode call(container_distribution_policy const& policy) + { + return policy.get_create_mode(); + } + }; } // namespace traits } // namespace hpx diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/default_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/default_distribution_policy.hpp index 3edf6ca738ed..1de3c0f8e8cf 100644 --- a/libs/full/distribution_policies/include/hpx/distribution_policies/default_distribution_policy.hpp +++ b/libs/full/distribution_policies/include/hpx/distribution_policies/default_distribution_policy.hpp @@ -62,19 +62,7 @@ namespace hpx::components { /// /// \param locs [in] The list of localities the new instance should /// represent - default_distribution_policy operator()( - std::vector<id_type> const& locs) const - { - return default_distribution_policy(locs); - } - - /// Create a new \a default_distribution policy representing the given - /// set of localities. - /// - /// \param locs [in] The list of localities the new instance should - /// represent - default_distribution_policy operator()( - std::vector<id_type>&& locs) const + default_distribution_policy operator()(std::vector<id_type> locs) const { return default_distribution_policy(HPX_MOVE(locs)); } @@ -84,9 +72,9 @@ namespace hpx::components { /// /// \param loc [in] The locality the new instance should /// represent - default_distribution_policy operator()(id_type const& loc) const + default_distribution_policy operator()(id_type loc) const { - return default_distribution_policy(loc); + return default_distribution_policy(HPX_MOVE(loc)); } /// Create one object on one of the localities associated by @@ -140,7 +128,7 @@ namespace hpx::components { /// \returns A future holding the list of global addresses that /// represent the newly created objects /// - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> hpx::future<std::vector<bulk_locality_result>> bulk_create( std::size_t count, Ts&&... vs) const { @@ -151,7 +139,7 @@ namespace hpx::components { objs.reserve(localities_->size()); for (hpx::id_type const& loc : *localities_) { - objs.emplace_back(bulk_create_async<Component>( + objs.emplace_back(bulk_create_async<WithCount, Component>( loc, get_num_items(count, loc), vs...)); } @@ -180,7 +168,8 @@ namespace hpx::components { hpx::id_type id = get_next_target(); hpx::future<std::vector<hpx::id_type>> f = - bulk_create_async<Component>(id, count, HPX_FORWARD(Ts, vs)...); + bulk_create_async<WithCount, Component>( + id, count, HPX_FORWARD(Ts, vs)...); return f.then(hpx::launch::sync, [id = HPX_MOVE(id)](hpx::future<std::vector<hpx::id_type>>&& f) @@ -317,9 +306,9 @@ namespace hpx::components { protected: /// \cond NOINTERNAL - explicit default_distribution_policy( - std::vector<id_type> const& localities) - : localities_(std::make_shared<std::vector<id_type>>(localities)) + explicit default_distribution_policy(std::vector<id_type> localities) + : localities_( + std::make_shared<std::vector<id_type>>(HPX_MOVE(localities))) { if (localities_->empty()) { @@ -330,20 +319,9 @@ namespace hpx::components { } } - explicit default_distribution_policy(std::vector<id_type>&& localities) + explicit default_distribution_policy(id_type locality) : localities_( - std::make_shared<std::vector<id_type>>(HPX_MOVE(localities))) - { - if (localities_->empty()) - { - HPX_THROW_EXCEPTION(hpx::error::invalid_status, - "default_distribution_policy::default_distribution_policy", - "unexpectedly empty list of localities"); - } - } - - explicit default_distribution_policy(id_type const& locality) - : localities_(std::make_shared<std::vector<id_type>>(1, locality)) + std::make_shared<std::vector<id_type>>(1, HPX_MOVE(locality))) { } diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/explicit_container_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/explicit_container_distribution_policy.hpp new file mode 100644 index 000000000000..23a89ba9ed72 --- /dev/null +++ b/libs/full/distribution_policies/include/hpx/distribution_policies/explicit_container_distribution_policy.hpp @@ -0,0 +1,160 @@ +// Copyright (c) 2014-2024 Hartmut Kaiser +// +// SPDX-License-Identifier: BSL-1.0 +// 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) + +#pragma once + +#include <hpx/config.hpp> +#include <hpx/actions_base/traits/is_distribution_policy.hpp> +#include <hpx/assert.hpp> +#include <hpx/components_base/agas_interface.hpp> +#include <hpx/distribution_policies/default_distribution_policy.hpp> +#include <hpx/serialization/serialize.hpp> +#include <hpx/serialization/shared_ptr.hpp> +#include <hpx/serialization/vector.hpp> + +#include <algorithm> +#include <cstddef> +#include <memory> +#include <type_traits> +#include <utility> +#include <vector> + +namespace hpx { + + /////////////////////////////////////////////////////////////////////////// + // This class specifies the block chunking policy parameters to use for the + // partitioning of the data in a hpx::partitioned_vector + struct explicit_container_distribution_policy + : components::default_distribution_policy + { + explicit_container_distribution_policy() = default; + + explicit_container_distribution_policy operator()( + std::vector<std::size_t> sizes, + traits::create_mode mode = traits::create_mode::resize) const + { + return {HPX_MOVE(sizes), get_localities(), mode}; + } + + explicit_container_distribution_policy operator()( + std::vector<std::size_t> sizes, hpx::id_type locality, + traits::create_mode mode = traits::create_mode::resize) const + { + return {HPX_MOVE(sizes), HPX_MOVE(locality), mode}; + } + + explicit_container_distribution_policy operator()( + std::vector<std::size_t> sizes, std::vector<id_type> localities, + traits::create_mode mode = traits::create_mode::resize) const + { + return {HPX_MOVE(sizes), HPX_MOVE(localities), mode}; + } + + /////////////////////////////////////////////////////////////////////// + [[nodiscard]] std::size_t get_num_partitions() const noexcept + { + return sizes_.size(); + } + + [[nodiscard]] std::vector<hpx::id_type> get_localities() const + { + if (!localities_) + { + // use this locality, if this object was default constructed + return std::vector<id_type>(1, + naming::get_id_from_locality_id(agas::get_locality_id())); + } + + HPX_ASSERT(!localities_->empty()); + return *localities_; + } + + [[nodiscard]] std::vector<std::size_t> get_sizes() const + { + return sizes_; + } + + [[nodiscard]] constexpr traits::create_mode get_create_mode() const + { + return mode_; + } + + private: + friend class hpx::serialization::access; + + template <typename Archive> + void serialize(Archive& ar, unsigned int const /* version */) + { + // clang-format off + ar & localities_ & sizes_ & mode_; + // clang-format on + } + + explicit_container_distribution_policy(std::vector<std::size_t> sizes, + std::vector<id_type> localities, traits::create_mode mode) + : components::default_distribution_policy(HPX_MOVE(localities)) + , sizes_(HPX_MOVE(sizes)) + , mode_(mode) + { + } + + explicit_container_distribution_policy(std::vector<std::size_t> sizes, + hpx::id_type locality, traits::create_mode mode) + : components::default_distribution_policy(HPX_MOVE(locality)) + , sizes_(HPX_MOVE(sizes)) + , mode_(mode) + { + } + + // number of chunks to create + std::vector<std::size_t> sizes_; + traits::create_mode mode_ = traits::create_mode::resize; + }; + + static explicit_container_distribution_policy const + explicit_container_layout{}; + + /////////////////////////////////////////////////////////////////////////// + namespace traits { + + template <> + struct is_distribution_policy<explicit_container_distribution_policy> + : std::true_type + { + }; + + template <> + struct num_container_partitions<explicit_container_distribution_policy> + { + static std::size_t call( + explicit_container_distribution_policy const& policy) + { + return policy.get_num_partitions(); + } + }; + + template <> + struct container_partition_sizes<explicit_container_distribution_policy> + { + static std::vector<std::size_t> call( + explicit_container_distribution_policy const& policy, + std::size_t) + { + return policy.get_sizes(); + } + }; + + template <> + struct allocation_mode<explicit_container_distribution_policy> + { + static create_mode call( + explicit_container_distribution_policy const& policy) + { + return policy.get_create_mode(); + } + }; + } // namespace traits +} // namespace hpx diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/target_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/target_distribution_policy.hpp index 42f2ee95a900..6a889f5eb37c 100644 --- a/libs/full/distribution_policies/include/hpx/distribution_policies/target_distribution_policy.hpp +++ b/libs/full/distribution_policies/include/hpx/distribution_policies/target_distribution_policy.hpp @@ -90,7 +90,7 @@ namespace hpx::components { /// \returns A future holding the list of global addresses which /// represent the newly created objects /// - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> hpx::future<std::vector<bulk_locality_result>> bulk_create( std::size_t count, Ts&&... vs) const { @@ -98,7 +98,7 @@ namespace hpx::components { // locality hpx::id_type id = get_next_target(); hpx::future<std::vector<hpx::id_type>> f = - components::bulk_create_async<Component>( + components::bulk_create_async<WithCount, Component>( id, count, HPX_FORWARD(Ts, vs)...); return f.then(hpx::launch::sync, diff --git a/libs/full/naming/src/credit_handling.cpp b/libs/full/naming/src/credit_handling.cpp index 175d10eb83c2..97d684f73f49 100644 --- a/libs/full/naming/src/credit_handling.cpp +++ b/libs/full/naming/src/credit_handling.cpp @@ -615,6 +615,9 @@ namespace hpx::naming { "client instead"); } + using preprocess_gid_types = + serialization::detail::preprocess_gid_types; + gid_type new_gid; if (hpx::id_type::management_type::unmanaged == type) { @@ -628,16 +631,15 @@ namespace hpx::naming { } else { - auto& split_gids = ar.get_extra_data< - serialization::detail::preprocess_gid_types>(); + auto& split_gids = ar.get_extra_data<preprocess_gid_types>(); new_gid = split_gids.get_new_gid(id_impl); HPX_ASSERT(new_gid != invalid_gid); } #if defined(HPX_DEBUG) - auto const* split_gids = ar.try_get_extra_data< - serialization::detail::preprocess_gid_types>(); + auto const* split_gids = + ar.try_get_extra_data<preprocess_gid_types>(); HPX_ASSERT(!split_gids || !split_gids->has_gid(id_impl)); #endif diff --git a/libs/full/runtime_components/include/hpx/runtime_components/create_component_helpers.hpp b/libs/full/runtime_components/include/hpx/runtime_components/create_component_helpers.hpp index dfc46a5fcc62..dda2afad561b 100644 --- a/libs/full/runtime_components/include/hpx/runtime_components/create_component_helpers.hpp +++ b/libs/full/runtime_components/include/hpx/runtime_components/create_component_helpers.hpp @@ -27,7 +27,7 @@ namespace hpx::components { template <typename Component, typename... Ts> struct create_component_action; - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> struct bulk_create_component_action; } // namespace server @@ -50,7 +50,7 @@ namespace hpx::components { return hpx::async<action_type>(gid, HPX_FORWARD(Ts, vs)...); } - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> future<std::vector<hpx::id_type>> bulk_create_async( hpx::id_type const& gid, std::size_t count, Ts&&... vs) { @@ -62,8 +62,8 @@ namespace hpx::components { "a locality"); } - using action_type = server::bulk_create_component_action<Component, - std::decay_t<Ts>...>; + using action_type = server::bulk_create_component_action<WithCount, + Component, std::decay_t<Ts>...>; return hpx::async<action_type>(gid, count, HPX_FORWARD(Ts, vs)...); } @@ -74,11 +74,12 @@ namespace hpx::components { return create_async<Component>(gid, HPX_FORWARD(Ts, vs)...).get(); } - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> std::vector<hpx::id_type> bulk_create( hpx::id_type const& gid, std::size_t count, Ts&&... vs) { - return bulk_create_async<Component>(gid, count, HPX_FORWARD(Ts, vs)...) + return bulk_create_async<WithCount, Component>( + gid, count, HPX_FORWARD(Ts, vs)...) .get(); } @@ -99,22 +100,22 @@ namespace hpx::components { return create_colocated_async(gid, HPX_FORWARD(Ts, vs)...).get(); } - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> static future<std::vector<hpx::id_type>> bulk_create_colocated_async( hpx::id_type const& gid, std::size_t count, Ts&&... vs) { - using action_type = server::bulk_create_component_action<Component, - std::decay_t<Ts>...>; + using action_type = server::bulk_create_component_action<WithCount, + Component, std::decay_t<Ts>...>; return hpx::detail::async_colocated<action_type>( gid, count, HPX_FORWARD(Ts, vs)...); } - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> std::vector<hpx::id_type> bulk_create_colocated( hpx::id_type const& id, std::size_t count, Ts&&... vs) { - return bulk_create_colocated_async<Component>( + return bulk_create_colocated_async<WithCount, Component>( id, count, HPX_FORWARD(Ts, vs)...) .get(); } diff --git a/libs/full/runtime_components/include/hpx/runtime_components/new.hpp b/libs/full/runtime_components/include/hpx/runtime_components/new.hpp index 41c2b6e1ceeb..21f0df716873 100644 --- a/libs/full/runtime_components/include/hpx/runtime_components/new.hpp +++ b/libs/full/runtime_components/include/hpx/runtime_components/new.hpp @@ -282,7 +282,7 @@ namespace hpx::components { static type call( hpx::id_type const& locality, std::size_t count, Ts&&... vs) { - return components::bulk_create_async<Component>( + return components::bulk_create_async<false, Component>( locality, count, HPX_FORWARD(Ts, vs)...); } @@ -294,7 +294,7 @@ namespace hpx::components { typename DistPolicy::bulk_locality_result; hpx::future<std::vector<bulk_locality_result>> f = - policy.template bulk_create<Component>( + policy.template bulk_create<false, Component>( count, HPX_FORWARD(Ts, vs)...); return f.then(launch::sync, diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp index a6e2a0de257d..4b0a4be19a52 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/runtime_support.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2013 Hartmut Kaiser +// Copyright (c) 2007-2024 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -58,81 +58,81 @@ namespace hpx { namespace components { /// Asynchronously create N new default constructed components using /// the runtime_support - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> std::vector<hpx::id_type> bulk_create_component( std::size_t /* count */, Ts&&... vs) { - return this->base_type::template bulk_create_component<Component>( - gid_, HPX_FORWARD(Ts, vs)...); + return this->base_type::template bulk_create_component<WithCount, + Component>(gid_, HPX_FORWARD(Ts, vs)...); } /// Asynchronously create a new component using the runtime_support - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> hpx::future<std::vector<hpx::id_type>> bulk_create_components_async( std::size_t /* count */, Ts&&... vs) { - return this->base_type::template bulk_create_component<Component>( - gid_, HPX_FORWARD(Ts, vs)...); + return this->base_type::template bulk_create_component<WithCount, + Component>(gid_, HPX_FORWARD(Ts, vs)...); } /////////////////////////////////////////////////////////////////////// - hpx::future<int> load_components_async() + hpx::future<int> load_components_async() const { return this->base_type::load_components_async(gid_); } - int load_components() + int load_components() const { return this->base_type::load_components(gid_); } - hpx::future<void> call_startup_functions_async(bool pre_startup) + hpx::future<void> call_startup_functions_async(bool pre_startup) const { return this->base_type::call_startup_functions_async( gid_, pre_startup); } - void call_startup_functions(bool pre_startup) + void call_startup_functions(bool pre_startup) const { this->base_type::call_startup_functions(gid_, pre_startup); } /// \brief Shutdown the given runtime system - hpx::future<void> shutdown_async(double timeout = -1) + hpx::future<void> shutdown_async(double timeout = -1) const { return this->base_type::shutdown_async(gid_, timeout); } - void shutdown(double timeout = -1) + void shutdown(double timeout = -1) const { this->base_type::shutdown(gid_, timeout); } /// \brief Shutdown the runtime systems of all localities - void shutdown_all(double timeout = -1) + void shutdown_all(double timeout = -1) const { this->base_type::shutdown_all(gid_, timeout); } /// \brief Terminate the given runtime system - hpx::future<void> terminate_async() + hpx::future<void> terminate_async() const { return this->base_type::terminate_async(gid_); } - void terminate() + void terminate() const { this->base_type::terminate(gid_); } /// \brief Terminate the runtime systems of all localities - void terminate_all() + void terminate_all() const { this->base_type::terminate_all(gid_); } /// \brief Retrieve configuration information - void get_config(util::section& ini) + void get_config(util::section& ini) const { this->base_type::get_config(gid_, ini); } diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp index c4770a6944f4..09196655947a 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/server/runtime_support.hpp @@ -125,10 +125,11 @@ namespace hpx::components::server { template <typename Component, typename T, typename... Ts> naming::gid_type create_component(T v, Ts... vs); - template <typename Component> + template <bool WithCount, typename Component> std::vector<naming::gid_type> bulk_create_component(std::size_t count); - template <typename Component, typename T, typename... Ts> + template <bool WithCount, typename Component, typename T, + typename... Ts> std::vector<naming::gid_type> bulk_create_component( std::size_t count, T v, Ts... vs); @@ -418,7 +419,7 @@ namespace hpx::components::server { } #endif - template <typename Component> + template <bool WithCount, typename Component> std::vector<naming::gid_type> runtime_support::bulk_create_component( std::size_t count) { @@ -431,7 +432,14 @@ namespace hpx::components::server { typedef typename Component::wrapping_type wrapping_type; for (std::size_t i = 0; i != count; ++i) { - ids.emplace_back(create<wrapping_type>()); + if constexpr (WithCount) + { + ids.emplace_back(create<wrapping_type>(i)); + } + else + { + ids.emplace_back(create<wrapping_type>()); + } } LRT_(info).format("successfully created {} component(s) of type: {}", @@ -440,7 +448,7 @@ namespace hpx::components::server { return ids; } - template <typename Component, typename T, typename... Ts> + template <bool WithCount, typename Component, typename T, typename... Ts> std::vector<naming::gid_type> runtime_support::bulk_create_component( std::size_t count, T v, Ts... vs) { @@ -453,7 +461,14 @@ namespace hpx::components::server { typedef typename Component::wrapping_type wrapping_type; for (std::size_t i = 0; i != count; ++i) { - ids.push_back(create<wrapping_type>(v, vs...)); + if constexpr (WithCount) + { + ids.push_back(create<wrapping_type>(i, v, vs...)); + } + else + { + ids.push_back(create<wrapping_type>(v, vs...)); + } } LRT_(info).format("successfully created {} component(s) of type: {}", @@ -634,40 +649,42 @@ namespace hpx::components::server { }; /////////////////////////////////////////////////////////////////////////// - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> struct bulk_create_component_action : ::hpx::actions::action<std::vector<naming::gid_type> ( runtime_support::*)(std::size_t, Ts...), - &runtime_support::bulk_create_component<Component, Ts...>, - bulk_create_component_action<Component, Ts...>> + &runtime_support::bulk_create_component<WithCount, Component, + Ts...>, + bulk_create_component_action<WithCount, Component, Ts...>> { }; - template <typename Component> - struct bulk_create_component_action<Component> + template <bool WithCount, typename Component> + struct bulk_create_component_action<WithCount, Component> : ::hpx::actions::action<std::vector<naming::gid_type> ( runtime_support::*)(std::size_t), - &runtime_support::bulk_create_component<Component>, - bulk_create_component_action<Component>> + &runtime_support::bulk_create_component<WithCount, Component>, + bulk_create_component_action<WithCount, Component>> { }; - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> struct bulk_create_component_direct_action : ::hpx::actions::direct_action<std::vector<naming::gid_type> ( runtime_support::*)( std::size_t, Ts...), - &runtime_support::bulk_create_component<Component, Ts...>, - bulk_create_component_direct_action<Component, Ts...>> + &runtime_support::bulk_create_component<WithCount, Component, + Ts...>, + bulk_create_component_direct_action<WithCount, Component, Ts...>> { }; - template <typename Component> - struct bulk_create_component_direct_action<Component> + template <bool WithCount, typename Component> + struct bulk_create_component_direct_action<WithCount, Component> : ::hpx::actions::direct_action<std::vector<naming::gid_type> ( runtime_support::*)(std::size_t), - &runtime_support::bulk_create_component<Component>, - bulk_create_component_direct_action<Component>> + &runtime_support::bulk_create_component<WithCount, Component>, + bulk_create_component_direct_action<WithCount, Component>> { }; diff --git a/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp b/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp index 673d7c864812..479eb66a5391 100644 --- a/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp +++ b/libs/full/runtime_distributed/include/hpx/runtime_distributed/stubs/runtime_support.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2021 Hartmut Kaiser +// Copyright (c) 2007-2024 Hartmut Kaiser // Copyright (c) 2011 Bryce Lelbach // // SPDX-License-Identifier: BSL-1.0 @@ -68,14 +68,14 @@ namespace hpx { namespace components { namespace stubs { } /// Create multiple new components \a type using the runtime_support - /// colocated with the with the given \a targetgid. This is a + /// colocated with the given \a targetgid. This is a /// non-blocking call. - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> static hpx::future<std::vector<hpx::id_type>> bulk_create_component_colocated_async( hpx::id_type const& gid, std::size_t count, Ts&&... vs) { - typedef server::bulk_create_component_action<Component, + typedef server::bulk_create_component_action<WithCount, Component, typename std::decay<Ts>::type...> action_type; @@ -84,20 +84,20 @@ namespace hpx { namespace components { namespace stubs { } /// Create multiple new components \a type using the runtime_support - /// colocated with the with the given \a targetgid. Block for the + /// colocated with the given \a targetgid. Block for the /// creation to finish. - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> static std::vector<hpx::id_type> bulk_create_component_colocated( hpx::id_type const& gid, std::size_t count, Ts&&... vs) { - return bulk_create_component_colocated_async<Component>( + return bulk_create_component_colocated_async<WithCount, Component>( gid, count, HPX_FORWARD(Ts, vs)...) .get(); } /// Create multiple new components \a type using the runtime_support /// on the given locality. This is a non-blocking call. - template <typename Component, typename... Ts> + template <bool WithCount, typename Component, typename... Ts> static hpx::future<std::vector<hpx::id_type>> bulk_create_component_async( hpx::id_type const& gid, std::size_t count, Ts&&... vs) @@ -111,7 +111,7 @@ namespace hpx { namespace components { namespace stubs { return hpx::make_ready_future(std::vector<hpx::id_type>()); } - typedef server::bulk_create_component_action<Component, + typedef server::bulk_create_component_action<WithCount, Component, typename std::decay<Ts>::type...> action_type; return hpx::async<action_type>(gid, count, HPX_FORWARD(Ts, vs)...); diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp index 09d52e4aabe8..407f0cbeb311 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/all_any_none.hpp @@ -25,7 +25,8 @@ #include <utility> #include <vector> -namespace hpx { namespace parallel { +namespace hpx::parallel { + /////////////////////////////////////////////////////////////////////////// // segmented_all_any_none namespace detail { @@ -479,10 +480,10 @@ namespace hpx { namespace parallel { } /// \endcond } // namespace detail -}} // namespace hpx::parallel +} // namespace hpx::parallel // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { // clang-format off template <typename InIter, @@ -603,4 +604,4 @@ namespace hpx { namespace segmented { hpx::parallel::detail::all_of(), HPX_FORWARD(ExPolicy, policy), first, last, HPX_FORWARD(F, f), hpx::identity_v, is_seq()); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp index 9b009de6d56e..8e8c27cefb28 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp @@ -25,25 +25,26 @@ #include <utility> #include <vector> -namespace hpx { namespace parallel { +namespace hpx::parallel { /////////////////////////////////////////////////////////////////////////// // segmented_for_each namespace detail { + /////////////////////////////////////////////////////////////////////// /// \cond NOINTERNAL // sequential remote implementation template <typename Algo, typename ExPolicy, typename SegIter, typename F, typename Proj> - static typename util::detail::algorithm_result<ExPolicy, SegIter>::type + static util::detail::algorithm_result_t<ExPolicy, SegIter> segmented_for_each(Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, F&& f, Proj&& proj, std::true_type) { - typedef hpx::traits::segmented_iterator_traits<SegIter> traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result<ExPolicy, SegIter> result; + using traits = hpx::traits::segmented_iterator_traits<SegIter>; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result<ExPolicy, SegIter>; segment_iterator sit = traits::segment(first); segment_iterator send = traits::segment(last); @@ -73,7 +74,7 @@ namespace hpx { namespace parallel { std::true_type(), beg, end, f, proj); } - // handle all of the full partitions + // handle all full partitions for (++sit; sit != send; ++sit) { beg = traits::begin(sit); @@ -105,18 +106,17 @@ namespace hpx { namespace parallel { // parallel remote implementation template <typename Algo, typename ExPolicy, typename SegIter, typename F, typename Proj> - static typename util::detail::algorithm_result<ExPolicy, SegIter>::type + static util::detail::algorithm_result_t<ExPolicy, SegIter> segmented_for_each(Algo&& algo, ExPolicy const& policy, SegIter first, SegIter last, F&& f, Proj&& proj, std::false_type) { - typedef hpx::traits::segmented_iterator_traits<SegIter> traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result<ExPolicy, SegIter> result; + using traits = hpx::traits::segmented_iterator_traits<SegIter>; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result<ExPolicy, SegIter>; - typedef std::integral_constant<bool, - !hpx::traits::is_forward_iterator<SegIter>::value> - forced_seq; + using forced_seq = std::integral_constant<bool, + !hpx::traits::is_forward_iterator_v<SegIter>>; segment_iterator sit = traits::segment(first); segment_iterator send = traits::segment(last); @@ -146,7 +146,7 @@ namespace hpx { namespace parallel { policy, forced_seq(), beg, end, f, proj)); } - // handle all of the full partitions + // handle all full partitions for (++sit; sit != send; ++sit) { beg = traits::begin(sit); @@ -181,22 +181,22 @@ namespace hpx { namespace parallel { } /// \endcond } // namespace detail -}} // namespace hpx::parallel +} // namespace hpx::parallel // The segmented iterators we support all live in namespace hpx::segmented -namespace hpx { namespace segmented { +namespace hpx::segmented { // clang-format off template <typename InIter, typename F, HPX_CONCEPT_REQUIRES_( - hpx::traits::is_iterator<InIter>::value && - hpx::traits::is_segmented_iterator<InIter>::value + hpx::traits::is_iterator_v<InIter> && + hpx::traits::is_segmented_iterator_v<InIter> )> // clang-format on InIter tag_invoke(hpx::for_each_t, InIter first, InIter last, F&& f) { - static_assert((hpx::traits::is_forward_iterator<InIter>::value), + static_assert((hpx::traits::is_forward_iterator_v<InIter>), "Requires at least input iterator."); using iterator_traits = hpx::traits::segmented_iterator_traits<InIter>; @@ -222,12 +222,11 @@ namespace hpx { namespace segmented { hpx::traits::is_segmented_iterator_v<SegIter> )> // clang-format on - typename hpx::parallel::util::detail::algorithm_result<ExPolicy, - SegIter>::type + hpx::parallel::util::detail::algorithm_result_t<ExPolicy, SegIter> tag_invoke( hpx::for_each_t, ExPolicy&& policy, SegIter first, SegIter last, F&& f) { - static_assert((hpx::traits::is_forward_iterator<SegIter>::value), + static_assert((hpx::traits::is_forward_iterator_v<SegIter>), "Requires at least forward iterator."); using is_seq = hpx::is_sequenced_execution_policy<ExPolicy>; @@ -253,13 +252,13 @@ namespace hpx { namespace segmented { template <typename InIter, typename Size, typename F, HPX_CONCEPT_REQUIRES_( - hpx::traits::is_iterator<InIter>::value && - hpx::traits::is_segmented_iterator<InIter>::value + hpx::traits::is_iterator_v<InIter> && + hpx::traits::is_segmented_iterator_v<InIter> )> // clang-format on InIter tag_invoke(hpx::for_each_n_t, InIter first, Size count, F&& f) { - static_assert((hpx::traits::is_input_iterator<InIter>::value), + static_assert((hpx::traits::is_input_iterator_v<InIter>), "Requires at least input iterator."); using iterator_traits = hpx::traits::segmented_iterator_traits<InIter>; @@ -270,7 +269,7 @@ namespace hpx { namespace segmented { } auto last = first; - hpx::parallel::detail::advance(last, std::size_t(count)); + hpx::parallel::detail::advance(last, static_cast<std::size_t>(count)); return hpx::parallel::detail::segmented_for_each( hpx::parallel::detail::for_each< typename iterator_traits::local_iterator>(), @@ -287,12 +286,11 @@ namespace hpx { namespace segmented { hpx::traits::is_segmented_iterator_v<SegIter> )> // clang-format on - typename hpx::parallel::util::detail::algorithm_result<ExPolicy, - SegIter>::type + hpx::parallel::util::detail::algorithm_result_t<ExPolicy, SegIter> tag_invoke( hpx::for_each_n_t, ExPolicy&& policy, SegIter first, Size count, F&& f) { - static_assert((hpx::traits::is_forward_iterator<SegIter>::value), + static_assert((hpx::traits::is_forward_iterator_v<SegIter>), "Requires at least input iterator."); using is_seq = hpx::is_sequenced_execution_policy<ExPolicy>; @@ -308,11 +306,11 @@ namespace hpx { namespace segmented { using iterator_traits = hpx::traits::segmented_iterator_traits<SegIter>; auto last = first; - hpx::parallel::detail::advance(last, std::size_t(count)); + hpx::parallel::detail::advance(last, static_cast<std::size_t>(count)); return segmented_for_each( hpx::parallel::detail::for_each< typename iterator_traits::local_iterator>(), HPX_FORWARD(ExPolicy, policy), first, last, HPX_FORWARD(F, f), hpx::identity_v, is_seq()); } -}} // namespace hpx::segmented +} // namespace hpx::segmented diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_for_each.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_for_each.cpp index dcc549ee4b64..45cc47a6345e 100644 --- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_for_each.cpp +++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_for_each.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2023 Hartmut Kaiser +// Copyright (c) 2014-2024 Hartmut Kaiser // Copyright (c) 2017 Ajai V George // // SPDX-License-Identifier: BSL-1.0 @@ -134,32 +134,84 @@ void test_for_each_async( verify_values_count_async(policy, v, val); } +template <typename T> +struct apply_wrap +{ + template <typename T_> + void operator()([[maybe_unused]] T_& val) const + { + } + + hpx::reference_wrapper<hpx::partitioned_vector<T>> v; + + template <typename Archive> + void serialize(Archive& ar, unsigned) + { + // clang-format off + ar & v; + // clang-format on + } +}; + +template <typename ExPolicy, typename T> +void test_for_each_apply(ExPolicy&& policy, hpx::partitioned_vector<T>& v) +{ + hpx::for_each(policy, v.begin(), v.end(), apply_wrap<T>{v}); +} + /////////////////////////////////////////////////////////////////////////////// template <typename T> void for_each_tests(std::vector<hpx::id_type>& localities) { + //{ + // hpx::partitioned_vector<T> v; + // hpx::for_each(v.begin(), v.end(), pfo()); + // hpx::for_each(hpx::execution::seq, v.begin(), v.end(), pfo()); + // hpx::for_each(hpx::execution::par, v.begin(), v.end(), pfo()); + // hpx::for_each(hpx::execution::seq(hpx::execution::task), v.begin(), + // v.end(), pfo()) + // .get(); + // hpx::for_each(hpx::execution::par(hpx::execution::task), v.begin(), + // v.end(), pfo()) + // .get(); + //} + + constexpr std::size_t length = 12; + + //{ + // hpx::partitioned_vector<T> v( + // length, T(0), hpx::container_layout(localities)); + // test_for_each(v, T(0)); + // test_for_each(hpx::execution::seq, v, T(1)); + // test_for_each(hpx::execution::par, v, T(2)); + // test_for_each_async(hpx::execution::seq(hpx::execution::task), v, T(3)); + // test_for_each_async(hpx::execution::par(hpx::execution::task), v, T(4)); + //} + { - hpx::partitioned_vector<T> v; - hpx::for_each(v.begin(), v.end(), pfo()); - hpx::for_each(hpx::execution::seq, v.begin(), v.end(), pfo()); - hpx::for_each(hpx::execution::par, v.begin(), v.end(), pfo()); - hpx::for_each(hpx::execution::seq(hpx::execution::task), v.begin(), - v.end(), pfo()) - .get(); - hpx::for_each(hpx::execution::par(hpx::execution::task), v.begin(), - v.end(), pfo()) - .get(); + hpx::partitioned_vector<T> v( + length, T(0), hpx::container_layout(localities)); + + v.register_as("foreach_test1"); + test_for_each_apply(hpx::execution::seq, v); + test_for_each_apply(hpx::execution::par, v); } { - constexpr std::size_t length = 12; + std::vector<std::size_t> sizes; + sizes.reserve(localities.size()); + + for (std::size_t i = 0; i != localities.size(); ++i) + { + sizes.push_back(length / localities.size()); + } + hpx::partitioned_vector<T> v( - length, T(0), hpx::container_layout(localities)); - test_for_each(v, T(0)); - test_for_each(hpx::execution::seq, v, T(1)); - test_for_each(hpx::execution::par, v, T(2)); - test_for_each_async(hpx::execution::seq(hpx::execution::task), v, T(3)); - test_for_each_async(hpx::execution::par(hpx::execution::task), v, T(4)); + length, T(0), hpx::explicit_container_layout(sizes, localities)); + + v.register_as("foreach_test2"); + test_for_each_apply(hpx::execution::seq, v); + test_for_each_apply(hpx::execution::par, v); } } diff --git a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_inclusive_scan.cpp b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_inclusive_scan.cpp index 16587be0207b..e56fba6ae927 100644 --- a/libs/full/segmented_algorithms/tests/unit/partitioned_vector_inclusive_scan.cpp +++ b/libs/full/segmented_algorithms/tests/unit/partitioned_vector_inclusive_scan.cpp @@ -1,11 +1,12 @@ // Copyright (c) 2016 Minh-Khanh Do -// Copyright (c) 2022 Hartmut Kaiser +// Copyright (c) 2022-2024 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // 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/config.hpp> + #if !defined(HPX_COMPUTE_DEVICE_CODE) #include <hpx/hpx_main.hpp> #include <hpx/include/parallel_scan.hpp> @@ -33,7 +34,6 @@ << g << " " << h << " " << i << " "; /////////////////////////////////////////////////////////////////////////////// - template <typename T> struct opt { @@ -322,9 +322,9 @@ template <typename T> void inclusive_scan_tests(std::vector<hpx::id_type>& localities) { #if defined(HPX_DEBUG) - std::size_t const length = 1000; + constexpr std::size_t length = 1000; #else - std::size_t const length = 10000; + constexpr std::size_t length = 10000; #endif inclusive_scan_tests_with_policy<T>(length, hpx::container_layout); @@ -357,4 +357,5 @@ int main() inclusive_scan_tests<long long>(localities); return hpx::util::report_errors(); } + #endif