[libcxx-commits] [libcxx] [libc++][pstl] Implementation of parallel std::search_n() based on __parallel_find() (PR #214069)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Aug 5 08:55:10 PDT 2026


================
@@ -0,0 +1,111 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_CPU_ALGOS_SEARCH_N_H
+#define _LIBCPP___PSTL_CPU_ALGOS_SEARCH_N_H
+
+#include <__algorithm/search_n.h>
+#include <__config>
+#include <__functional/operations.h>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.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 <__type_traits/is_execution_policy.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
+namespace __pstl {
+
+template <class _Backend, class _RawExecutionPolicy>
+struct __cpu_parallel_search_n {
+  template <class _Policy, class _ForwardIterator, class _Size, class _Tp, class _Predicate>
+  _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator>
+  operator()(_Policy&&,
+             _ForwardIterator __first,
+             _ForwardIterator __last,
+             _Size __count,
+             const _Tp& __value,
+             _Predicate __pred) const noexcept {
+    if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> &&
+                  __has_random_access_iterator_category_or_concept<_ForwardIterator>::value) {
+      typedef typename std::iterator_traits<_ForwardIterator>::difference_type _DifferenceType;
+      if (static_cast<_DifferenceType>(__count) <= 0) {
+        return __first; // If the count is non-positive, the first iterator is returned.
+      }
+      _DifferenceType __size = __last - __first;
+      if (__size < static_cast<_DifferenceType>(__count)) {
+        return __last; // The range is too small to contain the requested number of consecutive elements.
+      }
+      // We're only interested in the range where a potential match can start.
+      _DifferenceType __n      = __size - static_cast<_DifferenceType>(__count) + 1;
+      _ForwardIterator __last2 = __first + __n;
+      // Run a parallel chunked find_if, covering the range where a potential match can start.
+      auto __res = __pstl::__parallel_find<_Backend>(
+          __first,
+          __last2,
+          [__count, &__value, &__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
----------------
ldionne wrote:

As discussed, I think it would be better to reimplement this in terms of the serial `search_n`. While it may not provide any benefits right now since `search_n` does nothing special, we're exposing ourselves to improvements (e.g. vectorization) in `search_n` in the future.

https://github.com/llvm/llvm-project/pull/214069


More information about the libcxx-commits mailing list