KASKADE 7 development version
localVectors.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2018-2018 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef LOCALVECTORS_HH
14#define LOCALVECTORS_HH
15
16#include <vector>
17#include <mutex>
18
19namespace Kaskade
20{
21
29 template <class Entry, class SortedIdx>
31 {
32 public:
33
34 LocalVector(SortedIdx const& idx, Entry* data_)
35 : idx_(idx), data(data_)
36 {
37 }
38
42 SortedIdx idx() const { return idx_; }
43
47 size_t size() const
48 {
49 return idx().size();
50 }
51
55 void relocate(Entry* newData)
56 {
57 data = newData;
58 }
59
63 Entry& operator[](int idx)
64 {
65 return data[idx];
66 }
67
68 Entry const& operator[](int idx) const
69 {
70 return data[idx];
71 }
72
73 private:
74 SortedIdx idx_;
75
76 // a pointer to the raw storage for the entries
77 Entry* data;
78 };
79
93 template <class Entry, class SortedIdx, class Vector>
95 {
96 public:
98
105 LocalVectors(Vector& globalVector, std::vector<std::mutex> & scatterMutexes_, size_t maxStorage=256*1024)
106 : globalVector(&globalVector), scatterMutexes(&scatterMutexes_)
107 {
108 // Allocate memory as desired. The vector will only grow if there is a local matrix with more entries than defined here.
109 localData.reserve(maxStorage/sizeof(Entry));
110 if(scatterMutexes_.empty())
111 {
112 throw DetailedException("At least one mutex must be given.",__FILE__,__LINE__);
113 }
114 }
115
122 {}
123
130 {
131 scatter();
132 }
133
142 void push_back(SortedIdx const& idx)
143 {
144 size_t size = idx.size();
145
146 // Appending the new vector exceeds the storage capacity. Scatter the existing vectors to their target and
147 // remove them.
148 if (localData.capacity() < localData.size()+size)
149 scatter();
150
151 // Append the new local vector. Note that either the capacity of localData is sufficient, and
152 // the localVectors data pointers remain valid, or the local vectors have been scattered,
153 // such that localVectors is empty and no pointer exists that could be invalidated.
154 Entry* pos = &*localData.insert(localData.end(),size,Entry(0));
155 localVectors.emplace_back(idx,pos);
156 }
157
161 value_type & operator[](int n) { return localVectors[n]; }
162 value_type const& operator[](int n) const { return localVectors[n]; }
163
167 value_type & back() { return localVectors.back(); }
168 value_type const& back() const { return localVectors.back(); }
169
173 size_t size() const { return localVectors.size(); }
174
182 void scatter()
183 {
184 if (localData.empty()) return;
185
186 if (!globalVector)
187 {
188 throw DetailedException("No global vector given to scatter to",__FILE__,__LINE__);
189 }
190
191 // step through all global vector ranges and scatter all the included local vectors' components
192 unsigned n = scatterMutexes->size();
193 for (unsigned ri=0; ri<n; ++ri)
194 {
195 // lock global vector range
196 std::lock_guard<std::mutex> lock((*scatterMutexes)[ri]);
197
198 // step through all local vectors
199 for (auto const& vec : localVectors)
200 {
201 size_t globalStartIdx = uniformWeightRangeStart(ri, n, globalVector->size());
202 size_t globalEndIdx = uniformWeightRangeStart(ri+1, n, globalVector->size());
203
204 for (auto const& glIdx : vec.idx())
205 {
206 // check which rows are inside the global vector range
207 if (glIdx.first >= globalEndIdx) break; // vec.idx() are sorted by global index
208 if (globalStartIdx <= glIdx.first)
209 {
210 (*globalVector)[glIdx.first] += vec[glIdx.second];
211 }
212 }
213 }
214 }
215
216 // everything's scattered - clean up
217 clear();
218 }
219
223 void clear()
224 {
225 localData.clear();
226 localVectors.clear();
227 }
228
232 size_t storageSize() const
233 {
234 return localData.size() * sizeof(Entry);
235 }
236
237 private:
238 // This allows to hold a single array into which the local vectors are scattered, and
239 // thus improves memory locality (for better cache hit rates and less false sharing).
240 // Contains the local vectors one after the other.
241 std::vector<Entry> localData;
242 // Storage for local vectors.
243 std::vector<value_type> localVectors;
244
245 Vector* globalVector = nullptr;
246 std::vector<std::mutex>* scatterMutexes = nullptr;
247 };
248
249}
250
251#endif
A wrapper class for conveniently providing exceptions with context information.
Providing a vector interface for contiguously stored entries.
Definition: localVectors.hh:31
size_t size() const
The number of entries stored.
Definition: localVectors.hh:47
Entry & operator[](int idx)
Access the matrix entries.
Definition: localVectors.hh:63
void relocate(Entry *newData)
Resets the data pointer.
Definition: localVectors.hh:55
LocalVector(SortedIdx const &idx, Entry *data_)
Definition: localVectors.hh:34
Entry const & operator[](int idx) const
Definition: localVectors.hh:68
SortedIdx idx() const
A sequence of indices, sorted ascendingly by global idx.
Definition: localVectors.hh:42
A structure for holding a sequence of several local vectors to be filled sequentially and to be scatt...
Definition: localVectors.hh:95
size_t size() const
The number of local vectors that are stored.
size_t storageSize() const
reports the size of the local vectors storage in bytes
value_type const & operator[](int n) const
value_type & back()
A reference to the last pushed local matrix.
void scatter()
Scatters the local vectors into the global one and removes them from the local container.
LocalVectors()
Default constructor.
value_type const & back() const
void push_back(SortedIdx const &idx)
Appends another (zero-initialized) local vector.
value_type & operator[](int n)
A reference to the n-th local matrix.
LocalVectors(Vector &globalVector, std::vector< std::mutex > &scatterMutexes_, size_t maxStorage=256 *1024)
void clear()
clears all the data, leaving an empty state
~LocalVectors()
Destructor.
Index uniformWeightRangeStart(BlockIndex i, BlockIndex n, Index m)
Computes partitioning points of ranges for uniform weight distributions.
Definition: threading.hh:75
Dune::FieldVector< Scalar, dim > Vector