xref: /llvm-project/pstl/include/pstl/internal/omp/parallel_for.h (revision 843c12d6a0cdfd64c5a92e24eb58ba9ee17ca1ee)
1 // -*- C++ -*-
2 // -*-===----------------------------------------------------------------------===//
3 //
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
7 // See https://llvm.org/LICENSE.txt for license information.
8 //
9 //===----------------------------------------------------------------------===//
10 
11 #ifndef _PSTL_INTERNAL_OMP_PARALLEL_FOR_H
12 #define _PSTL_INTERNAL_OMP_PARALLEL_FOR_H
13 
14 #include <cstddef>
15 
16 #include "util.h"
17 
18 namespace __pstl
19 {
20 namespace __omp_backend
21 {
22 
23 template <class _Index, class _Fp>
24 void
__parallel_for_body(_Index __first,_Index __last,_Fp __f)25 __parallel_for_body(_Index __first, _Index __last, _Fp __f)
26 {
27     // initial partition of the iteration space into chunks
28     auto __policy = __omp_backend::__chunk_partitioner(__first, __last);
29 
30     // To avoid over-subscription we use taskloop for the nested parallelism
31     _PSTL_PRAGMA(omp taskloop untied mergeable)
32     for (std::size_t __chunk = 0; __chunk < __policy.__n_chunks; ++__chunk)
33     {
34         __pstl::__omp_backend::__process_chunk(__policy, __first, __chunk, __f);
35     }
36 }
37 
38 //------------------------------------------------------------------------
39 // Notation:
40 // Evaluation of brick f[i,j) for each subrange [i,j) of [first, last)
41 //------------------------------------------------------------------------
42 
43 template <class _ExecutionPolicy, class _Index, class _Fp>
44 void
__parallel_for(__pstl::__internal::__openmp_backend_tag,_ExecutionPolicy &&,_Index __first,_Index __last,_Fp __f)45 __parallel_for(__pstl::__internal::__openmp_backend_tag, _ExecutionPolicy&&, _Index __first, _Index __last, _Fp __f)
46 {
47     if (omp_in_parallel())
48     {
49         // we don't create a nested parallel region in an existing parallel
50         // region: just create tasks
51         __pstl::__omp_backend::__parallel_for_body(__first, __last, __f);
52     }
53     else
54     {
55         // in any case (nested or non-nested) one parallel region is created and
56         // only one thread creates a set of tasks
57         _PSTL_PRAGMA(omp parallel)
58         _PSTL_PRAGMA(omp single nowait) { __pstl::__omp_backend::__parallel_for_body(__first, __last, __f); }
59     }
60 }
61 
62 } // namespace __omp_backend
63 } // namespace __pstl
64 #endif // _PSTL_INTERNAL_OMP_PARALLEL_FOR_H
65