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 | // -- GODOT start -- |
25 | // throw std::runtime_error("task cancelled"); |
26 | abort(); |
27 | // -- GODOT end -- |
28 | } |
29 | #elif defined(TASKING_TBB) |
30 | #if TBB_INTERFACE_VERSION >= 12002 |
31 | tbb::task_group_context context; |
32 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
33 | func(i); |
34 | },context); |
35 | if (context.is_group_execution_cancelled()) |
36 | // -- GODOT start -- |
37 | // throw std::runtime_error("task cancelled"); |
38 | abort(); |
39 | // -- GODOT end -- |
40 | #else |
41 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
42 | func(i); |
43 | }); |
44 | if (tbb::task::self().is_cancelled()) |
45 | // -- GODOT start -- |
46 | // throw std::runtime_error("task cancelled"); |
47 | abort(); |
48 | // -- GODOT end -- |
49 | #endif |
50 | |
51 | #elif defined(TASKING_PPL) |
52 | concurrency::parallel_for(Index(0),N,Index(1),[&](Index i) { |
53 | func(i); |
54 | }); |
55 | #else |
56 | # error "no tasking system enabled" |
57 | #endif |
58 | } |
59 | |
60 | /* parallel for with range and granulatity */ |
61 | template<typename Index, typename Func> |
62 | __forceinline void parallel_for( const Index first, const Index last, const Index minStepSize, const Func& func) |
63 | { |
64 | assert(first <= last); |
65 | #if defined(TASKING_INTERNAL) |
66 | TaskScheduler::spawn(first,last,minStepSize,func); |
67 | if (!TaskScheduler::wait()) |
68 | // -- GODOT start -- |
69 | // throw std::runtime_error("task cancelled"); |
70 | abort(); |
71 | // -- GODOT end -- |
72 | |
73 | #elif defined(TASKING_TBB) |
74 | #if TBB_INTERFACE_VERSION >= 12002 |
75 | tbb::task_group_context context; |
76 | tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) { |
77 | func(range<Index>(r.begin(),r.end())); |
78 | },context); |
79 | if (context.is_group_execution_cancelled()) |
80 | // -- GODOT start -- |
81 | // throw std::runtime_error("task cancelled"); |
82 | abort(); |
83 | // -- GODOT end -- |
84 | #else |
85 | tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) { |
86 | func(range<Index>(r.begin(),r.end())); |
87 | }); |
88 | if (tbb::task::self().is_cancelled()) |
89 | // -- GODOT start -- |
90 | // throw std::runtime_error("task cancelled"); |
91 | abort(); |
92 | // -- GODOT end -- |
93 | #endif |
94 | |
95 | #elif defined(TASKING_PPL) |
96 | concurrency::parallel_for(first, last, Index(1) /*minStepSize*/, [&](Index i) { |
97 | func(range<Index>(i,i+1)); |
98 | }); |
99 | |
100 | #else |
101 | # error "no tasking system enabled" |
102 | #endif |
103 | } |
104 | |
105 | /* parallel for with range */ |
106 | template<typename Index, typename Func> |
107 | __forceinline void parallel_for( const Index first, const Index last, const Func& func) |
108 | { |
109 | assert(first <= last); |
110 | parallel_for(first,last,(Index)1,func); |
111 | } |
112 | |
113 | #if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION > 4001) |
114 | |
115 | template<typename Index, typename Func> |
116 | __forceinline void parallel_for_static( const Index N, const Func& func) |
117 | { |
118 | #if TBB_INTERFACE_VERSION >= 12002 |
119 | tbb::task_group_context context; |
120 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
121 | func(i); |
122 | },tbb::simple_partitioner(),context); |
123 | if (context.is_group_execution_cancelled()) |
124 | // -- GODOT start -- |
125 | // throw std::runtime_error("task cancelled"); |
126 | abort(); |
127 | // -- GODOT end -- |
128 | #else |
129 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
130 | func(i); |
131 | },tbb::simple_partitioner()); |
132 | if (tbb::task::self().is_cancelled()) |
133 | // -- GODOT start -- |
134 | // throw std::runtime_error("task cancelled"); |
135 | abort(); |
136 | // -- GODOT end -- |
137 | #endif |
138 | } |
139 | |
140 | typedef tbb::affinity_partitioner affinity_partitioner; |
141 | |
142 | template<typename Index, typename Func> |
143 | __forceinline void parallel_for_affinity( const Index N, const Func& func, tbb::affinity_partitioner& ap) |
144 | { |
145 | #if TBB_INTERFACE_VERSION >= 12002 |
146 | tbb::task_group_context context; |
147 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
148 | func(i); |
149 | },ap,context); |
150 | if (context.is_group_execution_cancelled()) |
151 | // -- GODOT start -- |
152 | // throw std::runtime_error("task cancelled"); |
153 | abort(); |
154 | // -- GODOT end -- |
155 | #else |
156 | tbb::parallel_for(Index(0),N,Index(1),[&](Index i) { |
157 | func(i); |
158 | },ap); |
159 | if (tbb::task::self().is_cancelled()) |
160 | // -- GODOT start -- |
161 | // throw std::runtime_error("task cancelled"); |
162 | abort(); |
163 | // -- GODOT end -- |
164 | #endif |
165 | } |
166 | |
167 | #else |
168 | |
169 | template<typename Index, typename Func> |
170 | __forceinline void parallel_for_static( const Index N, const Func& func) |
171 | { |
172 | parallel_for(N,func); |
173 | } |
174 | |
175 | struct affinity_partitioner { |
176 | }; |
177 | |
178 | template<typename Index, typename Func> |
179 | __forceinline void parallel_for_affinity( const Index N, const Func& func, affinity_partitioner& ap) |
180 | { |
181 | parallel_for(N,func); |
182 | } |
183 | |
184 | #endif |
185 | } |
186 | |