// -*- C++ -*- // -*-===----------------------------------------------------------------------===// // // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // //===----------------------------------------------------------------------===// #ifndef _PSTL_INTERNAL_OMP_PARALLEL_REDUCE_H #define _PSTL_INTERNAL_OMP_PARALLEL_REDUCE_H #include "util.h" namespace __pstl { namespace __omp_backend { template _Value __parallel_reduce_body(_RandomAccessIterator __first, _RandomAccessIterator __last, _Value __identity, _RealBody __real_body, _Reduction __reduce) { if (__should_run_serial(__first, __last)) { return __real_body(__first, __last, __identity); } auto __middle = __first + ((__last - __first) / 2); _Value __v1(__identity), __v2(__identity); __parallel_invoke_body( [&]() { __v1 = __parallel_reduce_body(__first, __middle, __identity, __real_body, __reduce); }, [&]() { __v2 = __parallel_reduce_body(__middle, __last, __identity, __real_body, __reduce); }); return __reduce(__v1, __v2); } //------------------------------------------------------------------------ // Notation: // r(i,j,init) returns reduction of init with reduction over [i,j) // c(x,y) combines values x and y that were the result of r //------------------------------------------------------------------------ template _Value __parallel_reduce(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _RandomAccessIterator __first, _RandomAccessIterator __last, _Value __identity, _RealBody __real_body, _Reduction __reduction) { // We don't create a nested parallel region in an existing parallel region: // just create tasks. if (omp_in_parallel()) { return __pstl::__omp_backend::__parallel_reduce_body(__first, __last, __identity, __real_body, __reduction); } // In any case (nested or non-nested) one parallel region is created and only // one thread creates a set of tasks. _Value __res = __identity; _PSTL_PRAGMA(omp parallel) _PSTL_PRAGMA(omp single nowait) { __res = __pstl::__omp_backend::__parallel_reduce_body(__first, __last, __identity, __real_body, __reduction); } return __res; } } // namespace __omp_backend } // namespace __pstl #endif // _PSTL_INTERNAL_OMP_PARALLEL_REDUCE_H