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

- File List
- File Members

# parallel_for.h

    00001 /*
    00002     Copyright 2005-2012 Intel Corporation.  All Rights Reserved.
    00003
    00004     This file is part of Threading Building Blocks.
    00005
    00006     Threading Building Blocks is free software; you can redistribute it
    00007     and/or modify it under the terms of the GNU General Public License
    00008     version 2 as published by the Free Software Foundation.
    00009
    00010     Threading Building Blocks is distributed in the hope that it will be
    00011     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    00012     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00013     GNU General Public License for more details.
    00014
    00015     You should have received a copy of the GNU General Public License
    00016     along with Threading Building Blocks; if not, write to the Free Software
    00017     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    00018
    00019     As a special exception, you may use this file as part of a free software
    00020     library without restriction.  Specifically, if other files instantiate
    00021     templates or use macros or inline functions from this file, or you compile
    00022     this file and link it with other files to produce an executable, this
    00023     file does not by itself cause the resulting executable to be covered by
    00024     the GNU General Public License.  This exception does not however
    00025     invalidate any other reasons why the executable file might be covered by
    00026     the GNU General Public License.
    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         /*override*/ 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         /*override*/ 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                 // Bound context prevents exceptions from body to affect nesting or sibling algorithms,
    00090                 // and allows users to handle exceptions safely by wrapping parallel_for in the try-block.
    00091                 task_group_context context;
    00092                 start_for& a = *new(task::allocate_root(context)) start_for(range,body,partitioner);
    00093 #endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */
    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 /* __TBB_TASK_GROUP_CONTEXT */
    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 } // namespace internal
    00121 } // namespace interfaceX
    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 } // namespace internal
    00147
    00148 // Requirements on Range concept are documented in blocked_range.h
    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 /* __TBB_TASK_GROUP_CONTEXT */
    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); // throws std::invalid_argument
    00228     else if (last > first) {
    00229         // Above "else" avoids "potential divide by zero" warning on some platforms
    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); // throws std::invalid_argument
    00285     else if (last > first) {
    00286         // Above "else" avoids "potential divide by zero" warning on some platforms
    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 /* __TBB_TASK_GROUP_CONTEXT */
    00338
    00339
    00340 } // namespace strict_ppl
    00341
    00342 using strict_ppl::parallel_for;
    00343
    00344 } // namespace tbb
    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 /* __TBB_parallel_for_H */
    00353

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