DUNE-FEM (unstable)

threaditerator.hh
1#ifndef DUNE_FEM_THREADITERATOR_HH
2#define DUNE_FEM_THREADITERATOR_HH
3
4#include <vector>
5
7
8#include <dune/fem/gridpart/filter/domainfilter.hh>
9#include <dune/fem/misc/threads/threaditeratorstorage.hh>
10#include <dune/fem/space/common/dofmanager.hh>
11#include <dune/fem/storage/dynamicarray.hh>
12
14
15namespace Dune
16{
17
18 namespace Fem
19 {
20
22 template <class GridPart, PartitionIteratorType ptype = InteriorBorder_Partition >
24 {
26 ThreadIterator& operator= ( const ThreadIterator& );
27 public:
28 // partition type of iterators used
29 static const PartitionIteratorType pitype = ptype ;
30
31 typedef GridPart GridPartType;
32 typedef typename GridPartType :: GridType GridType;
33 typedef typename GridPartType :: template Codim< 0 > :: template Partition< pitype > :: IteratorType IteratorType ;
34 typedef typename GridPartType :: template Codim< 0 > :: EntityType EntityType ;
35 typedef typename GridPartType :: IndexSetType IndexSetType ;
37
38 typedef DomainFilter<GridPartType> FilterType;
39
40
41 protected:
42 const GridPartType& gridPart_;
43 const DofManagerType& dofManager_;
44 const IndexSetType& indexSet_;
45
46 int sequence_;
47 int numThreads_;
48
49 std::vector< IteratorType > iterators_;
50 DynamicArray< int > threadNum_;
51 std::vector< std::vector< int > > threadId_;
52 std::vector< std::unique_ptr< FilterType > > filters_;
53
54 // if true, thread 0 does only communication and no computation
55 const bool communicationThread_;
56 const bool verbose_ ;
57
58 public:
60 explicit ThreadIterator( const GridPartType& gridPart, const ParameterReader &parameter = Parameter::container() )
61 : gridPart_( gridPart )
62 , dofManager_( DofManagerType :: instance( gridPart_.grid() ) )
63 , indexSet_( gridPart_.indexSet() )
64 , sequence_( -1 )
65 , numThreads_( MPIManager::numThreads() )
66 , iterators_( MPIManager::maxThreads() + 1 , gridPart_.template end< 0, pitype >() )
67 , threadId_( MPIManager::maxThreads() )
68 , filters_( MPIManager::maxThreads() )
69 , communicationThread_( parameter.getValue<bool>("fem.threads.communicationthread", false)
70 && Fem :: MPIManager :: maxThreads() > 1 ) // only possible if maxThreads > 1
71 , verbose_( Parameter::verbose() &&
72 parameter.getValue<bool>("fem.threads.verbose", false ) )
73 {
74 threadNum_.setMemoryFactor( 1.1 );
75 for(int thread=0; thread < Fem :: MPIManager :: maxThreads(); ++thread )
76 {
77 filters_[ thread ].reset( new FilterType( gridPart_, threadNum_, thread ) );
78 }
79 update();
80 }
81
83 const FilterType& filter( const unsigned int thread ) const
84 {
85 assert( thread < filters_.size() );
86 return *(filters_[ thread ]);
87 }
88
90 void update()
91 {
92 const int sequence = dofManager_.sequence();
93 // if grid got updated also update iterators
94 if( sequence_ != sequence || numThreads_ != MPIManager :: numThreads() )
95 {
96 if( ! MPIManager :: singleThreadMode() )
97 {
98 std::cerr << "Don't call ThreadIterator::update in a parallel environment!" << std::endl;
99 assert( false );
100 abort();
101 }
102
103 // update currently used thread numbers
104 numThreads_ = MPIManager :: numThreads() ;
105 // check that grid is viewThreadSafe otherwise weird bugs can occur
106 if( (numThreads_ > 1) && (! Dune::Capabilities::viewThreadSafe< GridType >:: v) )
107 {
108 DUNE_THROW(InvalidStateException,"ThreadIterator needs a grid with viewThreadSafe capability!");
109 }
110
111 const size_t numThreads = numThreads_;
112
113 // get end iterator
114 const IteratorType endit = gridPart_.template end< 0, pitype >();
115
116 // pass default value to resize to initialize all iterators
117 iterators_.resize( numThreads+1, endit );
118
119 IteratorType it = gridPart_.template begin< 0, pitype >();
120 if( it == endit )
121 {
122 // set all iterators to end iterators
123 for( size_t thread = 0; thread <= numThreads; ++thread )
124 iterators_[ thread ] = endit ;
125
126 // free memory here
127 threadNum_.resize( 0 );
128
129 // update sequence number
130 sequence_ = sequence;
131 return ;
132 }
133
134 // thread 0 starts at begin
135 iterators_[ 0 ] = it ;
136
137 // get size for index set (this only works well when pitype == All_Partition)
138 // otherwise element have to be counted
139 const size_t iterSize = countElements( it, endit );
140 const size_t size = indexSet_.size( 0 );
141
142 // resize threads storage
143 threadNum_.resize( size );
144 // set all values to default value
145 for(size_t i = 0; i<size; ++i) threadNum_[ i ] = -1;
146
147 // here use iterator to count
148 size_t checkSize = 0;
149 const size_t roundOff = (iterSize % numThreads);
150 const size_t counterBase = ((size_t) iterSize / numThreads );
151
152 // just for diagnostics
153 std::vector< int > nElems( numThreads, 0 );
154
155 for( size_t thread = 1; thread <= numThreads; ++thread )
156 {
157 size_t i = 0;
158 const size_t counter = counterBase + (( (thread-1) < roundOff ) ? 1 : 0);
159 nElems[ thread-1 ] = counter ;
160 checkSize += counter ;
161 //std::cout << counter << " for thread " << thread-1 << std::endl;
162 while( (i < counter) && (it != endit) )
163 {
164 const EntityType &entity = *it;
165 assert( std::size_t( indexSet_.index( entity ) ) < std::size_t( threadNum_.size() ) );
166 threadNum_[ indexSet_.index( entity ) ] = thread - 1;
167 ++i;
168 ++it;
169 }
170 iterators_[ thread ] = it ;
171 }
172 iterators_[ numThreads ] = endit ;
173
174 if( checkSize != iterSize )
175 {
176 assert( checkSize == iterSize );
177 DUNE_THROW(InvalidStateException,"Partitioning inconsistent!");
178 }
179
180 // update sequence number
181 sequence_ = sequence;
182
183 if( verbose_ )
184 {
185 std::cout << "ThreadIterator: sequence = " << sequence_ << " size = " << checkSize << std::endl;
186 const size_t counterSize = nElems.size();
187 for(size_t i = 0; i<counterSize; ++i )
188 std::cout << "ThreadIterator: T[" << i << "] = " << nElems[ i ] << std::endl;
189 }
190
191 checkConsistency( iterSize );
192
193 //for(size_t i = 0; i<size; ++i )
194 // std::cout << threadNum_[ i ] << std::endl;
195 }
196 }
197
199 IteratorType begin() const
200 {
201 if( MPIManager :: singleThreadMode() )
202 {
203 return gridPart_.template begin< 0, pitype >();
204 }
205 // in multi thread mode return iterators for each thread
206 else
207 {
208 assert( MPIManager :: thread() < numThreads_ );
209 return iterators_[ MPIManager :: thread() ];
210 }
211 }
212 IteratorType begin(int thread) const
213 {
214 return iterators_[ thread ];
215 }
216
218 IteratorType end() const
219 {
220 if( MPIManager :: singleThreadMode() )
221 {
222 return gridPart_.template end< 0, pitype >();
223 }
224 // in multi thread mode return iterators for each thread
225 else
226 {
227 assert( MPIManager :: thread() < numThreads_ );
228 return iterators_[ MPIManager :: thread() + 1 ];
229 }
230 }
231 IteratorType end(int thread) const
232 {
233 return iterators_[ thread + 1 ];
234 }
235
237 int index( const EntityType& entity ) const
238 {
239 return indexSet_.index( entity );
240 }
241
242 int threadParallel( const EntityType& entity ) const
243 {
244 assert( std::size_t( threadNum_.size() ) > std::size_t( indexSet_.index( entity ) ) );
245 // NOTE: this number can also be negative for ghost elements or elements
246 // that do not belong to the set covered by the space iterators
247 return threadNum_[ indexSet_.index( entity ) ];
248 }
250 int thread( const EntityType& entity ) const
251 {
252 if( MPIManager::singleThreadMode() )
253 return 0;
254 else
255 return threadParallel(entity);
256 }
257
259 void setMasterRatio( const double ratio )
260 {
261 }
262
263 protected:
264 template < class Iterator >
265 size_t countElements( const Iterator& begin, const Iterator& end ) const
266 {
267 size_t count = 0;
268 for( Iterator it = begin; it != end; ++ it )
269 ++count ;
270 return count ;
271 }
272
273 // check that we have a non-overlapping iterator decomposition
274 void checkConsistency( const size_t totalElements )
275 {
276#ifndef NDEBUG
277 const int numThreads = MPIManager :: numThreads() ;
278 std::set< int > indices ;
279 for( int thread = 0; thread < numThreads; ++ thread )
280 {
281 const IteratorType end = iterators_[ thread+1 ];
282 for( IteratorType it = iterators_[ thread ]; it != end; ++it )
283 {
284 const int idx = gridPart_.indexSet().index( *it );
285 assert( indices.find( idx ) == indices.end() ) ;
286 indices.insert( idx );
287 }
288 }
289 assert( indices.size() == totalElements );
290#endif
291 }
292 };
293
295 template <class GridPart, PartitionIteratorType pitype = InteriorBorder_Partition >
297 : public ThreadIteratorStorageBase< ThreadIterator< GridPart, pitype > >
298 {
300 public:
301 ThreadIteratorStorage( const GridPart& gridPart )
302 : BaseType( gridPart )
303 {}
304 };
305
306 } // namespace Fem
307
308} // namespace Dune
309
310#endif // #ifndef DUNE_FEM_THREADITERATOR_HH
Definition: dofmanager.hh:786
void setMemoryFactor(double memFactor)
set memory factor
Definition: dynamicarray.hh:296
void resize(size_type nsize)
Definition: dynamicarray.hh:334
Container for User Specified Parameters.
Definition: parameter.hh:191
size_type size() const
return size of array
Definition: dynamicarray.hh:170
Storage of thread iterators using domain decomposition.
Definition: threaditeratorstorage.hh:22
Storage of thread iterators.
Definition: threaditerator.hh:298
Thread iterators.
Definition: threaditerator.hh:24
int thread(const EntityType &entity) const
return thread number this entity belongs to
Definition: threaditerator.hh:250
IteratorType end() const
return end iterator for current thread
Definition: threaditerator.hh:218
void update()
update internal list of iterators
Definition: threaditerator.hh:90
void setMasterRatio(const double ratio)
set ratio between master thread and other threads in comp time
Definition: threaditerator.hh:259
IteratorType begin() const
return begin iterator for current thread
Definition: threaditerator.hh:199
const FilterType & filter(const unsigned int thread) const
return filter for given thread
Definition: threaditerator.hh:83
int index(const EntityType &entity) const
return thread number this entity belongs to
Definition: threaditerator.hh:237
ThreadIterator(const GridPartType &gridPart, const ParameterReader &parameter=Parameter::container())
contructor creating thread iterators
Definition: threaditerator.hh:60
Default exception if a function was called while the object is not in a valid state for that function...
Definition: exceptions.hh:281
A few common exception classes.
A set of traits classes to store static information about grid implementation.
int sequence() const
return number of sequence, if dofmanagers memory was changed by calling some method like resize,...
Definition: dofmanager.hh:1007
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
PartitionIteratorType
Parameter to be used for the parallel level- and leaf iterators.
Definition: gridenums.hh:136
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
Specialize with 'true' if the grid implementation is thread safe, while it is not modified....
Definition: capabilities.hh:169
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 24, 22:29, 2024)