partitioner.h Source File

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

- File List
- File Members

# partitioner.h

    00001 /*
    00002     Copyright 2005-2010 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> class start_reduce_with_affinity;
    00069 template<typename Range, typename Body, typename Partitioner> class start_scan;
    00070
    00071 } // namespace internal
    00073
    00075
    00077 class simple_partitioner {
    00078 public:
    00079     simple_partitioner() {}
    00080 private:
    00081     template<typename Range, typename Body, typename Partitioner> friend class internal::start_for;
    00082     template<typename Range, typename Body, typename Partitioner> friend class internal::start_reduce;
    00083     template<typename Range, typename Body, typename Partitioner> friend class internal::start_scan;
    00084
    00085     class partition_type: public internal::partition_type_base {
    00086     public:
    00087         bool should_execute_range(const task& ) {return false;}
    00088         partition_type( const simple_partitioner& ) {}
    00089         partition_type( const partition_type&, split ) {}
    00090     };
    00091 };
    00092
    00094
    00097 class auto_partitioner {
    00098 public:
    00099     auto_partitioner() {}
    00100
    00101 private:
    00102     template<typename Range, typename Body, typename Partitioner> friend class internal::start_for;
    00103     template<typename Range, typename Body, typename Partitioner> friend class internal::start_reduce;
    00104     template<typename Range, typename Body, typename Partitioner> friend class internal::start_scan;
    00105
    00106     class partition_type: public internal::partition_type_base {
    00107         size_t num_chunks;
    00108         static const size_t VICTIM_CHUNKS = 4;
    00109 public:
    00110         bool should_execute_range(const task &t) {
    00111             if( num_chunks<VICTIM_CHUNKS && t.is_stolen_task() )
    00112                 num_chunks = VICTIM_CHUNKS;
    00113             return num_chunks==1;
    00114         }
    00115         partition_type( const auto_partitioner& ) : num_chunks(internal::get_initial_auto_partitioner_divisor()) {}
    00116         partition_type( partition_type& pt, split ) {
    00117             num_chunks = pt.num_chunks /= 2u;
    00118         }
    00119     };
    00120 };
    00121
    00123 class affinity_partitioner: internal::affinity_partitioner_base_v3 {
    00124 public:
    00125     affinity_partitioner() {}
    00126
    00127 private:
    00128     template<typename Range, typename Body, typename Partitioner> friend class internal::start_for;
    00129     template<typename Range, typename Body, typename Partitioner> friend class internal::start_reduce;
    00130     template<typename Range, typename Body> friend class internal::start_reduce_with_affinity;
    00131     template<typename Range, typename Body, typename Partitioner> friend class internal::start_scan;
    00132
    00133     typedef internal::affinity_partition_type partition_type;
    00134     friend class internal::affinity_partition_type;
    00135 };
    00136
    00138 namespace internal {
    00139
    00140 class affinity_partition_type: public no_copy {
    00142     static const unsigned factor = 16;
    00143     static const size_t VICTIM_CHUNKS = 4;
    00144
    00145     internal::affinity_id* my_array;
    00146     task_list delay_list;
    00147     unsigned map_begin, map_end;
    00148     size_t num_chunks;
    00149 public:
    00150     affinity_partition_type( affinity_partitioner& ap ) {
    00151         __TBB_ASSERT( (factor&(factor-1))==0, "factor must be power of two" );
    00152         ap.resize(factor);
    00153         my_array = ap.my_array;
    00154         map_begin = 0;
    00155         map_end = unsigned(ap.my_size);
    00156         num_chunks = internal::get_initial_auto_partitioner_divisor();
    00157     }
    00158     affinity_partition_type(affinity_partition_type& p, split) : my_array(p.my_array) {
    00159         __TBB_ASSERT( p.map_end-p.map_begin<factor || (p.map_end-p.map_begin)%factor==0, NULL );
    00160         num_chunks = p.num_chunks /= 2;
    00161         unsigned e = p.map_end;
    00162         unsigned d = (e - p.map_begin)/2;
    00163         if( d>factor )
    00164             d &= 0u-factor;
    00165         map_end = e;
    00166         map_begin = p.map_end = e-d;
    00167     }
    00168
    00169     bool should_execute_range(const task &t) {
    00170         if( num_chunks < VICTIM_CHUNKS && t.is_stolen_task() )
    00171             num_chunks = VICTIM_CHUNKS;
    00172         return num_chunks == 1;
    00173     }
    00174
    00175     void set_affinity( task &t ) {
    00176         if( map_begin<map_end )
    00177             t.set_affinity( my_array[map_begin] );
    00178     }
    00179     void note_affinity( task::affinity_id id ) {
    00180         if( map_begin<map_end )
    00181             my_array[map_begin] = id;
    00182     }
    00183     task* continue_after_execute_range() {
    00184         task* first = NULL;
    00185         if( !delay_list.empty() ) {
    00186             first = &delay_list.pop_front();
    00187             while( !delay_list.empty() ) {
    00188                 task::spawn(*first);
    00189                 first = &delay_list.pop_front();
    00190             }
    00191         }
    00192         return first;
    00193     }
    00194     bool decide_whether_to_delay() {
    00195         // The possible underflow caused by "-1u" is deliberate
    00196         return (map_begin&(factor-1))==0 && map_end-map_begin-1u<factor;
    00197     }
    00198     void spawn_or_delay( bool delay, task& b ) {
    00199         if( delay )
    00200             delay_list.push_back(b);
    00201         else
    00202             task::spawn(b);
    00203     }
    00204
    00205     ~affinity_partition_type() {
    00206         // The delay_list can be non-empty if an exception is thrown.
    00207         while( !delay_list.empty() ) {
    00208             task& t = delay_list.pop_front();
    00209             t.destroy(t);
    00210         }
    00211     }
    00212 };
    00213
    00214 } // namespace internal
    00216
    00217
    00218 } // namespace tbb
    00219
    00220 #endif /* __TBB_partitioner_H */

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