00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __TBB_parallel_for_H
00022 #define __TBB_parallel_for_H
00023
00024 #include <new>
00025 #include "task.h"
00026 #include "partitioner.h"
00027 #include "blocked_range.h"
00028 #include "tbb_exception.h"
00029
00030 namespace tbb {
00031
00032 namespace interface6 {
00034 namespace internal {
00035
00037
00038 template<typename Range, typename Body, typename Partitioner>
00039 class start_for: public task {
00040 Range my_range;
00041 const Body my_body;
00042 typename Partitioner::task_partition_type my_partition;
00043 task* execute();
00044
00045 public:
00047 start_for( const Range& range, const Body& body, Partitioner& partitioner ) :
00048 my_range(range),
00049 my_body(body),
00050 my_partition(partitioner)
00051 {
00052 }
00054
00055 start_for( start_for& parent_, split ) :
00056 my_range(parent_.my_range,split()),
00057 my_body(parent_.my_body),
00058 my_partition(parent_.my_partition, split())
00059 {
00060 my_partition.set_affinity(*this);
00061 }
00063
00064 start_for( start_for& parent_, const Range& r, depth_t d ) :
00065 my_range(r),
00066 my_body(parent_.my_body),
00067 my_partition(parent_.my_partition,split())
00068 {
00069 my_partition.set_affinity(*this);
00070 my_partition.align_depth( d );
00071 }
00073 void note_affinity( affinity_id id ) {
00074 my_partition.note_affinity( id );
00075 }
00076 static void run( const Range& range, const Body& body, const Partitioner& partitioner ) {
00077 if( !range.empty() ) {
00078 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
00079 start_for& a = *new(task::allocate_root()) start_for(range,body,const_cast<Partitioner&>(partitioner));
00080 #else
00081
00082
00083 task_group_context context;
00084 start_for& a = *new(task::allocate_root(context)) start_for(range,body,const_cast<Partitioner&>(partitioner));
00085 #endif
00086 task::spawn_root_and_wait(a);
00087 }
00088 }
00089 #if __TBB_TASK_GROUP_CONTEXT
00090 static void run( const Range& range, const Body& body, const Partitioner& partitioner, task_group_context& context ) {
00091 if( !range.empty() ) {
00092 start_for& a = *new(task::allocate_root(context)) start_for(range,body,const_cast<Partitioner&>(partitioner));
00093 task::spawn_root_and_wait(a);
00094 }
00095 }
00096 #endif
00098 flag_task *create_continuation() {
00099 return new( allocate_continuation() ) flag_task();
00100 }
00102 void run_body( Range &r ) { my_body( r ); }
00103 };
00104
00105 template<typename Range, typename Body, typename Partitioner>
00106 task* start_for<Range,Body,Partitioner>::execute() {
00107 my_partition.check_being_stolen( *this );
00108 my_partition.execute(*this, my_range);
00109 return NULL;
00110 }
00111 }
00113 }
00114
00116 namespace internal {
00117 using interface6::internal::start_for;
00118
00120 template<typename Function, typename Index>
00121 class parallel_for_body : internal::no_assign {
00122 const Function &my_func;
00123 const Index my_begin;
00124 const Index my_step;
00125 public:
00126 parallel_for_body( const Function& _func, Index& _begin, Index& _step)
00127 : my_func(_func), my_begin(_begin), my_step(_step) {}
00128
00129 void operator()( tbb::blocked_range<Index>& r ) const {
00130 for( Index i = r.begin(), k = my_begin + i * my_step; i < r.end(); i++, k = k + my_step)
00131 my_func( k );
00132 }
00133 };
00134 }
00136
00137
00138
00149
00151
00152 template<typename Range, typename Body>
00153 void parallel_for( const Range& range, const Body& body ) {
00154 internal::start_for<Range,Body,__TBB_DEFAULT_PARTITIONER>::run(range,body,__TBB_DEFAULT_PARTITIONER());
00155 }
00156
00158
00159 template<typename Range, typename Body>
00160 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner ) {
00161 internal::start_for<Range,Body,simple_partitioner>::run(range,body,partitioner);
00162 }
00163
00165
00166 template<typename Range, typename Body>
00167 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) {
00168 internal::start_for<Range,Body,auto_partitioner>::run(range,body,partitioner);
00169 }
00170
00172
00173 template<typename Range, typename Body>
00174 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) {
00175 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner);
00176 }
00177
00178 #if __TBB_TASK_GROUP_CONTEXT
00180
00181 template<typename Range, typename Body>
00182 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
00183 internal::start_for<Range,Body,simple_partitioner>::run(range, body, partitioner, context);
00184 }
00185
00187
00188 template<typename Range, typename Body>
00189 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner, task_group_context& context ) {
00190 internal::start_for<Range,Body,auto_partitioner>::run(range, body, partitioner, context);
00191 }
00192
00194
00195 template<typename Range, typename Body>
00196 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner, task_group_context& context ) {
00197 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner, context);
00198 }
00199 #endif
00200
00201
00202 namespace strict_ppl {
00203
00205
00206 template <typename Index, typename Function>
00207 void parallel_for(Index first, Index last, Index step, const Function& f) {
00208 if (step <= 0 )
00209 internal::throw_exception(internal::eid_nonpositive_step);
00210 else if (last > first) {
00211
00212 Index end = (last - first - Index(1)) / step + Index(1);
00213 tbb::blocked_range<Index> range(static_cast<Index>(0), end);
00214 internal::parallel_for_body<Function, Index> body(f, first, step);
00215 tbb::parallel_for(range, body, tbb::auto_partitioner());
00216 }
00217 }
00219 template <typename Index, typename Function>
00220 void parallel_for(Index first, Index last, const Function& f) {
00221 parallel_for(first, last, static_cast<Index>(1), f);
00222 }
00223
00224 #if __TBB_TASK_GROUP_CONTEXT
00226 template <typename Index, typename Function>
00227 void parallel_for(Index first, Index last, Index step, const Function& f, tbb::task_group_context &context) {
00228 if (step <= 0 )
00229 internal::throw_exception(internal::eid_nonpositive_step);
00230 else if (last > first) {
00231
00232 Index end = (last - first - Index(1)) / step + Index(1);
00233 tbb::blocked_range<Index> range(static_cast<Index>(0), end);
00234 internal::parallel_for_body<Function, Index> body(f, first, step);
00235 tbb::parallel_for(range, body, tbb::auto_partitioner(), context);
00236 }
00237 }
00239 template <typename Index, typename Function>
00240 void parallel_for(Index first, Index last, const Function& f, tbb::task_group_context &context) {
00241 parallel_for(first, last, static_cast<Index>(1), f, context);
00242 }
00243 #endif
00244
00245
00246 }
00247
00248 using strict_ppl::parallel_for;
00249
00250 }
00251
00252 #if TBB_PREVIEW_SERIAL_SUBSET
00253 #define __TBB_NORMAL_EXECUTION
00254 #include "../serial/tbb/parallel_for.h"
00255 #undef __TBB_NORMAL_EXECUTION
00256 #endif
00257
00258 #endif
00259