dune-fem  2.4.1-rc
threaditerator.hh
Go to the documentation of this file.
1 #ifndef DUNE_FEM_THREADITERATOR_HH
2 #define DUNE_FEM_THREADITERATOR_HH
3 
4 #include <vector>
5 
6 #include <dune/common/exceptions.hh>
7 
13 
14 namespace Dune
15 {
16 
17  namespace Fem
18  {
19 
21  template <class GridPart, PartitionIteratorType ptype = InteriorBorder_Partition >
23  {
25  ThreadIterator& operator= ( const ThreadIterator& );
26  public:
27  // partition type of iterators used
28  static const PartitionIteratorType pitype = ptype ;
29 
30  typedef GridPart GridPartType;
31  typedef typename GridPartType :: GridType GridType;
32  typedef typename GridPartType :: template Codim< 0 > :: template Partition< pitype > :: IteratorType IteratorType ;
33  typedef typename GridPartType :: template Codim< 0 > :: EntityType EntityType ;
34  typedef typename GridPartType :: IndexSetType IndexSetType ;
36 
38 
39 
40  protected:
41  const GridPartType& gridPart_;
42  const DofManagerType& dofManager_;
43  const IndexSetType& indexSet_;
44 
45 #ifdef USE_SMP_PARALLEL
46  int sequence_;
47  std::vector< IteratorType > iterators_;
48  MutableArray< int > threadNum_;
49  std::vector< std::vector< int > > threadId_;
50  std::vector< FilterType* > filters_;
51 #endif
52 
53  // if true, thread 0 does only communication and no computation
55  const bool verbose_ ;
56 
57  public:
59  explicit ThreadIterator( const GridPartType& gridPart, const ParameterReader &parameter = Parameter::container() )
60  : gridPart_( gridPart )
61  , dofManager_( DofManagerType :: instance( gridPart_.grid() ) )
62  , indexSet_( gridPart_.indexSet() )
63 #ifdef USE_SMP_PARALLEL
64  , sequence_( -1 )
65  , iterators_( ThreadManager::maxThreads() + 1 , gridPart_.template end< 0, pitype >() )
66  , threadId_( ThreadManager::maxThreads() )
67 #endif
68  , communicationThread_( parameter.getValue<bool>("fem.threads.communicationthread", false)
69  && Fem :: ThreadManager :: maxThreads() > 1 ) // only possible if maxThreads > 1
70  , verbose_( Parameter::verbose() &&
71  parameter.getValue<bool>("fem.threads.verbose", false ) )
72  {
73 #ifdef USE_SMP_PARALLEL
74  threadNum_.setMemoryFactor( 1.1 );
75  filters_.resize( Fem :: ThreadManager :: maxThreads(), (FilterType *) 0 );
77  {
78  filters_[ thread ] = new FilterType( gridPart_, threadNum_, thread );
79  }
80 #endif
81  update();
82  }
83 
84 #ifdef USE_SMP_PARALLEL
86  {
87  for(size_t i = 0; i<filters_.size(); ++i )
88  {
89  delete filters_[ i ];
90  }
91  }
92 
94  const FilterType& filter( const unsigned int thread ) const
95  {
96  assert( thread < filters_.size() );
97  return *(filters_[ thread ]);
98  }
99 #endif
100 
102  void update()
103  {
104 #ifdef USE_SMP_PARALLEL
105  const int sequence = gridPart_.sequence();
106  // if grid got updated also update iterators
107  if( sequence_ != sequence )
108  {
110  {
111  std::cerr << "Don't call ThreadIterator::update in a parallel environment!" << std::endl;
112  assert( false );
113  abort();
114  }
115 
116  const size_t maxThreads = ThreadManager :: maxThreads() ;
117 
118  // get end iterator
119  const IteratorType endit = gridPart_.template end< 0, pitype >();
120  IteratorType it = gridPart_.template begin< 0, pitype >();
121  if( it == endit )
122  {
123  // set all iterators to end iterators
124  for( size_t thread = 0; thread <= maxThreads; ++thread )
125  iterators_[ thread ] = endit ;
126 
127  // free memory here
128  threadNum_.resize( 0 );
129 
130  // update sequence number
131  sequence_ = sequence;
132  return ;
133  }
134 
135  // thread 0 starts at begin
136  iterators_[ 0 ] = it ;
137 
138  // get size for index set (this only works well when pitype == All_Partition)
139  // otherwise element have to be counted
140  const size_t iterSize = countElements( it, endit );
141  const size_t size = indexSet_.size( 0 );
142 
143  // resize threads storage
144  threadNum_.resize( size );
145  // set all values to default value
146  for(size_t i = 0; i<size; ++i) threadNum_[ i ] = -1;
147 
148  // here use iterator to count
149  size_t checkSize = 0;
150  const size_t roundOff = (iterSize % maxThreads);
151  const size_t counterBase = ((size_t) iterSize / maxThreads );
152 
153  // just for diagnostics
154  std::vector< int > nElems( maxThreads, 0 );
155 
156  for( size_t thread = 1; thread <= maxThreads; ++thread )
157  {
158  size_t i = 0;
159  const size_t counter = counterBase + (( (thread-1) < roundOff ) ? 1 : 0);
160  nElems[ thread-1 ] = counter ;
161  checkSize += counter ;
162  //std::cout << counter << " for thread " << thread-1 << std::endl;
163  while( (i < counter) && (it != endit) )
164  {
165  const EntityType &entity = *it;
166  assert( std::size_t( indexSet_.index( entity ) ) < std::size_t( threadNum_.size() ) );
167  threadNum_[ indexSet_.index( entity ) ] = thread - 1;
168  ++i;
169  ++it;
170  }
171  iterators_[ thread ] = it ;
172  }
173  iterators_[ maxThreads ] = endit ;
174 
175  if( checkSize != iterSize )
176  {
177  assert( checkSize == iterSize );
178  DUNE_THROW(InvalidStateException,"Partitioning inconsistent!");
179  }
180 
181  // update sequence number
182  sequence_ = sequence;
183 
184  if( verbose_ )
185  {
186  std::cout << "ThreadIterator: sequence = " << sequence_ << " size = " << checkSize << std::endl;
187  const size_t counterSize = nElems.size();
188  for(size_t i = 0; i<counterSize; ++i )
189  std::cout << "ThreadIterator: T[" << i << "] = " << nElems[ i ] << std::endl;
190  }
191 
192  checkConsistency( iterSize );
193 
194  //for(size_t i = 0; i<size; ++i )
195  // std::cout << threadNum_[ i ] << std::endl;
196  }
197 #endif
198  }
199 
201  IteratorType begin() const
202  {
203 #ifdef USE_SMP_PARALLEL
204  return iterators_[ ThreadManager :: thread() ];
205 #else
206  return gridPart_.template begin< 0, pitype >();
207 #endif
208  }
209 
211  IteratorType end() const
212  {
213 #ifdef USE_SMP_PARALLEL
214  return iterators_[ ThreadManager :: thread() + 1 ];
215 #else
216  return gridPart_.template end< 0, pitype >();
217 #endif
218  }
219 
221  int index( const EntityType& entity ) const
222  {
223  return indexSet_.index( entity );
224  }
225 
227  int thread( const EntityType& entity ) const
228  {
229 #ifdef USE_SMP_PARALLEL
230  assert( std::size_t( threadNum_.size() ) > std::size_t( indexSet_.index( entity ) ) );
231  // NOTE: this number can also be negative for ghost elements or elements
232  // that do not belong to the set covered by the space iterators
233  return threadNum_[ indexSet_.index( entity ) ];
234 #else
235  return 0;
236 #endif
237  }
238 
240  void setMasterRatio( const double ratio )
241  {
242  }
243 
244  protected:
245  template < class Iterator >
246  size_t countElements( const Iterator& begin, const Iterator& end ) const
247  {
248  size_t count = 0;
249  for( Iterator it = begin; it != end; ++ it )
250  ++count ;
251  return count ;
252  }
253 
254 #ifdef USE_SMP_PARALLEL
255  // check that we have a non-overlapping iterator decomposition
256  void checkConsistency( const size_t totalElements )
257  {
258 #ifndef NDEBUG
259  const int maxThreads = ThreadManager :: maxThreads() ;
260  std::set< int > indices ;
261  for( int thread = 0; thread < maxThreads; ++ thread )
262  {
263  const IteratorType end = iterators_[ thread+1 ];
264  for( IteratorType it = iterators_[ thread ]; it != end; ++it )
265  {
266  const int idx = gridPart_.indexSet().index( *it );
267  assert( indices.find( idx ) == indices.end() ) ;
268  indices.insert( idx );
269  }
270  }
271  assert( indices.size() == totalElements );
272 #endif
273  }
274 #endif
275  };
276 
278  template <class GridPart, PartitionIteratorType pitype = InteriorBorder_Partition >
280  : public ThreadIteratorStorageBase< ThreadIterator< GridPart, pitype > >
281  {
283  public:
284  ThreadIteratorStorage( const GridPart& gridPart )
285  : BaseType( gridPart )
286  {}
287  };
288 
289  } // namespace Fem
290 
291 } // namespace Dune
292 
293 #endif // #ifndef DUNE_FEM_THREADITERATOR_HH
int thread(const EntityType &entity) const
return thread number this entity belongs to
Definition: threaditerator.hh:227
size_t size() const
return number of enties of array
Definition: arrays.hh:213
Thread iterators.
Definition: threaditerator.hh:22
Container for User Specified Parameters.
Definition: io/parameter.hh:187
int index(const EntityType &entity) const
return thread number this entity belongs to
Definition: threaditerator.hh:221
static const PartitionIteratorType pitype
Definition: threaditerator.hh:28
ThreadFilter< GridPartType > FilterType
Definition: threaditerator.hh:37
ThreadIteratorStorage(const GridPart &gridPart)
Definition: threaditerator.hh:284
ThreadIterator(const GridPartType &gridPart, const ParameterReader &parameter=Parameter::container())
contructor creating thread iterators
Definition: threaditerator.hh:59
void resize(size_t nsize)
Definition: arrays.hh:491
The ThreadManager wrapps basic shared memory functionality provided by OpenMP or pthreads such as thr...
Definition: threadmanager.hh:199
Definition: arrays.hh:36
Definition: datacollector.hh:45
const bool verbose_
Definition: threaditerator.hh:55
IteratorType end() const
return end iterator for current thread
Definition: threaditerator.hh:211
GridPartType::template Codim< 0 >::EntityType EntityType
Definition: threaditerator.hh:33
static int thread()
return thread number
Definition: threadmanager.hh:208
size_t countElements(const Iterator &begin, const Iterator &end) const
Definition: threaditerator.hh:246
const IndexSetType & indexSet_
Definition: threaditerator.hh:43
Definition: coordinate.hh:4
IteratorType begin() const
return begin iterator for current thread
Definition: threaditerator.hh:201
Storage of thread iterators using domain decomposition.
Definition: threaditeratorstorage.hh:23
void update()
update internal list of iterators
Definition: threaditerator.hh:102
const bool communicationThread_
Definition: threaditerator.hh:54
GridPartType::template Codim< 0 >::template Partition< pitype >::IteratorType IteratorType
Definition: threaditerator.hh:32
static ParameterContainer & container()
Definition: io/parameter.hh:190
DofManager< GridType > DofManagerType
Definition: threaditerator.hh:35
void setMemoryFactor(const double memFactor)
set memory factor
Definition: arrays.hh:465
GridPartType::GridType GridType
Definition: threaditerator.hh:31
Definition: threadfilter.hh:20
static int maxThreads()
return maximal number of threads possbile in the current run
Definition: threadmanager.hh:202
void setMasterRatio(const double ratio)
set ratio between master thread and other threads in comp time
Definition: threaditerator.hh:240
Storage of thread iterators.
Definition: threaditerator.hh:279
GridPartType::IndexSetType IndexSetType
Definition: threaditerator.hh:34
const DofManagerType & dofManager_
Definition: threaditerator.hh:42
static bool singleThreadMode()
returns true if program is operating on one thread currently
Definition: threadmanager.hh:217
const GridPartType & gridPart_
Definition: threaditerator.hh:41
GridPart GridPartType
Definition: threaditerator.hh:30