Sierra Toolkit Version of the Day
AlgorithmRunnerTBB.cpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 Sandia Corporation.                     */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 
00010 #include <stk_algsup/AlgorithmRunner.hpp>
00011 
00012 #ifdef STK_HAVE_TBB
00013 
00014 #include <tbb/task_scheduler_init.h>
00015 #include <tbb/blocked_range.h>
00016 #include <tbb/parallel_for.h>
00017 #include <tbb/parallel_reduce.h>
00018 #include <tbb/scalable_allocator.h>
00019 #include <tbb/partitioner.h>
00020 
00021 #include <stk_mesh/base/BulkData.hpp>
00022 #include <stk_mesh/base/Bucket.hpp>
00023 
00024 namespace stk {
00025 namespace {
00026 
00027 //----------------------------------------------------------------------
00028 
00029 struct RunTBB {
00030   const mesh::Selector & selector ;
00031   const mesh::PartVector & union_parts ;
00032   const std::vector<mesh::Bucket*> & buckets ;
00033   const AlgorithmInterface         & alg ;
00034 
00035   void operator()(const tbb::blocked_range<int>& r) const;
00036 
00037   RunTBB( const mesh::Selector & arg_selector ,
00038           const mesh::PartVector & arg_union_parts ,
00039           const std::vector<mesh::Bucket*> & arg_buckets ,
00040           const AlgorithmInterface         & arg_alg );
00041 
00042   ~RunTBB();
00043 };
00044 
00045 RunTBB::RunTBB(
00046   const mesh::Selector    & arg_selector ,
00047   const mesh::PartVector & arg_union_parts ,
00048   const std::vector<mesh::Bucket*> & arg_buckets ,
00049   const AlgorithmInterface         & arg_alg )
00050   : selector( arg_selector ),
00051     union_parts( arg_union_parts ),
00052     buckets( arg_buckets ),
00053     alg( arg_alg )
00054 {}
00055 
00056 RunTBB::~RunTBB()
00057 {
00058 }
00059 
00060 void RunTBB::operator()( const tbb::blocked_range<int> & r ) const
00061 {
00062   for ( int i = r.begin() ; i < r.end() ; ++i ) {
00063     alg.apply_one( selector , union_parts , * buckets[i] , NULL );
00064   }
00065 }
00066 
00067 struct RunTBBreduce {
00068   const mesh::Selector    & selector ;
00069   const mesh::PartVector & union_parts ;
00070   const std::vector<mesh::Bucket*> & buckets ;
00071   const AlgorithmInterface         & alg ;
00072   void                             * reduce ;
00073 
00074   void operator()(const tbb::blocked_range<int>& r);
00075 
00076   void join( const RunTBBreduce & rhs ) const ;
00077 
00078   RunTBBreduce( const RunTBBreduce & rhs , tbb::split );
00079 
00080   RunTBBreduce( const mesh::Selector    & arg_selector ,
00081           const mesh::PartVector & arg_union_parts ,
00082           const std::vector<mesh::Bucket*> & arg_buckets ,
00083           const AlgorithmInterface         & arg_alg ,
00084           void                             * arg_reduce = NULL );
00085 
00086   ~RunTBBreduce();
00087 };
00088 
00089 RunTBBreduce::RunTBBreduce( const RunTBBreduce & rhs , tbb::split )
00090   : selector( rhs.selector ),
00091     union_parts( rhs.union_parts ),
00092     buckets(  rhs.buckets ),
00093     alg(      rhs.alg ),
00094     reduce( NULL )
00095 {
00096   if ( rhs.reduce ) {
00097     reduce = malloc( alg.m_reduce_allocation_size ); //scalable_malloc ?
00098     alg.init( reduce );
00099   }
00100 }
00101 
00102 RunTBBreduce::~RunTBBreduce()
00103 {
00104   if ( reduce ) { free( reduce ); /* scalable_free ? */}
00105 }
00106 
00107 void RunTBBreduce::join( const RunTBBreduce & rhs ) const
00108 {
00109   alg.join( reduce , rhs.reduce );
00110 }
00111 
00112 void RunTBBreduce::operator()( const tbb::blocked_range<int> & r )
00113 {
00114   for ( int i = r.begin() ; i < r.end() ; ++i ) {
00115     alg.apply_one( selector , union_parts, * buckets[i] , reduce );
00116   }
00117 }
00118 
00119 RunTBBreduce::RunTBBreduce(
00120   const mesh::Selector    & arg_selector ,
00121   const mesh::PartVector & arg_union_parts ,
00122   const std::vector<mesh::Bucket*> & arg_buckets ,
00123   const AlgorithmInterface         & arg_alg ,
00124   void                              * arg_reduce )
00125   : selector( arg_selector ),
00126     union_parts( arg_union_parts ),
00127     buckets( arg_buckets ),
00128     alg( arg_alg ),
00129     reduce( arg_reduce )
00130 {}
00131 
00132 //----------------------------------------------------------------------
00133 
00134 class AlgorithmRunnerTBB : public AlgorithmRunnerInterface {
00135 public:
00136   AlgorithmRunnerTBB(int nthreads)
00137    : tbb_task_init_(NULL)
00138   {
00139     tbb_task_init_ = new tbb::task_scheduler_init(nthreads);
00140   }
00141 
00142   ~AlgorithmRunnerTBB()
00143   {
00144     delete tbb_task_init_;
00145   }
00146 
00147   void run_alg( const mesh::Selector & selector ,
00148                 const mesh::PartVector & union_parts ,
00149                 const std::vector< mesh::Bucket * > & buckets ,
00150                 const AlgorithmInterface      & alg ,
00151                 void                          * reduce ) const ;
00152 
00153 private:
00154   tbb::task_scheduler_init* tbb_task_init_;
00155 };
00156  
00157 void AlgorithmRunnerTBB::run_alg(
00158   const mesh::Selector & selector ,
00159   const mesh::PartVector & union_parts ,
00160   const std::vector< mesh::Bucket * > & buckets ,
00161   const AlgorithmInterface      & alg ,
00162   void * reduce ) const
00163 {
00164   static tbb::affinity_partitioner ap;
00165 
00166   if ( reduce && ! alg.m_reduce_allocation_size ) {
00167     std::string msg("AlgorithmRunnerTBB: ERROR reduce value with zero size");
00168     throw std::invalid_argument(msg);
00169   }
00170 
00171   if ( ! buckets.empty() ) {
00172 
00173     tbb::blocked_range<int> range( 0 , buckets.size() );
00174 
00175     if ( reduce ) {
00176       RunTBBreduce tmp( selector , union_parts , buckets , alg, reduce );
00177 
00178       tbb::parallel_reduce( range , tmp , ap );
00179       tmp.reduce = NULL ; /* Prevent the tbb::scalable_free( tmp.reduce ); */
00180     }
00181     else {
00182       RunTBB tmp( selector , union_parts , buckets , alg );
00183 
00184       tbb::parallel_for( range, tmp , ap);
00185     }
00186   }
00187 }
00188 
00189 } // namespace
00190 
00191 AlgorithmRunnerInterface * algorithm_runner_tbb( int nthreads )
00192 {
00193   static AlgorithmRunnerTBB runner(nthreads) ;
00194 
00195   return & runner ;
00196 }
00197 
00198 } // namespace stk
00199 
00200 #else
00201 
00202 namespace stk {
00203 
00204 AlgorithmRunnerInterface * algorithm_runner_tbb( int nthreads )
00205 {
00206   return NULL ;
00207 }
00208 
00209 } // namespace stk
00210 
00211 #endif
00212 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends