FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
muxer.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
10#include <kernel/util/dist.hpp>
11#include <kernel/lafem/dense_vector.hpp>
12
13#include <vector>
14
15namespace FEAT
16{
17 namespace Global
18 {
66 template<typename LocalVector_, typename Mirror_>
67 class Muxer
68 {
69 public:
71 typedef typename LocalVector_::DataType DataType;
73 typedef typename LocalVector_::IndexType IndexType;
75 typedef LocalVector_ LocalVectorType;
77 typedef Mirror_ MirrorType;
80
82 template <typename LocalVector2_, typename Mirror2_>
84
86 template <typename DataType2_, typename IndexType2_>
88 typename LocalVector_::template ContainerType<DataType2_, IndexType2_>,
89 typename Mirror_::template MirrorType<DataType2_, IndexType2_> >;
90
91 public:
94
97
100
103
105 std::vector<Mirror_> _child_mirrors;
106
107 public:
110 _sibling_comm(nullptr),
111 _parent_rank(-1),
112 _buffer_size(0),
115 {
116 }
117
119 Muxer(Muxer&& other) :
123 _parent_mirror(std::forward<Mirror_>(other._parent_mirror)),
124 _child_mirrors(std::forward<std::vector<Mirror_>>(other._child_mirrors))
125 {
126 }
127
129 virtual ~Muxer()
130 {
131 }
132
135 {
136 if(this == &other)
137 return *this;
138
139 _sibling_comm = other._sibling_comm;
140 _parent_rank = other._parent_rank;
141 _buffer_size = other._buffer_size;
142 _parent_mirror = std::forward<Mirror_>(other._parent_mirror);
143 _child_mirrors = std::forward<std::vector<Mirror_>>(other._child_mirrors);
144
145 return *this;
146 }
147
154 template<typename LVT2_, typename MT2_>
155 void convert(const Muxer<LVT2_, MT2_>& other)
156 {
157 if((void*)this == (void*)&other)
158 return;
159
160 this->_sibling_comm = other._sibling_comm;
161 this->_parent_rank = other._parent_rank;
162 this->_buffer_size = other._buffer_size;
163 this->_parent_mirror.convert(other._parent_mirror);
164
165 this->_child_mirrors.resize(other._child_mirrors.size());
166 for(std::size_t i(0); i < other._child_mirrors.size(); ++i)
167 {
168 this->_child_mirrors.at(i).convert(other._child_mirrors.at(i));
169 }
170 }
171
187 template<typename LVT2_>
188 void convert(const Muxer<LVT2_, Mirror_>& other, LocalVector_&& vector, LAFEM::CloneMode mode = LAFEM::CloneMode::Shallow)
189 {
190 if((void*)this == (void*)&other)
191 return;
192
193 this->_sibling_comm = other._sibling_comm;
194 this->_parent_rank = other._parent_rank;
195 this->_buffer_size = Index(0); // will be rebuild by compile function
196 this->_parent_mirror.clone(other._parent_mirror, mode);
197
198 this->_child_mirrors.clear();
199 this->_child_mirrors.resize(other._child_mirrors.size());
200
201 for(std::size_t i(0); i < other._child_mirrors.size(); ++i)
202 {
203 this->_child_mirrors.at(i).clone(other._child_mirrors.at(i), mode);
204 }
205
206 // compile this muxer
207 compile(std::forward<LocalVector_>(vector));
208 }
209
211 std::size_t bytes() const
212 {
213 std::size_t b = _parent_mirror.bytes();
214 for(const auto& cm : _child_mirrors)
215 b += cm.bytes();
216 return b;
217 }
218
225 bool is_child() const
226 {
227 return (_sibling_comm != nullptr) && (_sibling_comm->size() > 0);
228 }
229
236 bool is_parent() const
237 {
238 return (_sibling_comm != nullptr) && (_sibling_comm->rank() == _parent_rank);
239 }
240
250 bool is_ghost() const
251 {
252 return is_child() && (!is_parent());
253 }
254
261 {
262 return _sibling_comm;
263 }
264
277 void set_parent(const Dist::Comm* sibling_comm_, int parent_rank, Mirror_&& parent_mirror)
278 {
279 _sibling_comm = sibling_comm_;
280 XASSERT(_sibling_comm != nullptr);
281 XASSERT(parent_rank >= 0);
282 XASSERT(parent_rank < _sibling_comm->size());
283 _parent_rank = parent_rank;
284 _parent_mirror = std::forward<Mirror_>(parent_mirror);
285 }
286
292 int get_parent_rank() const
293 {
294 return _parent_rank;
295 }
296
302 const Mirror_& get_parent_mirror() const
303 {
304 return _parent_mirror;
305 }
306
313 void push_child(Mirror_&& child_mirror)
314 {
315 _child_mirrors.push_back(std::forward<Mirror_>(child_mirror));
316 }
317
323 const std::vector<Mirror_>& get_child_mirrors() const
324 {
325 return _child_mirrors;
326 }
327
334 void compile(const LocalVector_& vec_tmp_)
335 {
336 if(!is_child())
337 return; // nothing to
338
339 XASSERT(_sibling_comm != nullptr);
340 XASSERT(_parent_rank >= 0);
341 XASSERT(_parent_rank < _sibling_comm->size());
342
343 Index bufsize(0);
344
345 // Is this the parent?
347 {
348 // loop over all child buffers and compute the largest buffer size
349 for(const auto& cm : _child_mirrors)
350 {
351 bufsize = Math::max(bufsize, cm.buffer_size(vec_tmp_));
352 }
353 }
354
355 // broadcast buffer size to all siblings
356 _sibling_comm->bcast(&bufsize, std::size_t(1), _parent_rank);
357
358 // verify against length of parent buffer
359 XASSERT(bufsize >= _parent_mirror.buffer_size(vec_tmp_));
360
361 // store buffer size
362 this->_buffer_size = bufsize;
363 }
364
375 void join_send(const LocalVector_& vec_src) const
376 {
377 XASSERT(_sibling_comm != nullptr);
378 XASSERT(_sibling_comm->size() > 1);
379 XASSERT(_sibling_comm->rank() != _parent_rank); // parent must call join() instead
380
381 // create parent buffer in device memory
382 BufferType parent_buffer(_buffer_size);
383
384 // gather source to parent buffer
385 _parent_mirror.gather(parent_buffer, vec_src);
386
387 // gather to parent sibling
388 DataType* dummy = nullptr;
389 _sibling_comm->gather(parent_buffer.elements(), _buffer_size, dummy, std::size_t(0), _parent_rank);
390 }
391
401 void join(const LocalVector_& vec_src, LocalVector_& vec_trg) const
402 {
403 // if this muxer is not a child, then this operation is a simple copy
404 if((_sibling_comm == nullptr) || (_sibling_comm->size() <= 1))
405 {
406 vec_trg.copy(vec_src);
407 return;
408 }
409
410 XASSERT(_sibling_comm != nullptr);
411 XASSERT(_sibling_comm->size() > 0);
413
414 const Index num_children = Index(_child_mirrors.size());
415
416 // allocate parent buffer
417 BufferType parent_buffer(_buffer_size);
418
419 // gather source to parent buffer
420 _parent_mirror.gather(parent_buffer, vec_src);
421
422 // allocate child buffers
423 BufferType child_buffers(_buffer_size * num_children);
424
425 // gather from siblings
426 _sibling_comm->gather(parent_buffer.elements(), _buffer_size, child_buffers.elements(), _buffer_size, _parent_rank);
427
428 // format target vector
429 vec_trg.format();
430
431 // scatter child buffers into target vector
432 for(Index i(0); i < num_children; ++i)
433 {
434 // scatter buffers
435 _child_mirrors.at(i).scatter_axpy(vec_trg, child_buffers, DataType(1), i*_buffer_size);
436 }
437 }
438
449 void split_recv(LocalVector_& vec_trg) const
450 {
451 XASSERT(_sibling_comm != nullptr);
452 XASSERT(_sibling_comm->size() > 1);
453 XASSERT(_sibling_comm->rank() != _parent_rank); // parent must call split() instead
454
455 // allocate parent buffer
456 BufferType parent_buffer(_buffer_size);
457
458 // receive scatter from parent sibling
459 DataType* dummy = nullptr;
460 _sibling_comm->scatter(dummy, std::size_t(0), parent_buffer.elements(), _buffer_size, _parent_rank);
461
462 // scatter into target vector
463 vec_trg.format();
464 _parent_mirror.scatter_axpy(vec_trg, parent_buffer);
465 }
466
476 void split(LocalVector_& vec_trg, const LocalVector_& vec_src) const
477 {
478 // if this muxer is not a child, then this operation is a simple copy
479 if((_sibling_comm == nullptr) || (_sibling_comm->size() <= 1))
480 {
481 vec_trg.copy(vec_src);
482 return;
483 }
484
485 XASSERT(_sibling_comm != nullptr);
486 XASSERT(_sibling_comm->size() > 0);
488
489 TimeStamp ts_execute;
490
491 const Index num_children = Index(_child_mirrors.size());
492
493 // allocate child buffers
494 BufferType child_buffers(_buffer_size * num_children);
495
496 // gather child buffers from target vector
497 for(Index i(0); i < num_children; ++i)
498 {
499 _child_mirrors.at(i).gather(child_buffers, vec_src, i*_buffer_size);
500 }
501
502 // create parent buffer
503 BufferType parent_buffer(_buffer_size);
504
505 // scatter to siblings
506 _sibling_comm->scatter(child_buffers.elements(), _buffer_size, parent_buffer.elements(), _buffer_size, _parent_rank);
507
508 // scatter into target vector
509 vec_trg.format();
510 _parent_mirror.scatter_axpy(vec_trg, parent_buffer);
511 }
512 }; // class Muxer<...>
513 } // namespace Global
514} // namespace FEAT
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
FEAT Kernel base header.
Communicator class.
Definition: dist.hpp:1349
void scatter(const void *sendbuf, std::size_t sendcount, const Datatype &sendtype, void *recvbuf, std::size_t recvcount, const Datatype &recvtype, int root) const
Blocking scatter.
Definition: dist.cpp:571
void bcast(void *buffer, std::size_t count, const Datatype &datatype, int root) const
Blocking broadcast.
Definition: dist.cpp:541
int size() const
Returns the size of this communicator.
Definition: dist.hpp:1506
void gather(const void *sendbuf, std::size_t sendcount, const Datatype &sendtype, void *recvbuf, std::size_t recvcount, const Datatype &recvtype, int root) const
Blocking gather.
Definition: dist.cpp:553
int rank() const
Returns the rank of this process in this communicator.
Definition: dist.hpp:1494
Global multiplexer/demultiplexer implementation.
Definition: muxer.hpp:68
Muxer(Muxer &&other)
move-constructor
Definition: muxer.hpp:119
LocalVector_::IndexType IndexType
the index type
Definition: muxer.hpp:73
bool is_child() const
Specifies whether this process represents a child in the muxer.
Definition: muxer.hpp:225
std::size_t bytes() const
Returns the internal data size in bytes.
Definition: muxer.hpp:211
void join_send(const LocalVector_ &vec_src) const
Sends a join operation to the parent process.
Definition: muxer.hpp:375
Mirror_ _parent_mirror
parent mirror (on all children)
Definition: muxer.hpp:102
std::vector< Mirror_ > _child_mirrors
child mirrors (only on parent)
Definition: muxer.hpp:105
Mirror_ MirrorType
the mirror type
Definition: muxer.hpp:77
void compile(const LocalVector_ &vec_tmp_)
Compiles the muxer.
Definition: muxer.hpp:334
Index _buffer_size
buffer size
Definition: muxer.hpp:99
bool is_ghost() const
Specifies whether this process is a ghost in the muxer.
Definition: muxer.hpp:250
void convert(const Muxer< LVT2_, MT2_ > &other)
Conversion function for same vector container type but with different MDI-Type.
Definition: muxer.hpp:155
Muxer()
standard constructor
Definition: muxer.hpp:109
LocalVector_::DataType DataType
the data type
Definition: muxer.hpp:71
virtual ~Muxer()
virtual destructor
Definition: muxer.hpp:129
const Mirror_ & get_parent_mirror() const
Returns the parent mirror.
Definition: muxer.hpp:302
Muxer & operator=(Muxer &&other)
move-assignment operator
Definition: muxer.hpp:134
const Dist::Comm * get_sibling_comm() const
Returns the sibling communicator.
Definition: muxer.hpp:260
bool is_parent() const
Specifies whether this process represents a parent in the muxer.
Definition: muxer.hpp:236
void convert(const Muxer< LVT2_, Mirror_ > &other, LocalVector_ &&vector, LAFEM::CloneMode mode=LAFEM::CloneMode::Shallow)
Conversion function for different vector container type.
Definition: muxer.hpp:188
void split_recv(LocalVector_ &vec_trg) const
Receives a split operation from the parent process.
Definition: muxer.hpp:449
int _parent_rank
the rank of the parent
Definition: muxer.hpp:96
void join(const LocalVector_ &vec_src, LocalVector_ &vec_trg) const
Performs a join operation on the parent process.
Definition: muxer.hpp:401
LocalVector_ LocalVectorType
the local vector type
Definition: muxer.hpp:75
const Dist::Comm * _sibling_comm
the sibling communicator
Definition: muxer.hpp:93
void push_child(Mirror_ &&child_mirror)
Adds a child rank and mirror for a parent process.
Definition: muxer.hpp:313
int get_parent_rank() const
Returns the parent rank.
Definition: muxer.hpp:292
void set_parent(const Dist::Comm *sibling_comm_, int parent_rank, Mirror_ &&parent_mirror)
Sets the sibling communicator.
Definition: muxer.hpp:277
const std::vector< Mirror_ > & get_child_mirrors() const
Returns the child mirror vector.
Definition: muxer.hpp:323
void split(LocalVector_ &vec_trg, const LocalVector_ &vec_src) const
Performs a split operation on the parent process.
Definition: muxer.hpp:476
LAFEM::DenseVector< DataType, IndexType > BufferType
the internal buffer vector type
Definition: muxer.hpp:79
Dense data vector class template.
DT_ * elements()
Get a pointer to the data array.
Time stamp class.
Definition: time_stamp.hpp:54
T_ max(T_ a, T_ b)
Returns the maximum of two values.
Definition: math.hpp:137
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.