1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "../tasking/taskscheduler.h" |
7 | #include "../sys/array.h" |
8 | #include "../math/math.h" |
9 | #include "../math/range.h" |
10 | |
11 | namespace embree |
12 | { |
13 | /* parallel_for without range */ |
14 | template<typename Index, typename Func> |
15 | __forceinline void parallel_for( const Index N, const Func& func) |
16 | { |
17 | #if defined(TASKING_INTERNAL) |
18 | if (N) { |
19 | TaskScheduler::spawn(Index(0),N,Index(1),[&] (const range<Index>& r) { |
20 | assert(r.size() == 1); |
21 | func(r.begin()); |
22 | }); |
23 | if (!TaskScheduler::wait()) |
24 | throw std::runtime_error("task cancelled" ); |
25 | } |
26 | |
27 | #elif defined(TASKING_TBB) |
28 | #if TBB_INTERFACE_VERSION >= 12002 |
29 | tbb::task_group_context context; |
30 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
31 | func(i); |
32 | },context); |
33 | if (context.is_group_execution_cancelled()) |
34 | throw std::runtime_error("task cancelled" ); |
35 | #else |
36 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
37 | func(i); |
38 | }); |
39 | if (tbb::task::self().is_cancelled()) |
40 | throw std::runtime_error("task cancelled" ); |
41 | #endif |
42 | |
43 | #elif defined(TASKING_PPL) |
44 | concurrency::parallel_for(Index(0),N,Index(1),[&](Index i) { |
45 | func(i); |
46 | }); |
47 | #else |
48 | # error "no tasking system enabled" |
49 | #endif |
50 | } |
51 | |
52 | /* parallel for with range and granulatity */ |
53 | template<typename Index, typename Func> |
54 | __forceinline void parallel_for( const Index first, const Index last, const Index minStepSize, const Func& func) |
55 | { |
56 | assert(first <= last); |
57 | #if defined(TASKING_INTERNAL) |
58 | TaskScheduler::spawn(first,last,minStepSize,func); |
59 | if (!TaskScheduler::wait()) |
60 | throw std::runtime_error("task cancelled" ); |
61 | |
62 | #elif defined(TASKING_TBB) |
63 | #if TBB_INTERFACE_VERSION >= 12002 |
64 | tbb::task_group_context context; |
65 | tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) { |
66 | func(range<Index>(r.begin(),r.end())); |
67 | },context); |
68 | if (context.is_group_execution_cancelled()) |
69 | throw std::runtime_error("task cancelled" ); |
70 | #else |
71 | tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) { |
72 | func(range<Index>(r.begin(),r.end())); |
73 | }); |
74 | if (tbb::task::self().is_cancelled()) |
75 | throw std::runtime_error("task cancelled" ); |
76 | #endif |
77 | |
78 | #elif defined(TASKING_PPL) |
79 | concurrency::parallel_for(first, last, Index(1) /*minStepSize*/, [&](Index i) { |
80 | func(range<Index>(i,i+1)); |
81 | }); |
82 | |
83 | #else |
84 | # error "no tasking system enabled" |
85 | #endif |
86 | } |
87 | |
88 | /* parallel for with range */ |
89 | template<typename Index, typename Func> |
90 | __forceinline void parallel_for( const Index first, const Index last, const Func& func) |
91 | { |
92 | assert(first <= last); |
93 | parallel_for(first,last,(Index)1,func); |
94 | } |
95 | |
96 | #if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION > 4001) |
97 | |
98 | template<typename Index, typename Func> |
99 | __forceinline void parallel_for_static( const Index N, const Func& func) |
100 | { |
101 | #if TBB_INTERFACE_VERSION >= 12002 |
102 | tbb::task_group_context context; |
103 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
104 | func(i); |
105 | },tbb::simple_partitioner(),context); |
106 | if (context.is_group_execution_cancelled()) |
107 | throw std::runtime_error("task cancelled" ); |
108 | #else |
109 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
110 | func(i); |
111 | },tbb::simple_partitioner()); |
112 | if (tbb::task::self().is_cancelled()) |
113 | throw std::runtime_error("task cancelled" ); |
114 | #endif |
115 | } |
116 | |
117 | typedef tbb::affinity_partitioner affinity_partitioner; |
118 | |
119 | template<typename Index, typename Func> |
120 | __forceinline void parallel_for_affinity( const Index N, const Func& func, tbb::affinity_partitioner& ap) |
121 | { |
122 | #if TBB_INTERFACE_VERSION >= 12002 |
123 | tbb::task_group_context context; |
124 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
125 | func(i); |
126 | },ap,context); |
127 | if (context.is_group_execution_cancelled()) |
128 | throw std::runtime_error("task cancelled" ); |
129 | #else |
130 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
131 | func(i); |
132 | },ap); |
133 | if (tbb::task::self().is_cancelled()) |
134 | throw std::runtime_error("task cancelled" ); |
135 | #endif |
136 | } |
137 | |
138 | #else |
139 | |
140 | template<typename Index, typename Func> |
141 | __forceinline void parallel_for_static( const Index N, const Func& func) |
142 | { |
143 | parallel_for(N,func); |
144 | } |
145 | |
146 | struct affinity_partitioner { |
147 | }; |
148 | |
149 | template<typename Index, typename Func> |
150 | __forceinline void parallel_for_affinity( const Index N, const Func& func, affinity_partitioner& ap) |
151 | { |
152 | parallel_for(N,func); |
153 | } |
154 | |
155 | #endif |
156 | } |
157 | |