[libcxx-commits] [libcxx] [libc++][pstl] Introduce a "statpart" backend (PR #230540)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Oct 12 06:50:22 PDT 2026
================
@@ -0,0 +1,1221 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___PSTL_STATPART_H
+#define _LIBCPP___PSTL_STATPART_H
+
+#include <__algorithm/find_end.h>
+#include <__algorithm/find_if.h>
+#include <__algorithm/for_each.h>
+#include <__algorithm/is_heap_until.h>
+#include <__algorithm/lower_bound.h>
+#include <__algorithm/merge.h>
+#include <__algorithm/min.h>
+#include <__algorithm/min_element.h>
+#include <__algorithm/minmax_element.h>
+#include <__algorithm/mismatch.h>
+#include <__algorithm/move.h>
+#include <__algorithm/reverse.h>
+#include <__algorithm/search.h>
+#include <__algorithm/search_n.h>
+#include <__algorithm/stable_sort.h>
+#include <__algorithm/swap_ranges.h>
+#include <__algorithm/transform.h>
+#include <__algorithm/upper_bound.h>
+#include <__atomic/atomic.h>
+#include <__config>
+#include <__functional/identity.h>
+#include <__functional/operations.h>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/move_iterator.h>
+#include <__iterator/next.h>
+#include <__iterator/reverse_iterator.h>
+#include <__memory/allocator.h>
+#include <__memory/construct_at.h>
+#include <__memory/destroy.h>
+#include <__memory/uninitialized_algorithms.h>
+#include <__memory/unique_ptr.h>
+#include <__numeric/reduce.h>
+#include <__numeric/transform_reduce.h>
+#include <__optional/nullopt_t.h>
+#include <__optional/optional.h>
+#include <__pstl/backend_fwd.h>
+#include <__pstl/cpu_algos/cpu_traits.h>
+#include <__pstl/cpu_algos/find_if.h>
+#include <__thread/thread.h>
+#include <__type_traits/is_assignable.h>
+#include <__type_traits/is_constructible.h>
+#include <__type_traits/is_execution_policy.h>
+#include <__type_traits/is_trivially_copyable.h>
+#include <__utility/convert_to_integral.h>
+#include <__utility/empty.h>
+#include <__utility/move.h>
+#include <__utility/pair.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
+namespace __pstl {
+namespace __statpart {
+
+// The backbone of the backend: applies the function to each of the indices [0, __chunk_count] in parallel.
+// The actual number of parallel workers and the order of application is unspecified.
+_LIBCPP_EXPORTED_FROM_ABI void
+__apply(size_t __chunk_count, void* __context, void (*__func)(void* __context, size_t __chunk)) noexcept;
+
+// The maximum number of partitions to be processed per each CPU
+constexpr inline size_t __max_partitions_per_cpu = 8;
+
+// The minimum number of elements to sort serially in a single partition
+constexpr inline size_t __min_sort_partition_size = 256;
+
+enum class __partitioning_result {
+ // returned when the partitioning result is not nullopt
+ __ok,
+ // returned when there is not enough element to produce a single partition or the final number of partitions is less
+ // than 2, i.e. there's no reason to process in parallel
+ __not_enough_elements,
+ // later: returned memory couldn't be allocated for the stashed forward iterators
+ __bad_alloc
+};
+
+template <class _Iterator>
+struct _LIBCPP_HIDE_FROM_ABI __iterator_range {
+ _Iterator __first;
+ _Iterator __last;
+};
+
+// __iterator_partitions<Iter> holds a finite per-determined set of partitions and allows to query each iterator range
+// in O(1) time.
+// TODO: Later to support forward iterators via a second implicit template argument.
+template <class _Iterator>
+struct _LIBCPP_HIDE_FROM_ABI __iterator_partitions {
+ _LIBCPP_HIDE_FROM_ABI size_t __partitions_count() const { return __partitions_count_; }
+
+ _LIBCPP_HIDE_FROM_ABI __iterator_range<_Iterator> __partition(size_t __n) const {
+ _Iterator __first = __base_ + __n * __partition_size_ + (__n < __remainder_ ? __n : __remainder_);
+ _Iterator __last = __first + __partition_size_ + (__n < __remainder_ ? 1 : 0);
+ return __iterator_range<_Iterator>{__first, __last};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI _Iterator __end() const { return __base_ + __count_; }
+
+private:
+ _Iterator __base_;
+ size_t __count_;
+ size_t __partition_size_;
+ size_t __remainder_;
+ size_t __partitions_count_;
+
+ template <class _Iter>
+ friend optional<__iterator_partitions<_Iter>>
+ __partition(_Iter, _Iter, __partitioning_result&, size_t, size_t, size_t, size_t) noexcept;
+};
+
+// Splits the input iterator range into a finite set of partitions, such as that every iterator sub-range can queried in
+// a O(1) time later.
+// In case partitioning failed returns nullopt and reports the reason in __result.
+// __min_partition_size specifies the minimal number of elements in every partition.
+// __prefix_to_skip and __suffix_to_skip allow to optionally trim the input range by specified numbers of elements
+// before partitioning.
+// __workers_count is normally implicitly queried from hardware_concurrency() and should be explicitly specified only in
+// unit tests.
+template <class _ForwardIterator>
+_LIBCPP_HIDE_FROM_ABI optional<__iterator_partitions<_ForwardIterator>> __partition(
+ _ForwardIterator __first,
+ _ForwardIterator __last,
+ __partitioning_result& __result,
+ size_t __min_partition_size = 1,
+ size_t __prefix_to_skip = 0,
+ size_t __suffix_to_skip = 0,
+ size_t __workers_count = thread::hardware_concurrency()) noexcept {
+ // forward iteratos to be supported later
+ static_assert(__has_random_access_iterator_category_or_concept<_ForwardIterator>::value);
+ // TODO: assert( __min_partition_size > 0 )?
----------------
ldionne wrote:
You can use `_LIBCPP_ASSERT_INTERNAL` -- that documents the assumption and catches it in debug mode.
https://github.com/llvm/llvm-project/pull/230540
More information about the libcxx-commits
mailing list