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, 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,partitioner);
00080 #else
00081
00082
00083 task_group_context context;
00084 start_for& a = *new(task::allocate_root(context)) start_for(range,body,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, Partitioner& partitioner, task_group_context& context ) {
00091 if( !range.empty() ) {
00092 start_for& a = *new(task::allocate_root(context)) start_for(range,body,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 #if __INTEL_COMPILER
00131 #pragma ivdep
00132 #endif
00133 for( Index i = r.begin(), k = my_begin + i * my_step; i < r.end(); i++, k = k + my_step)
00134 my_func( k );
00135 }
00136 };
00137 }
00139
00140
00141
00152
00154
00155 template<typename Range, typename Body>
00156 void parallel_for( const Range& range, const Body& body ) {
00157 internal::start_for<Range,Body,const __TBB_DEFAULT_PARTITIONER>::run(range,body,__TBB_DEFAULT_PARTITIONER());
00158 }
00159
00161
00162 template<typename Range, typename Body>
00163 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner ) {
00164 internal::start_for<Range,Body,const simple_partitioner>::run(range,body,partitioner);
00165 }
00166
00168
00169 template<typename Range, typename Body>
00170 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) {
00171 internal::start_for<Range,Body,const auto_partitioner>::run(range,body,partitioner);
00172 }
00173
00175
00176 template<typename Range, typename Body>
00177 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) {
00178 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner);
00179 }
00180
00181 #if __TBB_TASK_GROUP_CONTEXT
00183
00184 template<typename Range, typename Body>
00185 void parallel_for( const Range& range, const Body& body, task_group_context& context ) {
00186 internal::start_for<Range,Body,const __TBB_DEFAULT_PARTITIONER>::run(range, body, __TBB_DEFAULT_PARTITIONER(), context);
00187 }
00188
00190
00191 template<typename Range, typename Body>
00192 void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner, task_group_context& context ) {
00193 internal::start_for<Range,Body,const simple_partitioner>::run(range, body, partitioner, context);
00194 }
00195
00197
00198 template<typename Range, typename Body>
00199 void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner, task_group_context& context ) {
00200 internal::start_for<Range,Body,const auto_partitioner>::run(range, body, partitioner, context);
00201 }
00202
00204
00205 template<typename Range, typename Body>
00206 void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner, task_group_context& context ) {
00207 internal::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner, context);
00208 }
00209 #endif
00210
00211
00212 namespace strict_ppl {
00213
00215
00216 template <typename Index, typename Function, typename Partitioner>
00217 void parallel_for_impl(Index first, Index last, Index step, const Function& f, Partitioner& partitioner) {
00218 if (step <= 0 )
00219 internal::throw_exception(internal::eid_nonpositive_step);
00220 else if (last > first) {
00221
00222 Index end = (last - first - Index(1)) / step + Index(1);
00223 tbb::blocked_range<Index> range(static_cast<Index>(0), end);
00224 internal::parallel_for_body<Function, Index> body(f, first, step);
00225 tbb::parallel_for(range, body, partitioner);
00226 }
00227 }
00228
00230 template <typename Index, typename Function>
00231 void parallel_for(Index first, Index last, Index step, const Function& f) {
00232 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, auto_partitioner());
00233 }
00235 template <typename Index, typename Function>
00236 void parallel_for(Index first, Index last, Index step, const Function& f, const simple_partitioner& partitioner) {
00237 parallel_for_impl<Index,Function,const simple_partitioner>(first, last, step, f, partitioner);
00238 }
00240 template <typename Index, typename Function>
00241 void parallel_for(Index first, Index last, Index step, const Function& f, const auto_partitioner& partitioner) {
00242 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, partitioner);
00243 }
00245 template <typename Index, typename Function>
00246 void parallel_for(Index first, Index last, Index step, const Function& f, affinity_partitioner& partitioner) {
00247 parallel_for_impl(first, last, step, f, partitioner);
00248 }
00249
00251 template <typename Index, typename Function>
00252 void parallel_for(Index first, Index last, const Function& f) {
00253 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, auto_partitioner());
00254 }
00256 template <typename Index, typename Function>
00257 void parallel_for(Index first, Index last, const Function& f, const simple_partitioner& partitioner) {
00258 parallel_for_impl<Index,Function,const simple_partitioner>(first, last, static_cast<Index>(1), f, partitioner);
00259 }
00261 template <typename Index, typename Function>
00262 void parallel_for(Index first, Index last, const Function& f, const auto_partitioner& partitioner) {
00263 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, partitioner);
00264 }
00266 template <typename Index, typename Function>
00267 void parallel_for(Index first, Index last, const Function& f, affinity_partitioner& partitioner) {
00268 parallel_for_impl(first, last, static_cast<Index>(1), f, partitioner);
00269 }
00270
00271 #if __TBB_TASK_GROUP_CONTEXT
00273 template <typename Index, typename Function, typename Partitioner>
00274 void parallel_for_impl(Index first, Index last, Index step, const Function& f, Partitioner& partitioner, tbb::task_group_context &context) {
00275 if (step <= 0 )
00276 internal::throw_exception(internal::eid_nonpositive_step);
00277 else if (last > first) {
00278
00279 Index end = (last - first - Index(1)) / step + Index(1);
00280 tbb::blocked_range<Index> range(static_cast<Index>(0), end);
00281 internal::parallel_for_body<Function, Index> body(f, first, step);
00282 tbb::parallel_for(range, body, partitioner, context);
00283 }
00284 }
00285
00287 template <typename Index, typename Function>
00288 void parallel_for(Index first, Index last, Index step, const Function& f, tbb::task_group_context &context) {
00289 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, auto_partitioner(), context);
00290 }
00292 template <typename Index, typename Function>
00293 void parallel_for(Index first, Index last, Index step, const Function& f, const simple_partitioner& partitioner, tbb::task_group_context &context) {
00294 parallel_for_impl<Index,Function,const simple_partitioner>(first, last, step, f, partitioner, context);
00295 }
00297 template <typename Index, typename Function>
00298 void parallel_for(Index first, Index last, Index step, const Function& f, const auto_partitioner& partitioner, tbb::task_group_context &context) {
00299 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, partitioner, context);
00300 }
00302 template <typename Index, typename Function>
00303 void parallel_for(Index first, Index last, Index step, const Function& f, affinity_partitioner& partitioner, tbb::task_group_context &context) {
00304 parallel_for_impl(first, last, step, f, partitioner, context);
00305 }
00306
00307
00309 template <typename Index, typename Function>
00310 void parallel_for(Index first, Index last, const Function& f, tbb::task_group_context &context) {
00311 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, auto_partitioner(), context);
00312 }
00314 template <typename Index, typename Function, typename Partitioner>
00315 void parallel_for(Index first, Index last, const Function& f, const simple_partitioner& partitioner, tbb::task_group_context &context) {
00316 parallel_for_impl<Index,Function,const simple_partitioner>(first, last, static_cast<Index>(1), f, partitioner, context);
00317 }
00319 template <typename Index, typename Function, typename Partitioner>
00320 void parallel_for(Index first, Index last, const Function& f, const auto_partitioner& partitioner, tbb::task_group_context &context) {
00321 parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, partitioner, context);
00322 }
00324 template <typename Index, typename Function, typename Partitioner>
00325 void parallel_for(Index first, Index last, const Function& f, affinity_partitioner& partitioner, tbb::task_group_context &context) {
00326 parallel_for_impl(first, last, static_cast<Index>(1), f, partitioner, context);
00327 }
00328
00329 #endif
00330
00331
00332 }
00333
00334 using strict_ppl::parallel_for;
00335
00336 }
00337
00338 #if TBB_PREVIEW_SERIAL_SUBSET
00339 #define __TBB_NORMAL_EXECUTION
00340 #include "../serial/tbb/parallel_for.h"
00341 #undef __TBB_NORMAL_EXECUTION
00342 #endif
00343
00344 #endif
00345