iterative-solver 0.0
 
Loading...
Searching...
No Matches
BufferManager.h
1#ifndef ITERATIVE_SOLVER_BUFFERMANAGER_H
2#define ITERATIVE_SOLVER_BUFFERMANAGER_H
3
4#include <future>
5#include <molpro/linalg/array/DistrArray.h>
6#include <molpro/linalg/array/util/Distribution.h>
7#include <vector>
8
10
19template <class T>
21 using VecRef = std::vector<std::reference_wrapper<T>>;
22 using CVecRef = std::vector<std::reference_wrapper<const T>>;
23 auto cwrap(const std::vector<T>& arrays) {
24 CVecRef w;
25 for (auto it = arrays.begin(); it != arrays.end(); ++it)
26 w.emplace_back(std::cref(*it));
27 return w;
28 }
29
30public:
39 BufferManager(const CVecRef& arrays, size_t buffer_size = 8192, int number_of_buffers = 2)
40 : m_arrays(arrays), m_buffer_size(buffer_size), m_number_of_buffers(number_of_buffers),
41 m_range(arrays.empty() ? std::pair<typename T::index_type, typename T::index_type>{0, 0}
42 : arrays.front().get().distribution().range(rank_in(arrays.front().get()))),
43 m_buffer(arrays.size() * number_of_buffers * buffer_size) {
44 assert(number_of_buffers > 0 && number_of_buffers < 3);
45 }
46
48 static int rank_in(const T& array) {
49 if (array.communicator() == molpro::mpi::comm_global())
50 return molpro::mpi::rank_global();
51 int rank = 0;
52#ifdef HAVE_MPI_H
53 MPI_Comm_rank(array.communicator(), &rank);
54#endif
55 return rank;
56 }
57
58 BufferManager(const std::vector<T>& arrays, size_t buffer_size = 8192, int number_of_buffers = 2)
59 : BufferManager(cwrap(arrays), buffer_size, number_of_buffers) {}
60 BufferManager(const T& array, size_t buffer_size = 8192, int number_of_buffers = 2)
61 : BufferManager(CVecRef{std::cref(array)}, buffer_size, number_of_buffers) {}
62
67 size_t buffer_size() const { return m_current_buffer_size; }
72 size_t buffer_stride() const { return m_buffer_size; }
77 size_t buffer_offset() const { return m_current_segment * m_buffer_size; }
78
79protected:
80 using value_type = typename T::value_type;
81 // Stored by value, not reference: the convenience constructors below
82 // delegate using temporaries (cwrap(arrays), CVecRef{std::cref(array)})
83 // that would dangle once the delegating call returns.
84 const CVecRef m_arrays; // the DistrArray objects data is being accessed from
85 const size_t m_buffer_size = 8192;
86 const int m_number_of_buffers = 2;
88
89public:
94 struct Iterator {
95 // iterator properties
96 using iterator_category = std::forward_iterator_tag;
97 using difference_type = std::ptrdiff_t;
101
109 Iterator(BufferManager& manager, bool begin = false, bool end = false)
110 : m_manager(manager), m_value(end ? value_type(nullptr, 0) : manager.next(begin)) {}
111
112 // iterator operators
113 reference operator*() const { return m_value; }
114
115 pointer operator->() { return &m_value; }
116
118 m_value = m_manager.next();
119 return *this;
120 }
121
123 Iterator tmp = *this;
124 ++(*this);
125 return tmp;
126 }
127
128 friend bool operator==(const Iterator& a, const Iterator& b) {
129 return (a.m_value.size() == b.m_value.size() and b.m_value.size() == 0) // special for end of file
130 or a.m_value.data() == b.m_value.data();
131 };
132
133 friend bool operator!=(const Iterator& a, const Iterator& b) { return not(a == b); };
134
135 private:
136 BufferManager& m_manager; // BufferManager object containing buffers
137 value_type m_value; // iterator value
138 };
139
140 [[nodiscard]] Iterator begin() { return Iterator(*this, true); }
141
142 [[nodiscard]] Iterator end() { return Iterator(*this, false, true); }
143
144protected:
150 [[nodiscard]] Span<value_type> next(bool initial = false) {
151 if (initial)
153 else
155 const auto buffer_id = m_current_segment % m_number_of_buffers;
156 const auto lo = m_range.first + m_current_segment * this->m_buffer_size;
157 if (lo >= m_range.second)
158 return Span<BufferManager::value_type>(nullptr, 0);
159 const auto hi = std::min(lo + this->m_buffer_size, m_range.second);
160 m_current_buffer_size = hi - lo;
161 {
162 if (m_number_of_buffers == 1 or lo == m_range.first) {
163 for (size_t iarray = 0; iarray < m_arrays.size(); ++iarray) {
164 assert(hi > lo);
165 assert(buffer_id * m_buffer_size * m_arrays.size() + iarray * m_buffer_size + hi - lo <= m_buffer.size());
166 m_arrays[iarray].get().get(
167 lo, hi, &m_buffer.at(buffer_id * m_buffer_size * m_arrays.size() + iarray * m_buffer_size));
168 }
169 } else {
170 m_read_future.wait();
171 }
172 }
173
174 const auto next_buffer_id = (m_current_segment + 1) % m_number_of_buffers;
175 const auto next_lo = m_range.first + (m_current_segment + 1) * this->m_buffer_size;
176 const auto next_hi = std::min(next_lo + this->m_buffer_size, m_range.second);
177 if (m_number_of_buffers > 1 and next_lo < m_range.second) {
178 m_read_future = std::async(std::launch::async, [this, next_lo, next_hi, next_buffer_id]() {
179 for (size_t iarray = 0; iarray < m_arrays.size(); ++iarray)
180 m_arrays[iarray].get().get(
181 next_lo, next_hi,
182 &m_buffer.at(next_buffer_id * m_buffer_size * m_arrays.size() + iarray * m_buffer_size));
183 });
184 }
185
186 return Span<value_type>(&m_buffer.at(buffer_id * m_buffer_size * m_arrays.size()), m_buffer_size * m_arrays.size());
187 }
188
189 size_t m_current_segment = 0; // current chunk
190 const std::pair<size_t, size_t>
191 m_range; // memory offsets for MPI found via distr_array_disk.distribution().range(...)
192 std::vector<typename T::value_type> m_buffer;
193 std::future<void> m_read_future;
194};
195
196} // namespace molpro::linalg::array::util
197
198#endif // ITERATIVE_SOLVER_BUFFERMANAGER_H
Non-owning container taking a pointer to the data buffer and its size and exposing routines for itera...
Definition Span.h:31
size_type size() const
Definition Span.h:77
iterator data()
Definition Span.h:66
BufferManager provides single-buffered or asynchronous double-buffered read access to the data in a c...
Definition BufferManager.h:20
const CVecRef m_arrays
Definition BufferManager.h:84
size_t buffer_offset() const
Definition BufferManager.h:77
static int rank_in(const T &array)
This process's rank in the array's own communicator, which need not be the global one.
Definition BufferManager.h:48
typename T::value_type value_type
Definition BufferManager.h:80
size_t m_current_segment
Definition BufferManager.h:189
const std::pair< size_t, size_t > m_range
Definition BufferManager.h:191
size_t buffer_size() const
Definition BufferManager.h:67
size_t buffer_stride() const
Definition BufferManager.h:72
Iterator end()
Definition BufferManager.h:142
BufferManager(const std::vector< T > &arrays, size_t buffer_size=8192, int number_of_buffers=2)
Definition BufferManager.h:58
Span< value_type > next(bool initial=false)
Move to the next segment of the arrays and complete loading of the buffer.
Definition BufferManager.h:150
size_t m_current_buffer_size
Definition BufferManager.h:87
const size_t m_buffer_size
Definition BufferManager.h:85
BufferManager(const CVecRef &arrays, size_t buffer_size=8192, int number_of_buffers=2)
Construct a new Buffer Manager object and allocate memory for the chunks.
Definition BufferManager.h:39
BufferManager(const T &array, size_t buffer_size=8192, int number_of_buffers=2)
Definition BufferManager.h:60
Iterator begin()
Definition BufferManager.h:140
std::future< void > m_read_future
Definition BufferManager.h:193
const int m_number_of_buffers
Definition BufferManager.h:86
std::vector< typename T::value_type > m_buffer
Definition BufferManager.h:192
Definition ArrayHandler.h:24
Custom iterator for the BufferManager. This iterator is responsible for loading data into the buffers...
Definition BufferManager.h:94
std::forward_iterator_tag iterator_category
Definition BufferManager.h:96
pointer operator->()
Definition BufferManager.h:115
friend bool operator!=(const Iterator &a, const Iterator &b)
Definition BufferManager.h:133
std::ptrdiff_t difference_type
Definition BufferManager.h:97
Iterator & operator++()
Definition BufferManager.h:117
Iterator(BufferManager &manager, bool begin=false, bool end=false)
Construct a new Iterator object.
Definition BufferManager.h:109
Iterator operator++(int)
Definition BufferManager.h:122
reference operator*() const
Definition BufferManager.h:113
friend bool operator==(const Iterator &a, const Iterator &b)
Definition BufferManager.h:128