dune-fem 2.8-git
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
14namespace 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:
44
45#ifdef USE_SMP_PARALLEL
46 int sequence_;
47 std::vector< IteratorType > iterators_;
48 DynamicArray< 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 );
76 for(int thread=0; thread < Fem :: ThreadManager :: maxThreads(); ++thread )
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
202 {
203#ifdef USE_SMP_PARALLEL
204 return iterators_[ ThreadManager :: thread() ];
205#else
206 return gridPart_.template begin< 0, pitype >();
207#endif
208 }
209
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
Definition: bindguard.hh:11
Definition: domainfilter.hh:55
Container for User Specified Parameters.
Definition: io/parameter.hh:191
static ParameterContainer & container()
Definition: io/parameter.hh:193
Thread iterators.
Definition: threaditerator.hh:23
DofManager< GridType > DofManagerType
Definition: threaditerator.hh:35
GridPartType::template Codim< 0 >::EntityType EntityType
Definition: threaditerator.hh:33
const bool verbose_
Definition: threaditerator.hh:55
GridPartType::GridType GridType
Definition: threaditerator.hh:31
static const PartitionIteratorType pitype
Definition: threaditerator.hh:28
int thread(const EntityType &entity) const
return thread number this entity belongs to
Definition: threaditerator.hh:227
GridPartType::IndexSetType IndexSetType
Definition: threaditerator.hh:34
IteratorType end() const
return end iterator for current thread
Definition: threaditerator.hh:211
void update()
update internal list of iterators
Definition: threaditerator.hh:102
void setMasterRatio(const double ratio)
set ratio between master thread and other threads in comp time
Definition: threaditerator.hh:240
DomainFilter< GridPartType > FilterType
Definition: threaditerator.hh:37
const IndexSetType & indexSet_
Definition: threaditerator.hh:43
GridPartType::template Codim< 0 >::template Partition< pitype >::IteratorType IteratorType
Definition: threaditerator.hh:32
const bool communicationThread_
Definition: threaditerator.hh:54
size_t countElements(const Iterator &begin, const Iterator &end) const
Definition: threaditerator.hh:246
GridPart GridPartType
Definition: threaditerator.hh:30
IteratorType begin() const
return begin iterator for current thread
Definition: threaditerator.hh:201
const GridPartType & gridPart_
Definition: threaditerator.hh:41
int index(const EntityType &entity) const
return thread number this entity belongs to
Definition: threaditerator.hh:221
const DofManagerType & dofManager_
Definition: threaditerator.hh:42
ThreadIterator(const GridPartType &gridPart, const ParameterReader &parameter=Parameter::container())
contructor creating thread iterators
Definition: threaditerator.hh:59
Storage of thread iterators.
Definition: threaditerator.hh:281
ThreadIteratorStorage(const GridPart &gridPart)
Definition: threaditerator.hh:284
Storage of thread iterators using domain decomposition.
Definition: threaditeratorstorage.hh:23
Definition: threadmanager.hh:45
static int maxThreads()
return maximal number of threads possbile in the current run
Definition: threadmanager.hh:59
static bool singleThreadMode()
returns true if program is operating on one thread currently
Definition: threadmanager.hh:74
static int thread()
return thread number
Definition: threadmanager.hh:65
Definition: dofmanager.hh:762
size_type size() const
return size of array
Definition: dynamicarray.hh:170
An implementation of DenseVector which uses a C-array of dynamic size as storage.
Definition: dynamicarray.hh:244
void setMemoryFactor(double memFactor)
set memory factor
Definition: dynamicarray.hh:296
void resize(size_type nsize)
Definition: dynamicarray.hh:334