From 1cb7be4b4544b81379196db52332631b4da94d2f Mon Sep 17 00:00:00 2001 From: Hartmut Kaiser 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 | 78 ++++- .../partitioned_vector_component_impl.hpp | 105 +++++-- .../partitioned_vector_decl.hpp | 267 ++++++++++++---- .../partitioned_vector_impl.hpp | 143 +++++---- .../partitioned_vector_predef.hpp | 29 +- .../partitioned_vector_segmented_iterator.hpp | 284 ++++++++++-------- .../serialization/partitioned_vector.hpp | 115 +++++++ .../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 | 15 + .../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 | 23 +- .../default_distribution_policy.hpp | 46 +-- ...explicit_container_distribution_policy.hpp | 144 +++++++++ .../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 | 65 ++-- .../unit/partitioned_vector_for_each.cpp | 88 ++++-- .../partitioned_vector_inclusive_scan.cpp | 9 +- 44 files changed, 1353 insertions(+), 547 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 @@ - + @@ -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..357941d3c9f0 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 #include #include +#include #include #include #include @@ -39,11 +40,33 @@ #include +namespace hpx::detail { + + HPX_HAS_XXX_TRAIT_DEF(allocator_type); + + template + struct extract_allocator_type + { + using type = std::allocator; + }; + + template + struct extract_allocator_type>> + { + using type = typename Data::allocator_type; + }; + + template + using extract_allocator_type_t = + typename extract_allocator_type::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 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; 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,15 @@ namespace hpx::server { /// size 0. partitioned_vector(); - explicit partitioned_vector(size_type partition_size); + enum class create_mode + { + resize = 0, + reserve = 1 + }; + + explicit partitioned_vector(std::size_t partnum, + std::vector const& partition_sizes, + create_mode = create_mode::resize); /// Constructor which create and initialize partitioned_vector_partition /// with all elements as \a val. @@ -79,9 +110,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 const& partition_sizes, T const& val); - partitioned_vector(size_type partition_size, T const& val, + partitioned_vector(std::size_t partnum, + std::vector const& partition_sizes, T const& val, allocator_type const& alloc); // support components::copy @@ -274,13 +307,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 + util::invoke_result_t apply( + std::size_t pos, F f, Ts... ts); + + template + struct apply_action + : hpx::actions::make_action_t< + decltype(&partitioned_vector::apply), + &partitioned_vector::apply, apply_action> + { + }; }; } // 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 +358,17 @@ namespace hpx::server { #define HPX_REGISTER_VECTOR_DECLARATION_1(type) \ HPX_REGISTER_VECTOR_DECLARATION_2(type, std::vector) \ -/**/ + /**/ #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 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 +611,7 @@ namespace hpx { /// hpx::future 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 +625,13 @@ namespace hpx { /// hpx::future 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 + hpx::future> 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..e0f47dea348f 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 HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT - partitioned_vector::partitioned_vector(size_type partition_size) - : partitioned_vector_partition_(partition_size) + partitioned_vector::partitioned_vector(std::size_t partnum, + std::vector const& partition_sizes, create_mode mode) { + if (mode == create_mode::resize) + { + partitioned_vector_partition_.resize(partition_sizes[partnum]); + } + else + { + partitioned_vector_partition_.reserve(partition_sizes[partnum]); + } } template HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT - partitioned_vector::partitioned_vector( - size_type partition_size, T const& val) - : partitioned_vector_partition_(partition_size, val) + partitioned_vector::partitioned_vector(std::size_t partnum, + std::vector const& partition_sizes, T const& val) + : partitioned_vector_partition_(partition_sizes[partnum], val) { } template HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT - partitioned_vector::partitioned_vector( - size_type partition_size, T const& val, allocator_type const& alloc) - : partitioned_vector_partition_(partition_size, val, alloc) + partitioned_vector::partitioned_vector(std::size_t partnum, + std::vector 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 + template + HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT + util::invoke_result_t + partitioned_vector::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 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, 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 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 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(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( - 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( - this->get_id(), pos); + return hpx::async( + typename server_type::get_value_action(), this->get_id(), pos); #else HPX_ASSERT(false); return hpx::future{}; @@ -421,8 +453,8 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async( - 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{}); @@ -452,7 +484,7 @@ namespace hpx { { #if !defined(HPX_COMPUTE_DEVICE_CODE) HPX_ASSERT(this->get_id()); - return hpx::async( + 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( - 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( + 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( - 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_partitionget_id()); - return hpx::async( + 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 */> + template + HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT + hpx::future> + partitioned_vector_partition::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(), + 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()); #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..21e4f6e52cff 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 #include #include -#include +#include +#include #include #include #include +#include #include #include @@ -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 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; 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::pointer; using const_pointer = @@ -173,6 +180,9 @@ namespace hpx { using partitioned_vector_partition_client = hpx::partitioned_vector_partition; + using create_mode = + typename partitioned_vector_partition_server::create_mode; + struct partition_data : server::partitioned_vector_config_data::partition_data { @@ -181,9 +191,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 +210,7 @@ namespace hpx { // size, and locality id. using partitions_vector_type = std::vector; - 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 +239,8 @@ namespace hpx { segmented::local_segment_vector_iterator; + using partition_data_type = partition_data; + private: friend class segmented::vector_iterator; friend class segmented::const_vector_iterator; @@ -239,9 +250,9 @@ namespace hpx { friend class segmented::const_segment_vector_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 @@ -285,15 +296,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(-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 @@ -322,19 +326,21 @@ namespace hpx { template static hpx::future> create_helper1( - DistPolicy const& policy, std::size_t count, std::size_t size); + DistPolicy const& policy, std::size_t count, + std::vector const& sizes, create_mode mode); template static hpx::future> 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 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 - void create(DistPolicy const& policy, Create&& creator); + void create(DistPolicy const& policy, Create&& creator, + create_mode mode = create_mode::resize); template void create(DistPolicy const& policy); @@ -345,21 +351,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 +400,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 + explicit partitioned_vector(DistPolicy const& policy, + std::enable_if_t>* = + 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 +422,12 @@ namespace hpx { /// template partitioned_vector(size_type size, DistPolicy const& policy, - std::enable_if_t< - traits::is_distribution_policy::value>* = nullptr); + std::enable_if_t>* = + 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 +438,8 @@ namespace hpx { template partitioned_vector(size_type size, T const& val, DistPolicy const& policy, - std::enable_if_t< - traits::is_distribution_policy::value>* = nullptr); + std::enable_if_t>* = + nullptr); /// Copy construction performs a deep copy of the right hand side /// vector. @@ -411,11 +454,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(-1); } public: @@ -469,15 +510,19 @@ namespace hpx { this->base_type::operator=(static_cast(rhs)); size_ = rhs.size_; - partition_size_ = rhs.partition_size_; partitions_ = HPX_MOVE(rhs.partitions_); rhs.size_ = 0; - rhs.partition_size_ = static_cast(-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 +535,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 // @@ -519,7 +573,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); @@ -990,21 +1046,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(pos_block_begin, pos_it)), - std::vector(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(pos_block_begin, pos_it)), + std::vector(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 +1077,38 @@ namespace hpx { return set_values(pos, val).get(); } + template + future> 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 + future> apply( + std::size_t pos, F f, Ts... ts) + { + return apply_on(get_partition(pos), pos, HPX_FORWARD(F, f), + HPX_FORWARD(Ts, ts)...); + } + + template + util::invoke_result_t apply( + launch::sync_policy, std::size_t pos, F f, Ts... ts) + { + return apply_on(get_partition(pos), 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 +1367,67 @@ namespace hpx { return segment_cend(naming::get_locality_id_from_id(id)); } }; + + /////////////////////////////////////////////////////////////////////////// + template + struct reference_wrapper> + { + using wrapped_type = partitioned_vector; + + // we define a default constructor to support serialization + reference_wrapper() = default; + + // clang-format off + template , 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 ptr{}; + }; + + template + reference_wrapper> ref( + partitioned_vector&& val) noexcept + { + return reference_wrapper>(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..434ba872f131 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 #include #include -#include +#include #include #include #include @@ -42,18 +42,28 @@ namespace hpx { template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t - partitioned_vector::get_partition_size() const + partitioned_vector::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 */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t - partitioned_vector::get_global_index( - std::size_t segment, std::size_t part_size, size_type local_index) const + partitioned_vector::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 */> @@ -72,11 +82,9 @@ namespace hpx { std::vector> 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,12 +182,25 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t partitioned_vector::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(); } @@ -189,15 +209,8 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t partitioned_vector::get_local_index(size_type global_index) const { - if (global_index == size_ || - partition_size_ == static_cast(-1) || - partition_size_ == 0) - { - return static_cast(-1); - } - - return (partition_size_ != size_) ? (global_index % partition_size_) : - global_index; + std::size_t partnum = get_partition(global_index); + return global_index - partitions_[partnum].first_; } template */> @@ -207,7 +220,9 @@ namespace hpx { std::vector indices) const { for (size_type& index : indices) + { index = get_local_index(index); + } return indices; } @@ -290,13 +305,15 @@ namespace hpx { template HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT hpx::future< std::vector::bulk_locality_result>> - partitioned_vector::create_helper1( - DistPolicy const& policy, std::size_t count, std::size_t size) + partitioned_vector::create_helper1(DistPolicy const& policy, + std::size_t count, std::vector const& sizes, + create_mode mode) { using component_type = typename partitioned_vector_partition_client::server_component_type; - return policy.template bulk_create(count, size); + return policy.template bulk_create( + count, sizes, mode); } template */> @@ -304,12 +321,13 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT hpx::future< std::vector::bulk_locality_result>> partitioned_vector::create_helper2(DistPolicy const& policy, - std::size_t count, std::size_t size, T const& val) + std::size_t count, std::vector const& sizes, T const& val) { using component_type = typename partitioned_vector_partition_client::server_component_type; - return policy.template bulk_create(count, size, val); + return policy.template bulk_create( + count, sizes, val); } template */> @@ -329,18 +347,19 @@ namespace hpx { template */> template void partitioned_vector::create( - DistPolicy const& policy, Create&& creator) + DistPolicy const& policy, Create&& creator, create_mode mode) { std::size_t num_parts = traits::num_container_partitions::call(policy); - std::size_t part_size = (size_ + num_parts - 1) / num_parts; + std::vector part_sizes = + traits::container_partition_sizes::call(policy, size_); // create as many partitions as required hpx::future> 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> 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]); HPX_ASSERT(l < num_parts); } } HPX_ASSERT(l == num_parts); hpx::wait_all(ptrs); - - // cache our partition size - partition_size_ = get_partition_size(); } template */> @@ -405,7 +420,8 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void partitioned_vector::create(DistPolicy const& policy) { - create(policy, &partitioned_vector::create_helper1); + create(policy, &partitioned_vector::create_helper1, + create_mode::reserve); } template */> @@ -414,19 +430,21 @@ namespace hpx { partitioned_vector::create(T const& val, DistPolicy const& policy) { create(policy, - hpx::bind_back(&partitioned_vector::create_helper2, - std::ref(val))); + [&val](DistPolicy const& policy, std::size_t num_parts, + std::vector const& part_sizes, create_mode) { + return create_helper2(policy, num_parts, part_sizes, val); + }); } template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void partitioned_vector::copy_from(partitioned_vector const& rhs) { - using const_iterator = typename partitions_vector_type::const_iterator; - std::vector> 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::partitioned_vector() : size_(0) - , partition_size_(static_cast(-1)) { } @@ -480,7 +497,6 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT partitioned_vector::partitioned_vector(size_type size) : size_(size) - , partition_size_(static_cast(-1)) { if (size != 0) create(hpx::container_layout); @@ -491,7 +507,6 @@ namespace hpx { partitioned_vector::partitioned_vector( size_type size, T const& val) : size_(size) - , partition_size_(static_cast(-1)) { if (size != 0) create(val, hpx::container_layout); @@ -502,23 +517,31 @@ namespace hpx { HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT partitioned_vector::partitioned_vector(size_type size, DistPolicy const& policy, - std::enable_if_t::value>*) + std::enable_if_t>*) : size_(size) - , partition_size_(static_cast(-1)) { if (size != 0) create(policy); } + template */> + template + HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT + partitioned_vector::partitioned_vector(DistPolicy const& policy, + std::enable_if_t>*) + : size_(0) + { + reserve(policy); + } + template */> template HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT partitioned_vector::partitioned_vector(size_type size, T const& val, DistPolicy const& policy, std::enable_if_t< - traits::is_distribution_policy::value>* /*= nullptr*/) + traits::is_distribution_policy_v>* /*= nullptr*/) : size_(size) - , partition_size_(static_cast(-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 +#include #include #include @@ -36,6 +37,12 @@ extern template hpx::partitioned_vector>::partitioned_vector(size_type, double const&, hpx::container_distribution_policy const&, void*); +extern template hpx::partitioned_vector>::partitioned_vector(size_type, + hpx::explicit_container_distribution_policy const&, void*); +extern template hpx::partitioned_vector>::partitioned_vector(size_type, double const&, + hpx::explicit_container_distribution_policy const&, void*); // partitioned_vector HPX_REGISTER_PARTITIONED_VECTOR_DECLARATION(int) @@ -49,9 +56,15 @@ extern template hpx::partitioned_vector>::partitioned_vector(size_type, int const&, hpx::container_distribution_policy const&, void*); +extern template hpx::partitioned_vector>::partitioned_vector(size_type, + hpx::explicit_container_distribution_policy const&, void*); +extern template hpx::partitioned_vector>::partitioned_vector(size_type, int const&, + hpx::explicit_container_distribution_policy const&, void*); // partitioned_vector -typedef long long long_long; +using long_long = long long; HPX_REGISTER_PARTITIONED_VECTOR_DECLARATION(long_long) extern template class hpx::server::partitioned_vector>::partitioned_vector(size_type, long long const&, hpx::container_distribution_policy const&, void*); +extern template hpx::partitioned_vector>::partitioned_vector(size_type, + hpx::explicit_container_distribution_policy const&, void*); +extern template hpx::partitioned_vector>::partitioned_vector(size_type, long long const&, + hpx::explicit_container_distribution_policy const&, void*); // partitioned_vector using partitioned_vector_std_string_argument = std::string; @@ -85,5 +104,11 @@ extern template hpx::partitioned_vector>::partitioned_vector(size_type, std::string const&, hpx::container_distribution_policy const&, void*); +extern template hpx::partitioned_vector>::partitioned_vector(size_type, + hpx::explicit_container_distribution_policy const&, void*); +extern template hpx::partitioned_vector>::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> const& data) + std::shared_ptr> 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> const& data) + std::shared_ptr> 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 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 const& it_; }; @@ -202,15 +226,23 @@ namespace hpx::segmented { struct vector_value_proxy { explicit vector_value_proxy( - hpx::partitioned_vector& v, std::size_t index) - : v_(v) + hpx::partitioned_vector& 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 , 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& v_; + private: + partitioned_vector* 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(-1)) - { - } + local_vector_iterator() = default; - local_vector_iterator(hpx::id_type const& partition, - size_type local_index, - std::shared_ptr> const& data) - : partition_(partitioned_vector_partition(partition)) + local_vector_iterator(hpx::id_type partition, + size_type const local_index, + std::shared_ptr> data) + : partition_( + partitioned_vector_partition(HPX_MOVE(partition))) , local_index_(local_index) - , data_(data) + , data_(HPX_MOVE(data)) { } local_vector_iterator(partitioned_vector_partition partition, - size_type local_index, - std::shared_ptr> const& data) - : partition_(partition) + size_type const local_index, + std::shared_ptr> 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 - void load(Archive& ar, unsigned /* version */) - { - ar & partition_ & local_index_; - } - template - 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(*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& get_partition() + partitioned_vector_partition& get_partition() noexcept { return partition_; } - partitioned_vector_partition get_partition() const + partitioned_vector_partition 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>& get_data() { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return data_; } std::shared_ptr> const& get_data() const { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return data_; } protected: // refer to a partition of the vector - partitioned_vector_partition partition_; + partitioned_vector_partition partition_{}; // local position in the referenced partition - size_type local_index_; + size_type local_index_ = static_cast(-1); // caching address of component - mutable std::shared_ptr> data_; + mutable std::shared_ptr> data_{}; }; template @@ -389,7 +421,6 @@ namespace hpx::segmented { T const, std::random_access_iterator_tag, segmented::detail::const_local_vector_value_proxy> { - private: using base_type = hpx::util::iterator_facade, 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(-1)) - { - } + const_local_vector_iterator() = default; - const_local_vector_iterator(hpx::id_type const& partition, - size_type local_index, - std::shared_ptr> const& data) - : partition_(partitioned_vector_partition(partition)) + const_local_vector_iterator(hpx::id_type partition, + size_type const local_index, + std::shared_ptr> data) + : partition_( + partitioned_vector_partition(HPX_MOVE(partition))) , local_index_(local_index) - , data_(data) + , data_(HPX_MOVE(data)) { } const_local_vector_iterator( partitioned_vector_partition partition, - size_type local_index, - std::shared_ptr> const& data) - : partition_(partition) + size_type const local_index, + std::shared_ptr> 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 - void load(Archive& ar, unsigned /* version */) + void serialize(Archive& ar, unsigned /* version */) { ar & partition_ & local_index_; } - template - 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 const& get_partition() const + partitioned_vector_partition 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>& get_data() { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return data_; } std::shared_ptr> const& get_data() const { if (partition_ && !data_) + { data_ = partition_.get_ptr(); + } return data_; } protected: // refer to a partition of the vector - partitioned_vector_partition partition_; + partitioned_vector_partition partition_{}; // local position in the referenced partition - size_type local_index_; + size_type local_index_ = static_cast(-1); // caching address of component - mutable std::shared_ptr> data_; + mutable std::shared_ptr> data_{}; }; /////////////////////////////////////////////////////////////////////////// @@ -552,10 +581,7 @@ namespace hpx::segmented { segment_vector_iterator, BaseIter>; public: - segment_vector_iterator() - : data_(nullptr) - { - } + segment_vector_iterator() = default; explicit segment_vector_iterator( BaseIter const& it, partitioned_vector* data = nullptr) @@ -564,11 +590,12 @@ namespace hpx::segmented { { } - partitioned_vector* get_data() + [[nodiscard]] partitioned_vector* get_data() noexcept { return data_; } - partitioned_vector const* get_data() const + [[nodiscard]] partitioned_vector const* get_data() + const noexcept { return data_; } @@ -580,7 +607,7 @@ namespace hpx::segmented { } private: - partitioned_vector* data_; + partitioned_vector* data_ = nullptr; }; template @@ -593,10 +620,7 @@ namespace hpx::segmented { const_segment_vector_iterator, BaseIter>; public: - const_segment_vector_iterator() - : data_(nullptr) - { - } + const_segment_vector_iterator() = default; template explicit const_segment_vector_iterator( @@ -613,7 +637,8 @@ namespace hpx::segmented { { } - partitioned_vector const* get_data() const + [[nodiscard]] partitioned_vector const* get_data() + const noexcept { return data_; } @@ -625,11 +650,12 @@ namespace hpx::segmented { } private: - partitioned_vector const* data_; + partitioned_vector const* data_ = nullptr; }; /////////////////////////////////////////////////////////////////////////// namespace detail { + template struct is_requested_locality { @@ -637,12 +663,12 @@ namespace hpx::segmented { typename std::iterator_traits::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> data_; @@ -759,30 +799,30 @@ namespace hpx::segmented { using local_iterator = typename partitioned_vector::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(-1)) - { - } + vector_iterator() = default; - vector_iterator( - partitioned_vector* data, size_type global_index) + vector_iterator(partitioned_vector* data, + size_type const global_index) noexcept : data_(data) , global_index_(global_index) { } - partitioned_vector* get_data() + [[nodiscard]] partitioned_vector* get_data() noexcept { return data_; } - partitioned_vector const* get_data() const + [[nodiscard]] partitioned_vector 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* data_; + partitioned_vector* data_ = nullptr; // global position in the referenced vector - size_type global_index_; + size_type global_index_ = static_cast(-1); }; /////////////////////////////////////////////////////////////////////////// @@ -853,25 +893,24 @@ namespace hpx::segmented { using local_iterator = typename partitioned_vector::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(-1)) - { - } + const_vector_iterator() = default; - const_vector_iterator( - partitioned_vector const* data, size_type global_index) + const_vector_iterator(partitioned_vector const* data, + size_type const global_index) noexcept : data_(data) , global_index_(global_index) { } - partitioned_vector const* get_data() const + partitioned_vector 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 const* data_; + partitioned_vector const* data_ = nullptr; // global position in the referenced vector - size_type global_index_; + size_type global_index_ = static_cast(-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..a843bb55c8f1 --- /dev/null +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp @@ -0,0 +1,115 @@ +// 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 +#include +#include + +namespace hpx::serialization { + + template + void serialize( + input_archive& ar, hpx::partitioned_vector& v, unsigned) + { + using partitioned_vector = hpx::partitioned_vector; + bool has_id = false; + ar >> has_id; + if (has_id) + { + hpx::id_type id; + std::size_t size; + std::vector + 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 + void serialize( + output_archive& ar, hpx::partitioned_vector 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 + void serialize(input_archive& ar, + hpx::reference_wrapper>& v, unsigned) + { + using partitioned_vector = hpx::partitioned_vector; + + bool has_id = false; + ar >> has_id; + if (has_id) + { + hpx::id_type id; + std::size_t size; + std::vector + 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 + void serialize(output_archive& ar, + hpx::reference_wrapper> 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 - - - +#include 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 - - - +#include 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 -#include -#include -#include - -#include - -namespace hpx::serialization { - - template - void serialize(input_archive& ar, hpx::partitioned_vector& v, unsigned) - { - std::string pvec_registered_name; - ar >> pvec_registered_name; - v.connect_to(pvec_registered_name).get(); - } - - template - void serialize( - output_archive& ar, const hpx::partitioned_vector& 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 +#include #include #include @@ -36,6 +37,12 @@ hpx::partitioned_vector>::partitioned_vector( template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector>::partitioned_vector( size_type, double const&, hpx::container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT +hpx::partitioned_vector>::partitioned_vector( + size_type, hpx::explicit_container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector>::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 +#include #include #include @@ -38,6 +39,12 @@ hpx::partitioned_vector>::partitioned_vector( template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector>::partitioned_vector( size_type, int const&, hpx::container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT +hpx::partitioned_vector>::partitioned_vector( + size_type, hpx::explicit_container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT +hpx::partitioned_vector>::partitioned_vector( + size_type, int const&, hpx::explicit_container_distribution_policy const&, void*); template class HPX_PARTITIONED_VECTOR_EXPORT hpx::server::partitioned_vector>; @@ -51,6 +58,12 @@ hpx::partitioned_vector>::partitioned_vector( template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector>::partitioned_vector(size_type, long long const&, hpx::container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT +hpx::partitioned_vector>::partitioned_vector( + size_type, hpx::explicit_container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector>::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 +#include #include #include @@ -39,6 +40,12 @@ template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector>::partitioned_vector(size_type, std::string const&, hpx::container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector>::partitioned_vector(size_type, + hpx::explicit_container_distribution_policy const&, void*); +template HPX_PARTITIONED_VECTOR_EXPORT hpx::partitioned_vector>::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 #include -#include #include +#include +#include #include #include @@ -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 buffer; - hpx::serialization::output_archive oarchive( - buffer, hpx::serialization::archive_flags::disable_data_chunking); - std::size_t sz = static_cast(maxval - minval); hpx::partitioned_vector 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> f = - policy.template bulk_create(num_parts); + policy.template bulk_create(num_parts); // now initialize our data structures init(f.get()); @@ -454,7 +454,7 @@ namespace hpx { // create as many partitions as required hpx::future> f = - policy.template bulk_create( + policy.template bulk_create( 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 ::value && !std::is_final::value> + bool Empty = std::is_empty_v && !std::is_final_v> 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 + +#include + +namespace hpx { + + /////////////////////////////////////////////////////////////////////////// + template + struct reference_wrapper : std::reference_wrapper + { + reference_wrapper() = delete; + + using std::reference_wrapper::referrence_wrapper; + }; + + template + [[nodiscard]] constexpr reference_wrapper ref(T& val) noexcept + { + return reference_wrapper(val); + } + + template + void ref(T const&&) = delete; + + template + [[nodiscard]] constexpr reference_wrapper ref( + reference_wrapper val) noexcept + { + return val; + } + + template + [[nodiscard]] constexpr reference_wrapper cref( + T const& val) noexcept + { + return reference_wrapper(val); + } + + template + void cref(T const&&) = delete; + + template + [[nodiscard]] constexpr reference_wrapper cref( + reference_wrapper 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 + +#include #include #include @@ -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 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 + template struct use_operator_brackets_proxy : std::integral_constant && - std::is_const_v)> + !(std::is_copy_constructible_v && + std::is_const_v)> + { + }; + + template + struct use_operator_brackets_proxy>> + : Iterator::use_brackets_proxy { }; template struct operator_brackets_result { - using type = - std::conditional_t::value, - operator_brackets_proxy, Value>; + using type = std::conditional_t< + use_operator_brackets_proxy::value, + operator_brackets_proxy, Value>; }; template @@ -319,11 +333,9 @@ namespace hpx::util { HPX_HOST_DEVICE iterator_facade_base() = default; - HPX_HOST_DEVICE constexpr - typename operator_brackets_result::type - operator[](difference_type n) const + HPX_HOST_DEVICE constexpr auto operator[](difference_type n) const { - using use_proxy = use_operator_brackets_proxy; + using use_proxy = use_operator_brackets_proxy; return make_operator_brackets_result( 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 \ { \ - }; /**/ + }; \ + /**/ #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..32dd0e48e7ba 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 #include +#include namespace hpx::traits { @@ -31,4 +32,18 @@ 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 + struct container_partition_sizes + { + static std::vector call( + Policy const& policy, std::size_t const size) + { + std::size_t const num_parts = policy.get_num_partitions(); + return std::vector( + num_parts, (size + num_parts - 1) / num_parts); + } + }; } // 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 + template hpx::future> 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(localities.back(), - num_partitions, ts..., HPX_MOVE(local_targets))); + components::bulk_create_async( + 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 const& localities_; }; - template + template struct create_bulk_helper { typedef std::pair> @@ -104,7 +104,7 @@ namespace hpx::components { for (std::size_t i = 0; i != to_create.size(); ++i) { - objs.emplace_back(bulk_create_async( + objs.emplace_back(bulk_create_async( 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 + template hpx::future> 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(localities_), count, - HPX_FORWARD(Ts, vs)...)); + detail::create_bulk_helper( + localities_), + count, HPX_FORWARD(Ts, vs)...)); } // handle special cases @@ -291,7 +292,8 @@ namespace hpx::components { localities_.front(); hpx::future> f = - bulk_create_async(id, count, HPX_FORWARD(Ts, vs)...); + bulk_create_async( + id, count, HPX_FORWARD(Ts, vs)...); return f.then(hpx::launch::sync, [id = HPX_MOVE(id)](hpx::future>&& 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( + naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)), + HPX_FORWARD(Ts, vs)...); + } return create_colocated_async( 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 + template hpx::future> 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( + f = bulk_create_async( + 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( id, count, HPX_FORWARD(Ts, vs)...); } else { id = id_; - f = bulk_create_colocated_async( + f = bulk_create_colocated_async( 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(policy, + naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)), + HPX_FORWARD(Ts, vs)...); + } return hpx::detail::async_colocated( 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(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( 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( + 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( 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( + naming::get_id_from_locality_id( + naming::get_locality_id_from_id(id_)), + policy, HPX_FORWARD(Ts, vs)...); + } return hpx::detail::post_colocated( 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( + 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( 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( + 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( 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..f222bdfe5a94 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 @@ -31,14 +31,12 @@ 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 { - return container_distribution_policy( - num_partitions, get_localities()); + return {num_partitions, get_localities()}; } container_distribution_policy operator()( @@ -52,10 +50,9 @@ namespace hpx { { if (num_partitions_ != static_cast(-1)) { - return container_distribution_policy( - num_partitions_, localities); + return {num_partitions_, localities}; } - return container_distribution_policy(localities.size(), localities); + return {localities.size(), localities}; } container_distribution_policy operator()( @@ -63,24 +60,21 @@ namespace hpx { { if (num_partitions_ != static_cast(-1)) { - return container_distribution_policy( - num_partitions_, HPX_MOVE(localities)); + return {num_partitions_, HPX_MOVE(localities)}; } - return container_distribution_policy( - localities.size(), HPX_MOVE(localities)); + return {localities.size(), HPX_MOVE(localities)}; } container_distribution_policy operator()(std::size_t num_partitions, std::vector const& localities) const { - return container_distribution_policy(num_partitions, localities); + return {num_partitions, localities}; } container_distribution_policy operator()( std::size_t num_partitions, std::vector&& localities) const { - return container_distribution_policy( - num_partitions, HPX_MOVE(localities)); + return {num_partitions, HPX_MOVE(localities)}; } /////////////////////////////////////////////////////////////////////// @@ -140,7 +134,6 @@ namespace hpx { { } - private: // number of chunks to create std::size_t num_partitions_ = static_cast(-1); }; 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 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&& locs) const + default_distribution_policy operator()(std::vector 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 + template hpx::future> 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( + objs.emplace_back(bulk_create_async( loc, get_num_items(count, loc), vs...)); } @@ -180,7 +168,8 @@ namespace hpx::components { hpx::id_type id = get_next_target(); hpx::future> f = - bulk_create_async(id, count, HPX_FORWARD(Ts, vs)...); + bulk_create_async( + id, count, HPX_FORWARD(Ts, vs)...); return f.then(hpx::launch::sync, [id = HPX_MOVE(id)](hpx::future>&& f) @@ -317,9 +306,9 @@ namespace hpx::components { protected: /// \cond NOINTERNAL - explicit default_distribution_policy( - std::vector const& localities) - : localities_(std::make_shared>(localities)) + explicit default_distribution_policy(std::vector localities) + : localities_( + std::make_shared>(HPX_MOVE(localities))) { if (localities_->empty()) { @@ -330,20 +319,9 @@ namespace hpx::components { } } - explicit default_distribution_policy(std::vector&& localities) + explicit default_distribution_policy(id_type locality) : localities_( - std::make_shared>(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>(1, locality)) + std::make_shared>(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..834ce9c0f396 --- /dev/null +++ b/libs/full/distribution_policies/include/hpx/distribution_policies/explicit_container_distribution_policy.hpp @@ -0,0 +1,144 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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 sizes) const + { + return {HPX_MOVE(sizes), get_localities()}; + } + + explicit_container_distribution_policy operator()( + std::vector sizes, hpx::id_type locality) const + { + return {HPX_MOVE(sizes), HPX_MOVE(locality)}; + } + + explicit_container_distribution_policy operator()( + std::vector sizes, + std::vector localities) const + { + return {HPX_MOVE(sizes), HPX_MOVE(localities)}; + } + + /////////////////////////////////////////////////////////////////////// + [[nodiscard]] std::size_t get_num_partitions() const noexcept + { + if (localities_) + { + return localities_->size(); + } + return static_cast(1); + } + + [[nodiscard]] std::vector get_localities() const + { + if (!localities_) + { + // use this locality, if this object was default constructed + return std::vector(1, + naming::get_id_from_locality_id(agas::get_locality_id())); + } + + HPX_ASSERT(!localities_->empty()); + return *localities_; + } + + [[nodiscard]] std::vector get_sizes() const + { + return sizes_; + } + + private: + friend class hpx::serialization::access; + + template + void serialize(Archive& ar, unsigned int const /* version */) + { + // clang-format off + ar & localities_ & sizes_; + // clang-format on + } + + explicit_container_distribution_policy( + std::vector sizes, std::vector localities) + : components::default_distribution_policy(HPX_MOVE(localities)) + , sizes_(HPX_MOVE(sizes)) + { + } + + explicit_container_distribution_policy( + std::vector sizes, hpx::id_type locality) + : components::default_distribution_policy(HPX_MOVE(locality)) + , sizes_(HPX_MOVE(sizes)) + { + } + + // number of chunks to create + std::vector sizes_; + }; + + static explicit_container_distribution_policy const + explicit_container_layout{}; + + /////////////////////////////////////////////////////////////////////////// + namespace traits { + + template <> + struct is_distribution_policy + : std::true_type + { + }; + + template <> + struct num_container_partitions + { + static std::size_t call( + explicit_container_distribution_policy const& policy) + { + return policy.get_num_partitions(); + } + }; + + template <> + struct container_partition_sizes + { + static std::vector call( + explicit_container_distribution_policy const& policy, + std::size_t) + { + return policy.get_sizes(); + } + }; + } // 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 + template hpx::future> 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> f = - components::bulk_create_async( + components::bulk_create_async( 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(); 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(); 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 struct create_component_action; - template + template struct bulk_create_component_action; } // namespace server @@ -50,7 +50,7 @@ namespace hpx::components { return hpx::async(gid, HPX_FORWARD(Ts, vs)...); } - template + template future> 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...>; + using action_type = server::bulk_create_component_action...>; return hpx::async(gid, count, HPX_FORWARD(Ts, vs)...); } @@ -74,11 +74,12 @@ namespace hpx::components { return create_async(gid, HPX_FORWARD(Ts, vs)...).get(); } - template + template std::vector bulk_create( hpx::id_type const& gid, std::size_t count, Ts&&... vs) { - return bulk_create_async(gid, count, HPX_FORWARD(Ts, vs)...) + return bulk_create_async( + 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 + template static future> bulk_create_colocated_async( hpx::id_type const& gid, std::size_t count, Ts&&... vs) { - using action_type = server::bulk_create_component_action...>; + using action_type = server::bulk_create_component_action...>; return hpx::detail::async_colocated( gid, count, HPX_FORWARD(Ts, vs)...); } - template + template std::vector bulk_create_colocated( hpx::id_type const& id, std::size_t count, Ts&&... vs) { - return bulk_create_colocated_async( + return bulk_create_colocated_async( 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( + return components::bulk_create_async( locality, count, HPX_FORWARD(Ts, vs)...); } @@ -294,7 +294,7 @@ namespace hpx::components { typename DistPolicy::bulk_locality_result; hpx::future> f = - policy.template bulk_create( + policy.template bulk_create( 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 + template std::vector bulk_create_component( std::size_t /* count */, Ts&&... vs) { - return this->base_type::template bulk_create_component( - gid_, HPX_FORWARD(Ts, vs)...); + return this->base_type::template bulk_create_component(gid_, HPX_FORWARD(Ts, vs)...); } /// Asynchronously create a new component using the runtime_support - template + template hpx::future> bulk_create_components_async( std::size_t /* count */, Ts&&... vs) { - return this->base_type::template bulk_create_component( - gid_, HPX_FORWARD(Ts, vs)...); + return this->base_type::template bulk_create_component(gid_, HPX_FORWARD(Ts, vs)...); } /////////////////////////////////////////////////////////////////////// - hpx::future load_components_async() + hpx::future 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 call_startup_functions_async(bool pre_startup) + hpx::future 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 shutdown_async(double timeout = -1) + hpx::future 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 terminate_async() + hpx::future 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 naming::gid_type create_component(T v, Ts... vs); - template + template std::vector bulk_create_component(std::size_t count); - template + template std::vector bulk_create_component( std::size_t count, T v, Ts... vs); @@ -418,7 +419,7 @@ namespace hpx::components::server { } #endif - template + template std::vector 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()); + if constexpr (WithCount) + { + ids.emplace_back(create(i)); + } + else + { + ids.emplace_back(create()); + } } LRT_(info).format("successfully created {} component(s) of type: {}", @@ -440,7 +448,7 @@ namespace hpx::components::server { return ids; } - template + template std::vector 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(v, vs...)); + if constexpr (WithCount) + { + ids.push_back(create(i, v, vs...)); + } + else + { + ids.push_back(create(v, vs...)); + } } LRT_(info).format("successfully created {} component(s) of type: {}", @@ -634,40 +649,42 @@ namespace hpx::components::server { }; /////////////////////////////////////////////////////////////////////////// - template + template struct bulk_create_component_action : ::hpx::actions::action ( runtime_support::*)(std::size_t, Ts...), - &runtime_support::bulk_create_component, - bulk_create_component_action> + &runtime_support::bulk_create_component, + bulk_create_component_action> { }; - template - struct bulk_create_component_action + template + struct bulk_create_component_action : ::hpx::actions::action ( runtime_support::*)(std::size_t), - &runtime_support::bulk_create_component, - bulk_create_component_action> + &runtime_support::bulk_create_component, + bulk_create_component_action> { }; - template + template struct bulk_create_component_direct_action : ::hpx::actions::direct_action ( runtime_support::*)( std::size_t, Ts...), - &runtime_support::bulk_create_component, - bulk_create_component_direct_action> + &runtime_support::bulk_create_component, + bulk_create_component_direct_action> { }; - template - struct bulk_create_component_direct_action + template + struct bulk_create_component_direct_action : ::hpx::actions::direct_action ( runtime_support::*)(std::size_t), - &runtime_support::bulk_create_component, - bulk_create_component_direct_action> + &runtime_support::bulk_create_component, + bulk_create_component_direct_action> { }; 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 + template static hpx::future> bulk_create_component_colocated_async( hpx::id_type const& gid, std::size_t count, Ts&&... vs) { - typedef server::bulk_create_component_action::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 + template static std::vector bulk_create_component_colocated( hpx::id_type const& gid, std::size_t count, Ts&&... vs) { - return bulk_create_component_colocated_async( + return bulk_create_component_colocated_async( 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 + template static hpx::future> 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()); } - typedef server::bulk_create_component_action::type...> action_type; return hpx::async(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 #include -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 #include -namespace hpx { namespace parallel { +namespace hpx::parallel { /////////////////////////////////////////////////////////////////////////// // segmented_for_each namespace detail { + /////////////////////////////////////////////////////////////////////// /// \cond NOINTERNAL // sequential remote implementation template - static typename util::detail::algorithm_result::type + static util::detail::algorithm_result_t 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 traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result result; + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; 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 - static typename util::detail::algorithm_result::type + static util::detail::algorithm_result_t 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 traits; - typedef typename traits::segment_iterator segment_iterator; - typedef typename traits::local_iterator local_iterator_type; - typedef util::detail::algorithm_result result; + using traits = hpx::traits::segmented_iterator_traits; + using segment_iterator = typename traits::segment_iterator; + using local_iterator_type = typename traits::local_iterator; + using result = util::detail::algorithm_result; - typedef std::integral_constant::value> - forced_seq; + using forced_seq = std::integral_constant>; 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 ::value && - hpx::traits::is_segmented_iterator::value + hpx::traits::is_iterator_v && + hpx::traits::is_segmented_iterator_v )> // clang-format on InIter tag_invoke(hpx::for_each_t, InIter first, InIter last, F&& f) { - static_assert((hpx::traits::is_forward_iterator::value), + static_assert((hpx::traits::is_forward_iterator_v), "Requires at least input iterator."); using iterator_traits = hpx::traits::segmented_iterator_traits; @@ -222,12 +222,11 @@ namespace hpx { namespace segmented { hpx::traits::is_segmented_iterator_v )> // clang-format on - typename hpx::parallel::util::detail::algorithm_result::type + hpx::parallel::util::detail::algorithm_result_t tag_invoke( hpx::for_each_t, ExPolicy&& policy, SegIter first, SegIter last, F&& f) { - static_assert((hpx::traits::is_forward_iterator::value), + static_assert((hpx::traits::is_forward_iterator_v), "Requires at least forward iterator."); using is_seq = hpx::is_sequenced_execution_policy; @@ -253,13 +252,13 @@ namespace hpx { namespace segmented { template ::value && - hpx::traits::is_segmented_iterator::value + hpx::traits::is_iterator_v && + hpx::traits::is_segmented_iterator_v )> // clang-format on InIter tag_invoke(hpx::for_each_n_t, InIter first, Size count, F&& f) { - static_assert((hpx::traits::is_input_iterator::value), + static_assert((hpx::traits::is_input_iterator_v), "Requires at least input iterator."); using iterator_traits = hpx::traits::segmented_iterator_traits; @@ -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(count)); return hpx::parallel::detail::segmented_for_each( hpx::parallel::detail::for_each< typename iterator_traits::local_iterator>(), @@ -287,12 +286,12 @@ namespace hpx { namespace segmented { hpx::traits::is_segmented_iterator_v )> // clang-format on - typename hpx::parallel::util::detail::algorithm_result::type + hpx::parallel::util::detail::algorithm_result_t tag_invoke( hpx::for_each_n_t, ExPolicy&& policy, SegIter first, Size count, F&& f) { - static_assert((hpx::traits::is_forward_iterator::value), + static_assert((hpx::traits::is_forward_iterator_v), "Requires at least input iterator."); using is_seq = hpx::is_sequenced_execution_policy; @@ -308,11 +307,11 @@ namespace hpx { namespace segmented { using iterator_traits = hpx::traits::segmented_iterator_traits; auto last = first; - hpx::parallel::detail::advance(last, std::size_t(count)); + hpx::parallel::detail::advance(last, static_cast(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 +struct apply_wrap +{ + template + void operator()([[maybe_unused]] T_& val) const + { + } + + hpx::reference_wrapper> v; + + template + void serialize(Archive& ar, unsigned) + { + // clang-format off + ar & v; + // clang-format on + } +}; + +template +void test_for_each_apply(ExPolicy&& policy, hpx::partitioned_vector& v) +{ + hpx::for_each(policy, v.begin(), v.end(), apply_wrap{v}); +} + /////////////////////////////////////////////////////////////////////////////// template void for_each_tests(std::vector& localities) { + //{ + // hpx::partitioned_vector 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 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 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 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 sizes; + sizes.reserve(localities.size()); + + for (std::size_t i = 0; i != localities.size(); ++i) + { + sizes.push_back(length / localities.size()); + } + hpx::partitioned_vector 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 + #if !defined(HPX_COMPUTE_DEVICE_CODE) #include #include @@ -33,7 +34,6 @@ << g << " " << h << " " << i << " "; /////////////////////////////////////////////////////////////////////////////// - template struct opt { @@ -322,9 +322,9 @@ template void inclusive_scan_tests(std::vector& 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(length, hpx::container_layout); @@ -357,4 +357,5 @@ int main() inclusive_scan_tests(localities); return hpx::util::report_errors(); } + #endif