21 #ifndef __TBB_parallel_for_H 22 #define __TBB_parallel_for_H 26 #include "partitioner.h" 27 #include "blocked_range.h" 28 #include "tbb_exception.h" 32 namespace interface9 {
37 void* allocate_sibling(task* start_for_task,
size_t bytes);
41 template<
typename Range,
typename Body,
typename Partitioner>
42 class start_for:
public task {
45 typename Partitioner::task_partition_type my_partition;
49 void note_affinity( affinity_id
id ) {
50 my_partition.note_affinity(
id );
55 start_for(
const Range& range,
const Body& body, Partitioner& partitioner ) :
58 my_partition(partitioner)
63 start_for( start_for& parent_,
typename Partitioner::split_type& split_obj) :
64 my_range(parent_.my_range, split_obj),
65 my_body(parent_.my_body),
66 my_partition(parent_.my_partition, split_obj)
68 my_partition.set_affinity(*
this);
72 start_for( start_for& parent_,
const Range& r, depth_t d ) :
74 my_body(parent_.my_body),
75 my_partition(parent_.my_partition, split())
77 my_partition.set_affinity(*
this);
78 my_partition.align_depth( d );
80 static void run(
const Range& range,
const Body& body, Partitioner& partitioner ) {
81 if( !range.empty() ) {
82 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP 83 start_for& a = *
new(task::allocate_root()) start_for(range,body,partitioner);
87 task_group_context context;
88 start_for& a = *
new(task::allocate_root(context)) start_for(range,body,partitioner);
90 task::spawn_root_and_wait(a);
93 #if __TBB_TASK_GROUP_CONTEXT 94 static void run(
const Range& range,
const Body& body, Partitioner& partitioner, task_group_context& context ) {
95 if( !range.empty() ) {
96 start_for& a = *
new(task::allocate_root(context)) start_for(range,body,partitioner);
97 task::spawn_root_and_wait(a);
101 void run_body( Range &r ) { my_body( r ); }
105 void offer_work(
typename Partitioner::split_type& split_obj) {
106 spawn( *
new( allocate_sibling(static_cast<task*>(
this),
sizeof(start_for)) ) start_for(*
this, split_obj) );
109 void offer_work(
const Range& r, depth_t d = 0) {
110 spawn( *
new( allocate_sibling(static_cast<task*>(
this),
sizeof(start_for)) ) start_for(*
this, r, d) );
116 inline void* allocate_sibling(task* start_for_task,
size_t bytes) {
117 task* parent_ptr =
new( start_for_task->allocate_continuation() ) flag_task();
118 start_for_task->set_parent(parent_ptr);
119 parent_ptr->set_ref_count(2);
120 return &parent_ptr->allocate_child().allocate(bytes);
124 template<
typename Range,
typename Body,
typename Partitioner>
125 task* start_for<Range,Body,Partitioner>::execute() {
126 my_partition.check_being_stolen( *
this );
127 my_partition.execute(*
this, my_range);
136 using interface9::internal::start_for;
139 template<
typename Function,
typename Index>
140 class parallel_for_body : internal::no_assign {
141 const Function &my_func;
142 const Index my_begin;
145 parallel_for_body(
const Function& _func, Index& _begin, Index& _step )
146 : my_func(_func), my_begin(_begin), my_step(_step) {}
153 Index k = my_begin + b*ms;
157 #if __TBB_ASSERT_ON_VECTORIZATION_FAILURE 158 #pragma vector always assert 161 for ( Index i = b; i < e; ++i, k += ms ) {
184 template<
typename Range,
typename Body>
186 internal::start_for<Range,Body,const __TBB_DEFAULT_PARTITIONER>::run(range,body,__TBB_DEFAULT_PARTITIONER());
191 template<
typename Range,
typename Body>
192 void parallel_for(
const Range& range,
const Body& body,
const simple_partitioner& partitioner ) {
193 internal::start_for<Range,Body,const simple_partitioner>::run(range,body,partitioner);
198 template<
typename Range,
typename Body>
199 void parallel_for(
const Range& range,
const Body& body,
const auto_partitioner& partitioner ) {
200 internal::start_for<Range,Body,const auto_partitioner>::run(range,body,partitioner);
203 #if TBB_PREVIEW_STATIC_PARTITIONER 206 template<
typename Range,
typename Body>
207 void parallel_for(
const Range& range,
const Body& body,
const static_partitioner& partitioner ) {
208 internal::start_for<Range,Body,const static_partitioner>::run(range,body,partitioner);
214 template<
typename Range,
typename Body>
215 void parallel_for(
const Range& range,
const Body& body, affinity_partitioner& partitioner ) {
216 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner);
219 #if __TBB_TASK_GROUP_CONTEXT 222 template<
typename Range,
typename Body>
223 void parallel_for(
const Range& range,
const Body& body, task_group_context& context ) {
224 internal::start_for<Range,Body,const __TBB_DEFAULT_PARTITIONER>::run(range, body, __TBB_DEFAULT_PARTITIONER(), context);
229 template<
typename Range,
typename Body>
230 void parallel_for(
const Range& range,
const Body& body,
const simple_partitioner& partitioner, task_group_context& context ) {
231 internal::start_for<Range,Body,const simple_partitioner>::run(range, body, partitioner, context);
236 template<
typename Range,
typename Body>
237 void parallel_for(
const Range& range,
const Body& body,
const auto_partitioner& partitioner, task_group_context& context ) {
238 internal::start_for<Range,Body,const auto_partitioner>::run(range, body, partitioner, context);
241 #if TBB_PREVIEW_STATIC_PARTITIONER 244 template<
typename Range,
typename Body>
245 void parallel_for(
const Range& range,
const Body& body,
const static_partitioner& partitioner, task_group_context& context ) {
246 internal::start_for<Range,Body,const static_partitioner>::run(range, body, partitioner, context);
252 template<
typename Range,
typename Body>
253 void parallel_for(
const Range& range,
const Body& body, affinity_partitioner& partitioner, task_group_context& context ) {
254 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner, context);
259 namespace strict_ppl {
262 template <
typename Index,
typename Function,
typename Partitioner>
264 void parallel_for_impl(Index first, Index last, Index step,
const Function& f, Partitioner& partitioner) {
266 internal::throw_exception(internal::eid_nonpositive_step);
267 else if (last > first) {
269 Index end = (last - first - Index(1)) / step + Index(1);
271 internal::parallel_for_body<Function, Index> body(f, first, step);
277 template <
typename Index,
typename Function>
278 void parallel_for(Index first, Index last, Index step,
const Function& f) {
279 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, auto_partitioner());
282 template <
typename Index,
typename Function>
283 void parallel_for(Index first, Index last, Index step,
const Function& f,
const simple_partitioner& partitioner) {
284 parallel_for_impl<Index,Function,const simple_partitioner>(first, last, step, f, partitioner);
287 template <
typename Index,
typename Function>
288 void parallel_for(Index first, Index last, Index step,
const Function& f,
const auto_partitioner& partitioner) {
289 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, partitioner);
291 #if TBB_PREVIEW_STATIC_PARTITIONER 292 template <
typename Index,
typename Function>
294 void parallel_for(Index first, Index last, Index step,
const Function& f,
const static_partitioner& partitioner) {
295 parallel_for_impl<Index,Function,const static_partitioner>(first, last, step, f, partitioner);
298 template <
typename Index,
typename Function>
300 void parallel_for(Index first, Index last, Index step,
const Function& f, affinity_partitioner& partitioner) {
301 parallel_for_impl(first, last, step, f, partitioner);
305 template <
typename Index,
typename Function>
307 parallel_for_impl<Index,Function,const auto_partitioner>(first, last,
static_cast<Index
>(1), f, auto_partitioner());
310 template <
typename Index,
typename Function>
311 void parallel_for(Index first, Index last,
const Function& f,
const simple_partitioner& partitioner) {
312 parallel_for_impl<Index,Function,const simple_partitioner>(first, last,
static_cast<Index
>(1), f, partitioner);
315 template <
typename Index,
typename Function>
316 void parallel_for(Index first, Index last,
const Function& f,
const auto_partitioner& partitioner) {
317 parallel_for_impl<Index,Function,const auto_partitioner>(first, last,
static_cast<Index
>(1), f, partitioner);
319 #if TBB_PREVIEW_STATIC_PARTITIONER 320 template <
typename Index,
typename Function>
322 void parallel_for(Index first, Index last,
const Function& f,
const static_partitioner& partitioner) {
323 parallel_for_impl<Index,Function,const static_partitioner>(first, last,
static_cast<Index
>(1), f, partitioner);
326 template <
typename Index,
typename Function>
328 void parallel_for(Index first, Index last,
const Function& f, affinity_partitioner& partitioner) {
329 parallel_for_impl(first, last, static_cast<Index>(1), f, partitioner);
332 #if __TBB_TASK_GROUP_CONTEXT 333 template <
typename Index,
typename Function,
typename Partitioner>
335 void parallel_for_impl(Index first, Index last, Index step,
const Function& f, Partitioner& partitioner, tbb::task_group_context &context) {
337 internal::throw_exception(internal::eid_nonpositive_step);
338 else if (last > first) {
340 Index end = (last - first - Index(1)) / step + Index(1);
342 internal::parallel_for_body<Function, Index> body(f, first, step);
348 template <
typename Index,
typename Function>
349 void parallel_for(Index first, Index last, Index step,
const Function& f, tbb::task_group_context &context) {
350 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, auto_partitioner(), context);
353 template <
typename Index,
typename Function>
354 void parallel_for(Index first, Index last, Index step,
const Function& f,
const simple_partitioner& partitioner, tbb::task_group_context &context) {
355 parallel_for_impl<Index,Function,const simple_partitioner>(first, last, step, f, partitioner, context);
358 template <
typename Index,
typename Function>
359 void parallel_for(Index first, Index last, Index step,
const Function& f,
const auto_partitioner& partitioner, tbb::task_group_context &context) {
360 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, partitioner, context);
362 #if TBB_PREVIEW_STATIC_PARTITIONER 363 template <
typename Index,
typename Function>
365 void parallel_for(Index first, Index last, Index step,
const Function& f,
const static_partitioner& partitioner, tbb::task_group_context &context) {
366 parallel_for_impl<Index,Function,const static_partitioner>(first, last, step, f, partitioner, context);
369 template <
typename Index,
typename Function>
371 void parallel_for(Index first, Index last, Index step,
const Function& f, affinity_partitioner& partitioner, tbb::task_group_context &context) {
372 parallel_for_impl(first, last, step, f, partitioner, context);
377 template <
typename Index,
typename Function>
378 void parallel_for(Index first, Index last,
const Function& f, tbb::task_group_context &context) {
379 parallel_for_impl<Index,Function,const auto_partitioner>(first, last,
static_cast<Index
>(1), f, auto_partitioner(), context);
382 template <
typename Index,
typename Function>
383 void parallel_for(Index first, Index last,
const Function& f,
const simple_partitioner& partitioner, tbb::task_group_context &context) {
384 parallel_for_impl<Index,Function,const simple_partitioner>(first, last,
static_cast<Index
>(1), f, partitioner, context);
387 template <
typename Index,
typename Function>
388 void parallel_for(Index first, Index last,
const Function& f,
const auto_partitioner& partitioner, tbb::task_group_context &context) {
389 parallel_for_impl<Index,Function,const auto_partitioner>(first, last,
static_cast<Index
>(1), f, partitioner, context);
391 #if TBB_PREVIEW_STATIC_PARTITIONER 392 template <
typename Index,
typename Function>
394 void parallel_for(Index first, Index last,
const Function& f,
const static_partitioner& partitioner, tbb::task_group_context &context) {
395 parallel_for_impl<Index,Function,const static_partitioner>(first, last,
static_cast<Index
>(1), f, partitioner, context);
398 template <
typename Index,
typename Function>
400 void parallel_for(Index first, Index last,
const Function& f, affinity_partitioner& partitioner, tbb::task_group_context &context) {
401 parallel_for_impl(first, last, static_cast<Index>(1), f, partitioner, context);
413 #if TBB_PREVIEW_SERIAL_SUBSET 414 #define __TBB_NORMAL_EXECUTION 415 #include "../serial/tbb/parallel_for.h" 416 #undef __TBB_NORMAL_EXECUTION const_iterator begin() const
Beginning of range.
Definition: blocked_range.h:62
A range over which to iterate.
Definition: blocked_range.h:40
const_iterator end() const
One past last value in range.
Definition: blocked_range.h:65
void parallel_for(const Range &range, const Body &body)
Parallel iteration over range with default partitioner.
Definition: parallel_for.h:185
void parallel_for(Index first, Index last, Index step, const Function &f)
Parallel iteration over a range of integers with a step provided and default partitioner.
Definition: parallel_for.h:278
Definition: _flow_graph_async_msg_impl.h:32
The namespace tbb contains all components of the library.
Definition: parallel_for.h:44