Intel(R) Threading Building Blocks Doxygen Documentation  version 4.2.3
parallel_reduce.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2005-2019 Intel Corporation
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 #ifndef __TBB_parallel_reduce_H
18 #define __TBB_parallel_reduce_H
19 
20 #include <new>
21 #include "task.h"
22 #include "aligned_space.h"
23 #include "partitioner.h"
24 #include "tbb_profiling.h"
25 
26 namespace tbb {
27 
28 namespace interface9 {
30 namespace internal {
31 
32  using namespace tbb::internal;
33 
35  enum {
37  };
38 
40  typedef char reduction_context;
41 
43 
44  template<typename Body>
45  class finish_reduce: public flag_task {
49  Body* my_body;
52  has_right_zombie(false), // TODO: substitute by flag_task::child_stolen?
53  my_context(context_),
54  my_body(NULL)
55  {
56  }
58  if( has_right_zombie )
59  zombie_space.begin()->~Body();
60  }
62  if( has_right_zombie ) {
63  // Right child was stolen.
64  Body* s = zombie_space.begin();
65  my_body->join( *s );
66  // Body::join() won't be called if canceled. Defer destruction to destructor
67  }
68  if( my_context==left_child )
69  itt_store_word_with_release( static_cast<finish_reduce*>(parent())->my_body, my_body );
70  return NULL;
71  }
72  template<typename Range,typename Body_, typename Partitioner>
73  friend class start_reduce;
74  };
75 
77  void allocate_sibling(task* start_reduce_task, task *tasks[], size_t start_bytes, size_t finish_bytes);
78 
80 
81  template<typename Range, typename Body, typename Partitioner>
82  class start_reduce: public task {
84  Body* my_body;
85  Range my_range;
86  typename Partitioner::task_partition_type my_partition;
88  task* execute() __TBB_override;
90  void note_affinity( affinity_id id ) __TBB_override {
91  my_partition.note_affinity( id );
92  }
93  template<typename Body_>
94  friend class finish_reduce;
95 
96 public:
98  start_reduce( const Range& range, Body* body, Partitioner& partitioner ) :
99  my_body(body),
100  my_range(range),
101  my_partition(partitioner),
102  my_context(root_task)
103  {
104  }
106 
107  start_reduce( start_reduce& parent_, typename Partitioner::split_type& split_obj ) :
108  my_body(parent_.my_body),
109  my_range(parent_.my_range, split_obj),
110  my_partition(parent_.my_partition, split_obj),
111  my_context(right_child)
112  {
113  my_partition.set_affinity(*this);
114  parent_.my_context = left_child;
115  }
117 
118  start_reduce( start_reduce& parent_, const Range& r, depth_t d ) :
119  my_body(parent_.my_body),
120  my_range(r),
121  my_partition(parent_.my_partition, split()),
122  my_context(right_child)
123  {
124  my_partition.set_affinity(*this);
125  my_partition.align_depth( d ); // TODO: move into constructor of partitioner
126  parent_.my_context = left_child;
127  }
128  static void run( const Range& range, Body& body, Partitioner& partitioner ) {
129  if( !range.empty() ) {
130 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
131  task::spawn_root_and_wait( *new(task::allocate_root()) start_reduce(range,&body,partitioner) );
132 #else
133  // Bound context prevents exceptions from body to affect nesting or sibling algorithms,
134  // and allows users to handle exceptions safely by wrapping parallel_for in the try-block.
135  task_group_context context(PARALLEL_REDUCE);
136  task::spawn_root_and_wait( *new(task::allocate_root(context)) start_reduce(range,&body,partitioner) );
137 #endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */
138  }
139  }
140 #if __TBB_TASK_GROUP_CONTEXT
141  static void run( const Range& range, Body& body, Partitioner& partitioner, task_group_context& context ) {
142  if( !range.empty() )
143  task::spawn_root_and_wait( *new(task::allocate_root(context)) start_reduce(range,&body,partitioner) );
144  }
145 #endif /* __TBB_TASK_GROUP_CONTEXT */
146  void run_body( Range &r ) { (*my_body)( r ); }
148 
150  // TODO: remove code duplication from 'offer_work' methods
151  void offer_work(typename Partitioner::split_type& split_obj) {
152  task *tasks[2];
153  allocate_sibling(static_cast<task*>(this), tasks, sizeof(start_reduce), sizeof(finish_type));
154  new((void*)tasks[0]) finish_type(my_context);
155  new((void*)tasks[1]) start_reduce(*this, split_obj);
156  spawn(*tasks[1]);
157  }
159  void offer_work(const Range& r, depth_t d = 0) {
160  task *tasks[2];
161  allocate_sibling(static_cast<task*>(this), tasks, sizeof(start_reduce), sizeof(finish_type));
162  new((void*)tasks[0]) finish_type(my_context);
163  new((void*)tasks[1]) start_reduce(*this, r, d);
164  spawn(*tasks[1]);
165  }
166  };
167 
169  // TODO: 'inline' here is to avoid multiple definition error but for sake of code size this should not be inlined
170  inline void allocate_sibling(task* start_reduce_task, task *tasks[], size_t start_bytes, size_t finish_bytes) {
171  tasks[0] = &start_reduce_task->allocate_continuation().allocate(finish_bytes);
172  start_reduce_task->set_parent(tasks[0]);
173  tasks[0]->set_ref_count(2);
174  tasks[1] = &tasks[0]->allocate_child().allocate(start_bytes);
175  }
176 
177  template<typename Range, typename Body, typename Partitioner>
179  my_partition.check_being_stolen( *this );
180  if( my_context==right_child ) {
181  finish_type* parent_ptr = static_cast<finish_type*>(parent());
182  if( !itt_load_word_with_acquire(parent_ptr->my_body) ) { // TODO: replace by is_stolen_task() or by parent_ptr->ref_count() == 2???
183  my_body = new( parent_ptr->zombie_space.begin() ) Body(*my_body,split());
184  parent_ptr->has_right_zombie = true;
185  }
186  } else __TBB_ASSERT(my_context==root_task,NULL);// because left leaf spawns right leafs without recycling
187  my_partition.execute(*this, my_range);
188  if( my_context==left_child ) {
189  finish_type* parent_ptr = static_cast<finish_type*>(parent());
190  __TBB_ASSERT(my_body!=parent_ptr->zombie_space.begin(),NULL);
191  itt_store_word_with_release(parent_ptr->my_body, my_body );
192  }
193  return NULL;
194  }
195 
197 
198  template<typename Body>
202 
204  my_left_body( body ),
205  my_right_body( body, split() )
206  {
207  }
209  my_left_body.join( my_right_body );
210  return NULL;
211  }
212  template<typename Range,typename Body_, typename Partitioner>
214  };
215 
217 
218  template<typename Range, typename Body, typename Partitioner>
221  Body &my_body;
222  Range my_range;
223  typename Partitioner::task_partition_type my_partition;
224  task* execute() __TBB_override;
225 
227  start_deterministic_reduce( const Range& range, Body& body, Partitioner& partitioner ) :
228  my_body( body ),
229  my_range( range ),
230  my_partition( partitioner )
231  {
232  }
234 
235  start_deterministic_reduce( start_deterministic_reduce& parent_, finish_type& c, typename Partitioner::split_type& split_obj ) :
236  my_body( c.my_right_body ),
237  my_range( parent_.my_range, split_obj ),
238  my_partition( parent_.my_partition, split_obj )
239  {
240  }
241 
242 public:
243  static void run( const Range& range, Body& body, Partitioner& partitioner ) {
244  if( !range.empty() ) {
245 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
247 #else
248  // Bound context prevents exceptions from body to affect nesting or sibling algorithms,
249  // and allows users to handle exceptions safely by wrapping parallel_for in the try-block.
250  task_group_context context(PARALLEL_REDUCE);
251  task::spawn_root_and_wait( *new(task::allocate_root(context)) start_deterministic_reduce(range,body,partitioner) );
252 #endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */
253  }
254  }
255 #if __TBB_TASK_GROUP_CONTEXT
256  static void run( const Range& range, Body& body, Partitioner& partitioner, task_group_context& context ) {
257  if( !range.empty() )
258  task::spawn_root_and_wait( *new(task::allocate_root(context)) start_deterministic_reduce(range,body,partitioner) );
259  }
260 #endif /* __TBB_TASK_GROUP_CONTEXT */
261 
262  void offer_work( typename Partitioner::split_type& split_obj) {
263  task* tasks[2];
264  allocate_sibling(static_cast<task*>(this), tasks, sizeof(start_deterministic_reduce), sizeof(finish_type));
265  new((void*)tasks[0]) finish_type(my_body);
266  new((void*)tasks[1]) start_deterministic_reduce(*this, *static_cast<finish_type*>(tasks[0]), split_obj);
267  spawn(*tasks[1]);
268  }
269 
270  void run_body( Range &r ) { my_body(r); }
271  };
272 
273  template<typename Range, typename Body, typename Partitioner>
275  my_partition.execute(*this, my_range);
276  return NULL;
277  }
278 } // namespace internal
280 } //namespace interfaceX
281 
283 namespace internal {
287 
291  template<typename Range, typename Value, typename RealBody, typename Reduction>
293 
294 //FIXME: decide if my_real_body, my_reduction, and identity_element should be copied or referenced
295 // (might require some performance measurements)
296 
297  const Value& identity_element;
298  const RealBody& my_real_body;
299  const Reduction& my_reduction;
300  Value my_value;
302  public:
303  lambda_reduce_body( const Value& identity, const RealBody& body, const Reduction& reduction )
304  : identity_element(identity)
305  , my_real_body(body)
306  , my_reduction(reduction)
307  , my_value(identity)
308  { }
311  , my_real_body(other.my_real_body)
312  , my_reduction(other.my_reduction)
313  , my_value(other.my_value)
314  { }
317  , my_real_body(other.my_real_body)
318  , my_reduction(other.my_reduction)
319  , my_value(other.identity_element)
320  { }
321  void operator()(Range& range) {
322  my_value = my_real_body(range, const_cast<const Value&>(my_value));
323  }
324  void join( lambda_reduce_body& rhs ) {
325  my_value = my_reduction(const_cast<const Value&>(my_value), const_cast<const Value&>(rhs.my_value));
326  }
327  Value result() const {
328  return my_value;
329  }
330  };
331 
332 } // namespace internal
334 
335 // Requirements on Range concept are documented in blocked_range.h
336 
355 
357 
358 template<typename Range, typename Body>
359 void parallel_reduce( const Range& range, Body& body ) {
361 }
362 
364 
365 template<typename Range, typename Body>
366 void parallel_reduce( const Range& range, Body& body, const simple_partitioner& partitioner ) {
368 }
369 
371 
372 template<typename Range, typename Body>
373 void parallel_reduce( const Range& range, Body& body, const auto_partitioner& partitioner ) {
375 }
376 
378 
379 template<typename Range, typename Body>
380 void parallel_reduce( const Range& range, Body& body, const static_partitioner& partitioner ) {
382 }
383 
385 
386 template<typename Range, typename Body>
387 void parallel_reduce( const Range& range, Body& body, affinity_partitioner& partitioner ) {
389 }
390 
391 #if __TBB_TASK_GROUP_CONTEXT
392 
394 template<typename Range, typename Body>
395 void parallel_reduce( const Range& range, Body& body, task_group_context& context ) {
397 }
398 
400 
401 template<typename Range, typename Body>
402 void parallel_reduce( const Range& range, Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
403  internal::start_reduce<Range,Body,const simple_partitioner>::run( range, body, partitioner, context );
404 }
405 
407 
408 template<typename Range, typename Body>
409 void parallel_reduce( const Range& range, Body& body, const auto_partitioner& partitioner, task_group_context& context ) {
410  internal::start_reduce<Range,Body,const auto_partitioner>::run( range, body, partitioner, context );
411 }
412 
414 
415 template<typename Range, typename Body>
416 void parallel_reduce( const Range& range, Body& body, const static_partitioner& partitioner, task_group_context& context ) {
417  internal::start_reduce<Range,Body,const static_partitioner>::run( range, body, partitioner, context );
418 }
419 
421 
422 template<typename Range, typename Body>
423 void parallel_reduce( const Range& range, Body& body, affinity_partitioner& partitioner, task_group_context& context ) {
424  internal::start_reduce<Range,Body,affinity_partitioner>::run( range, body, partitioner, context );
425 }
426 #endif /* __TBB_TASK_GROUP_CONTEXT */
427 
431 
433 template<typename Range, typename Value, typename RealBody, typename Reduction>
434 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction ) {
435  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
436  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const __TBB_DEFAULT_PARTITIONER>
437  ::run(range, body, __TBB_DEFAULT_PARTITIONER() );
438  return body.result();
439 }
440 
442 
443 template<typename Range, typename Value, typename RealBody, typename Reduction>
444 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
445  const simple_partitioner& partitioner ) {
446  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
447  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const simple_partitioner>
448  ::run(range, body, partitioner );
449  return body.result();
450 }
451 
453 
454 template<typename Range, typename Value, typename RealBody, typename Reduction>
455 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
456  const auto_partitioner& partitioner ) {
457  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
458  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const auto_partitioner>
459  ::run( range, body, partitioner );
460  return body.result();
461 }
462 
464 
465 template<typename Range, typename Value, typename RealBody, typename Reduction>
466 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
467  const static_partitioner& partitioner ) {
468  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
469  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const static_partitioner>
470  ::run( range, body, partitioner );
471  return body.result();
472 }
473 
475 
476 template<typename Range, typename Value, typename RealBody, typename Reduction>
477 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
478  affinity_partitioner& partitioner ) {
479  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
480  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,affinity_partitioner>
481  ::run( range, body, partitioner );
482  return body.result();
483 }
484 
485 #if __TBB_TASK_GROUP_CONTEXT
486 
488 template<typename Range, typename Value, typename RealBody, typename Reduction>
489 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
490  task_group_context& context ) {
491  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
492  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const __TBB_DEFAULT_PARTITIONER>
493  ::run( range, body, __TBB_DEFAULT_PARTITIONER(), context );
494  return body.result();
495 }
496 
498 
499 template<typename Range, typename Value, typename RealBody, typename Reduction>
500 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
501  const simple_partitioner& partitioner, task_group_context& context ) {
502  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
503  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const simple_partitioner>
504  ::run( range, body, partitioner, context );
505  return body.result();
506 }
507 
509 
510 template<typename Range, typename Value, typename RealBody, typename Reduction>
511 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
512  const auto_partitioner& partitioner, task_group_context& context ) {
513  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
514  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const auto_partitioner>
515  ::run( range, body, partitioner, context );
516  return body.result();
517 }
518 
520 
521 template<typename Range, typename Value, typename RealBody, typename Reduction>
522 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
523  const static_partitioner& partitioner, task_group_context& context ) {
524  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
525  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const static_partitioner>
526  ::run( range, body, partitioner, context );
527  return body.result();
528 }
529 
531 
532 template<typename Range, typename Value, typename RealBody, typename Reduction>
533 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
534  affinity_partitioner& partitioner, task_group_context& context ) {
535  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
536  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,affinity_partitioner>
537  ::run( range, body, partitioner, context );
538  return body.result();
539 }
540 #endif /* __TBB_TASK_GROUP_CONTEXT */
541 
543 
544 template<typename Range, typename Body>
545 void parallel_deterministic_reduce( const Range& range, Body& body ) {
547 }
548 
550 
551 template<typename Range, typename Body>
552 void parallel_deterministic_reduce( const Range& range, Body& body, const simple_partitioner& partitioner ) {
554 }
555 
557 
558 template<typename Range, typename Body>
559 void parallel_deterministic_reduce( const Range& range, Body& body, const static_partitioner& partitioner ) {
561 }
562 
563 #if __TBB_TASK_GROUP_CONTEXT
564 
566 template<typename Range, typename Body>
567 void parallel_deterministic_reduce( const Range& range, Body& body, task_group_context& context ) {
569 }
570 
572 
573 template<typename Range, typename Body>
574 void parallel_deterministic_reduce( const Range& range, Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
576 }
577 
579 
580 template<typename Range, typename Body>
581 void parallel_deterministic_reduce( const Range& range, Body& body, const static_partitioner& partitioner, task_group_context& context ) {
583 }
584 #endif /* __TBB_TASK_GROUP_CONTEXT */
585 
589 // TODO: consider making static_partitioner the default
592 template<typename Range, typename Value, typename RealBody, typename Reduction>
593 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction ) {
594  return parallel_deterministic_reduce(range, identity, real_body, reduction, simple_partitioner());
595 }
596 
598 
599 template<typename Range, typename Value, typename RealBody, typename Reduction>
600 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, const simple_partitioner& partitioner ) {
601  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
602  internal::start_deterministic_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>, const simple_partitioner>
603  ::run(range, body, partitioner);
604  return body.result();
605 }
606 
608 
609 template<typename Range, typename Value, typename RealBody, typename Reduction>
610 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, const static_partitioner& partitioner ) {
611  internal::lambda_reduce_body<Range, Value, RealBody, Reduction> body(identity, real_body, reduction);
612  internal::start_deterministic_reduce<Range, internal::lambda_reduce_body<Range, Value, RealBody, Reduction>, const static_partitioner>
613  ::run(range, body, partitioner);
614  return body.result();
615 }
616 #if __TBB_TASK_GROUP_CONTEXT
617 
619 template<typename Range, typename Value, typename RealBody, typename Reduction>
620 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
621  task_group_context& context ) {
622  return parallel_deterministic_reduce(range, identity, real_body, reduction, simple_partitioner(), context);
623 }
624 
626 
627 template<typename Range, typename Value, typename RealBody, typename Reduction>
628 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
629  const simple_partitioner& partitioner, task_group_context& context ) {
630  internal::lambda_reduce_body<Range, Value, RealBody, Reduction> body(identity, real_body, reduction);
631  internal::start_deterministic_reduce<Range, internal::lambda_reduce_body<Range, Value, RealBody, Reduction>, const simple_partitioner>
632  ::run(range, body, partitioner, context);
633  return body.result();
634 }
635 
637 
638 template<typename Range, typename Value, typename RealBody, typename Reduction>
639 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
640  const static_partitioner& partitioner, task_group_context& context ) {
641  internal::lambda_reduce_body<Range, Value, RealBody, Reduction> body(identity, real_body, reduction);
642  internal::start_deterministic_reduce<Range, internal::lambda_reduce_body<Range, Value, RealBody, Reduction>, const static_partitioner>
643  ::run(range, body, partitioner, context);
644  return body.result();
645 }
646 #endif /* __TBB_TASK_GROUP_CONTEXT */
647 
648 
649 } // namespace tbb
650 
651 #endif /* __TBB_parallel_reduce_H */
void * allocate_sibling(task *start_for_task, size_t bytes)
allocate right task with new parent
finish_deterministic_reduce< Body > finish_type
void parallel_deterministic_reduce(const Range &range, Body &body)
Parallel iteration with deterministic reduction and default simple partitioner.
#define __TBB_override
Definition: tbb_stddef.h:240
start_reduce(start_reduce &parent_, typename Partitioner::split_type &split_obj)
Splitting constructor used to generate children.
A static partitioner.
Definition: partitioner.h:629
lambda_reduce_body(const lambda_reduce_body &other)
A simple partitioner.
Definition: partitioner.h:583
static void run(const Range &range, Body &body, Partitioner &partitioner)
lambda_reduce_body(const Value &identity, const RealBody &body, const Reduction &reduction)
task * execute() __TBB_override
Should be overridden by derived classes.
void offer_work(typename Partitioner::split_type &split_obj)
void const char const char int ITT_FORMAT __itt_group_sync s
static void spawn_root_and_wait(task &root)
Spawn task allocated by allocate_root, wait for it to complete, and deallocate it.
Definition: task.h:778
void offer_work(typename Partitioner::split_type &split_obj)
spawn right task, serves as callback for partitioner
Partitioner::task_partition_type my_partition
start_reduce(const Range &range, Body *body, Partitioner &partitioner)
Constructor used for root task.
The graph class.
Used to form groups of tasks.
Definition: task.h:332
lambda_reduce_body(lambda_reduce_body &other, tbb::split)
internal::allocate_child_proxy & allocate_child()
Returns proxy for overloaded new that allocates a child task of *this.
Definition: task.h:651
static void run(const Range &range, Body &body, Partitioner &partitioner, task_group_context &context)
Task type used to split the work of parallel_deterministic_reduce.
An auto partitioner.
Definition: partitioner.h:610
Task type used to combine the partial results of parallel_reduce.
T * begin() const
Pointer to beginning of array.
Definition: aligned_space.h:35
start_reduce(start_reduce &parent_, const Range &r, depth_t d)
Construct right child from the given range as response to the demand.
void itt_store_word_with_release(tbb::atomic< T > &dst, U src)
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id parent
void parallel_reduce(const Range &range, Body &body)
Parallel iteration with reduction and default partitioner.
An affinity partitioner.
Definition: partitioner.h:648
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d
lambda_reduce_body & operator=(const lambda_reduce_body &other)
bool has_right_zombie
Pointer to body, or NULL if the left child has not yet finished.
void set_ref_count(int count)
Set reference count.
Definition: task.h:731
#define __TBB_DEFAULT_PARTITIONER
Definition: tbb_config.h:595
internal::affinity_id affinity_id
An id as used for specifying affinity.
Definition: task.h:884
Base class for user-defined tasks.
Definition: task.h:589
internal::allocate_continuation_proxy & allocate_continuation()
Returns proxy for overloaded new that allocates a continuation task of *this.
Definition: task.h:646
static internal::allocate_root_proxy allocate_root()
Returns proxy for overloaded new that allocates a root task.
Definition: task.h:633
virtual task * execute()=0
Should be overridden by derived classes.
void join(lambda_reduce_body &rhs)
Task type used to combine the partial results of parallel_deterministic_reduce.
void set_parent(task *p)
sets parent task pointer to specified value
Definition: task.h:838
Join task node that contains shared flag for stealing feedback.
Definition: partitioner.h:125
finish_reduce(reduction_context context_)
void offer_work(const Range &r, depth_t d=0)
spawn right task, serves as callback for partitioner
T itt_load_word_with_acquire(const tbb::atomic< T > &src)
task * execute() __TBB_override
Should be overridden by derived classes.
Identifiers declared inside namespace internal should never be used directly by client code.
Definition: atomic.h:51
Auxiliary class for parallel_reduce; for internal use only.
task * execute() __TBB_override
Should be overridden by derived classes.
static void run(const Range &range, Body &body, Partitioner &partitioner, task_group_context &context)
Task type used to split the work of parallel_reduce.
static void run(const Range &range, Body &body, Partitioner &partitioner)
start_deterministic_reduce(start_deterministic_reduce &parent_, finish_type &c, typename Partitioner::split_type &split_obj)
Splitting constructor used to generate children.
task * execute() __TBB_override
Should be overridden by derived classes.
Dummy type that distinguishes splitting constructor from copy constructor.
Definition: tbb_stddef.h:395

Copyright © 2005-2019 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.