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..b98773f25d5b 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 @@ -51,9 +74,9 @@ namespace hpx::server { components::component_base>> { public: - using data_type = Data; + using data_type = std::decay_t; - 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,9 @@ namespace hpx::server { /// size 0. partitioned_vector(); - explicit partitioned_vector(size_type partition_size); + explicit partitioned_vector(std::size_t partnum, + std::vector const& partition_sizes, + traits::create_mode = traits::create_mode::resize); /// Constructor which create and initialize partitioned_vector_partition /// with all elements as \a val. @@ -79,9 +104,11 @@ namespace hpx::server { /// param partition_size The size of vector /// param val Default value for the elements in partitioned_vector_partition /// - partitioned_vector(size_type partition_size, T const& val); + partitioned_vector(std::size_t partnum, + std::vector 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 +301,31 @@ namespace hpx::server { // HPX_DEFINE_COMPONENT_ACTION(partitioned_vector_partition, clear) HPX_DEFINE_COMPONENT_DIRECT_ACTION(partitioned_vector, get_copied_data) HPX_DEFINE_COMPONENT_DIRECT_ACTION(partitioned_vector, set_data) + + /// Invoke given function on given element + /// + /// \return This returns whatever the given function invocation returns + template + 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 +352,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 +605,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 +619,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..f2e5359fddea 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, traits::create_mode mode) { + if (mode == traits::create_mode::resize) + { + partitioned_vector_partition_.resize(partition_sizes[partnum]); + } + else + { + partitioned_vector_partition_.reserve(partition_sizes[partnum]); + } } template 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) { } @@ -196,9 +205,24 @@ namespace hpx::server { partitioned_vector::get_values( std::vector const& pos) const { + if (pos.empty()) + { + if constexpr (std::is_same_v, data_type>) + { + return partitioned_vector_partition_; + } + else + { + std::vector result; + result.resize(pos.size()); + std::copy(partitioned_vector_partition_.begin(), + partitioned_vector_partition_.end(), result.begin()); + return result; + } + } + std::vector result; result.reserve(pos.size()); - for (std::size_t i = 0; i != pos.size(); ++i) result.push_back(partitioned_vector_partition_[pos[i]]); @@ -253,11 +277,20 @@ namespace hpx::server { partitioned_vector::set_values( std::vector const& pos, std::vector const& val) { - HPX_ASSERT(pos.size() == val.size()); - HPX_ASSERT(pos.size() <= partitioned_vector_partition_.size()); + if (pos.empty()) + { + HPX_ASSERT(val.size() == partitioned_vector_partition_.size()); + std::copy( + val.begin(), val.end(), partitioned_vector_partition_.begin()); + } + else + { + HPX_ASSERT(pos.size() == val.size()); + HPX_ASSERT(pos.size() <= partitioned_vector_partition_.size()); - for (std::size_t i = 0; i != pos.size(); ++i) - partitioned_vector_partition_[pos[i]] = val[i]; + for (std::size_t i = 0; i != pos.size(); ++i) + partitioned_vector_partition_[pos[i]] = val[i]; + } } template @@ -266,12 +299,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 +335,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 +345,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 { @@ -336,8 +392,13 @@ namespace hpx { partitioned_vector_partition::get_ptr() const { error_code ec(throwmode::lightweight); - return hpx::get_ptr>( - hpx::launch::sync, this->get_id(), ec); + hpx::id_type id = this->get_id(ec); + if (!ec) + { + return hpx::get_ptr>( + hpx::launch::sync, HPX_MOVE(id), ec); + } + return {}; } template */> @@ -346,7 +407,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 +436,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 +459,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 +482,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 +513,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 +528,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 +552,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 +576,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..66312a3c0b8b 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,8 @@ namespace hpx { using partitioned_vector_partition_client = hpx::partitioned_vector_partition; + using create_mode = traits::create_mode; + struct partition_data : server::partitioned_vector_config_data::partition_data { @@ -181,9 +190,9 @@ namespace hpx { partition_data() = default; - partition_data(id_type const& part, std::size_t size, - std::uint32_t locality_id) - : base_type(part, size, locality_id) + partition_data(id_type const& part, std::size_t first, + std::size_t size, std::uint32_t locality_id) + : base_type(part, first, size, locality_id) { } @@ -200,8 +209,7 @@ namespace hpx { // size, and locality id. using partitions_vector_type = std::vector; - size_type size_; // overall size of the vector - size_type partition_size_; // cached partition size + size_type size_; // overall size of the vector // This is the vector representing the base_index and corresponding // global ID's of the underlying partitioned_vector_partitions. @@ -230,6 +238,8 @@ namespace hpx { segmented::local_segment_vector_iterator; + using partition_data_type = partition_data; + private: friend class segmented::vector_iterator; friend class segmented::const_vector_iterator; @@ -239,40 +249,42 @@ 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 // name. void get_data_helper( - id_type id, server::partitioned_vector_config_data data); + id_type id, server::partitioned_vector_config_data&& data); // this will be called by the base class once the registered id becomes // available future connect_to_helper(id_type id); public: - future connect_to(std::string const& symbolic_name); - void connect_to(launch::sync_policy, std::string const& symbolic_name); + future connect_to(std::string symbolic_name); + void connect_to(launch::sync_policy, std::string symbolic_name); // Register this vector with AGAS using the given symbolic name - future register_as(std::string const& symbolic_name); + future register_as(std::string symbolic_name); - void register_as(launch::sync_policy, std::string const& symbolic_name); + void register_as(launch::sync_policy, std::string symbolic_name); // construct from id partitioned_vector(future&& f); + void copy_data_from(partitioned_vector const& rhs); + public: - // Return the sequence number of the segment corresponding to the - // given global index + // Return the sequence number of the segment corresponding to the given + // global index std::size_t get_partition(size_type global_index) const; - // Return the local index inside the segment corresponding to the - // given global index - std::size_t get_local_index(size_type global_index) const; + // Return the local index inside the given segment + std::size_t get_local_index( + size_type partnum, size_type global_index) const; // Return the local indices inside the segment corresponding to the // given global indices @@ -285,15 +297,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 @@ -304,14 +309,13 @@ namespace hpx { // Return the local iterator referencing an element inside a segment // based on the given global index. - local_iterator get_local_iterator(size_type global_index) const; - const_local_iterator get_const_local_iterator( - size_type global_index) const; + local_iterator get_local_iterator(size_type global_index); + const_local_iterator get_local_iterator(size_type global_index) const; - // Return the segment iterator referencing a segment based on the - // given global index. + // Return the segment iterator referencing a segment based on the given + // global index. segment_iterator get_segment_iterator(size_type global_index); - const_segment_iterator get_const_segment_iterator( + const_segment_iterator get_segment_iterator( size_type global_index) const; protected: @@ -322,19 +326,19 @@ 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); - - struct get_ptr_helper; + DistPolicy const& policy, std::size_t count, + std::vector const& sizes, T const& val); // 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 +349,61 @@ namespace hpx { // Perform a deep copy from the given vector void copy_from(partitioned_vector const& rhs); + partitioned_vector(partitioned_vector const& rhs, bool make_unmanaged) + : base_type(rhs.get_id(), make_unmanaged) + , size_(rhs.size_) + , partitions_(rhs.partitions_) + { + if (make_unmanaged) + { + for (auto& part : partitions_) + { + part.partition_.make_unmanaged(); + } + } + } + + 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) + { + std::uint32_t locality_id = get_locality_id(); + for (auto& p : partitions) + { + if (p.locality_id_ == locality_id && !p.local_data_) + { + p.local_data_ = + hpx::get_ptr( + hpx::launch::sync, p.partition_); + } + } + + 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 +413,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 +435,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 +451,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 +467,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 +523,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(bool make_unmanaged = true) const + { + return {*this, make_unmanaged}; + } + /////////////////////////////////////////////////////////////////////// // Capacity related APIs in vector class @@ -485,11 +543,20 @@ namespace hpx { /// /// \return Return the number of elements in the vector /// - size_type size() const + [[nodiscard]] constexpr size_type size() const noexcept { return size_; } + /// \brief Compute the information about the underlying partitions. + /// + /// \return Return the partitions + /// + constexpr partitions_vector_type const& partitions() const + { + return partitions_; + } + // // Element access APIs in vector class // @@ -503,8 +570,8 @@ namespace hpx { /// T get_value(launch::sync_policy, size_type pos) const { - return get_value( - launch::sync, get_partition(pos), get_local_index(pos)); + auto part = get_partition(pos); + return get_value(launch::sync, part, get_local_index(part, pos)); } /// Returns the element at position \a pos in the vector container. @@ -519,8 +586,9 @@ namespace hpx { { partition_data const& part_data = partitions_[part]; if (part_data.local_data_) + { return part_data.local_data_->get_value(pos); - + } return partitioned_vector_partition_client(part_data.partition_) .get_value(launch::sync, pos); } @@ -535,7 +603,8 @@ namespace hpx { /// future get_value(size_type pos) const { - return get_value(get_partition(pos), get_local_index(pos)); + auto part = get_partition(pos); + return get_value(part, get_local_index(part, pos)); } /// Returns the element at position \a pos in the given partition in @@ -554,7 +623,6 @@ namespace hpx { return make_ready_future( partitions_[part].local_data_->get_value(pos)); } - return partitioned_vector_partition_client( partitions_[part].partition_) .get_value(pos); @@ -594,9 +662,10 @@ namespace hpx { { partition_data const& part_data = partitions_[part]; if (part_data.local_data_) + { return make_ready_future( part_data.local_data_->get_values(pos)); - + } return partitioned_vector_partition_client(part_data.partition_) .get_values(pos); } @@ -837,8 +906,9 @@ namespace hpx { template void set_value(launch::sync_policy, size_type pos, T_&& val) { - return set_value(launch::sync, get_partition(pos), - get_local_index(pos), HPX_FORWARD(T_, val)); + auto part = get_partition(pos); + return set_value(launch::sync, part, get_local_index(part, pos), + HPX_FORWARD(T_, val)); } /// Copy the value of \a val in the element at position \a pos in @@ -876,8 +946,9 @@ namespace hpx { template future set_value(size_type pos, T_&& val) { + auto part = get_partition(pos); return set_value( - get_partition(pos), get_local_index(pos), HPX_FORWARD(T_, val)); + part, get_local_index(part, pos), HPX_FORWARD(T_, val)); } /// Asynchronously set the element at position \a pos in @@ -911,10 +982,21 @@ namespace hpx { /// \param pos Position of the element in the vector /// \param val The value to be copied /// - void set_values(launch::sync_policy, size_type /* part */, + void set_values(launch::sync_policy, size_type part, std::vector const& pos, std::vector const& val) { - set_values(pos, val).get(); + HPX_ASSERT(pos.empty() || pos.size() == val.size()); + + if (partitions_[part].local_data_) + { + partitions_[part].local_data_->set_values(pos, val); + return; + } + + return partitioned_vector_partition_client( + partitions_[part].partition_) + .set_values(pos, val) + .get(); } /// Asynchronously set the element at position \a pos in @@ -930,7 +1012,7 @@ namespace hpx { future set_values(size_type part, std::vector const& pos, std::vector const& val) { - HPX_ASSERT(pos.size() == val.size()); + HPX_ASSERT(pos.empty() || pos.size() == val.size()); if (partitions_[part].local_data_) { @@ -990,21 +1072,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 +1103,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 + auto apply(std::size_t pos, F f, Ts... ts) + { + auto part = get_partition(pos); + return apply_on(part, get_local_index(part, pos), HPX_FORWARD(F, f), + HPX_FORWARD(Ts, ts)...); + } + + template + auto apply(launch::sync_policy, std::size_t pos, F f, Ts... ts) + { + auto part = get_partition(pos); + return apply_on(part, get_local_index(part, pos), HPX_FORWARD(F, f), + HPX_FORWARD(Ts, ts)...) + .get(); + } + // //CLEAR // // TODO if number of partitions is kept constant every time then // // clear should modify (clear each partitioned_vector_partition @@ -1281,4 +1393,11 @@ namespace hpx { return segment_cend(naming::get_locality_id_from_id(id)); } }; + + // serialization of partitioned_vector requires special handling + template + struct traits::needs_reference_semantics> + : std::true_type + { + }; } // 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..7206cd26d6df 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,24 +42,34 @@ 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 */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void partitioned_vector::get_data_helper( - id_type id, server::partitioned_vector_config_data data) + id_type id, server::partitioned_vector_config_data&& data) { partitions_.clear(); partitions_.reserve(data.partitions_.size()); @@ -69,25 +79,16 @@ namespace hpx { std::back_inserter(partitions_)); std::uint32_t this_locality = get_locality_id(); - 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) + for (auto& p : partitions_) { - if (it->locality_id_ == this_locality) + if (p.locality_id_ == this_locality && !p.local_data_) { - ptrs.push_back( - get_ptr(it->partition_) - .then(get_ptr_helper{l, partitions_})); + p.local_data_ = + hpx::get_ptr( + hpx::launch::sync, p.partition_); } } - hpx::wait_all(ptrs); - partition_size_ = get_partition_size(); this->base_type::reset(HPX_MOVE(id)); } @@ -112,9 +113,9 @@ namespace hpx { template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT hpx::future - partitioned_vector::connect_to(std::string const& symbolic_name) + partitioned_vector::connect_to(std::string symbolic_name) { - this->base_type::connect_to(symbolic_name); + this->base_type::connect_to(HPX_MOVE(symbolic_name)); return this->base_type::share().then( [HPX_CXX20_CAPTURE_THIS(=)]( shared_future&& f) -> hpx::future { @@ -125,14 +126,14 @@ namespace hpx { template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void partitioned_vector::connect_to( - launch::sync_policy, std::string const& symbolic_name) + launch::sync_policy, std::string symbolic_name) { - connect_to(symbolic_name).get(); + connect_to(HPX_MOVE(symbolic_name)).get(); } template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT hpx::future - partitioned_vector::register_as(std::string const& symbolic_name) + partitioned_vector::register_as(std::string symbolic_name) { std::vector partitions; @@ -148,15 +149,15 @@ namespace hpx { server::partitioned_vector_config_data>>( hpx::find_here(), HPX_MOVE(data))); - return this->base_type::register_as(symbolic_name); + return this->base_type::register_as(HPX_MOVE(symbolic_name)); } template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void partitioned_vector::register_as( - launch::sync_policy, std::string const& symbolic_name) + launch::sync_policy, std::string symbolic_name) { - register_as(symbolic_name).get(); + register_as(HPX_MOVE(symbolic_name)).get(); } /////////////////////////////////////////////////////////////////////////// @@ -175,29 +176,35 @@ 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(); } template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT std::size_t - partitioned_vector::get_local_index(size_type global_index) const + partitioned_vector::get_local_index( + size_type partnum, 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; + return global_index - partitions_[partnum].first_; } template */> @@ -207,15 +214,16 @@ namespace hpx { std::vector indices) const { for (size_type& index : indices) - index = get_local_index(index); + { + index = get_local_index(get_partition(index), index); + } return indices; } template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT typename partitioned_vector::local_iterator - partitioned_vector::get_local_iterator( - size_type global_index) const + partitioned_vector::get_local_iterator(size_type global_index) { HPX_ASSERT(global_index != static_cast(-1)); @@ -228,7 +236,7 @@ namespace hpx { back.partition_, back.size_, back.local_data_); } - std::size_t local_index = get_local_index(global_index); + std::size_t local_index = get_local_index(part, global_index); HPX_ASSERT(local_index != static_cast(-1)); return local_iterator(partitions_[part].partition_, local_index, @@ -238,7 +246,7 @@ namespace hpx { template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT typename partitioned_vector::const_local_iterator - partitioned_vector::get_const_local_iterator( + partitioned_vector::get_local_iterator( size_type global_index) const { HPX_ASSERT(global_index != static_cast(-1)); @@ -252,7 +260,7 @@ namespace hpx { back.partition_, back.size_, back.local_data_); } - std::size_t local_index = get_local_index(global_index); + std::size_t local_index = get_local_index(part, global_index); HPX_ASSERT(local_index != static_cast(-1)); return const_local_iterator(partitions_[part].partition_, local_index, @@ -275,7 +283,7 @@ namespace hpx { template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT typename partitioned_vector::const_segment_iterator - partitioned_vector::get_const_segment_iterator( + partitioned_vector::get_segment_iterator( size_type global_index) const { std::size_t part = get_partition(global_index); @@ -290,13 +298,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,45 +314,31 @@ 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 */> - struct partitioned_vector::get_ptr_helper - { - std::size_t loc; - partitions_vector_type& partitions; - - void operator()( - future>&& f) - const - { - partitions[loc].local_data_ = f.get(); - } - }; - 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::vector> ptrs; - ptrs.reserve(num_parts); + std::uint32_t const this_locality = get_locality_id(); std::size_t num_part = 0; std::size_t allocated_size = 0; @@ -360,14 +356,15 @@ 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) { - ptrs.push_back( - get_ptr(id).then( - get_ptr_helper{l, partitions_})); + partitions_[l].local_data_ = + hpx::get_ptr( + hpx::launch::sync, id); } ++l; @@ -377,7 +374,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 +382,12 @@ namespace hpx { } break; } - else - { - HPX_ASSERT(size == part_size); - } + + HPX_ASSERT(size == part_sizes[l - 1]); HPX_ASSERT(l < num_parts); } } HPX_ASSERT(l == num_parts); - - hpx::wait_all(ptrs); - - // cache our partition size - partition_size_ = get_partition_size(); } template */> @@ -405,7 +395,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, + traits::allocation_mode::call(policy)); } template */> @@ -414,19 +405,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:: @@ -437,42 +430,46 @@ namespace hpx { hpx::wait_all(objs); std::uint32_t this_locality = get_locality_id(); - std::vector> ptrs; - ptrs.reserve(rhs.partitions_.size()); - // Fixing the size of partitions to avoid race conditions between - // possible reallocations during push back and the continuation - // to set the local partition data partitions_vector_type partitions; - partitions.resize(rhs.partitions_.size()); + partitions.reserve(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.push_back(partition_data(objs[i].get(), + rhs.partitions_[i].first_, rhs.partitions_[i].size_, locality)); if (locality == this_locality) { - ptrs.push_back(get_ptr( - partitions[i].partition_) - .then(get_ptr_helper{i, partitions})); + partitions.back().local_data_ = + hpx::get_ptr( + hpx::launch::sync, partitions.back().partition_); } } - hpx::wait_all(ptrs); - size_ = rhs.size_; - partition_size_ = rhs.partition_size_; std::swap(partitions_, partitions); } + template */> + HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT void + partitioned_vector::copy_data_from(partitioned_vector const& rhs) + { + std::vector const empty; + for (std::size_t i = 0; i != rhs.partitions_.size(); ++i) + { + auto values = rhs.get_values(hpx::launch::sync, i, empty); + set_values(hpx::launch::sync, i, empty, HPX_MOVE(values)); + } + } + /////////////////////////////////////////////////////////////////////////// template */> HPX_PARTITIONED_VECTOR_SPECIALIZATION_EXPORT partitioned_vector::partitioned_vector() : size_(0) - , partition_size_(static_cast(-1)) { } @@ -480,7 +477,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 +487,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 +497,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..220477155d0d 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 @@ -1,5 +1,5 @@ // Copyright (c) 2014 Anuj R. Sharma -// Copyright (c) 2014-2022 Hartmut Kaiser +// Copyright (c) 2014-2024 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -31,6 +31,7 @@ #include #include #include +#include namespace hpx::segmented { @@ -54,9 +55,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 +103,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 +145,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 +183,7 @@ namespace hpx::segmented { return *this; } + private: local_vector_iterator const& it_; }; @@ -184,6 +196,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 +218,7 @@ namespace hpx::segmented { return *it_.local(); } + private: const_local_vector_iterator const& it_; }; @@ -202,15 +227,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 +280,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)) { } @@ -279,15 +310,19 @@ namespace hpx::segmented { /////////////////////////////////////////////////////////////////////// local_raw_iterator local() { - if (partition_ && !data_) + if (!data_ && partition_) + { data_ = partition_.get_ptr(); + } return local_raw_iterator( data_->begin() + local_index_, data_); //-V522 } local_raw_const_iterator local() const { - if (partition_ && !data_) + if (!data_ && partition_) + { data_ = partition_.get_ptr(); + } return local_raw_iterator( data_->cbegin() + local_index_, data_); //-V522 } @@ -296,18 +331,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,65 +350,70 @@ 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_; } std::shared_ptr>& get_data() { - if (partition_ && !data_) + if (!data_ && partition_) + { data_ = partition_.get_ptr(); + } return data_; } std::shared_ptr> const& get_data() const { - if (partition_ && !data_) + if (!data_ && partition_) + { 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 +422,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 +431,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)) { } @@ -438,15 +467,19 @@ namespace hpx::segmented { /////////////////////////////////////////////////////////////////////// local_raw_iterator local() { - if (partition_ && !data_) + if (!data_ && partition_) + { data_ = partition_.get_ptr(); + } return local_raw_iterator( data_->cbegin() + local_index_, data_); //-V522 } local_raw_const_iterator local() const { - if (partition_ && !data_) + if (!data_ && partition_) + { data_ = partition_.get_ptr(); + } return local_raw_const_iterator( data_->cbegin() + local_index_, data_); //-V522 } @@ -455,18 +488,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; @@ -482,61 +508,65 @@ 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_; } std::shared_ptr>& get_data() { - if (partition_ && !data_) + if (!data_ && partition_) + { data_ = partition_.get_ptr(); + } return data_; } std::shared_ptr> const& get_data() const { - if (partition_ && !data_) + if (!data_ && partition_) + { 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 +582,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 +591,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 +608,7 @@ namespace hpx::segmented { } private: - partitioned_vector* data_; + partitioned_vector* data_ = nullptr; }; template @@ -593,10 +621,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 +638,8 @@ namespace hpx::segmented { { } - partitioned_vector const* get_data() const + [[nodiscard]] partitioned_vector const* get_data() + const noexcept { return data_; } @@ -625,11 +651,12 @@ namespace hpx::segmented { } private: - partitioned_vector const* data_; + partitioned_vector const* data_ = nullptr; }; /////////////////////////////////////////////////////////////////////////// namespace detail { + template struct is_requested_locality { @@ -637,12 +664,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 +721,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 +749,13 @@ namespace hpx::segmented { ++(this->base_reference()); if (this->base() != end_) + { data_ = this->base()->local_data_; + } else + { data_.reset(); + } } void satisfy_predicate() @@ -727,9 +764,13 @@ namespace hpx::segmented { ++(this->base_reference()); if (this->base() != end_) + { data_ = this->base()->local_data_; + } else + { data_.reset(); + } } std::shared_ptr> data_; @@ -740,7 +781,7 @@ namespace hpx::segmented { /////////////////////////////////////////////////////////////////////////// /// This class implements the (global) iterator functionality for /// hpx::partitioned_vector. - template + template > class vector_iterator : public hpx::util::iterator_facade, T, std::random_access_iterator_tag, @@ -759,30 +800,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 +843,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,14 +869,14 @@ 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); }; /////////////////////////////////////////////////////////////////////////// - template + template > class const_vector_iterator : public hpx::util::iterator_facade, T const, std::random_access_iterator_tag, T const> @@ -853,25 +894,30 @@ 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 + const_vector_iterator(vector_iterator const& it) noexcept + : data_(it.data_) + , global_index_(it.global_index_) + { + } + + 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 +925,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 +936,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 +963,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 +1032,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( @@ -1033,7 +1082,7 @@ namespace hpx::traits { // the iterator is currently pointing to (i.e. just global iterator). static segment_iterator segment(iterator iter) { - return iter.get_data()->get_const_segment_iterator( + return iter.get_data()->get_segment_iterator( iter.get_global_index()); } @@ -1042,8 +1091,7 @@ namespace hpx::traits { static local_iterator local(iterator const& iter) { HPX_ASSERT(iter.get_data()); // avoid dereferencing end iterator - return iter.get_data()->get_const_local_iterator( - iter.get_global_index()); + return iter.get_data()->get_local_iterator(iter.get_global_index()); } // Build a full iterator from the segment and local iterators @@ -1076,7 +1124,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..27389d1128a9 --- /dev/null +++ b/components/containers/partitioned_vector/include/hpx/components/containers/partitioned_vector/serialization/partitioned_vector.hpp @@ -0,0 +1,69 @@ +// 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 + +#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; + } + } +} // 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/command_line_handling_local/include/hpx/command_line_handling_local/command_line_handling_local.hpp b/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/command_line_handling_local.hpp index 83bb82d0ed27..fbb2c32552ae 100644 --- a/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/command_line_handling_local.hpp +++ b/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/command_line_handling_local.hpp @@ -66,8 +66,8 @@ namespace hpx::local::detail { std::vector& ini_config); void store_command_line(int argc, char** argv); - void store_unregistered_options(std::string const& cmd_name, - std::vector const& unregistered_options); + void store_unregistered_options(std::string const& cmd_name, int argc, + char* argv[], std::vector const& unregistered_options); bool handle_help_options( hpx::program_options::options_description const& help); diff --git a/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/parse_command_line_local.hpp b/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/parse_command_line_local.hpp index c639ef6b8e99..a4066dfa8a56 100644 --- a/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/parse_command_line_local.hpp +++ b/libs/core/command_line_handling_local/include/hpx/command_line_handling_local/parse_command_line_local.hpp @@ -113,7 +113,7 @@ namespace hpx::local::detail { options_map& all_options); HPX_CORE_EXPORT std::string reconstruct_command_line( - hpx::program_options::variables_map const& vm); + int argc, char* argv[]); HPX_CORE_EXPORT bool parse_commandline(util::section const& rtcfg, options_map& all_options, @@ -140,7 +140,4 @@ namespace hpx::local::detail { util::commandline_error_mode::return_on_error, hpx::program_options::options_description* visible = nullptr, std::vector* unregistered_options = nullptr); - - HPX_CORE_EXPORT std::string reconstruct_command_line( - hpx::program_options::variables_map const& vm); } // namespace hpx::local::detail diff --git a/libs/core/command_line_handling_local/src/command_line_handling_local.cpp b/libs/core/command_line_handling_local/src/command_line_handling_local.cpp index 62f08268c05e..752ace407ed8 100644 --- a/libs/core/command_line_handling_local/src/command_line_handling_local.cpp +++ b/libs/core/command_line_handling_local/src/command_line_handling_local.cpp @@ -744,7 +744,7 @@ namespace hpx::local::detail { /////////////////////////////////////////////////////////////////////////// void command_line_handling::store_unregistered_options( - std::string const& cmd_name, + std::string const& cmd_name, int argc, char* argv[], std::vector const& unregistered_options) { std::string unregistered_options_cmd_line; @@ -771,9 +771,9 @@ namespace hpx::local::detail { } ini_config_.emplace_back("hpx.program_name!=" + cmd_name); - ini_config_.emplace_back("hpx.reconstructed_cmd_line!=" + - encode_and_enquote(cmd_name) + " " + reconstruct_command_line(vm_) + - " " + unregistered_options_cmd_line); + ini_config_.emplace_back( + "hpx.reconstructed_cmd_line!=" + encode_and_enquote(cmd_name) + + " " + reconstruct_command_line(argc, argv)); } /////////////////////////////////////////////////////////////////////////// @@ -1014,7 +1014,7 @@ namespace hpx::local::detail { { // store unregistered command line and arguments store_command_line(argc, argv); - store_unregistered_options(argv[0], unregistered_options); + store_unregistered_options(argv[0], argc, argv, unregistered_options); // add all remaining ini settings to the global configuration rtcfg_.reconfigure(ini_config_); diff --git a/libs/core/command_line_handling_local/src/parse_command_line_local.cpp b/libs/core/command_line_handling_local/src/parse_command_line_local.cpp index f4788e8896fd..18396386773c 100644 --- a/libs/core/command_line_handling_local/src/parse_command_line_local.cpp +++ b/libs/core/command_line_handling_local/src/parse_command_line_local.cpp @@ -732,53 +732,14 @@ namespace hpx::local::detail { return s; } - void add_as_option( - std::string& command_line, std::string const& k, std::string const& v) - { - command_line += "--" + k; - if (!v.empty()) - command_line += "=" + v; - } - - std::string reconstruct_command_line( - hpx::program_options::variables_map const& vm) + std::string reconstruct_command_line(int argc, char* argv[]) { std::string command_line; - for (auto const& v : vm) + for (int i = 0; i != argc; ++i) { - hpx::program_options::any const& value = v.second.value(); - if (hpx::program_options::any_cast(&value)) - { - add_as_option(command_line, v.first, - embed_in_quotes(v.second.as())); - if (!command_line.empty()) - command_line += " "; - } - else if (hpx::program_options::any_cast(&value)) - { - add_as_option(command_line, v.first, - std::to_string(v.second.as())); - if (!command_line.empty()) - command_line += " "; - } - else if (hpx::program_options::any_cast(&value)) - { - add_as_option( - command_line, v.first, std::to_string(v.second.as())); - if (!command_line.empty()) - command_line += " "; - } - else if (hpx::program_options::any_cast>( - &value)) - { - auto const& vec = v.second.as>(); - for (std::string const& e : vec) - { - add_as_option(command_line, v.first, embed_in_quotes(e)); - if (!command_line.empty()) - command_line += " "; - } - } + if (!command_line.empty()) + command_line += " "; + command_line += embed_in_quotes(argv[i]); } return command_line; } 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..6a83881d9638 100644 --- a/libs/core/functional/CMakeLists.txt +++ b/libs/core/functional/CMakeLists.txt @@ -33,9 +33,11 @@ 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 + hpx/functional/serialization/reference_wrapper.hpp hpx/functional/serialization/serializable_function.hpp hpx/functional/serialization/serializable_move_only_function.hpp hpx/functional/traits/get_action_name.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..57b840d14a54 --- /dev/null +++ b/libs/core/functional/include/hpx/functional/reference_wrapper.hpp @@ -0,0 +1,166 @@ +// 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 +#include + +#include +#include + +namespace hpx { + + /////////////////////////////////////////////////////////////////////////// + template + struct reference_wrapper : std::reference_wrapper + { + reference_wrapper() = delete; + + using std::reference_wrapper::reference_wrapper; + }; + + template + reference_wrapper(T&) -> reference_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 traits { + + template + struct needs_reference_semantics : std::false_type + { + }; + + template + struct needs_reference_semantics : needs_reference_semantics + { + }; + + template + inline constexpr bool needs_reference_semantics_v = + needs_reference_semantics::value; + } // namespace traits + + template + struct reference_wrapper>> + { + using type = T; + + // we define a default constructor to support serialization + reference_wrapper() = default; + + // clang-format off + template , reference_wrapper>>> + // clang-format on + reference_wrapper(U&& val) + : ptr(val.ref()) + { + } + + reference_wrapper(reference_wrapper const& rhs) + : ptr(rhs.get()) + { + } + reference_wrapper(reference_wrapper&& rhs) = default; + + reference_wrapper& operator=(reference_wrapper const& rhs) + { + ptr = rhs.get(); + return *this; + } + reference_wrapper& operator=(reference_wrapper&& rhs) = default; + + operator type() const + { + return ptr.ref(); + } + + [[nodiscard]] type get() const + { + return ptr.ref(); + } + + private: + T ptr{}; + }; + + template >> + reference_wrapper ref(T&& val) noexcept + { + return reference_wrapper(HPX_FORWARD(T, val)); + } + + namespace util { + + template + struct unwrap_reference<::hpx::reference_wrapper> + { + using type = T; + }; + + template + struct unwrap_reference<::hpx::reference_wrapper const> + { + using type = T; + }; + + template + struct detail::decay_unwrap_impl<::hpx::reference_wrapper, + std::enable_if_t>> + { + using type = X; + + constexpr static decltype(auto) call( + ::hpx::reference_wrapper ref) noexcept + { + return ref.get(); + } + }; + } // namespace util +} // namespace hpx diff --git a/libs/core/functional/include/hpx/functional/serialization/reference_wrapper.hpp b/libs/core/functional/include/hpx/functional/serialization/reference_wrapper.hpp new file mode 100644 index 000000000000..ab73a75eeeb6 --- /dev/null +++ b/libs/core/functional/include/hpx/functional/serialization/reference_wrapper.hpp @@ -0,0 +1,32 @@ +// 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::reference_wrapper& ref, unsigned) + { + T val; + ar >> val; + ref = hpx::ref(HPX_MOVE(val)); + } + + template >> + void serialize(output_archive& ar, hpx::reference_wrapper& ref, unsigned) + { + ar << ref.get(); + } +} // namespace hpx::serialization 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/runtime_configuration/src/runtime_configuration.cpp b/libs/core/runtime_configuration/src/runtime_configuration.cpp index 205b5d85647d..52919551eee6 100644 --- a/libs/core/runtime_configuration/src/runtime_configuration.cpp +++ b/libs/core/runtime_configuration/src/runtime_configuration.cpp @@ -1026,12 +1026,15 @@ namespace hpx::util { { if (num_os_threads == 0) { - num_os_threads = 1; if (util::section const* sec = get_section("hpx"); nullptr != sec) { num_os_threads = hpx::util::get_entry_as( *sec, "os_threads", 1); } + else + { + num_os_threads = 1; + } } return static_cast(num_os_threads); } diff --git a/libs/core/serialization/include/hpx/serialization/serialization_fwd.hpp b/libs/core/serialization/include/hpx/serialization/serialization_fwd.hpp index 1b8eef54f1d8..09a6b9773209 100644 --- a/libs/core/serialization/include/hpx/serialization/serialization_fwd.hpp +++ b/libs/core/serialization/include/hpx/serialization/serialization_fwd.hpp @@ -37,9 +37,12 @@ namespace hpx::serialization { namespace detail { - template - void serialize_one(Archive& ar, T& t); - } + template + void serialize_one(output_archive& ar, T const& t); + + template + void serialize_one(input_archive& ar, T& t); + } // namespace detail template class array; diff --git a/libs/core/serialization/include/hpx/serialization/serialize.hpp b/libs/core/serialization/include/hpx/serialization/serialize.hpp index a533c1d86786..4788b5b476b5 100644 --- a/libs/core/serialization/include/hpx/serialization/serialize.hpp +++ b/libs/core/serialization/include/hpx/serialization/serialize.hpp @@ -46,12 +46,16 @@ namespace hpx::serialization { namespace detail { - template - void serialize_one(Archive& ar, T& t) + template + void serialize_one(output_archive& ar, T const& t) { - // clang-format off - ar & t; - // clang-format on + ar.save(t); + } + + template + void serialize_one(input_archive& ar, T& t) + { + ar.load(t); } } // namespace detail } // namespace hpx::serialization 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/core/type_support/include/hpx/type_support/decay.hpp b/libs/core/type_support/include/hpx/type_support/decay.hpp index 2d83eeb9434f..a56ff92ce0e8 100644 --- a/libs/core/type_support/include/hpx/type_support/decay.hpp +++ b/libs/core/type_support/include/hpx/type_support/decay.hpp @@ -18,7 +18,7 @@ namespace hpx::util { /////////////////////////////////////////////////////////////////////////// namespace detail { - template + template struct decay_unwrap_impl { using type = TD; 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..07e82d3b309c 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 @@ -8,7 +8,9 @@ #pragma once #include +#include #include +#include namespace hpx::traits { @@ -31,4 +33,35 @@ namespace hpx::traits { return policy.get_num_localities(); } }; + + // By default, the sizes of the partitions are equal across the localities + // represented by the given distribution policy. + template + 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); + } + }; + + // By default, the container distribution policy resizes the underlying + // vectors. + enum class create_mode : std::uint8_t + { + resize = 0, + reserve = 1 + }; + + template + struct allocation_mode + { + static create_mode call(Policy const&) + { + return create_mode::resize; + } + }; } // namespace hpx::traits diff --git a/libs/full/async_distributed/include/hpx/async_distributed/bind_action.hpp b/libs/full/async_distributed/include/hpx/async_distributed/bind_action.hpp index 31ab9a1e3769..3df7de531891 100644 --- a/libs/full/async_distributed/include/hpx/async_distributed/bind_action.hpp +++ b/libs/full/async_distributed/include/hpx/async_distributed/bind_action.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -137,11 +138,13 @@ namespace hpx { typename Enable = std::enable_if_t>>> detail::bound_action, - util::make_index_pack_t, std::decay_t...> + util::make_index_pack_t, + hpx::util::decay_unwrap_t...> bind(Ts&&... vs) { using result_type = detail::bound_action, - util::make_index_pack_t, std::decay_t...>; + util::make_index_pack_t, + hpx::util::decay_unwrap_t...>; return result_type(Action(), HPX_FORWARD(Ts, vs)...); } @@ -154,7 +157,8 @@ namespace hpx { Ts&&... vs) { using result_type = detail::bound_action, std::decay_t...>; + util::make_index_pack_t, + hpx::util::decay_unwrap_t...>; return result_type( static_cast(action), HPX_FORWARD(Ts, vs)...); 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/async_distributed/include/hpx/async_distributed/trigger_lco.hpp b/libs/full/async_distributed/include/hpx/async_distributed/trigger_lco.hpp index 0177ae06e552..9371aa490271 100644 --- a/libs/full/async_distributed/include/hpx/async_distributed/trigger_lco.hpp +++ b/libs/full/async_distributed/include/hpx/async_distributed/trigger_lco.hpp @@ -100,8 +100,8 @@ namespace hpx { /////////////////////////////////////////////////////////////////////// template - void set_lco_value(hpx::id_type const& id, naming::address&& addr, - Result&& t, bool move_credits) + void set_lco_value(hpx::id_type id, naming::address&& addr, Result&& t, + bool move_credits) { constexpr launch::async_policy policy( actions::action_priority(), @@ -127,8 +127,8 @@ namespace hpx { /////////////////////////////////////////////////////////////////////// template - void set_lco_value(hpx::id_type const& id, naming::address&& addr, - Result&& t, hpx::id_type const& cont, bool move_credits) + void set_lco_value(hpx::id_type id, naming::address&& addr, Result&& t, + hpx::id_type const& cont, bool move_credits) { if (move_credits && id.get_management_type() != @@ -156,7 +156,7 @@ namespace hpx { /// \cond NOINTERNAL template - void set_lco_value([[maybe_unused]] hpx::id_type const& id, + void set_lco_value([[maybe_unused]] hpx::id_type id, [[maybe_unused]] naming::address&& addr, [[maybe_unused]] Result&& t, [[maybe_unused]] bool move_credits) { @@ -199,7 +199,7 @@ namespace hpx { } template - void set_lco_value([[maybe_unused]] hpx::id_type const& id, + void set_lco_value([[maybe_unused]] hpx::id_type id, [[maybe_unused]] naming::address&& addr, [[maybe_unused]] Result&& t, [[maybe_unused]] hpx::id_type const& cont, [[maybe_unused]] bool move_credits) diff --git a/libs/full/async_distributed/include/hpx/async_distributed/trigger_lco_fwd.hpp b/libs/full/async_distributed/include/hpx/async_distributed/trigger_lco_fwd.hpp index 4fd847b95dae..91d4ae3c15a6 100644 --- a/libs/full/async_distributed/include/hpx/async_distributed/trigger_lco_fwd.hpp +++ b/libs/full/async_distributed/include/hpx/async_distributed/trigger_lco_fwd.hpp @@ -30,8 +30,8 @@ namespace hpx { /// \param move_credits [in] If this is set to \a true then it is ok to /// send all credits in \a id along with the generated /// message. The default value is \a true. - HPX_EXPORT void trigger_lco_event(hpx::id_type const& id, - naming::address&& addr, bool move_credits = true); + HPX_EXPORT void trigger_lco_event( + hpx::id_type id, naming::address&& addr, bool move_credits = true); /////////////////////////////////////////////////////////////////////////// /// \brief Trigger the LCO referenced by the given id @@ -57,9 +57,8 @@ namespace hpx { /// \param move_credits [in] If this is set to \a true then it is ok to /// send all credits in \a id along with the generated /// message. The default value is \a true. - HPX_EXPORT void trigger_lco_event(hpx::id_type const& id, - naming::address&& addr, hpx::id_type const& cont, - bool move_credits = true); + HPX_EXPORT void trigger_lco_event(hpx::id_type id, naming::address&& addr, + hpx::id_type const& cont, bool move_credits = true); /// \brief Trigger the LCO referenced by the given id /// @@ -86,8 +85,8 @@ namespace hpx { /// send all credits in \a id along with the generated /// message. The default value is \a true. template - void set_lco_value(hpx::id_type const& id, naming::address&& addr, - Result&& t, bool move_credits = true); + void set_lco_value(hpx::id_type id, naming::address&& addr, Result&& t, + bool move_credits = true); /// \brief Set the result value for the (managed) LCO referenced by the given id /// @@ -137,8 +136,8 @@ namespace hpx { /// send all credits in \a id along with the generated /// message. The default value is \a true. template - void set_lco_value(hpx::id_type const& id, naming::address&& addr, - Result&& t, hpx::id_type const& cont, bool move_credits = true); + void set_lco_value(hpx::id_type id, naming::address&& addr, Result&& t, + hpx::id_type const& cont, bool move_credits = true); /// \brief Set the result value for the (managed) LCO referenced by the given id /// @@ -192,9 +191,8 @@ namespace hpx { /// \param move_credits [in] If this is set to \a true then it is ok to /// send all credits in \a id along with the generated /// message. The default value is \a true. - HPX_EXPORT void set_lco_error(hpx::id_type const& id, - naming::address&& addr, std::exception_ptr const& e, - bool move_credits = true); + HPX_EXPORT void set_lco_error(hpx::id_type id, naming::address&& addr, + std::exception_ptr const& e, bool move_credits = true); /// \brief Set the error state for the LCO referenced by the given id /// @@ -207,9 +205,8 @@ namespace hpx { /// \param move_credits [in] If this is set to \a true then it is ok to /// send all credits in \a id along with the generated /// message. The default value is \a true. - HPX_EXPORT void set_lco_error(hpx::id_type const& id, - naming::address&& addr, std::exception_ptr&& e, - bool move_credits = true); + HPX_EXPORT void set_lco_error(hpx::id_type id, naming::address&& addr, + std::exception_ptr&& e, bool move_credits = true); /// \brief Set the error state for the LCO referenced by the given id /// @@ -253,9 +250,9 @@ namespace hpx { /// \param move_credits [in] If this is set to \a true then it is ok to /// send all credits in \a id along with the generated /// message. The default value is \a true. - HPX_EXPORT void set_lco_error(hpx::id_type const& id, - naming::address&& addr, std::exception_ptr const& e, - hpx::id_type const& cont, bool move_credits = true); + HPX_EXPORT void set_lco_error(hpx::id_type id, naming::address&& addr, + std::exception_ptr const& e, hpx::id_type const& cont, + bool move_credits = true); /// \brief Set the error state for the LCO referenced by the given id /// @@ -269,9 +266,9 @@ namespace hpx { /// \param move_credits [in] If this is set to \a true then it is ok to /// send all credits in \a id along with the generated /// message. The default value is \a true. - HPX_EXPORT void set_lco_error(hpx::id_type const& id, - naming::address&& addr, std::exception_ptr&& e, - hpx::id_type const& cont, bool move_credits = true); + HPX_EXPORT void set_lco_error(hpx::id_type id, naming::address&& addr, + std::exception_ptr&& e, hpx::id_type const& cont, + bool move_credits = true); /// \brief Set the error state for the LCO referenced by the given id /// diff --git a/libs/full/async_distributed/src/trigger_lco.cpp b/libs/full/async_distributed/src/trigger_lco.cpp index 960edea55463..f8d3770bd6a6 100644 --- a/libs/full/async_distributed/src/trigger_lco.cpp +++ b/libs/full/async_distributed/src/trigger_lco.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2023 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 @@ -20,7 +20,7 @@ namespace hpx { - void trigger_lco_event([[maybe_unused]] hpx::id_type const& id, + void trigger_lco_event([[maybe_unused]] hpx::id_type id, [[maybe_unused]] naming::address&& addr, [[maybe_unused]] bool move_credits) { @@ -49,7 +49,7 @@ namespace hpx { #endif } - void trigger_lco_event([[maybe_unused]] hpx::id_type const& id, + void trigger_lco_event([[maybe_unused]] hpx::id_type id, [[maybe_unused]] naming::address&& addr, [[maybe_unused]] hpx::id_type const& cont, [[maybe_unused]] bool move_credits) @@ -89,7 +89,7 @@ namespace hpx { #endif } - void set_lco_error([[maybe_unused]] hpx::id_type const& id, + void set_lco_error([[maybe_unused]] hpx::id_type id, [[maybe_unused]] naming::address&& addr, [[maybe_unused]] std::exception_ptr const& e, [[maybe_unused]] bool move_credits) @@ -119,7 +119,7 @@ namespace hpx { #endif } - void set_lco_error([[maybe_unused]] hpx::id_type const& id, + void set_lco_error([[maybe_unused]] hpx::id_type id, [[maybe_unused]] naming::address&& addr, [[maybe_unused]] std::exception_ptr&& e, [[maybe_unused]] bool move_credits) @@ -151,7 +151,7 @@ namespace hpx { #endif } - void set_lco_error([[maybe_unused]] hpx::id_type const& id, + void set_lco_error([[maybe_unused]] hpx::id_type id, [[maybe_unused]] naming::address&& addr, [[maybe_unused]] std::exception_ptr const& e, [[maybe_unused]] hpx::id_type const& cont, @@ -192,7 +192,7 @@ namespace hpx { #endif } - void set_lco_error([[maybe_unused]] hpx::id_type const& id, + void set_lco_error([[maybe_unused]] hpx::id_type id, [[maybe_unused]] naming::address&& addr, [[maybe_unused]] std::exception_ptr&& e, [[maybe_unused]] hpx::id_type const& cont, diff --git a/libs/full/components/include/hpx/components/client_base.hpp b/libs/full/components/include/hpx/components/client_base.hpp index fb075ba17461..3a2cd7ed1ef4 100644 --- a/libs/full/components/include/hpx/components/client_base.hpp +++ b/libs/full/components/include/hpx/components/client_base.hpp @@ -337,6 +337,28 @@ namespace hpx::components { shared_state_->set_value(HPX_MOVE(id)); } + client_base(id_type const& id, bool make_unmanaged) + : shared_state_(new shared_state_type) + { + if (make_unmanaged) + { + shared_state_->set_value(id.make_unmanaged()); + } + else + { + shared_state_->set_value(id); + } + } + client_base(id_type&& id, bool make_unmanaged) + : shared_state_(new shared_state_type) + { + if (make_unmanaged) + { + id.make_unmanaged(); + } + shared_state_->set_value(HPX_MOVE(id)); + } + explicit client_base(hpx::shared_future const& f) noexcept : shared_state_( hpx::traits::future_access::get_shared_state(f)) 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..7cbafcf7e68c 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,11 +79,11 @@ namespace hpx::components { std::vector const& localities_; }; - template + template struct create_bulk_helper { - typedef std::pair> - bulk_locality_result; + using bulk_locality_result = + std::pair>; explicit create_bulk_helper( std::vector const& localities) @@ -102,10 +102,23 @@ namespace hpx::components { std::vector>> objs; objs.reserve(localities_.size()); + [[maybe_unused]] std::size_t first = 0; for (std::size_t i = 0; i != to_create.size(); ++i) { - objs.emplace_back(bulk_create_async( - localities_[i], to_create[i], vs...)); + if constexpr (WithCount) + { + std::size_t const local_count = to_create[i]; + objs.emplace_back( + bulk_create_async( + localities_[i], local_count, vs...)); + first += local_count; + } + else + { + objs.emplace_back( + bulk_create_async( + localities_[i], to_create[i], vs...)); + } } // consolidate all results @@ -238,7 +251,7 @@ namespace hpx::components { naming::get_id_from_locality_id(agas::get_locality_id()), HPX_FORWARD(Ts, vs)...); } - else if (localities_.size() == 1) + if (localities_.size() == 1) { return create_async( localities_.front(), HPX_FORWARD(Ts, vs)...); @@ -269,7 +282,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 +294,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 +305,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..ab94af56ba27 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,14 +126,45 @@ namespace hpx::components { if (!id_) { id = naming::get_id_from_locality_id(agas::get_locality_id()); - f = bulk_create_async( - id, count, HPX_FORWARD(Ts, vs)...); + if constexpr (WithCount) + { + f = bulk_create_async( + id, count, 0, HPX_FORWARD(Ts, vs)...); + } + else + { + 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_)); + if constexpr (WithCount) + { + f = bulk_create_async( + id, count, 0, HPX_FORWARD(Ts, vs)...); + } + else + { + f = bulk_create_async( + id, count, HPX_FORWARD(Ts, vs)...); + } } else { id = id_; - f = bulk_create_colocated_async( - id, count, HPX_FORWARD(Ts, vs)...); + if constexpr (WithCount) + { + f = bulk_create_colocated_async( + id, count, 0, HPX_FORWARD(Ts, vs)...); + } + else + { + f = bulk_create_colocated_async( + id, count, HPX_FORWARD(Ts, vs)...); + } } return f.then(hpx::launch::sync, @@ -160,6 +197,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 +221,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 +245,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 +266,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 +292,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 +314,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..2e2e3e118dc8 100644 --- a/libs/full/distribution_policies/include/hpx/distribution_policies/container_distribution_policy.hpp +++ b/libs/full/distribution_policies/include/hpx/distribution_policies/container_distribution_policy.hpp @@ -1,5 +1,5 @@ // Copyright (c) 2014 Bibek Ghimire -// Copyright (c) 2014-2023 Hartmut Kaiser +// Copyright (c) 2014-2024 Hartmut Kaiser // // SPDX-License-Identifier: BSL-1.0 // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -31,56 +31,59 @@ namespace hpx { struct container_distribution_policy : components::default_distribution_policy { - public: - constexpr container_distribution_policy() = default; + container_distribution_policy() = default; - container_distribution_policy operator()( - std::size_t num_partitions) const + container_distribution_policy operator()(std::size_t num_partitions, + traits::create_mode mode = traits::create_mode::resize) const { - return container_distribution_policy( - num_partitions, get_localities()); + return {num_partitions, get_localities(), mode}; } - container_distribution_policy operator()( - hpx::id_type const& locality) const + container_distribution_policy operator()(traits::create_mode mode) const + { + return container_distribution_policy(mode); + } + + container_distribution_policy operator()(hpx::id_type const& locality, + traits::create_mode mode = traits::create_mode::resize) const { - return container_distribution_policy(locality); + return {locality, mode}; } container_distribution_policy operator()( - std::vector const& localities) const + std::vector const& localities, + traits::create_mode mode = traits::create_mode::resize) const { if (num_partitions_ != static_cast(-1)) { - return container_distribution_policy( - num_partitions_, localities); + return {num_partitions_, localities, mode}; } - return container_distribution_policy(localities.size(), localities); + return {localities.size(), localities, mode}; } container_distribution_policy operator()( - std::vector&& localities) const + std::vector&& localities, + traits::create_mode mode = traits::create_mode::resize) const { if (num_partitions_ != static_cast(-1)) { - return container_distribution_policy( - num_partitions_, HPX_MOVE(localities)); + return {num_partitions_, HPX_MOVE(localities), mode}; } - return container_distribution_policy( - localities.size(), HPX_MOVE(localities)); + return {localities.size(), HPX_MOVE(localities), mode}; } container_distribution_policy operator()(std::size_t num_partitions, - std::vector const& localities) const + std::vector const& localities, + traits::create_mode mode = traits::create_mode::resize) const { - return container_distribution_policy(num_partitions, localities); + return {num_partitions, localities, mode}; } - container_distribution_policy operator()( - std::size_t num_partitions, std::vector&& localities) const + container_distribution_policy operator()(std::size_t num_partitions, + std::vector&& localities, + traits::create_mode mode = traits::create_mode::resize) const { - return container_distribution_policy( - num_partitions, HPX_MOVE(localities)); + return {num_partitions, HPX_MOVE(localities), mode}; } /////////////////////////////////////////////////////////////////////// @@ -110,6 +113,11 @@ namespace hpx { return *localities_; } + [[nodiscard]] constexpr traits::create_mode get_create_mode() const + { + return mode_; + } + private: friend class hpx::serialization::access; @@ -117,32 +125,41 @@ namespace hpx { void serialize(Archive& ar, const unsigned int /* version */) { // clang-format off - ar & localities_ & num_partitions_; + ar & localities_ & num_partitions_ & mode_; // clang-format on } - container_distribution_policy( - std::size_t num_partitions, std::vector const& localities) + container_distribution_policy(std::size_t num_partitions, + std::vector const& localities, traits::create_mode mode) : components::default_distribution_policy(localities) , num_partitions_(num_partitions) + , mode_(mode) { } - container_distribution_policy( - std::size_t num_partitions, std::vector&& localities) + container_distribution_policy(std::size_t num_partitions, + std::vector&& localities, traits::create_mode mode) : components::default_distribution_policy(HPX_MOVE(localities)) , num_partitions_(num_partitions) + , mode_(mode) { } - explicit container_distribution_policy(hpx::id_type const& locality) + container_distribution_policy( + hpx::id_type const& locality, traits::create_mode mode) : components::default_distribution_policy(locality) + , mode_(mode) + { + } + + explicit container_distribution_policy(traits::create_mode mode) + : mode_(mode) { } - private: // number of chunks to create std::size_t num_partitions_ = static_cast(-1); + traits::create_mode mode_ = traits::create_mode::resize; }; static container_distribution_policy const container_layout{}; @@ -164,5 +181,14 @@ namespace hpx { return policy.get_num_partitions(); } }; + + template <> + struct allocation_mode + { + static create_mode call(container_distribution_policy const& policy) + { + return policy.get_create_mode(); + } + }; } // namespace traits } // namespace hpx diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/default_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/default_distribution_policy.hpp index 3edf6ca738ed..56f823104e5f 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 { @@ -149,10 +137,23 @@ namespace hpx::components { // schedule creation of all objects across given localities std::vector>> objs; objs.reserve(localities_->size()); + + [[maybe_unused]] std::size_t first = 0; for (hpx::id_type const& loc : *localities_) { - objs.emplace_back(bulk_create_async( - loc, get_num_items(count, loc), vs...)); + if constexpr (WithCount) + { + std::size_t const local_count = + get_num_items(count, loc); + objs.emplace_back(bulk_create_async( + loc, local_count, first, vs...)); + first += local_count; + } + else + { + objs.emplace_back(bulk_create_async( + loc, get_num_items(count, loc), vs...)); + } } // consolidate all results @@ -179,8 +180,17 @@ namespace hpx::components { // handle special cases hpx::id_type id = get_next_target(); - hpx::future> f = - bulk_create_async(id, count, HPX_FORWARD(Ts, vs)...); + hpx::future> f; + if constexpr (WithCount) + { + f = bulk_create_async( + id, count, 0, HPX_FORWARD(Ts, vs)...); + } + else + { + f = bulk_create_async( + id, count, HPX_FORWARD(Ts, vs)...); + } return f.then(hpx::launch::sync, [id = HPX_MOVE(id)](hpx::future>&& f) @@ -317,9 +327,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 +340,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..23a89ba9ed72 --- /dev/null +++ b/libs/full/distribution_policies/include/hpx/distribution_policies/explicit_container_distribution_policy.hpp @@ -0,0 +1,160 @@ +// Copyright (c) 2014-2024 Hartmut Kaiser +// +// SPDX-License-Identifier: BSL-1.0 +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#pragma once + +#include +#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, + traits::create_mode mode = traits::create_mode::resize) const + { + return {HPX_MOVE(sizes), get_localities(), mode}; + } + + explicit_container_distribution_policy operator()( + std::vector sizes, hpx::id_type locality, + traits::create_mode mode = traits::create_mode::resize) const + { + return {HPX_MOVE(sizes), HPX_MOVE(locality), mode}; + } + + explicit_container_distribution_policy operator()( + std::vector sizes, std::vector localities, + traits::create_mode mode = traits::create_mode::resize) const + { + return {HPX_MOVE(sizes), HPX_MOVE(localities), mode}; + } + + /////////////////////////////////////////////////////////////////////// + [[nodiscard]] std::size_t get_num_partitions() const noexcept + { + return sizes_.size(); + } + + [[nodiscard]] std::vector 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_; + } + + [[nodiscard]] constexpr traits::create_mode get_create_mode() const + { + return mode_; + } + + private: + friend class hpx::serialization::access; + + template + void serialize(Archive& ar, unsigned int const /* version */) + { + // clang-format off + ar & localities_ & sizes_ & mode_; + // clang-format on + } + + explicit_container_distribution_policy(std::vector sizes, + std::vector localities, traits::create_mode mode) + : components::default_distribution_policy(HPX_MOVE(localities)) + , sizes_(HPX_MOVE(sizes)) + , mode_(mode) + { + } + + explicit_container_distribution_policy(std::vector sizes, + hpx::id_type locality, traits::create_mode mode) + : components::default_distribution_policy(HPX_MOVE(locality)) + , sizes_(HPX_MOVE(sizes)) + , mode_(mode) + { + } + + // number of chunks to create + std::vector sizes_; + traits::create_mode mode_ = traits::create_mode::resize; + }; + + static explicit_container_distribution_policy const + explicit_container_layout{}; + + /////////////////////////////////////////////////////////////////////////// + namespace traits { + + template <> + struct is_distribution_policy + : 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(); + } + }; + + template <> + struct allocation_mode + { + static create_mode call( + explicit_container_distribution_policy const& policy) + { + return policy.get_create_mode(); + } + }; + } // namespace traits +} // namespace hpx diff --git a/libs/full/distribution_policies/include/hpx/distribution_policies/target_distribution_policy.hpp b/libs/full/distribution_policies/include/hpx/distribution_policies/target_distribution_policy.hpp index 42f2ee95a900..4d73b1b9fef9 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 @@ -73,8 +73,8 @@ namespace hpx::components { } /// \cond NOINTERNAL - typedef std::pair> - bulk_locality_result; + using bulk_locality_result = + std::pair>; /// \endcond /// Create multiple objects on the localities associated by @@ -90,16 +90,25 @@ 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 { // by default the object will be created on the current // locality hpx::id_type id = get_next_target(); - hpx::future> f = - components::bulk_create_async( + + hpx::future> f; + if constexpr (WithCount) + { + f = components::bulk_create_async( + id, count, 0, HPX_FORWARD(Ts, vs)...); + } + else + { + f = components::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/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/naming_base/include/hpx/naming_base/id_type.hpp b/libs/full/naming_base/include/hpx/naming_base/id_type.hpp index cb55c2953e8f..e7df2b4c7b19 100644 --- a/libs/full/naming_base/include/hpx/naming_base/id_type.hpp +++ b/libs/full/naming_base/include/hpx/naming_base/id_type.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2023 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 @@ -133,7 +133,8 @@ namespace hpx { // Convert this id into an unmanaged one (in-place) - Use with maximum // care, or better, don't use this at all. - void make_unmanaged() const; + void make_unmanaged(); + hpx::id_type make_unmanaged() const; hpx::intrusive_ptr& impl() noexcept { @@ -410,10 +411,15 @@ namespace hpx { gid_->set_lsb(lsb); } - inline void id_type::make_unmanaged() const + inline void id_type::make_unmanaged() { gid_->set_management_type(management_type::unmanaged); } + + inline hpx::id_type id_type::make_unmanaged() const + { + return {*impl(), management_type::unmanaged}; + } } // namespace hpx namespace hpx::naming { 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..686995b94ed9 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) + std::size_t count, Ts&&... vs) { - return this->base_type::template bulk_create_component( - gid_, HPX_FORWARD(Ts, vs)...); + return this->base_type::bulk_create_component( + gid_, count, 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) + std::size_t count, Ts&&... vs) { - return this->base_type::template bulk_create_component( - gid_, HPX_FORWARD(Ts, vs)...); + return this->base_type::bulk_create_component( + gid_, count, 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..8dd975155a92 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 @@ -54,7 +54,7 @@ namespace hpx::components::server { class runtime_support { private: - typedef hpx::spinlock plugin_map_mutex_type; + using plugin_map_mutex_type = hpx::spinlock; struct plugin_factory { @@ -71,14 +71,14 @@ namespace hpx::components::server { hpx::util::plugin::dll const& second; bool isenabled; }; - typedef plugin_factory plugin_factory_type; - typedef std::map plugin_map_type; + using plugin_factory_type = plugin_factory; + using plugin_map_type = std::map; - typedef std::map modules_map_type; - typedef std::vector static_modules_type; + using modules_map_type = std::map; + using static_modules_type = std::vector; public: - typedef runtime_support type_holder; + using type_holder = runtime_support; static component_type get_component_type() { @@ -125,12 +125,13 @@ namespace hpx::components::server { template naming::gid_type create_component(T v, Ts... vs); - 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); + std::size_t count, Ts... vs); + + template + std::vector bulk_create_component_with_count( + std::size_t count, Ts... vs); template naming::gid_type copy_create_component( @@ -189,7 +190,7 @@ namespace hpx::components::server { #endif /////////////////////////////////////////////////////////////////////// - // Each of the exposed functions needs to be encapsulated into a action + // Each of the exposed functions needs to be encapsulated into an action // type, allowing to generate all require boilerplate code for threads, // serialization, etc. HPX_DEFINE_COMPONENT_ACTION(runtime_support, load_components) @@ -348,7 +349,7 @@ namespace hpx::components::server { std::atomic shutdown_all_invoked_; #if defined(HPX_HAVE_NETWORKING) - typedef hpx::spinlock dijkstra_mtx_type; + using dijkstra_mtx_type = hpx::spinlock; dijkstra_mtx_type dijkstra_mtx_; std::unique_ptr dijkstra_cond_; std::atomic dijkstra_color_; // false: white, true: black @@ -390,7 +391,7 @@ namespace hpx::components::server { components::component_type const type = components::get_component_type(); - typedef typename Component::wrapping_type wrapping_type; + using wrapping_type = typename Component::wrapping_type; naming::gid_type id = create(); LRT_(info).format("successfully created component {} of type: {}", id, components::get_component_type_name(type)); @@ -404,7 +405,7 @@ namespace hpx::components::server { components::component_type const type = components::get_component_type(); - typedef typename Component::wrapping_type wrapping_type; + using wrapping_type = typename Component::wrapping_type; // Note, T and Ts can't be (non-const) references, and parameters // should be moved to allow for move-only constructor argument // types. @@ -418,9 +419,9 @@ namespace hpx::components::server { } #endif - template + template std::vector runtime_support::bulk_create_component( - std::size_t count) + std::size_t count, Ts... vs) { components::component_type const type = components::get_component_type(); @@ -428,10 +429,10 @@ namespace hpx::components::server { std::vector ids; ids.reserve(count); - typedef typename Component::wrapping_type wrapping_type; + using wrapping_type = typename Component::wrapping_type; for (std::size_t i = 0; i != count; ++i) { - ids.emplace_back(create()); + ids.push_back(create(vs...)); } LRT_(info).format("successfully created {} component(s) of type: {}", @@ -440,26 +441,40 @@ namespace hpx::components::server { return ids; } - template - std::vector runtime_support::bulk_create_component( - std::size_t count, T v, Ts... vs) - { - components::component_type const type = - components::get_component_type(); - - std::vector ids; - ids.reserve(count); + namespace detail { - typedef typename Component::wrapping_type wrapping_type; - for (std::size_t i = 0; i != count; ++i) + template + std::vector bulk_create_component_with_count_helper( + std::size_t count, std::size_t first, Ts... vs) { - ids.push_back(create(v, vs...)); - } + components::component_type const type = + components::get_component_type< + typename Component::wrapped_type>(); - LRT_(info).format("successfully created {} component(s) of type: {}", - count, components::get_component_type_name(type)); + std::vector ids; + ids.reserve(count); - return ids; + using wrapping_type = typename Component::wrapping_type; + for (std::size_t i = 0; i != count; ++i) + { + ids.push_back(create(first + i, vs...)); + } + + LRT_(info).format( + "successfully created {} component(s) of type: {}", count, + components::get_component_type_name(type)); + + return ids; + } + } // namespace detail + + template + std::vector + runtime_support::bulk_create_component_with_count( + std::size_t count, Ts... vs) + { + return detail::bulk_create_component_with_count_helper( + count, HPX_MOVE(vs)...); } template @@ -469,7 +484,7 @@ namespace hpx::components::server { components::component_type const type = components::get_component_type(); - typedef typename Component::wrapping_type wrapping_type; + using wrapping_type = typename Component::wrapping_type; naming::gid_type id; if (!local_op) @@ -499,7 +514,7 @@ namespace hpx::components::server { // AGAS naming::gid_type migrated_id = to_migrate.get_gid(); - typedef typename Component::wrapping_type wrapping_type; + using wrapping_type = typename Component::wrapping_type; typename wrapping_type::derived_type* new_instance = nullptr; naming::gid_type id = create_migrated( @@ -634,40 +649,43 @@ 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> + 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::*)(std::size_t, Ts...), + &runtime_support::bulk_create_component_with_count, + 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> + 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::*)( + std::size_t, Ts...), + &runtime_support::bulk_create_component_with_count, + 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..39aaf392592c 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 @@ -50,9 +50,8 @@ namespace hpx { namespace components { namespace stubs { return hpx::make_ready_future(hpx::invalid_id); } - typedef server::create_component_action::type...> - action_type; + using action_type = + server::create_component_action...>; return hpx::async(gid, HPX_FORWARD(Ts, vs)...); } @@ -68,36 +67,35 @@ 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; + using action_type = server::bulk_create_component_action...>; return hpx::detail::async_colocated( gid, count, HPX_FORWARD(Ts, vs)...); } /// 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) @@ -108,22 +106,20 @@ namespace hpx { namespace components { namespace stubs { "stubs::runtime_support::bulk_create_component_async", "The id passed as the first argument is not representing" " a locality"); - return hpx::make_ready_future(std::vector()); } - typedef server::bulk_create_component_action::type...> - action_type; + using action_type = server::bulk_create_component_action...>; return hpx::async(gid, count, HPX_FORWARD(Ts, vs)...); } /// Create multiple new components \a type using the runtime_support /// on the given locality. Block for the creation to finish. - template + template static std::vector bulk_create_component( hpx::id_type const& gid, std::size_t count, Ts&&... vs) { - return bulk_create_component_async( + return bulk_create_component_async( gid, count, HPX_FORWARD(Ts, vs)...) .get(); } @@ -136,9 +132,8 @@ namespace hpx { namespace components { namespace stubs { static hpx::future create_component_colocated_async( hpx::id_type const& gid, Ts&&... vs) { - typedef server::create_component_action::type...> - action_type; + using action_type = + server::create_component_action...>; return hpx::detail::async_colocated( gid, HPX_FORWARD(Ts, vs)...); } @@ -170,8 +165,8 @@ namespace hpx { namespace components { namespace stubs { return hpx::make_ready_future(hpx::invalid_id); } - typedef typename server::copy_create_component_action - action_type; + using action_type = + typename server::copy_create_component_action; return hpx::async(gid, p, local_op); } @@ -201,8 +196,8 @@ namespace hpx { namespace components { namespace stubs { return hpx::make_ready_future(hpx::invalid_id); } - typedef typename server::migrate_component_here_action - action_type; + using action_type = + typename server::migrate_component_here_action; return hpx::async(target_locality, p, to_migrate); } @@ -211,8 +206,8 @@ namespace hpx { namespace components { namespace stubs { DistPolicy const& policy, std::shared_ptr const& p, hpx::id_type const& to_migrate) { - typedef typename server::migrate_component_here_action - action_type; + using action_type = + typename server::migrate_component_here_action; return hpx::async(policy, p, to_migrate); } 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 #include +#include #include #include @@ -306,7 +307,7 @@ namespace hpx::parallel::detail { typename algo_type::result_type>::type; algorithm_invoker_action...)> + result_type(hpx::util::decay_unwrap_t...)> act; return hpx::async(act, hpx::colocated(id), HPX_FORWARD(Algo, algo), diff --git a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp index 9b009de6d56e..8e8c27cefb28 100644 --- a/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp +++ b/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp @@ -25,25 +25,26 @@ #include #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,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_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 +306,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..f967f2c3d5d9 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,6 +134,31 @@ 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) @@ -151,8 +176,9 @@ void for_each_tests(std::vector& localities) .get(); } + constexpr std::size_t length = 12; + { - constexpr std::size_t length = 12; hpx::partitioned_vector v( length, T(0), hpx::container_layout(localities)); test_for_each(v, T(0)); @@ -161,6 +187,32 @@ void for_each_tests(std::vector& localities) 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( + 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); + } + + { + 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::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