21 #ifndef __TBB_partitioner_H 22 #define __TBB_partitioner_H 24 #ifndef __TBB_INITIAL_CHUNKS 26 #define __TBB_INITIAL_CHUNKS 2 28 #ifndef __TBB_RANGE_POOL_CAPACITY 30 #define __TBB_RANGE_POOL_CAPACITY 8 32 #ifndef __TBB_INIT_DEPTH 34 #define __TBB_INIT_DEPTH 5 36 #ifndef __TBB_DEMAND_DEPTH_ADD 38 #define __TBB_DEMAND_DEPTH_ADD 1 40 #ifndef __TBB_STATIC_THRESHOLD 42 #define __TBB_STATIC_THRESHOLD 40000 45 #define __TBB_NONUNIFORM_TASK_CREATION 1 46 #ifdef __TBB_time_stamp 47 #define __TBB_USE_MACHINE_TIME_STAMPS 1 48 #define __TBB_task_duration() __TBB_STATIC_THRESHOLD 49 #endif // __TBB_machine_time_stamp 50 #endif // __TBB_DEFINE_MIC 58 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) 60 #pragma warning (push) 61 #pragma warning (disable: 4244) 66 class auto_partitioner;
67 class simple_partitioner;
68 class static_partitioner;
69 class affinity_partitioner;
71 namespace interface9 {
73 class affinity_partition_type;
110 template<
typename Range,
typename Body,
typename Partitioner>
class start_scan;
115 namespace interface9 {
116 template<
typename Range,
typename Body,
typename Partitioner>
class start_for;
120 namespace interface9 {
124 template<
typename Range,
typename Body,
typename Partitioner>
class start_for;
125 template<
typename Range,
typename Body,
typename Partitioner>
class start_reduce;
136 #if TBB_USE_THREADING_TOOLS 141 #endif //TBB_USE_THREADING_TOOLS 154 template <
typename T, depth_t MaxCapacity>
159 depth_t my_depth[MaxCapacity];
166 new(
static_cast<void *
>(my_pool.
begin()) ) T(elem);
169 while( !empty() ) pop_back();
171 bool empty()
const {
return my_size == 0; }
172 depth_t
size()
const {
return my_size; }
176 while( my_size < MaxCapacity && is_divisible(max_depth) ) {
177 depth_t prev = my_head;
178 my_head = (my_head + 1) % MaxCapacity;
179 new(my_pool.
begin()+my_head) T(my_pool.
begin()[prev]);
180 my_pool.
begin()[prev].~T();
182 my_depth[my_head] = ++my_depth[prev];
187 __TBB_ASSERT(my_size > 0,
"range_vector::pop_back() with empty size");
188 my_pool.
begin()[my_head].~T();
190 my_head = (my_head + MaxCapacity - 1) % MaxCapacity;
193 __TBB_ASSERT(my_size > 0,
"range_vector::pop_front() with empty size");
194 my_pool.
begin()[my_tail].~T();
196 my_tail = (my_tail + 1) % MaxCapacity;
199 __TBB_ASSERT(my_size > 0,
"range_vector::back() with empty size");
200 return my_pool.
begin()[my_head];
203 __TBB_ASSERT(my_size > 0,
"range_vector::front() with empty size");
204 return my_pool.
begin()[my_tail];
208 __TBB_ASSERT(my_size > 0,
"range_vector::front_depth() with empty size");
209 return my_depth[my_tail];
212 __TBB_ASSERT(my_size > 0,
"range_vector::back_depth() with empty size");
213 return my_depth[my_head];
216 return back_depth() < max_depth && back().is_divisible();
221 template <
typename Partition>
233 Partition&
self() {
return *
static_cast<Partition*
>(
this); }
235 template<
typename StartType,
typename Range>
237 start.run_body( range );
240 template<
typename StartType,
typename Range>
241 void execute(StartType &start, Range &range) {
249 if ( range.is_divisible() ) {
250 if (
self().is_divisible() ) {
252 typename Partition::split_type split_obj =
self().
template get_split<Range>();
253 start.offer_work( split_obj );
254 }
while ( range.is_divisible() &&
self().is_divisible() );
257 self().work_balance(start, range);
266 template <
typename Range>
273 template <
typename range_type>
static no& decide(...);
277 static const bool value = (
sizeof(decide<Range>(0)) ==
sizeof(yes));
281 template <
typename Partition>
289 static const unsigned factor = 1;
299 template <
typename Partition>
308 #if __TBB_ENABLE_RANGE_FEEDBACK 309 size_t portion = size_t(
float(src.
my_divisor) *
float(split_obj.
right())
310 /
float(split_obj.
left() + split_obj.
right()) + 0.5f);
312 size_t portion = split_obj.
right() * my_partition::factor;
314 portion = (portion + my_partition::factor/2) & (0ul - my_partition::factor);
315 #if __TBB_ENABLE_RANGE_FEEDBACK 318 portion = my_partition::factor;
320 portion = src.
my_divisor - my_partition::factor;
326 return self().my_divisor > my_partition::factor;
328 #if _MSC_VER && !defined(__INTEL_COMPILER) 330 #pragma warning( push ) 331 #pragma warning( disable: 4127 ) 333 template <
typename Range>
336 size_t size =
self().my_divisor / my_partition::factor;
337 #if __TBB_NONUNIFORM_TASK_CREATION 338 size_t right = (size + 2) / 3;
340 size_t right = size / 2;
342 size_t left = size - right;
348 #if _MSC_VER && !defined(__INTEL_COMPILER) 349 #pragma warning( pop ) 350 #endif // warning 4127 is back 357 return size_t(current_index);
361 template <
typename Partition>
367 my_max_affinity(self().my_divisor) {}
369 , my_head((src.my_head + src.my_divisor) % src.my_max_affinity), my_max_affinity(src.my_max_affinity) {}
371 , my_head((src.my_head + src.my_divisor) % src.my_max_affinity), my_max_affinity(src.my_max_affinity) {}
373 if(
self().my_divisor )
382 #ifdef __TBB_USE_MACHINE_TIME_STAMPS 393 #ifdef __TBB_USE_MACHINE_TIME_STAMPS
400 #ifdef __TBB_USE_MACHINE_TIME_STAMPS
404 , my_max_depth(p.my_max_depth) {}
407 #ifdef __TBB_USE_MACHINE_TIME_STAMPS
411 , my_max_depth(p.my_max_depth) {}
413 if( !(
self().my_divisor / Mode::my_partition::factor) ) {
414 self().my_divisor = 1;
416 #if __TBB_USE_OPTIONAL_RTTI 424 if( !my_max_depth ) my_max_depth++;
434 my_max_depth -= base;
436 template<
typename StartType,
typename Range>
438 if( !range.is_divisible() || !
self().max_depth() ) {
439 start.run_body( range );
442 internal::range_vector<Range, range_pool_size> range_pool(range);
444 range_pool.split_to_fill(
self().max_depth());
445 if(
self().check_for_demand( start ) ) {
446 if( range_pool.size() > 1 ) {
447 start.offer_work( range_pool.front(), range_pool.front_depth() );
448 range_pool.pop_front();
451 if( range_pool.is_divisible(
self().max_depth()) )
454 start.run_body( range_pool.back() );
455 range_pool.pop_back();
456 }
while( !range_pool.empty() && !start.is_cancelled() );
460 if( pass == my_delay ) {
461 if(
self().my_divisor > 1 )
463 else if(
self().my_divisor && my_max_depth ) {
464 self().my_divisor = 0;
471 }
else if(
begin == my_delay ) {
472 #ifndef __TBB_USE_MACHINE_TIME_STAMPS 477 }
else if( run == my_delay ) {
485 #endif // __TBB_USE_MACHINE_TIME_STAMPS 500 if( my_divisor > 1 )
return true;
501 if( my_divisor && my_max_depth ) {
521 template<
typename StartType,
typename Range>
522 void execute(StartType &start, Range &range) {
523 split_type split_obj =
split();
524 while( range.is_divisible() )
525 start.offer_work( split_obj );
526 start.run_body( range );
542 static const unsigned factor_power = 4;
545 static const unsigned factor = 1 << factor_power;
549 __TBB_ASSERT( (factor&(factor-1))==0,
"factor must be power of two" );
552 my_max_depth = factor_power + 1;
557 , my_array(p.my_array) {}
560 , my_array(p.my_array) {}
563 if( !my_array[my_head] )
572 my_array[my_head] =
id;
579 static const size_t VICTIM_CHUNKS = 4;
583 num_chunks = VICTIM_CHUNKS;
584 return num_chunks==1;
610 template<
typename Range,
typename Body,
typename Partitioner>
friend class internal::start_scan;
622 typedef interface9::internal::simple_partition_type::split_type
split_type;
637 template<
typename Range,
typename Body,
typename Partitioner>
friend class internal::start_scan;
644 typedef interface9::internal::auto_partition_type::split_type
split_type;
656 template<
typename Range,
typename Body,
typename Partitioner>
friend class internal::start_scan;
675 template<
typename Range,
typename Body,
typename Partitioner>
friend class internal::start_scan;
687 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) 688 #pragma warning (pop) 689 #endif // warning 4244 is back 690 #undef __TBB_INITIAL_CHUNKS 691 #undef __TBB_RANGE_POOL_CAPACITY 692 #undef __TBB_INIT_DEPTH proportional_split split_type
#define __TBB_time_stamp()
linear_affinity_mode(linear_affinity_mode &src, split)
size_t do_split(adaptive_mode &src, split)
bool should_execute_range(const task &)
Provides backward-compatible methods for partition objects without affinity.
unsigned short affinity_id
An id as used for specifying affinity.
T * begin() const
Pointer to beginning of array.
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 id
~affinity_partitioner_base_v3()
Deallocates my_array.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
void spawn_or_delay(bool, task &b)
adaptive_mode(adaptive_mode &src, split)
affinity_partitioner_base_v3()
Zeros the fields.
static bool is_peer_stolen(task &t)
Task type used to split the work of parallel_deterministic_reduce.
proportional_mode(proportional_mode &src, const proportional_split &split_obj)
simple_partition_type(const simple_partitioner &)
Provides default splitting strategy for partition objects.
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 __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp begin
void execute(StartType &start, Range &range)
Range pool stores ranges of type T in a circular buffer with MaxCapacity.
Backward-compatible partition for auto and affinity partition objects.
bool decide_whether_to_delay()
static void mark_task_stolen(task &t)
Type enables transmission of splitting proportion from partitioners to range objects.
void set_affinity(task &)
Provides default linear indexing of partitioner's sequence.
internal::affinity_id affinity_id
An id as used for specifying affinity.
void split_to_fill(depth_t max_depth)
old_auto_partition_type(const auto_partitioner &)
affinity_partition_type(tbb::internal::affinity_partitioner_base_v3 &ap)
interface9::internal::static_partition_type task_partition_type
partition_type(const partition_type &, split)
interface9::internal::old_auto_partition_type partition_type
Initial task to split the work.
range_vector(const T &elem)
initialize via first range in pool
dynamic_grainsize_mode(dynamic_grainsize_mode &p, const proportional_split &split_obj)
void const char const char int ITT_FORMAT __itt_group_sync p
auto_partition_type(const auto_partitioner &)
#define __TBB_RANGE_POOL_CAPACITY
partition_type(const simple_partitioner &)
bool is_stolen_task() const
True if task was stolen from the task pool of another thread.
int ref_count() const
The internal reference count.
void __TBB_EXPORTED_METHOD resize(unsigned factor)
Resize my_array.
depth_t front_depth()
similarly to front(), returns depth of the first range in the pool
#define __TBB_EXPORTED_METHOD
old_auto_partition_type(const affinity_partitioner &)
tbb::atomic< bool > my_child_stolen
interface9::internal::affinity_partition_type::split_type split_type
dynamic_grainsize_mode(dynamic_grainsize_mode &p, split)
static_partition_type(const static_partitioner &)
interface9::internal::static_partition_type::split_type split_type
static_partition_type(static_partition_type &p, split)
task * continue_after_execute_range()
static size_t get_initial_partition_head()
auto_partition_type(auto_partition_type &src, split)
interface9::internal::affinity_partition_type task_partition_type
bool check_being_stolen(task &t)
Task type used in parallel_for.
affinity_partition_type(affinity_partition_type &p, split)
bool check_being_stolen(task &)
size_t do_split(proportional_mode &src, const proportional_split &split_obj)
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 __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long value
static const unsigned factor
task * parent() const
task on whose behalf this task is working, or NULL if this is a root.
void work_balance(StartType &start, Range &range)
proportional_split split_type
Defines entry point for affinity partitioner into tbb run-time library.
interface9::internal::simple_partition_type task_partition_type
#define __TBB_EXPORTED_FUNC
interface9::internal::simple_partition_type::split_type split_type
size_t __TBB_EXPORTED_FUNC get_initial_auto_partitioner_divisor()
value_type fetch_and_store(value_type value)
tbb::internal::affinity_id * my_array
void note_affinity(task::affinity_id)
void align_depth(depth_t)
size_t my_size
Number of elements in my_array.
void work_balance(StartType &start, Range &range)
#define __TBB_DEMAND_DEPTH_ADD
bool should_execute_range(const task &t)
task * execute() __TBB_override
Should be overridden by derived classes.
void execute(StartType &start, Range &range)
simplified algorithm
Join task node that contains shared flag for stealing feedback.
bool is_divisible(depth_t max_depth)
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 size
Base class for user-defined tasks.
interface9::internal::old_auto_partition_type partition_type
int current_thread_index()
Returns the index, aka slot number, of the calling thread in its current arena.
interface9::internal::old_auto_partition_type partition_type
void set_affinity(affinity_id id)
Set affinity for this task.
affinity_id * my_array
Array that remembers affinities of tree positions to affinity_id.
void set_affinity(task &t)
proportional_split get_split()
void set_affinity(task &t)
bool check_for_demand(task &t)
Dummy type that distinguishes splitting constructor from copy constructor.
Task type used to split the work of parallel_reduce.
bool check_for_demand(task &t)
Provides proportional splitting strategy for partition objects.
#define __TBB_INITIAL_CHUNKS
Base class for types that should not be copied or assigned.
void note_affinity(task::affinity_id id)
Identifiers declared inside namespace internal should never be used directly by client code...
bool check_for_demand(task &)
void align_depth(depth_t base)
void note_affinity(task::affinity_id)
tbb::aligned_space< T, MaxCapacity > my_pool
proportional_mode(proportional_mode &src, split)
static const int not_initialized
linear_affinity_mode(linear_affinity_mode &src, const proportional_split &split_obj)
interface9::internal::auto_partition_type::split_type split_type
affinity_partition_type(affinity_partition_type &p, const proportional_split &split_obj)
Enables one or the other code branches.
old_auto_partition_type(old_auto_partition_type &pt, split)
simple_partition_type(const simple_partition_type &, split)
interface9::internal::auto_partition_type task_partition_type
void set_affinity(task &)
static_partition_type(static_partition_type &p, const proportional_split &split_obj)