1627f7eb2Smrg // -*- C++ -*-
2627f7eb2Smrg //===-- parallel_impl.h ---------------------------------------------------===//
3627f7eb2Smrg //
4627f7eb2Smrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5627f7eb2Smrg // See https://llvm.org/LICENSE.txt for license information.
6627f7eb2Smrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7627f7eb2Smrg //
8627f7eb2Smrg //===----------------------------------------------------------------------===//
9627f7eb2Smrg
10*4c3eb207Smrg #ifndef _PSTL_PARALLEL_IMPL_H
11*4c3eb207Smrg #define _PSTL_PARALLEL_IMPL_H
12627f7eb2Smrg
13627f7eb2Smrg #include <atomic>
14627f7eb2Smrg // This header defines the minimum set of parallel routines required to support Parallel STL,
15627f7eb2Smrg // implemented on top of Intel(R) Threading Building Blocks (Intel(R) TBB) library
16627f7eb2Smrg
17627f7eb2Smrg namespace __pstl
18627f7eb2Smrg {
19627f7eb2Smrg namespace __internal
20627f7eb2Smrg {
21627f7eb2Smrg
22627f7eb2Smrg //------------------------------------------------------------------------
23627f7eb2Smrg // parallel_find
24627f7eb2Smrg //-----------------------------------------------------------------------
25627f7eb2Smrg /** Return extremum value returned by brick f[i,j) for subranges [i,j) of [first,last)
26627f7eb2Smrg Each f[i,j) must return a value in [i,j). */
27627f7eb2Smrg template <class _ExecutionPolicy, class _Index, class _Brick, class _Compare>
28627f7eb2Smrg _Index
__parallel_find(_ExecutionPolicy && __exec,_Index __first,_Index __last,_Brick __f,_Compare __comp,bool __b_first)29627f7eb2Smrg __parallel_find(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f, _Compare __comp, bool __b_first)
30627f7eb2Smrg {
31627f7eb2Smrg typedef typename std::iterator_traits<_Index>::difference_type _DifferenceType;
32627f7eb2Smrg const _DifferenceType __n = __last - __first;
33627f7eb2Smrg _DifferenceType __initial_dist = __b_first ? __n : -1;
34627f7eb2Smrg std::atomic<_DifferenceType> __extremum(__initial_dist);
35627f7eb2Smrg // TODO: find out what is better here: parallel_for or parallel_reduce
36627f7eb2Smrg __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
37627f7eb2Smrg [__comp, __f, __first, &__extremum](_Index __i, _Index __j) {
38627f7eb2Smrg // See "Reducing Contention Through Priority Updates", PPoPP '13, for discussion of
39627f7eb2Smrg // why using a shared variable scales fairly well in this situation.
40627f7eb2Smrg if (__comp(__i - __first, __extremum))
41627f7eb2Smrg {
42627f7eb2Smrg _Index __res = __f(__i, __j);
43627f7eb2Smrg // If not '__last' returned then we found what we want so put this to extremum
44627f7eb2Smrg if (__res != __j)
45627f7eb2Smrg {
46627f7eb2Smrg const _DifferenceType __k = __res - __first;
47627f7eb2Smrg for (_DifferenceType __old = __extremum; __comp(__k, __old);
48627f7eb2Smrg __old = __extremum)
49627f7eb2Smrg {
50627f7eb2Smrg __extremum.compare_exchange_weak(__old, __k);
51627f7eb2Smrg }
52627f7eb2Smrg }
53627f7eb2Smrg }
54627f7eb2Smrg });
55627f7eb2Smrg return __extremum != __initial_dist ? __first + __extremum : __last;
56627f7eb2Smrg }
57627f7eb2Smrg
58627f7eb2Smrg //------------------------------------------------------------------------
59627f7eb2Smrg // parallel_or
60627f7eb2Smrg //------------------------------------------------------------------------
61627f7eb2Smrg //! Return true if brick f[i,j) returns true for some subrange [i,j) of [first,last)
62627f7eb2Smrg template <class _ExecutionPolicy, class _Index, class _Brick>
63627f7eb2Smrg bool
__parallel_or(_ExecutionPolicy && __exec,_Index __first,_Index __last,_Brick __f)64627f7eb2Smrg __parallel_or(_ExecutionPolicy&& __exec, _Index __first, _Index __last, _Brick __f)
65627f7eb2Smrg {
66627f7eb2Smrg std::atomic<bool> __found(false);
67627f7eb2Smrg __par_backend::__parallel_for(std::forward<_ExecutionPolicy>(__exec), __first, __last,
68627f7eb2Smrg [__f, &__found](_Index __i, _Index __j) {
69627f7eb2Smrg if (!__found.load(std::memory_order_relaxed) && __f(__i, __j))
70627f7eb2Smrg {
71627f7eb2Smrg __found.store(true, std::memory_order_relaxed);
72627f7eb2Smrg __par_backend::__cancel_execution();
73627f7eb2Smrg }
74627f7eb2Smrg });
75627f7eb2Smrg return __found;
76627f7eb2Smrg }
77627f7eb2Smrg
78627f7eb2Smrg } // namespace __internal
79627f7eb2Smrg } // namespace __pstl
80627f7eb2Smrg
81*4c3eb207Smrg #endif /* _PSTL_PARALLEL_IMPL_H */
82