FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
synch_vec.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
9#include <kernel/util/dist.hpp>
10#include <kernel/util/time_stamp.hpp>
11#include <kernel/util/statistics.hpp>
12#include <kernel/lafem/dense_vector.hpp>
13
14namespace FEAT
15{
16 namespace Global
17 {
25 template <typename VT_, typename VMT_>
27 {
28 public:
31
32 protected:
35
36#if defined(FEAT_HAVE_MPI) || defined(DOXYGEN)
38 VT_* _target;
42 const std::vector<VMT_>* _mirrors;
46 std::vector<BufferType> _send_bufs, _recv_bufs;
47#endif // FEAT_HAVE_MPI || DOXYGEN
48
49 public:
52#if defined(FEAT_HAVE_MPI) || defined(DOXYGEN)
53 _finished(true),
54 _target(nullptr),
55 _comm(nullptr),
56 _mirrors(nullptr),
57 _send_reqs(),
58 _recv_reqs(),
59 _send_bufs(),
60 _recv_bufs()
61#else
62 _finished(true)
63#endif // FEAT_HAVE_MPI || DOXYGEN
64 {
65 }
66
82#if defined(FEAT_HAVE_MPI) || defined(DOXYGEN)
83 SynchVectorTicket(VT_ & target, const Dist::Comm& comm, const std::vector<int>& ranks, const std::vector<VMT_> & mirrors) :
84 _finished(false),
85 _target(&target),
86 _comm(&comm),
87 _mirrors(&mirrors)
88 {
89 TimeStamp ts_start;
90 const std::size_t n = ranks.size();
91
92 XASSERTM(_mirrors->size() == n, "invalid vector mirror count");
93
94 // post receives
95 _recv_reqs.reserve(n);
96 _recv_bufs.resize(n);
97 for(std::size_t i(0); i < n; ++i)
98 {
99 // create buffer vector in main memory
100 _recv_bufs.at(i) = BufferType(_mirrors->at(i).buffer_size(*_target));
101
102 // post receive
103 _recv_reqs.push_back(_comm->irecv(_recv_bufs.at(i).elements(), _recv_bufs.at(i).size(), ranks.at(i)));
104 }
105
106 // post sends
108 _send_bufs.resize(n);
109 for(std::size_t i(0); i < n; ++i)
110 {
111 // create buffer in device memory
112 _send_bufs.at(i) = BufferType(_mirrors->at(i).buffer_size(*_target));
113
114 // gather from mirror
115 _mirrors->at(i).gather(_send_bufs.at(i), *_target);
116
117 // post send
118 _send_reqs.push_back(_comm->isend(_send_bufs.at(i).elements(), _send_bufs.at(i).size(), ranks.at(i)));
119 }
120
121 Statistics::add_time_mpi_execute_blas2(ts_start.elapsed_now());
122 }
123#else // non-MPI version
124 SynchVectorTicket(VT_ &, const Dist::Comm&, const std::vector<int>& ranks, const std::vector<VMT_> &) :
125 _finished(false)
126 {
127 XASSERT(ranks.empty());
128 }
129#endif // FEAT_HAVE_MPI
131 SynchVectorTicket(const SynchVectorTicket &) = delete;
134
137#if defined(FEAT_HAVE_MPI) || defined(DOXYGEN)
138 _finished(other._finished),
139 _target(other._target),
140 _comm(other._comm),
141 _mirrors(other._mirrors),
142 _send_reqs(std::forward<Dist::RequestVector>(other._send_reqs)),
143 _recv_reqs(std::forward<Dist::RequestVector>(other._recv_reqs)),
144 _send_bufs(std::forward<std::vector<BufferType>>(other._send_bufs)),
145 _recv_bufs(std::forward<std::vector<BufferType>>(other._recv_bufs))
146 {
147 other._finished = true;
148 other._comm = nullptr;
149 other._target = nullptr;
150 other._mirrors = nullptr;
151 }
152#else
153 _finished(other._finished)
154 {
155 other._finished = true;
156 }
157#endif // FEAT_HAVE_MPI
158
161 {
162 if(this == &other)
163 return *this;
164
165#if defined(FEAT_HAVE_MPI) || defined(DOXYGEN)
166 _finished = other._finished;
167 _target = other._target;
168 _comm = other._comm;
169 _mirrors = other._mirrors;
170 _send_reqs = std::forward<Dist::RequestVector>(other._send_reqs);
171 _recv_reqs = std::forward<Dist::RequestVector>(other._recv_reqs);
172 _send_bufs = std::forward<std::vector<BufferType>>(other._send_bufs);
173 _recv_bufs = std::forward<std::vector<BufferType>>(other._recv_bufs);
174
175 other._finished = true;
176 other._comm = nullptr;
177 other._target = nullptr;
178 other._mirrors = nullptr;
179#else
180 _finished = other._finished;
181 other._finished = true;
182#endif // FEAT_HAVE_MPI
183
184 return *this;
185 }
186
193 void wait()
194 {
195 XASSERTM(!_finished, "ticket was already completed by a wait call");
196
197#ifdef FEAT_HAVE_MPI
198 TimeStamp ts_start;
199
200 // process all pending receives
201 for(std::size_t idx(0u); _recv_reqs.wait_any(idx); )
202 {
203 // scatter the receive buffer
204 _mirrors->at(idx).scatter_axpy(*_target, _recv_bufs.at(idx));
205 }
206
207 // wait for all sends to finish
209
210 Statistics::add_time_mpi_wait_blas2(ts_start.elapsed_now());
211#endif // FEAT_HAVE_MPI
212
213 _finished = true;
214 }
215
218 {
219 XASSERTM(_finished, "trying to destroy an unfinished SynchVectorTicket");
220 }
221 }; // class SynchVectorTicket
222 } // namespace Global
223} // namespace FEAT
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
FEAT Kernel base header.
Communicator class.
Definition: dist.hpp:1349
Request irecv(void *buffer, std::size_t count, const Datatype &datatype, int source, int tag=0) const
Nonblocking Receive.
Definition: dist.cpp:716
Request isend(const void *buffer, std::size_t count, const Datatype &datatype, int dest, int tag=0) const
Nonblocking Send.
Definition: dist.cpp:704
Communication Request vector class.
Definition: dist.hpp:640
void push_back(Request &&request)
Inserts a new request at the end of the request vector.
Definition: dist.hpp:886
void reserve(std::size_t size_)
Reserves sufficient space for a specified number of requests.
Definition: dist.hpp:813
bool wait_any(std::size_t &idx, Status &status)
Blocks until one of the active requests has been fulfilled.
Definition: dist.cpp:329
void wait_all()
Blocks until all active requests are fulfilled.
Definition: dist.cpp:324
Ticket class for asynchronous global operations on vectors.
Definition: synch_vec.hpp:27
SynchVectorTicket()
default constructor
Definition: synch_vec.hpp:51
const std::vector< VMT_ > * _mirrors
the vector mirrors
Definition: synch_vec.hpp:42
SynchVectorTicket(VT_ &target, const Dist::Comm &comm, const std::vector< int > &ranks, const std::vector< VMT_ > &mirrors)
Constructor.
Definition: synch_vec.hpp:83
VT_ * _target
the vector to be synchronized
Definition: synch_vec.hpp:38
SynchVectorTicket & operator=(SynchVectorTicket &&other)
move-assign operator
Definition: synch_vec.hpp:160
SynchVectorTicket(SynchVectorTicket &&other)
move constructor
Definition: synch_vec.hpp:136
const Dist::Comm * _comm
our communicator
Definition: synch_vec.hpp:40
LAFEM::DenseVector< typename VT_::DataType, typename VT_::IndexType > BufferType
the buffer vector type
Definition: synch_vec.hpp:30
Dist::RequestVector _send_reqs
send and receive request vectors
Definition: synch_vec.hpp:44
SynchVectorTicket & operator=(const SynchVectorTicket &)=delete
Unwanted copy assignment operator: Do not implement!
std::vector< BufferType > _send_bufs
send and receive buffers
Definition: synch_vec.hpp:46
bool _finished
signals, whether wait was already called
Definition: synch_vec.hpp:34
Dense data vector class template.
Time stamp class.
Definition: time_stamp.hpp:54
double elapsed_now() const
Calculates the time elapsed between the time stamp and now.
Definition: time_stamp.hpp:121
FEAT namespace.
Definition: adjactor.hpp:12