ls1-MarDyn
ls1-MarDyn molecular dynamics code
ConcatenatedAlignedArrayRMM.h
1/*
2 * ConcatenatedAlignedArrayRMM.h
3 *
4 * Created on: Sep 30, 2017
5 * Author: tchipevn
6 */
7
8#ifndef UTILS_CONCATENATEDALIGNEDARRAYRMM_H_
9#define UTILS_CONCATENATEDALIGNEDARRAYRMM_H_
10
11#include <utils/AlignedArray.h>
13#include <array>
14
15template <typename real_calc_t, typename real_accum_t, typename uid_t>
17public:
18 enum class Quantity_t { RX = 0, RY = 1, RZ = 2, VX = 3, VY = 4, VZ = 5, UID = 6};
19
20 ConcatenatedAlignedArrayRMM(size_t initialSize = 0) : _byteBuffer(0), _numEntriesPerArray(0) {
21 mardyn_assert(sizeof(real_calc_t) <= sizeof(uid_t));
23 }
24
25 void prefetchForForce() const;
26
27 real_calc_t* begin_calc(Quantity_t coord);
28 real_accum_t* begin_accum(Quantity_t coord);
29 uid_t* begin_uid(Quantity_t coord);
30 real_calc_t& get_calc(Quantity_t coord, size_t i);
31 real_accum_t& get_accum(Quantity_t coord, size_t i);
32 uid_t& get_uid(Quantity_t coord, size_t i);
33
34 const real_calc_t* begin_calc(Quantity_t coord) const;
35 const real_accum_t* begin_accum(Quantity_t coord) const;
36 const uid_t* begin_uid(Quantity_t coord) const;
37 const real_calc_t& get_calc(Quantity_t coord, size_t i) const;
38 const real_accum_t& get_accum(Quantity_t coord, size_t i) const;
39 const uid_t& get_uid(Quantity_t coord, size_t i) const;
40
41 void zero(size_t start_idx = 0);
42
46 void resize(size_t nEntriesPerArray);
47
48 void increaseStorage(size_t oldNumElements, size_t additionalElements);
49
50 void appendValues(std::array<real_calc_t, 3> calcs, std::array<real_accum_t, 3> accums, uid_t uid, size_t oldNumElements);
51
52 size_t get_dynamic_memory() const {
53 return _byteBuffer.get_dynamic_memory();
54 }
55
56private:
57 typedef unsigned char byte_t;
58 byte_t* begin(Quantity_t coord);
59 const byte_t* begin(Quantity_t coord) const;
60
62
64 size_t _numEntriesPerArray;
65};
66
67template <typename real_calc_t, typename real_accum_t, typename uid_t>
68inline typename ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::byte_t* ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::begin(Quantity_t coord) {
69 byte_t * rx = _byteBuffer;
70 byte_t * ry = rx + _numEntriesPerArray * sizeof(real_calc_t);
71 byte_t * rz = ry + _numEntriesPerArray * sizeof(real_calc_t);
72 byte_t * vx = rz + _numEntriesPerArray * sizeof(real_calc_t);
73 byte_t * vy = vx + _numEntriesPerArray * sizeof(real_accum_t);
74 byte_t * vz = vy + _numEntriesPerArray * sizeof(real_accum_t);
75 byte_t * uid = vz + _numEntriesPerArray * sizeof(real_accum_t);
76 byte_t * starts[7] = {rx, ry, rz, vx, vy, vz, uid};
77 return _numEntriesPerArray > 0 ? starts[size_t(coord)] : nullptr;
78}
79
80template <typename real_calc_t, typename real_accum_t, typename uid_t>
81inline const typename ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::byte_t* ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::begin(Quantity_t coord) const {
82 const byte_t * rx = _byteBuffer;
83 const byte_t * ry = rx + _numEntriesPerArray * sizeof(real_calc_t);
84 const byte_t * rz = ry + _numEntriesPerArray * sizeof(real_calc_t);
85 const byte_t * vx = rz + _numEntriesPerArray * sizeof(real_calc_t);
86 const byte_t * vy = vx + _numEntriesPerArray * sizeof(real_accum_t);
87 const byte_t * vz = vy + _numEntriesPerArray * sizeof(real_accum_t);
88 const byte_t * uid = vz + _numEntriesPerArray * sizeof(real_accum_t);
89 const byte_t * starts[7] = {rx, ry, rz, vx, vy, vz, uid};
90 return _numEntriesPerArray > 0 ? starts[size_t(coord)] : nullptr;
91}
92
93template <typename real_calc_t, typename real_accum_t, typename uid_t>
95 mardyn_assert(coord < Quantity_t::VX);
96 byte_t * ret = begin(coord);
97 return reinterpret_cast<real_calc_t*>(ret);
98}
99
100template <typename real_calc_t, typename real_accum_t, typename uid_t>
102 mardyn_assert(coord >= Quantity_t::VX and coord < Quantity_t::UID);
103 byte_t * ret = begin(coord);
104 return reinterpret_cast<real_accum_t*>(ret);
105}
106
107template <typename real_calc_t, typename real_accum_t, typename uid_t>
109 mardyn_assert(coord == Quantity_t::UID);
110 byte_t * ret = begin(coord);
111 return reinterpret_cast<uid_t*>(ret);
112}
113
114template <typename real_calc_t, typename real_accum_t, typename uid_t>
115inline real_calc_t& ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::get_calc(Quantity_t coord, size_t i) {
116 mardyn_assert(coord < Quantity_t::VX);
117 mardyn_assert(i < _numEntriesPerArray);
118 byte_t * startByte = begin(coord);
119 real_calc_t * startReal = reinterpret_cast<real_calc_t*>(startByte);
120 real_calc_t & ret = startReal[i];
121 return ret;
122}
123
124template <typename real_calc_t, typename real_accum_t, typename uid_t>
125inline real_accum_t& ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::get_accum(Quantity_t coord, size_t i) {
126 mardyn_assert(coord >= Quantity_t::VX and coord < Quantity_t::UID);
127 mardyn_assert(i < _numEntriesPerArray);
128 byte_t * startByte = begin(coord);
129 real_accum_t * startReal = reinterpret_cast<real_accum_t*>(startByte);
130 real_accum_t & ret = startReal[i];
131 return ret;
132}
133
134template <typename real_calc_t, typename real_accum_t, typename uid_t>
135inline uid_t& ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::get_uid(Quantity_t coord, size_t i) {
136 mardyn_assert(coord == Quantity_t::UID);
137 mardyn_assert(i < _numEntriesPerArray);
138 byte_t * startByte = begin(coord);
139 uid_t * startUID = reinterpret_cast<uid_t*>(startByte);
140 uid_t & ret = startUID[i];
141 return ret;
142}
143
144template <typename real_calc_t, typename real_accum_t, typename uid_t>
145inline const real_calc_t* ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::begin_calc(Quantity_t coord) const {
146 mardyn_assert(coord < Quantity_t::VX);
147 const byte_t * ret = begin(coord);
148 return reinterpret_cast<const real_calc_t*>(ret);
149}
150
151template <typename real_calc_t, typename real_accum_t, typename uid_t>
152inline const real_accum_t* ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::begin_accum(Quantity_t coord) const {
153 mardyn_assert(coord >= Quantity_t::VX and coord < Quantity_t::UID);
154 const byte_t * ret = begin(coord);
155 return reinterpret_cast<const real_accum_t*>(ret);
156}
157
158template <typename real_calc_t, typename real_accum_t, typename uid_t>
159inline const uid_t* ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::begin_uid(Quantity_t coord) const {
160 mardyn_assert(coord == Quantity_t::UID);
161 const byte_t * ret = begin(coord);
162 return reinterpret_cast<const uid_t*>(ret);
163}
164
165template <typename real_calc_t, typename real_accum_t, typename uid_t>
166inline const real_calc_t& ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::get_calc(Quantity_t coord, size_t i) const {
167 mardyn_assert(coord < Quantity_t::VX);
168 mardyn_assert(i < _numEntriesPerArray);
169 const byte_t * startByte = begin(coord);
170 const real_calc_t * startReal = reinterpret_cast<const real_calc_t*>(startByte);
171 const real_calc_t & ret = startReal[i];
172 return ret;
173}
174
175template <typename real_calc_t, typename real_accum_t, typename uid_t>
176inline const real_accum_t& ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::get_accum(Quantity_t coord, size_t i) const {
177 mardyn_assert(coord >= Quantity_t::VX and coord < Quantity_t::UID);
178 mardyn_assert(i < _numEntriesPerArray);
179 const byte_t * startByte = begin(coord);
180 const real_accum_t * startReal = reinterpret_cast<const real_accum_t*>(startByte);
181 const real_accum_t & ret = startReal[i];
182 return ret;
183}
184
185template <typename real_calc_t, typename real_accum_t, typename uid_t>
186inline const uid_t& ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::get_uid(Quantity_t coord, size_t i) const {
187 mardyn_assert(coord == Quantity_t::UID);
188 mardyn_assert(i < _numEntriesPerArray);
189 const byte_t * startByte = begin(coord);
190 const uid_t * startUID = reinterpret_cast<const uid_t*>(startByte);
191 const uid_t & ret = startUID[i];
192 return ret;
193}
194
195template <typename real_calc_t, typename real_accum_t, typename uid_t>
197
198 if (nEntriesPerArray == 0 and _numEntriesPerArray == 0)
199 return;
200
201 _numEntriesPerArray = AlignedArray<real_calc_t, VCP_ALIGNMENT>::_round_up(nEntriesPerArray);
202 size_t numBytesForReals = 3 * _numEntriesPerArray * (sizeof(real_calc_t) + sizeof(real_accum_t));
203 size_t numBytesForUID = _numEntriesPerArray * sizeof(uid_t);
204 size_t totalNumBytes = numBytesForReals + numBytesForUID;
205
206 _byteBuffer.resize(totalNumBytes);
207
208 if (_numEntriesPerArray > nEntriesPerArray) {
209 zero(nEntriesPerArray);
210 }
211}
212
213template<typename real_calc_t, typename real_accum_t, typename uid_t>
215 if (start_idx == 0) {
216 _byteBuffer.zero(start_idx);
217 return;
218 }
219 size_t num_to_zero = _numEntriesPerArray - start_idx;
220 if (_numEntriesPerArray > 0 and num_to_zero > 0) {
221 const int qbegin = static_cast<int>(Quantity_t::RX);
222 const int qmid = static_cast<int>(Quantity_t::VX);
223 const int qend = static_cast<int>(Quantity_t::UID);
224 for (int i = qbegin; i < qmid; ++i) {
225 Quantity_t q = static_cast<Quantity_t>(i);
226 std::memset(&(get_calc(q,start_idx)), 0, num_to_zero * sizeof(real_calc_t));
227 }
228 for (int i = qmid; i < qend; ++i) {
229 Quantity_t q = static_cast<Quantity_t>(i);
230 std::memset(&(get_accum(q,start_idx)), 0, num_to_zero * sizeof(real_accum_t));
231 }
232
233 size_t startIndex = begin(Quantity_t::UID) - begin(Quantity_t::RX) + start_idx * sizeof(uid_t);
234 _byteBuffer.zero(startIndex);
235 }
236}
237
238template<typename real_calc_t, typename real_accum_t, typename uid_t>
239inline void ConcatenatedAlignedArrayRMM<real_calc_t, real_accum_t, uid_t>::increaseStorage(size_t oldNumElements, size_t additionalElements) {
240 mardyn_assert(oldNumElements <= _numEntriesPerArray);
241
242 size_t newNumElements = oldNumElements + additionalElements;
243
244 if (newNumElements <= _numEntriesPerArray) {
245 // no need to resize
246 return;
247 }
248
249 // do we need to keep contents?
250 if (oldNumElements > 0) {
251 // yes
252 AlignedArray<byte_t, CACHE_LINE_SIZE> backupCopy(_byteBuffer);
253
254 size_t oldNumEntriesPerArray = _numEntriesPerArray;
255 resize(newNumElements);
256
257 const int qbegin = static_cast<int>(Quantity_t::RX);
258 const int qend = static_cast<int>(Quantity_t::UID);
259 for (int i = qbegin; i < qend; ++i) {
260 Quantity_t q = static_cast<Quantity_t>(i);
261 std::memcpy(begin(q), &(backupCopy[i*oldNumEntriesPerArray*sizeof(real_calc_t)]), oldNumElements * sizeof(real_calc_t));
262 }
263 std::memcpy(begin(Quantity_t::UID), &(backupCopy[6*oldNumEntriesPerArray*sizeof(real_calc_t)]), oldNumElements * sizeof(uid_t));
264 } else {
265 // no
266 resize(newNumElements);
267 }
268}
269
270template<typename real_calc_t, typename real_accum_t, typename uid_t>
272 std::array<real_calc_t, 3> calcs, std::array<real_accum_t, 3> accums, uid_t uid, size_t oldNumElements) {
273 mardyn_assert(oldNumElements <= _numEntriesPerArray);
274 if (oldNumElements < _numEntriesPerArray) {
275 // no need to resize, baby
276 } else {
277 increaseStorage(oldNumElements, 1);
278 }
279 get_calc(Quantity_t::RX, oldNumElements) = calcs[0];
280 get_calc(Quantity_t::RY, oldNumElements) = calcs[1];
281 get_calc(Quantity_t::RZ, oldNumElements) = calcs[2];
282 get_accum(Quantity_t::VX, oldNumElements) = accums[0];
283 get_accum(Quantity_t::VY, oldNumElements) = accums[1];
284 get_accum(Quantity_t::VZ, oldNumElements) = accums[2];
285 get_uid(Quantity_t::UID, oldNumElements) = uid;
286}
287
288template<typename real_calc_t, typename real_accum_t, typename uid_t>
290 // prefetch all up to uid begin
291 const byte_t * b = begin(Quantity_t::RX);
292 const byte_t * e = begin(Quantity_t::UID);
293 const size_t stride = CACHE_LINE_SIZE / sizeof(byte_t);
294
295 for (const byte_t * p = b; p < e; p += stride) {
296#if defined(__SSE3__)
297 _mm_prefetch(reinterpret_cast<const char*>(p), _MM_HINT_T1);
298#else
299#endif
300 }
301}
302
303#endif /* UTILS_CONCATENATEDALIGNEDARRAYRMM_H_ */
AlignedArray.h.
Defines the length of the vectors and the corresponding functions.
An aligned array.
Definition: AlignedArray.h:75
Definition: ConcatenatedAlignedArrayRMM.h:16
void resize(size_t nEntriesPerArray)
Reallocate the array. All content may be lost.
Definition: ConcatenatedAlignedArrayRMM.h:196