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 
18 
19 */
20 
21 #ifndef __TBB_parallel_reduce_H
22 #define __TBB_parallel_reduce_H
23 
24 #include <new>
25 #include "task.h"
26 #include "aligned_space.h"
27 #include "partitioner.h"
28 #include "tbb_profiling.h"
29 
30 namespace tbb {
31 
32 namespace interface9 {
34 namespace internal {
35 
36  using namespace tbb::internal;
37 
39  enum {
41  };
42 
44  typedef char reduction_context;
45 
47 
48  template<typename Body>
49  class finish_reduce: public flag_task {
53  Body* my_body;
56  has_right_zombie(false), // TODO: substitute by flag_task::child_stolen?
57  my_context(context_),
58  my_body(NULL)
59  {
60  }
62  if( has_right_zombie )
63  zombie_space.begin()->~Body();
64  }
66  if( has_right_zombie ) {
67  // Right child was stolen.
68  Body* s = zombie_space.begin();
69  my_body->join( *s );
70  // Body::join() won't be called if canceled. Defer destruction to destructor
71  }
72  if( my_context==left_child )
73  itt_store_word_with_release( static_cast<finish_reduce*>(parent())->my_body, my_body );
74  return NULL;
75  }
76  template<typename Range,typename Body_, typename Partitioner>
77  friend class start_reduce;
78  };
79 
81  void allocate_sibling(task* start_reduce_task, task *tasks[], size_t start_bytes, size_t finish_bytes);
82 
84 
85  template<typename Range, typename Body, typename Partitioner>
86  class start_reduce: public task {
88  Body* my_body;
89  Range my_range;
90  typename Partitioner::task_partition_type my_partition;
92  task* execute() __TBB_override;
94  void note_affinity( affinity_id id ) __TBB_override {
95  my_partition.note_affinity( id );
96  }
97  template<typename Body_>
98  friend class finish_reduce;
99 
100 public:
102  start_reduce( const Range& range, Body* body, Partitioner& partitioner ) :
103  my_body(body),
104  my_range(range),
105  my_partition(partitioner),
106  my_context(root_task)
107  {
108  }
110 
111  start_reduce( start_reduce& parent_, typename Partitioner::split_type& split_obj ) :
112  my_body(parent_.my_body),
113  my_range(parent_.my_range, split_obj),
114  my_partition(parent_.my_partition, split_obj),
115  my_context(right_child)
116  {
117  my_partition.set_affinity(*this);
118  parent_.my_context = left_child;
119  }
121 
122  start_reduce( start_reduce& parent_, const Range& r, depth_t d ) :
123  my_body(parent_.my_body),
124  my_range(r),
125  my_partition(parent_.my_partition, split()),
126  my_context(right_child)
127  {
128  my_partition.set_affinity(*this);
129  my_partition.align_depth( d ); // TODO: move into constructor of partitioner
130  parent_.my_context = left_child;
131  }
132  static void run( const Range& range, Body& body, Partitioner& partitioner ) {
133  if( !range.empty() ) {
134 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
135  task::spawn_root_and_wait( *new(task::allocate_root()) start_reduce(range,&body,partitioner) );
136 #else
137  // Bound context prevents exceptions from body to affect nesting or sibling algorithms,
138  // and allows users to handle exceptions safely by wrapping parallel_for in the try-block.
139  task_group_context context(PARALLEL_REDUCE);
140  task::spawn_root_and_wait( *new(task::allocate_root(context)) start_reduce(range,&body,partitioner) );
141 #endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */
142  }
143  }
144 #if __TBB_TASK_GROUP_CONTEXT
145  static void run( const Range& range, Body& body, Partitioner& partitioner, task_group_context& context ) {
146  if( !range.empty() )
147  task::spawn_root_and_wait( *new(task::allocate_root(context)) start_reduce(range,&body,partitioner) );
148  }
149 #endif /* __TBB_TASK_GROUP_CONTEXT */
150  void run_body( Range &r ) { (*my_body)( r ); }
152 
154  // TODO: remove code duplication from 'offer_work' methods
155  void offer_work(typename Partitioner::split_type& split_obj) {
156  task *tasks[2];
157  allocate_sibling(static_cast<task*>(this), tasks, sizeof(start_reduce), sizeof(finish_type));
158  new((void*)tasks[0]) finish_type(my_context);
159  new((void*)tasks[1]) start_reduce(*this, split_obj);
160  spawn(*tasks[1]);
161  }
163  void offer_work(const Range& r, depth_t d = 0) {
164  task *tasks[2];
165  allocate_sibling(static_cast<task*>(this), tasks, sizeof(start_reduce), sizeof(finish_type));
166  new((void*)tasks[0]) finish_type(my_context);
167  new((void*)tasks[1]) start_reduce(*this, r, d);
168  spawn(*tasks[1]);
169  }
170  };
171 
173  // TODO: 'inline' here is to avoid multiple definition error but for sake of code size this should not be inlined
174  inline void allocate_sibling(task* start_reduce_task, task *tasks[], size_t start_bytes, size_t finish_bytes) {
175  tasks[0] = &start_reduce_task->allocate_continuation().allocate(finish_bytes);
176  start_reduce_task->set_parent(tasks[0]);
177  tasks[0]->set_ref_count(2);
178  tasks[1] = &tasks[0]->allocate_child().allocate(start_bytes);
179  }
180 
181  template<typename Range, typename Body, typename Partitioner>
183  my_partition.check_being_stolen( *this );
184  if( my_context==right_child ) {
185  finish_type* parent_ptr = static_cast<finish_type*>(parent());
186  if( !itt_load_word_with_acquire(parent_ptr->my_body) ) { // TODO: replace by is_stolen_task() or by parent_ptr->ref_count() == 2???
187  my_body = new( parent_ptr->zombie_space.begin() ) Body(*my_body,split());
188  parent_ptr->has_right_zombie = true;
189  }
190  } else __TBB_ASSERT(my_context==root_task,NULL);// because left leaf spawns right leafs without recycling
191  my_partition.execute(*this, my_range);
192  if( my_context==left_child ) {
193  finish_type* parent_ptr = static_cast<finish_type*>(parent());
194  __TBB_ASSERT(my_body!=parent_ptr->zombie_space.begin(),NULL);
195  itt_store_word_with_release(parent_ptr->my_body, my_body );
196  }
197  return NULL;
198  }
199 
201 
202  template<typename Body>
206 
208  my_left_body( body ),
209  my_right_body( body, split() )
210  {
211  }
213  my_left_body.join( my_right_body );
214  return NULL;
215  }
216  template<typename Range,typename Body_, typename Partitioner>
218  };
219 
221 
222  template<typename Range, typename Body, typename Partitioner>
225  Body &my_body;
226  Range my_range;
227  typename Partitioner::task_partition_type my_partition;
228  task* execute() __TBB_override;
229 
231  start_deterministic_reduce( const Range& range, Body& body, Partitioner& partitioner ) :
232  my_body( body ),
233  my_range( range ),
234  my_partition( partitioner )
235  {
236  }
238 
239  start_deterministic_reduce( start_deterministic_reduce& parent_, finish_type& c, typename Partitioner::split_type& split_obj ) :
240  my_body( c.my_right_body ),
241  my_range( parent_.my_range, split_obj ),
242  my_partition( parent_.my_partition, split_obj )
243  {
244  }
245 
246 public:
247  static void run( const Range& range, Body& body, Partitioner& partitioner ) {
248  if( !range.empty() ) {
249 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
251 #else
252  // Bound context prevents exceptions from body to affect nesting or sibling algorithms,
253  // and allows users to handle exceptions safely by wrapping parallel_for in the try-block.
254  task_group_context context(PARALLEL_REDUCE);
255  task::spawn_root_and_wait( *new(task::allocate_root(context)) start_deterministic_reduce(range,body,partitioner) );
256 #endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */
257  }
258  }
259 #if __TBB_TASK_GROUP_CONTEXT
260  static void run( const Range& range, Body& body, Partitioner& partitioner, task_group_context& context ) {
261  if( !range.empty() )
262  task::spawn_root_and_wait( *new(task::allocate_root(context)) start_deterministic_reduce(range,body,partitioner) );
263  }
264 #endif /* __TBB_TASK_GROUP_CONTEXT */
265 
266  void offer_work( typename Partitioner::split_type& split_obj) {
267  task* tasks[2];
268  allocate_sibling(static_cast<task*>(this), tasks, sizeof(start_deterministic_reduce), sizeof(finish_type));
269  new((void*)tasks[0]) finish_type(my_body);
270  new((void*)tasks[1]) start_deterministic_reduce(*this, *static_cast<finish_type*>(tasks[0]), split_obj);
271  spawn(*tasks[1]);
272  }
273 
274  void run_body( Range &r ) { my_body(r); }
275  };
276 
277  template<typename Range, typename Body, typename Partitioner>
279  my_partition.execute(*this, my_range);
280  return NULL;
281  }
282 } // namespace internal
284 } //namespace interfaceX
285 
287 namespace internal {
291 
295  template<typename Range, typename Value, typename RealBody, typename Reduction>
297 
298 //FIXME: decide if my_real_body, my_reduction, and identity_element should be copied or referenced
299 // (might require some performance measurements)
300 
301  const Value& identity_element;
302  const RealBody& my_real_body;
303  const Reduction& my_reduction;
304  Value my_value;
306  public:
307  lambda_reduce_body( const Value& identity, const RealBody& body, const Reduction& reduction )
308  : identity_element(identity)
309  , my_real_body(body)
310  , my_reduction(reduction)
311  , my_value(identity)
312  { }
315  , my_real_body(other.my_real_body)
316  , my_reduction(other.my_reduction)
317  , my_value(other.my_value)
318  { }
321  , my_real_body(other.my_real_body)
322  , my_reduction(other.my_reduction)
323  , my_value(other.identity_element)
324  { }
325  void operator()(Range& range) {
326  my_value = my_real_body(range, const_cast<const Value&>(my_value));
327  }
328  void join( lambda_reduce_body& rhs ) {
329  my_value = my_reduction(const_cast<const Value&>(my_value), const_cast<const Value&>(rhs.my_value));
330  }
331  Value result() const {
332  return my_value;
333  }
334  };
335 
336 } // namespace internal
338 
339 // Requirements on Range concept are documented in blocked_range.h
340 
359 
361 
362 template<typename Range, typename Body>
363 void parallel_reduce( const Range& range, Body& body ) {
365 }
366 
368 
369 template<typename Range, typename Body>
370 void parallel_reduce( const Range& range, Body& body, const simple_partitioner& partitioner ) {
372 }
373 
375 
376 template<typename Range, typename Body>
377 void parallel_reduce( const Range& range, Body& body, const auto_partitioner& partitioner ) {
379 }
380 
382 
383 template<typename Range, typename Body>
384 void parallel_reduce( const Range& range, Body& body, const static_partitioner& partitioner ) {
386 }
387 
389 
390 template<typename Range, typename Body>
391 void parallel_reduce( const Range& range, Body& body, affinity_partitioner& partitioner ) {
393 }
394 
395 #if __TBB_TASK_GROUP_CONTEXT
396 
398 template<typename Range, typename Body>
399 void parallel_reduce( const Range& range, Body& body, task_group_context& context ) {
401 }
402 
404 
405 template<typename Range, typename Body>
406 void parallel_reduce( const Range& range, Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
407  internal::start_reduce<Range,Body,const simple_partitioner>::run( range, body, partitioner, context );
408 }
409 
411 
412 template<typename Range, typename Body>
413 void parallel_reduce( const Range& range, Body& body, const auto_partitioner& partitioner, task_group_context& context ) {
414  internal::start_reduce<Range,Body,const auto_partitioner>::run( range, body, partitioner, context );
415 }
416 
418 
419 template<typename Range, typename Body>
420 void parallel_reduce( const Range& range, Body& body, const static_partitioner& partitioner, task_group_context& context ) {
421  internal::start_reduce<Range,Body,const static_partitioner>::run( range, body, partitioner, context );
422 }
423 
425 
426 template<typename Range, typename Body>
427 void parallel_reduce( const Range& range, Body& body, affinity_partitioner& partitioner, task_group_context& context ) {
428  internal::start_reduce<Range,Body,affinity_partitioner>::run( range, body, partitioner, context );
429 }
430 #endif /* __TBB_TASK_GROUP_CONTEXT */
431 
435 
437 template<typename Range, typename Value, typename RealBody, typename Reduction>
438 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction ) {
439  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
440  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const __TBB_DEFAULT_PARTITIONER>
441  ::run(range, body, __TBB_DEFAULT_PARTITIONER() );
442  return body.result();
443 }
444 
446 
447 template<typename Range, typename Value, typename RealBody, typename Reduction>
448 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
449  const simple_partitioner& partitioner ) {
450  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
451  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const simple_partitioner>
452  ::run(range, body, partitioner );
453  return body.result();
454 }
455 
457 
458 template<typename Range, typename Value, typename RealBody, typename Reduction>
459 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
460  const auto_partitioner& partitioner ) {
461  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
462  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const auto_partitioner>
463  ::run( range, body, partitioner );
464  return body.result();
465 }
466 
468 
469 template<typename Range, typename Value, typename RealBody, typename Reduction>
470 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
471  const static_partitioner& partitioner ) {
472  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
473  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const static_partitioner>
474  ::run( range, body, partitioner );
475  return body.result();
476 }
477 
479 
480 template<typename Range, typename Value, typename RealBody, typename Reduction>
481 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
482  affinity_partitioner& partitioner ) {
483  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
484  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,affinity_partitioner>
485  ::run( range, body, partitioner );
486  return body.result();
487 }
488 
489 #if __TBB_TASK_GROUP_CONTEXT
490 
492 template<typename Range, typename Value, typename RealBody, typename Reduction>
493 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
494  task_group_context& context ) {
495  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
496  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const __TBB_DEFAULT_PARTITIONER>
497  ::run( range, body, __TBB_DEFAULT_PARTITIONER(), context );
498  return body.result();
499 }
500 
502 
503 template<typename Range, typename Value, typename RealBody, typename Reduction>
504 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
505  const simple_partitioner& partitioner, task_group_context& context ) {
506  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
507  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const simple_partitioner>
508  ::run( range, body, partitioner, context );
509  return body.result();
510 }
511 
513 
514 template<typename Range, typename Value, typename RealBody, typename Reduction>
515 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
516  const auto_partitioner& partitioner, task_group_context& context ) {
517  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
518  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const auto_partitioner>
519  ::run( range, body, partitioner, context );
520  return body.result();
521 }
522 
524 
525 template<typename Range, typename Value, typename RealBody, typename Reduction>
526 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
527  const static_partitioner& partitioner, task_group_context& context ) {
528  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
529  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,const static_partitioner>
530  ::run( range, body, partitioner, context );
531  return body.result();
532 }
533 
535 
536 template<typename Range, typename Value, typename RealBody, typename Reduction>
537 Value parallel_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
538  affinity_partitioner& partitioner, task_group_context& context ) {
539  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
540  internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>,affinity_partitioner>
541  ::run( range, body, partitioner, context );
542  return body.result();
543 }
544 #endif /* __TBB_TASK_GROUP_CONTEXT */
545 
547 
548 template<typename Range, typename Body>
549 void parallel_deterministic_reduce( const Range& range, Body& body ) {
551 }
552 
554 
555 template<typename Range, typename Body>
556 void parallel_deterministic_reduce( const Range& range, Body& body, const simple_partitioner& partitioner ) {
558 }
559 
561 
562 template<typename Range, typename Body>
563 void parallel_deterministic_reduce( const Range& range, Body& body, const static_partitioner& partitioner ) {
565 }
566 
567 #if __TBB_TASK_GROUP_CONTEXT
568 
570 template<typename Range, typename Body>
571 void parallel_deterministic_reduce( const Range& range, Body& body, task_group_context& context ) {
573 }
574 
576 
577 template<typename Range, typename Body>
578 void parallel_deterministic_reduce( const Range& range, Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
580 }
581 
583 
584 template<typename Range, typename Body>
585 void parallel_deterministic_reduce( const Range& range, Body& body, const static_partitioner& partitioner, task_group_context& context ) {
587 }
588 #endif /* __TBB_TASK_GROUP_CONTEXT */
589 
593 // TODO: consider making static_partitioner the default
596 template<typename Range, typename Value, typename RealBody, typename Reduction>
597 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction ) {
598  return parallel_deterministic_reduce(range, identity, real_body, reduction, simple_partitioner());
599 }
600 
602 
603 template<typename Range, typename Value, typename RealBody, typename Reduction>
604 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, const simple_partitioner& partitioner ) {
605  internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(identity, real_body, reduction);
606  internal::start_deterministic_reduce<Range,internal::lambda_reduce_body<Range,Value,RealBody,Reduction>, const simple_partitioner>
607  ::run(range, body, partitioner);
608  return body.result();
609 }
610 
612 
613 template<typename Range, typename Value, typename RealBody, typename Reduction>
614 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction, const static_partitioner& partitioner ) {
615  internal::lambda_reduce_body<Range, Value, RealBody, Reduction> body(identity, real_body, reduction);
616  internal::start_deterministic_reduce<Range, internal::lambda_reduce_body<Range, Value, RealBody, Reduction>, const static_partitioner>
617  ::run(range, body, partitioner);
618  return body.result();
619 }
620 #if __TBB_TASK_GROUP_CONTEXT
621 
623 template<typename Range, typename Value, typename RealBody, typename Reduction>
624 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
625  task_group_context& context ) {
626  return parallel_deterministic_reduce(range, identity, real_body, reduction, simple_partitioner(), context);
627 }
628 
630 
631 template<typename Range, typename Value, typename RealBody, typename Reduction>
632 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
633  const simple_partitioner& partitioner, task_group_context& context ) {
634  internal::lambda_reduce_body<Range, Value, RealBody, Reduction> body(identity, real_body, reduction);
635  internal::start_deterministic_reduce<Range, internal::lambda_reduce_body<Range, Value, RealBody, Reduction>, const simple_partitioner>
636  ::run(range, body, partitioner, context);
637  return body.result();
638 }
639 
641 
642 template<typename Range, typename Value, typename RealBody, typename Reduction>
643 Value parallel_deterministic_reduce( const Range& range, const Value& identity, const RealBody& real_body, const Reduction& reduction,
644  const static_partitioner& partitioner, task_group_context& context ) {
645  internal::lambda_reduce_body<Range, Value, RealBody, Reduction> body(identity, real_body, reduction);
646  internal::start_deterministic_reduce<Range, internal::lambda_reduce_body<Range, Value, RealBody, Reduction>, const static_partitioner>
647  ::run(range, body, partitioner, context);
648  return body.result();
649 }
650 #endif /* __TBB_TASK_GROUP_CONTEXT */
651 
652 
653 } // namespace tbb
654 
655 #endif /* __TBB_parallel_reduce_H */
#define __TBB_override
Definition: tbb_stddef.h:244
internal::allocate_child_proxy & allocate_child()
Returns proxy for overloaded new that allocates a child task of *this.
Definition: task.h:654
An auto partitioner.
Definition: partitioner.h:614
T * begin() const
Pointer to beginning of array.
Definition: aligned_space.h:39
start_reduce(start_reduce &parent_, const Range &r, depth_t d)
Construct right child from the given range as response to the demand.
virtual task * execute()=0
Should be overridden by derived classes.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
task * execute() __TBB_override
Should be overridden by derived classes.
void itt_store_word_with_release(tbb::atomic< T > &dst, U src)
task * execute() __TBB_override
Should be overridden by derived classes.
Used to form groups of tasks.
Definition: task.h:335
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
Task type used to split the work of parallel_deterministic_reduce.
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:781
task * execute() __TBB_override
Should be overridden by derived classes.
Task type used to combine the partial results of parallel_reduce.
void * allocate_sibling(task *start_for_task, size_t bytes)
allocate right task with new parent
T itt_load_word_with_acquire(const tbb::atomic< T > &src)
Base class for user-defined tasks.
Definition: task.h:592
finish_reduce(reduction_context context_)
finish_deterministic_reduce< Body > finish_type
void set_parent(task *p)
sets parent task pointer to specified value
Definition: task.h:833
Task type used to combine the partial results of parallel_deterministic_reduce.
lambda_reduce_body(const lambda_reduce_body &other)
internal::affinity_id affinity_id
An id as used for specifying affinity.
Definition: task.h:879
void offer_work(const Range &r, depth_t d=0)
spawn right task, serves as callback for partitioner
internal::allocate_continuation_proxy & allocate_continuation()
Returns proxy for overloaded new that allocates a continuation task of *this.
Definition: task.h:649
bool has_right_zombie
Pointer to body, or NULL if the left child has not yet finished.
static void run(const Range &range, Body &body, Partitioner &partitioner, task_group_context &context)
start_reduce(start_reduce &parent_, typename Partitioner::split_type &split_obj)
Splitting constructor used to generate children.
void offer_work(typename Partitioner::split_type &split_obj)
void parallel_deterministic_reduce(const Range &range, Body &body)
Parallel iteration with deterministic reduction and default simple partitioner.
static void run(const Range &range, Body &body, Partitioner &partitioner)
void parallel_reduce(const Range &range, Body &body)
Parallel iteration with reduction and default partitioner.
The graph class.
task * execute() __TBB_override
Should be overridden by derived classes.
static void run(const Range &range, Body &body, Partitioner &partitioner)
Dummy type that distinguishes splitting constructor from copy constructor.
Definition: tbb_stddef.h:399
void offer_work(typename Partitioner::split_type &split_obj)
spawn right task, serves as callback for partitioner
Partitioner::task_partition_type my_partition
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
An affinity partitioner.
Definition: partitioner.h:652
start_deterministic_reduce(start_deterministic_reduce &parent_, finish_type &c, typename Partitioner::split_type &split_obj)
Splitting constructor used to generate children.
lambda_reduce_body(lambda_reduce_body &other, tbb::split)
#define __TBB_DEFAULT_PARTITIONER
Definition: tbb_config.h:597
void const char const char int ITT_FORMAT __itt_group_sync s
void set_ref_count(int count)
Set reference count.
Definition: task.h:734
lambda_reduce_body(const Value &identity, const RealBody &body, const Reduction &reduction)
static internal::allocate_root_proxy allocate_root()
Returns proxy for overloaded new that allocates a root task.
Definition: task.h:636
void join(lambda_reduce_body &rhs)
Join task node that contains shared flag for stealing feedback.
Definition: partitioner.h:129
lambda_reduce_body & operator=(const lambda_reduce_body &other)
Identifiers declared inside namespace internal should never be used directly by client code.
Definition: atomic.h:55
start_reduce(const Range &range, Body *body, Partitioner &partitioner)
Constructor used for root task.
static void run(const Range &range, Body &body, Partitioner &partitioner, task_group_context &context)
Auxiliary class for parallel_reduce; for internal use only.
A static partitioner.
Definition: partitioner.h:633
Task type used to split the work of parallel_reduce.
A simple partitioner.
Definition: partitioner.h:587

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.