Skip to content

Commit b97859b

Browse files
committed
[libc++][PSTL] Move the already implemented functions to the new dispatching scheme
Reviewed By: ldionne, #libc Spies: arichardson, pcwang-thead, libcxx-commits, miyuki Differential Revision: https://reviews.llvm.org/D150277
1 parent 88149fb commit b97859b

File tree

17 files changed

+427
-289
lines changed

17 files changed

+427
-289
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ set(files
7272
__algorithm/pstl_any_all_none_of.h
7373
__algorithm/pstl_backend.h
7474
__algorithm/pstl_backends/cpu_backend.h
75+
__algorithm/pstl_backends/cpu_backends/any_of.h
7576
__algorithm/pstl_backends/cpu_backends/backend.h
77+
__algorithm/pstl_backends/cpu_backends/fill.h
78+
__algorithm/pstl_backends/cpu_backends/find_if.h
7679
__algorithm/pstl_backends/cpu_backends/for_each.h
7780
__algorithm/pstl_backends/cpu_backends/serial.h
7881
__algorithm/pstl_fill.h
@@ -538,7 +541,6 @@ set(files
538541
__pstl/internal/parallel_backend_serial.h
539542
__pstl/internal/parallel_backend_tbb.h
540543
__pstl/internal/parallel_backend_utils.h
541-
__pstl/internal/parallel_impl.h
542544
__pstl/internal/unseq_backend_simd.h
543545
__pstl/internal/utils.h
544546
__pstl_algorithm

libcxx/include/__algorithm/pstl_any_all_none_of.h

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@
99
#ifndef _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H
1010
#define _LIBCPP___ALGORITHM_PSTL_ANY_ALL_NONE_OF_H
1111

12-
#include <__algorithm/any_of.h>
12+
#include <__algorithm/pstl_find.h>
13+
#include <__algorithm/pstl_frontend_dispatch.h>
1314
#include <__config>
1415
#include <__iterator/iterator_traits.h>
15-
#include <__pstl/internal/execution_impl.h>
16-
#include <__pstl/internal/parallel_impl.h>
17-
#include <__pstl/internal/unseq_backend_simd.h>
1816
#include <__type_traits/enable_if.h>
1917
#include <__type_traits/is_execution_policy.h>
2018
#include <__type_traits/remove_cvref.h>
@@ -28,50 +26,66 @@
2826

2927
_LIBCPP_BEGIN_NAMESPACE_STD
3028

29+
template <class>
30+
void __pstl_any_of(); // declaration needed for the frontend dispatch below
31+
3132
template <class _ExecutionPolicy,
3233
class _ForwardIterator,
3334
class _Predicate,
34-
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0>
35+
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
36+
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
3537
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool
3638
any_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
37-
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
38-
__is_cpp17_random_access_iterator<_ForwardIterator>::value) {
39-
return std::__terminate_on_exception([&] {
40-
return __pstl::__internal::__parallel_or(
41-
__pstl::__internal::__par_backend_tag{},
42-
__policy,
43-
__first,
44-
__last,
45-
[&__policy, &__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
46-
return std::any_of(std::__remove_parallel_policy(__policy), __brick_first, __brick_last, __pred);
47-
});
48-
});
49-
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
50-
__is_cpp17_random_access_iterator<_ForwardIterator>::value) {
51-
return __pstl::__unseq_backend::__simd_or(__first, __last - __first, __pred);
52-
} else {
53-
return std::any_of(__first, __last, __pred);
54-
}
39+
return std::__pstl_frontend_dispatch(
40+
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_any_of),
41+
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Predicate __g_pred) {
42+
return std::find_if(__policy, __g_first, __g_last, __g_pred) != __g_last;
43+
},
44+
std::move(__first),
45+
std::move(__last),
46+
std::move(__pred));
5547
}
5648

49+
template <class>
50+
void __pstl_all_of(); // declaration needed for the frontend dispatch below
51+
5752
template <class _ExecutionPolicy,
5853
class _ForwardIterator,
5954
class _Pred,
60-
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0>
55+
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
56+
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
6157
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool
6258
all_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) {
63-
return !std::any_of(__policy, __first, __last, [&](__iter_reference<_ForwardIterator> __value) {
64-
return !__pred(__value);
65-
});
59+
return std::__pstl_frontend_dispatch(
60+
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_all_of),
61+
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) {
62+
return !std::any_of(__policy, __g_first, __g_last, [&](__iter_reference<_ForwardIterator> __value) {
63+
return !__g_pred(__value);
64+
});
65+
},
66+
std::move(__first),
67+
std::move(__last),
68+
std::move(__pred));
6669
}
6770

71+
template <class>
72+
void __pstl_none_of(); // declaration needed for the frontend dispatch below
73+
6874
template <class _ExecutionPolicy,
6975
class _ForwardIterator,
7076
class _Pred,
71-
enable_if_t<is_execution_policy_v<__remove_cvref_t<_ExecutionPolicy>>, int> = 0>
77+
class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
78+
enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
7279
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI bool
7380
none_of(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Pred __pred) {
74-
return !std::any_of(__policy, __first, __last, __pred);
81+
return std::__pstl_frontend_dispatch(
82+
_LIBCPP_PSTL_CUSTOMIZATION_POINT(__pstl_none_of),
83+
[&](_ForwardIterator __g_first, _ForwardIterator __g_last, _Pred __g_pred) {
84+
return !std::any_of(__policy, __g_first, __g_last, __g_pred);
85+
},
86+
std::move(__first),
87+
std::move(__last),
88+
std::move(__pred));
7589
}
7690

7791
_LIBCPP_END_NAMESPACE_STD

libcxx/include/__algorithm/pstl_backend.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ A PSTL parallel backend is a tag type to which the following functions are assoc
2929
template <class _ExecutionPolicy, class _Iterator, class _Func>
3030
void __pstl_for_each(_Backend, _ExecutionPolicy&&, _Iterator __first, _Iterator __last, _Func __f);
3131
32+
template <class _ExecutionPolicy, class _Iterator, class _Predicate>
33+
_Iterator __pstl_find_if(_Backend, _Iterator __first, _Iterator __last, _Predicate __pred);
34+
3235
// TODO: Complete this list
3336
3437
The following functions are optional but can be provided. If provided, they are used by the corresponding
@@ -38,6 +41,21 @@ implemented, all the algorithms will eventually forward to the basis algorithms
3841
template <class _ExecutionPolicy, class _Iterator, class _Size, class _Func>
3942
void __pstl_for_each_n(_Backend, _ExecutionPolicy&&, _Iterator __first, _Size __n, _Func __f);
4043
44+
template <class _ExecutionPolicy, class _Iterator, class _Predicate>
45+
bool __pstl_any_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred);
46+
47+
template <class _ExecutionPolicy, class _Iterator, class _Predicate>
48+
bool __pstl_all_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred);
49+
50+
template <class _ExecutionPolicy, class _Iterator, class _Predicate>
51+
bool __pstl_none_of(_Backend, _Iterator __first, _iterator __last, _Predicate __pred);
52+
53+
template <class _ExecutionPolicy, class _Iterator, class _Tp>
54+
void __pstl_fill(_Iterator __first, _Iterator __last, const _Tp& __value);
55+
56+
template <class _ExecutionPolicy, class _Iterator, class _SizeT, class _Tp>
57+
void __pstl_fill_n(_Iterator __first, _SizeT __n, const _Tp& __value);
58+
4159
// TODO: Complete this list
4260
4361
*/

libcxx/include/__algorithm/pstl_backends/cpu_backend.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,15 @@
1717
template <class _RandomAccessIterator, class _Functor>
1818
void __parallel_for(_RandomAccessIterator __first, _RandomAccessIterator __last, _Functor __func);
1919
20+
// Cancel the execution of other jobs - they aren't needed anymore
21+
void __cancel_execution();
22+
2023
TODO: Document the parallel backend
2124
*/
2225

26+
#include <__algorithm/pstl_backends/cpu_backends/any_of.h>
27+
#include <__algorithm/pstl_backends/cpu_backends/fill.h>
28+
#include <__algorithm/pstl_backends/cpu_backends/find_if.h>
2329
#include <__algorithm/pstl_backends/cpu_backends/for_each.h>
2430

2531
#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_H
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H
10+
#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H
11+
12+
#include <__algorithm/any_of.h>
13+
#include <__algorithm/find_if.h>
14+
#include <__algorithm/pstl_backends/cpu_backends/backend.h>
15+
#include <__atomic/atomic.h>
16+
#include <__atomic/memory_order.h>
17+
#include <__config>
18+
#include <__functional/operations.h>
19+
#include <__iterator/iterator_traits.h>
20+
#include <__type_traits/is_execution_policy.h>
21+
#include <__utility/pair.h>
22+
#include <__utility/terminate_on_exception.h>
23+
#include <cstdint>
24+
25+
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
26+
27+
_LIBCPP_BEGIN_NAMESPACE_STD
28+
29+
template <class _Index, class _Brick>
30+
_LIBCPP_HIDE_FROM_ABI bool __parallel_or(_Index __first, _Index __last, _Brick __f) {
31+
std::atomic<bool> __found(false);
32+
__par_backend::__parallel_for(__first, __last, [__f, &__found](_Index __i, _Index __j) {
33+
if (!__found.load(std::memory_order_relaxed) && __f(__i, __j)) {
34+
__found.store(true, std::memory_order_relaxed);
35+
__par_backend::__cancel_execution();
36+
}
37+
});
38+
return __found;
39+
}
40+
41+
// TODO: check whether __simd_first() can be used here
42+
template <class _Index, class _DifferenceType, class _Pred>
43+
_LIBCPP_HIDE_FROM_ABI bool __simd_or(_Index __first, _DifferenceType __n, _Pred __pred) noexcept {
44+
_DifferenceType __block_size = 4 < __n ? 4 : __n;
45+
const _Index __last = __first + __n;
46+
while (__last != __first) {
47+
int32_t __flag = 1;
48+
_PSTL_PRAGMA_SIMD_REDUCTION(& : __flag)
49+
for (_DifferenceType __i = 0; __i < __block_size; ++__i)
50+
if (__pred(*(__first + __i)))
51+
__flag = 0;
52+
if (!__flag)
53+
return true;
54+
55+
__first += __block_size;
56+
if (__last - __first >= __block_size << 1) {
57+
// Double the block _Size. Any unnecessary iterations can be amortized against work done so far.
58+
__block_size <<= 1;
59+
} else {
60+
__block_size = __last - __first;
61+
}
62+
}
63+
return false;
64+
}
65+
66+
template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate>
67+
_LIBCPP_HIDE_FROM_ABI bool
68+
__pstl_any_of(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
69+
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
70+
__is_cpp17_random_access_iterator<_ForwardIterator>::value) {
71+
return std::__terminate_on_exception([&] {
72+
return std::__parallel_or(
73+
__first, __last, [&__pred](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
74+
return std::__pstl_any_of<__remove_parallel_policy_t<_ExecutionPolicy>>(
75+
__cpu_backend_tag{}, __brick_first, __brick_last, __pred);
76+
});
77+
});
78+
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
79+
__is_cpp17_random_access_iterator<_ForwardIterator>::value) {
80+
return std::__simd_or(__first, __last - __first, __pred);
81+
} else {
82+
return std::any_of(__first, __last, __pred);
83+
}
84+
}
85+
86+
_LIBCPP_END_NAMESPACE_STD
87+
88+
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
89+
90+
#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKEND_ANY_OF_H
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H
10+
#define _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H
11+
12+
#include <__algorithm/fill.h>
13+
#include <__algorithm/pstl_backends/cpu_backends/backend.h>
14+
#include <__config>
15+
#include <__iterator/iterator_traits.h>
16+
#include <__type_traits/is_execution_policy.h>
17+
#include <__utility/terminate_on_exception.h>
18+
19+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20+
# pragma GCC system_header
21+
#endif
22+
23+
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
24+
25+
_LIBCPP_BEGIN_NAMESPACE_STD
26+
27+
template <class _Index, class _DifferenceType, class _Tp>
28+
_LIBCPP_HIDE_FROM_ABI _Index __simd_fill_n(_Index __first, _DifferenceType __n, const _Tp& __value) noexcept {
29+
_PSTL_USE_NONTEMPORAL_STORES_IF_ALLOWED
30+
_PSTL_PRAGMA_SIMD
31+
for (_DifferenceType __i = 0; __i < __n; ++__i)
32+
__first[__i] = __value;
33+
return __first + __n;
34+
}
35+
36+
template <class _ExecutionPolicy, class _ForwardIterator, class _Tp>
37+
_LIBCPP_HIDE_FROM_ABI void
38+
__pstl_fill(__cpu_backend_tag, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {
39+
if constexpr (__is_parallel_execution_policy_v<_ExecutionPolicy> &&
40+
__is_cpp17_random_access_iterator<_ForwardIterator>::value) {
41+
std::__terminate_on_exception([&] {
42+
__par_backend::__parallel_for(
43+
__first, __last, [&__value](_ForwardIterator __brick_first, _ForwardIterator __brick_last) {
44+
std::__pstl_fill<__remove_parallel_policy_t<_ExecutionPolicy>>(
45+
__cpu_backend_tag{}, __brick_first, __brick_last, __value);
46+
});
47+
});
48+
} else if constexpr (__is_unsequenced_execution_policy_v<_ExecutionPolicy> &&
49+
__is_cpp17_random_access_iterator<_ForwardIterator>::value) {
50+
std::__simd_fill_n(__first, __last - __first, __value);
51+
} else {
52+
std::fill(__first, __last, __value);
53+
}
54+
}
55+
56+
_LIBCPP_END_NAMESPACE_STD
57+
58+
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17
59+
60+
#endif // _LIBCPP___ALGORITHM_PSTL_BACKENDS_CPU_BACKENDS_FILL_H

0 commit comments

Comments
 (0)