|
Sierra Toolkit
Version of the Day
|
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_classic { 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_classic 00199 00200 #else 00201 00202 namespace stk_classic { 00203 00204 AlgorithmRunnerInterface * algorithm_runner_tbb( int nthreads ) 00205 { 00206 return NULL ; 00207 } 00208 00209 } // namespace stk_classic 00210 00211 #endif 00212