partitioner.h Source File

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# partitioner.h

    00001 /*
    00002     Copyright 2005-2011 Intel Corporation.  All Rights Reserved.
    00003
    00004     The source code contained or described herein and all documents related
    00005     to the source code ("Material") are owned by Intel Corporation or its
    00006     suppliers or licensors.  Title to the Material remains with Intel
    00007     Corporation or its suppliers and licensors.  The Material is protected
    00008     by worldwide copyright laws and treaty provisions.  No part of the
    00009     Material may be used, copied, reproduced, modified, published, uploaded,
    00010     posted, transmitted, distributed, or disclosed in any way without
    00011     Intel's prior express written permission.
    00012
    00013     No license under any patent, copyright, trade secret or other
    00014     intellectual property right is granted to or conferred upon you by
    00015     disclosure or delivery of the Materials, either expressly, by
    00016     implication, inducement, estoppel or otherwise.  Any license under such
    00017     intellectual property rights must be express and approved by Intel in
    00018     writing.
    00019 */
    00020
    00021 #ifndef __TBB_partitioner_H
    00022 #define __TBB_partitioner_H
    00023
    00024 #include "task.h"
    00025
    00026 namespace tbb {
    00027 class affinity_partitioner;
    00028
    00030 namespace internal {
    00031 size_t __TBB_EXPORTED_FUNC get_initial_auto_partitioner_divisor();
    00032
    00034
    00035 class affinity_partitioner_base_v3: no_copy {
    00036     friend class tbb::affinity_partitioner;
    00038
    00039     affinity_id* my_array;
    00041     size_t my_size;
    00043     affinity_partitioner_base_v3() : my_array(NULL), my_size(0) {}
    00045     ~affinity_partitioner_base_v3() {resize(0);}
    00047
    00048     void __TBB_EXPORTED_METHOD resize( unsigned factor );
    00049     friend class affinity_partition_type;
    00050 };
    00051
    00053 class partition_type_base {
    00054 public:
    00055     void set_affinity( task & ) {}
    00056     void note_affinity( task::affinity_id ) {}
    00057     task* continue_after_execute_range() {return NULL;}
    00058     bool decide_whether_to_delay() {return false;}
    00059     void spawn_or_delay( bool, task& b ) {
    00060         task::spawn(b);
    00061     }
    00062 };
    00063
    00064 class affinity_partition_type;
    00065
    00066 template<typename Range, typename Body, typename Partitioner> class start_for;
    00067 template<typename Range, typename Body, typename Partitioner> class start_reduce;
    00068 template<typename Range, typename Body, typename Partitioner> class start_scan;
    00069
    00070 } // namespace internal
    00072
    00074
    00076 class simple_partitioner {
    00077 public:
    00078     simple_partitioner() {}
    00079 private:
    00080     template<typename Range, typename Body, typename Partitioner> friend class internal::start_for;
    00081     template<typename Range, typename Body, typename Partitioner> friend class internal::start_reduce;
    00082     template<typename Range, typename Body, typename Partitioner> friend class internal::start_scan;
    00083
    00084     class partition_type: public internal::partition_type_base {
    00085     public:
    00086         bool should_execute_range(const task& ) {return false;}
    00087         partition_type( const simple_partitioner& ) {}
    00088         partition_type( const partition_type&, split ) {}
    00089     };
    00090 };
    00091
    00093
    00096 class auto_partitioner {
    00097 public:
    00098     auto_partitioner() {}
    00099
    00100 private:
    00101     template<typename Range, typename Body, typename Partitioner> friend class internal::start_for;
    00102     template<typename Range, typename Body, typename Partitioner> friend class internal::start_reduce;
    00103     template<typename Range, typename Body, typename Partitioner> friend class internal::start_scan;
    00104
    00105     class partition_type: public internal::partition_type_base {
    00106         size_t num_chunks;
    00107         static const size_t VICTIM_CHUNKS = 4;
    00108 public:
    00109         bool should_execute_range(const task &t) {
    00110             if( num_chunks<VICTIM_CHUNKS && t.is_stolen_task() )
    00111                 num_chunks = VICTIM_CHUNKS;
    00112             return num_chunks==1;
    00113         }
    00114         partition_type( const auto_partitioner& ) : num_chunks(internal::get_initial_auto_partitioner_divisor()) {}
    00115         partition_type( partition_type& pt, split ) {
    00116             num_chunks = pt.num_chunks /= 2u;
    00117         }
    00118     };
    00119 };
    00120
    00122 class affinity_partitioner: internal::affinity_partitioner_base_v3 {
    00123 public:
    00124     affinity_partitioner() {}
    00125
    00126 private:
    00127     template<typename Range, typename Body, typename Partitioner> friend class internal::start_for;
    00128     template<typename Range, typename Body, typename Partitioner> friend class internal::start_reduce;
    00129     template<typename Range, typename Body, typename Partitioner> friend class internal::start_scan;
    00130
    00131     typedef internal::affinity_partition_type partition_type;
    00132     friend class internal::affinity_partition_type;
    00133 };
    00134
    00136 namespace internal {
    00137
    00138 class affinity_partition_type: public no_copy {
    00140     static const unsigned factor = 16;
    00141     static const size_t VICTIM_CHUNKS = 4;
    00142
    00143     internal::affinity_id* my_array;
    00144     task_list delay_list;
    00145     unsigned map_begin, map_end;
    00146     size_t num_chunks;
    00147 public:
    00148     affinity_partition_type( affinity_partitioner& ap ) {
    00149         __TBB_ASSERT( (factor&(factor-1))==0, "factor must be power of two" );
    00150         ap.resize(factor);
    00151         my_array = ap.my_array;
    00152         map_begin = 0;
    00153         map_end = unsigned(ap.my_size);
    00154         num_chunks = internal::get_initial_auto_partitioner_divisor();
    00155     }
    00156     affinity_partition_type(affinity_partition_type& p, split) : my_array(p.my_array) {
    00157         __TBB_ASSERT( p.map_end-p.map_begin<factor || (p.map_end-p.map_begin)%factor==0, NULL );
    00158         num_chunks = p.num_chunks /= 2;
    00159         unsigned e = p.map_end;
    00160         unsigned d = (e - p.map_begin)/2;
    00161         if( d>factor )
    00162             d &= 0u-factor;
    00163         map_end = e;
    00164         map_begin = p.map_end = e-d;
    00165     }
    00166
    00167     bool should_execute_range(const task &t) {
    00168         if( num_chunks < VICTIM_CHUNKS && t.is_stolen_task() )
    00169             num_chunks = VICTIM_CHUNKS;
    00170         return num_chunks == 1;
    00171     }
    00172
    00173     void set_affinity( task &t ) {
    00174         if( map_begin<map_end )
    00175             t.set_affinity( my_array[map_begin] );
    00176     }
    00177     void note_affinity( task::affinity_id id ) {
    00178         if( map_begin<map_end )
    00179             my_array[map_begin] = id;
    00180     }
    00181     task* continue_after_execute_range() {
    00182         task* first = NULL;
    00183         if( !delay_list.empty() ) {
    00184             first = &delay_list.pop_front();
    00185             while( !delay_list.empty() ) {
    00186                 task::spawn(*first);
    00187                 first = &delay_list.pop_front();
    00188             }
    00189         }
    00190         return first;
    00191     }
    00192     bool decide_whether_to_delay() {
    00193         // The possible underflow caused by "-1u" is deliberate
    00194         return (map_begin&(factor-1))==0 && map_end-map_begin-1u<factor;
    00195     }
    00196     void spawn_or_delay( bool delay, task& b ) {
    00197         if( delay )
    00198             delay_list.push_back(b);
    00199         else
    00200             task::spawn(b);
    00201     }
    00202
    00203     ~affinity_partition_type() {
    00204         // The delay_list can be non-empty if an exception is thrown.
    00205         while( !delay_list.empty() ) {
    00206             task& t = delay_list.pop_front();
    00207             t.destroy(t);
    00208         }
    00209     }
    00210 };
    00211
    00212 } // namespace internal
    00214
    00215
    00216 } // namespace tbb
    00217
    00218 #endif /* __TBB_partitioner_H */

Copyright © 2005-2011 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.