00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef __TBB_parallel_for_H
00030 #define __TBB_parallel_for_H
00031
00032 #include <new>
00033 #include "task.h"
00034 #include "partitioner.h"
00035 #include "blocked_range.h"
00036 #include "tbb_exception.h"
00037
00038 namespace tbb {
00039
00040 namespace interface6 {
00042 namespace internal {
00043
00045
00046 template<typename Range, typename Body, typename Partitioner>
00047 class start_for: public task {
00048 Range my_range;
00049 const Body my_body;
00050 typename Partitioner::task_partition_type my_partition;
00051 task* execute();
00052
00053 public:
00055 start_for( const Range& range, const Body& body, Partitioner& partitioner ) :
00056 my_range(range),
00057 my_body(body),
00058 my_partition(partitioner)
00059 {
00060 }
00062
00063 start_for( start_for& parent_, split ) :
00064 my_range(parent_.my_range,split()),
00065 my_body(parent_.my_body),
00066 my_partition(parent_.my_partition, split())
00067 {
00068 my_partition.set_affinity(*this);
00069 }
00071
00072 start_for( start_for& parent_, const Range& r, depth_t d ) :
00073 my_range(r),
00074 my_body(parent_.my_body),
00075 my_partition(parent_.my_partition,split())
00076 {
00077 my_partition.set_affinity(*this);
00078 my_partition.align_depth( d );
00079 }
00081 void note_affinity( affinity_id id ) {
00082 my_partition.note_affinity( id );
00083 }
00084 static void run( const Range& range, const Body& body, Partitioner& partitioner ) {
00085 if( !range.empty() ) {
00086 #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
00087 start_for& a = *new(task::allocate_root()) start_for(range,body,partitioner);
00088 #else
00089
00090
00091 task_group_context context;
00092 start_for& a = *new(task::allocate_root(context)) start_for(range,body,partitioner);
00093 #endif
00094 task::spawn_root_and_wait(a);
00095 }
00096 }
00097 #if __TBB_TASK_GROUP_CONTEXT
00098 static void run( const Range& range, const Body& body, Partitioner& partitioner, task_group_context& context ) {
00099 if( !range.empty() ) {
00100 start_for& a = *new(task::allocate_root(context)) start_for(range,body,partitioner);
00101 task::spawn_root_and_wait(a);
00102 }
00103 }
00104 #endif
00106 flag_task *create_continuation() {
00107 return new( allocate_continuation() ) flag_task();
00108 }
00110 void run_body( Range &r ) { my_body( r ); }
00111 };
00112
00113 template<typename Range, typename Body, typename Partitioner>
00114 task* start_for<Range,Body,Partitioner>::execute() {
00115 my_partition.check_being_stolen( *this );
00116 my_partition.execute(*this, my_range);
00117 return NULL;
00118 }
00119 }
00121 }
00122
00124 namespace internal {
00125 using interface6::internal::start_for;
00126
00128 template<typename Function, typename Index>
00129 class parallel_for_body : internal::no_assign {
00130 const Function &my_func;
00131 const Index my_begin;
00132 const Index my_step;
00133 public:
00134 parallel_for_body( const Function& _func, Index& _begin, Index& _step)
00135 : my_func(_func), my_begin(_begin), my_step(_step) {}
00136
00137 void operator()( tbb::blocked_range<Index>& r ) const {
00138 #if __INTEL_COMPILER
00139 #pragma ivdep
00140 #endif
00141 for( Index i = r.begin(), k = my_begin + i * my_step; i < r.end(); i++, k = k + my_step)
00142 my_func( k );
00143 }
00144 };
00145 }
00147
00148
00149
00160
00162
00163 template<typename Range, typename Body>
00164 void parallel_for( const Range& range, const Body& body ) {
00165 internal::start_for<Range,Body,const __TBB_DEFAULT_PARTITIONER>::run(range,body,__TBB_DEFAULT_PARTITIONER());
00166 }
00167
00169
00170 template<typename Range, typename Body>
00171 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner ) {
00172 internal::start_for<Range,Body,const simple_partitioner>::run(range,body,partitioner);
00173 }
00174
00176
00177 template<typename Range, typename Body>
00178 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) {
00179 internal::start_for<Range,Body,const auto_partitioner>::run(range,body,partitioner);
00180 }
00181
00183
00184 template<typename Range, typename Body>
00185 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) {
00186 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner);
00187 }
00188
00189 #if __TBB_TASK_GROUP_CONTEXT
00191
00192 template<typename Range, typename Body>
00193 void parallel_for( const Range& range, const Body& body, task_group_context& context ) {
00194 internal::start_for<Range,Body,const __TBB_DEFAULT_PARTITIONER>::run(range, body, __TBB_DEFAULT_PARTITIONER(), context);
00195 }
00196
00198
00199 template<typename Range, typename Body>
00200 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
00201 internal::start_for<Range,Body,const simple_partitioner>::run(range, body, partitioner, context);
00202 }
00203
00205
00206 template<typename Range, typename Body>
00207 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner, task_group_context& context ) {
00208 internal::start_for<Range,Body,const auto_partitioner>::run(range, body, partitioner, context);
00209 }
00210
00212
00213 template<typename Range, typename Body>
00214 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner, task_group_context& context ) {
00215 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner, context);
00216 }
00217 #endif
00218
00219
00220 namespace strict_ppl {
00221
00223
00224 template <typename Index, typename Function, typename Partitioner>
00225 void parallel_for_impl(Index first, Index last, Index step, const Function& f, Partitioner& partitioner) {
00226 if (step <= 0 )
00227 internal::throw_exception(internal::eid_nonpositive_step);
00228 else if (last > first) {
00229
00230 Index end = (last - first - Index(1)) / step + Index(1);
00231 tbb::blocked_range<Index> range(static_cast<Index>(0), end);
00232 internal::parallel_for_body<Function, Index> body(f, first, step);
00233 tbb::parallel_for(range, body, partitioner);
00234 }
00235 }
00236
00238 template <typename Index, typename Function>
00239 void parallel_for(Index first, Index last, Index step, const Function& f) {
00240 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, auto_partitioner());
00241 }
00243 template <typename Index, typename Function>
00244 void parallel_for(Index first, Index last, Index step, const Function& f, const simple_partitioner& partitioner) {
00245 parallel_for_impl<Index,Function,const simple_partitioner>(first, last, step, f, partitioner);
00246 }
00248 template <typename Index, typename Function>
00249 void parallel_for(Index first, Index last, Index step, const Function& f, const auto_partitioner& partitioner) {
00250 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, partitioner);
00251 }
00253 template <typename Index, typename Function>
00254 void parallel_for(Index first, Index last, Index step, const Function& f, affinity_partitioner& partitioner) {
00255 parallel_for_impl(first, last, step, f, partitioner);
00256 }
00257
00259 template <typename Index, typename Function>
00260 void parallel_for(Index first, Index last, const Function& f) {
00261 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, auto_partitioner());
00262 }
00264 template <typename Index, typename Function>
00265 void parallel_for(Index first, Index last, const Function& f, const simple_partitioner& partitioner) {
00266 parallel_for_impl<Index,Function,const simple_partitioner>(first, last, static_cast<Index>(1), f, partitioner);
00267 }
00269 template <typename Index, typename Function>
00270 void parallel_for(Index first, Index last, const Function& f, const auto_partitioner& partitioner) {
00271 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, partitioner);
00272 }
00274 template <typename Index, typename Function>
00275 void parallel_for(Index first, Index last, const Function& f, affinity_partitioner& partitioner) {
00276 parallel_for_impl(first, last, static_cast<Index>(1), f, partitioner);
00277 }
00278
00279 #if __TBB_TASK_GROUP_CONTEXT
00281 template <typename Index, typename Function, typename Partitioner>
00282 void parallel_for_impl(Index first, Index last, Index step, const Function& f, Partitioner& partitioner, tbb::task_group_context &context) {
00283 if (step <= 0 )
00284 internal::throw_exception(internal::eid_nonpositive_step);
00285 else if (last > first) {
00286
00287 Index end = (last - first - Index(1)) / step + Index(1);
00288 tbb::blocked_range<Index> range(static_cast<Index>(0), end);
00289 internal::parallel_for_body<Function, Index> body(f, first, step);
00290 tbb::parallel_for(range, body, partitioner, context);
00291 }
00292 }
00293
00295 template <typename Index, typename Function>
00296 void parallel_for(Index first, Index last, Index step, const Function& f, tbb::task_group_context &context) {
00297 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, auto_partitioner(), context);
00298 }
00300 template <typename Index, typename Function>
00301 void parallel_for(Index first, Index last, Index step, const Function& f, const simple_partitioner& partitioner, tbb::task_group_context &context) {
00302 parallel_for_impl<Index,Function,const simple_partitioner>(first, last, step, f, partitioner, context);
00303 }
00305 template <typename Index, typename Function>
00306 void parallel_for(Index first, Index last, Index step, const Function& f, const auto_partitioner& partitioner, tbb::task_group_context &context) {
00307 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, partitioner, context);
00308 }
00310 template <typename Index, typename Function>
00311 void parallel_for(Index first, Index last, Index step, const Function& f, affinity_partitioner& partitioner, tbb::task_group_context &context) {
00312 parallel_for_impl(first, last, step, f, partitioner, context);
00313 }
00314
00315
00317 template <typename Index, typename Function>
00318 void parallel_for(Index first, Index last, const Function& f, tbb::task_group_context &context) {
00319 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, auto_partitioner(), context);
00320 }
00322 template <typename Index, typename Function, typename Partitioner>
00323 void parallel_for(Index first, Index last, const Function& f, const simple_partitioner& partitioner, tbb::task_group_context &context) {
00324 parallel_for_impl<Index,Function,const simple_partitioner>(first, last, static_cast<Index>(1), f, partitioner, context);
00325 }
00327 template <typename Index, typename Function, typename Partitioner>
00328 void parallel_for(Index first, Index last, const Function& f, const auto_partitioner& partitioner, tbb::task_group_context &context) {
00329 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, partitioner, context);
00330 }
00332 template <typename Index, typename Function, typename Partitioner>
00333 void parallel_for(Index first, Index last, const Function& f, affinity_partitioner& partitioner, tbb::task_group_context &context) {
00334 parallel_for_impl(first, last, static_cast<Index>(1), f, partitioner, context);
00335 }
00336
00337 #endif
00338
00339
00340 }
00341
00342 using strict_ppl::parallel_for;
00343
00344 }
00345
00346 #if TBB_PREVIEW_SERIAL_SUBSET
00347 #define __TBB_NORMAL_EXECUTION
00348 #include "../serial/tbb/parallel_for.h"
00349 #undef __TBB_NORMAL_EXECUTION
00350 #endif
00351
00352 #endif
00353