1181254a7Smrg // -*- C++ -*-
2181254a7Smrg //===-- parallel_impl.h ---------------------------------------------------===//
3181254a7Smrg //
4181254a7Smrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5181254a7Smrg // See https://llvm.org/LICENSE.txt for license information.
6181254a7Smrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7181254a7Smrg //
8181254a7Smrg //===----------------------------------------------------------------------===//
9181254a7Smrg
10*fb8a8121Smrg #ifndef _PSTL_PARALLEL_IMPL_H
11*fb8a8121Smrg #define _PSTL_PARALLEL_IMPL_H
12181254a7Smrg
13181254a7Smrg #include <atomic>
14181254a7Smrg // This header defines the minimum set of parallel routines required to support Parallel STL,
15181254a7Smrg // implemented on top of Intel(R) Threading Building Blocks (Intel(R) TBB) library
16181254a7Smrg
17181254a7Smrg namespace __pstl
18181254a7Smrg {
19181254a7Smrg namespace __internal
20181254a7Smrg {
21181254a7Smrg
22181254a7Smrg //------------------------------------------------------------------------
23181254a7Smrg // parallel_find
24181254a7Smrg //-----------------------------------------------------------------------
25181254a7Smrg /** Return extremum value returned by brick f[i,j) for subranges [i,j) of [first,last)
26181254a7Smrg Each f[i,j) must return a value in [i,j). */
27181254a7Smrg template <class _ExecutionPolicy, class _Index, class _Brick, class _Compare>
28181254a7Smrg _Index
__parallel_find(_ExecutionPolicy && __exec,_Index __first,_Index __last,_Brick __f,_Compare __comp,bool __b_first)29181254a7Smrg __parallel_find(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f, _Compare __comp, bool __b_first)
30181254a7Smrg {
31181254a7Smrg typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType;
32181254a7Smrg const _DifferenceType __n = __last - __first;
33181254a7Smrg _DifferenceType __initial_dist = __b_first ? __n : -1;
34181254a7Smrg std::atomic<_DifferenceType> __extremum(__initial_dist);
35181254a7Smrg // TODO: find out what is better here: parallel_for or parallel_reduce
36181254a7Smrg __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
37181254a7Smrg [__comp, __f, __first, &__extremum](_Index __i, _Index __j) {
38181254a7Smrg // See "Reducing Contention Through Priority Updates", PPoPP '13, for discussion of
39181254a7Smrg // why using a shared variable scales fairly well in this situation.
40181254a7Smrg if (__comp(__i - __first, __extremum))
41181254a7Smrg {
42181254a7Smrg _Index __res = __f(__i, __j);
43181254a7Smrg // If not '__last' returned then we found what we want so put this to extremum
44181254a7Smrg if (__res != __j)
45181254a7Smrg {
46181254a7Smrg const _DifferenceType __k = __res - __first;
47181254a7Smrg for (_DifferenceType __old = __extremum; __comp(__k, __old);
48181254a7Smrg __old = __extremum)
49181254a7Smrg {
50181254a7Smrg __extremum.compare_exchange_weak(__old, __k);
51181254a7Smrg }
52181254a7Smrg }
53181254a7Smrg }
54181254a7Smrg });
55181254a7Smrg return __extremum != __initial_dist ? __first + __extremum : __last;
56181254a7Smrg }
57181254a7Smrg
58181254a7Smrg //------------------------------------------------------------------------
59181254a7Smrg // parallel_or
60181254a7Smrg //------------------------------------------------------------------------
61181254a7Smrg //! Return true if brick f[i,j) returns true for some subrange [i,j) of [first,last)
62181254a7Smrg template <class _ExecutionPolicy, class _Index, class _Brick>
63181254a7Smrg bool
__parallel_or(_ExecutionPolicy && __exec,_Index __first,_Index __last,_Brick __f)64181254a7Smrg __parallel_or(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f)
65181254a7Smrg {
66181254a7Smrg std::atomic<bool> __found(false);
67181254a7Smrg __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
68181254a7Smrg [__f, &__found](_Index __i, _Index __j) {
69181254a7Smrg if (!__found.load(std::memory_order_relaxed) && __f(__i, __j))
70181254a7Smrg {
71181254a7Smrg __found.store(true, std::memory_order_relaxed);
72181254a7Smrg __par_backend::__cancel_execution();
73181254a7Smrg }
74181254a7Smrg });
75181254a7Smrg return __found;
76181254a7Smrg }
77181254a7Smrg
78181254a7Smrg } // namespace __internal
79181254a7Smrg } // namespace __pstl
80181254a7Smrg
81*fb8a8121Smrg #endif /* _PSTL_PARALLEL_IMPL_H */
82