8#ifndef UTILS_CONCATENATEDALIGNEDARRAYRMM_H_
9#define UTILS_CONCATENATEDALIGNEDARRAYRMM_H_
15template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
18 enum class Quantity_t { RX = 0, RY = 1, RZ = 2, VX = 3, VY = 4, VZ = 5, UID = 6};
21 mardyn_assert(
sizeof(real_calc_t) <=
sizeof(uid_t));
25 void prefetchForForce()
const;
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);
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;
41 void zero(
size_t start_idx = 0);
46 void resize(
size_t nEntriesPerArray);
48 void increaseStorage(
size_t oldNumElements,
size_t additionalElements);
50 void appendValues(std::array<real_calc_t, 3> calcs, std::array<real_accum_t, 3> accums, uid_t uid,
size_t oldNumElements);
52 size_t get_dynamic_memory()
const {
53 return _byteBuffer.get_dynamic_memory();
57 typedef unsigned char byte_t;
58 byte_t* begin(Quantity_t coord);
59 const byte_t* begin(Quantity_t coord)
const;
64 size_t _numEntriesPerArray;
67template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
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;
80template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
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;
93template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
95 mardyn_assert(coord < Quantity_t::VX);
96 byte_t * ret = begin(coord);
97 return reinterpret_cast<real_calc_t*
>(ret);
100template <
typename real_calc_t,
typename real_accum_t,
typename u
id_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);
107template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
109 mardyn_assert(coord == Quantity_t::UID);
110 byte_t * ret = begin(coord);
111 return reinterpret_cast<uid_t*
>(ret);
114template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
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];
124template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
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];
134template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
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];
144template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
146 mardyn_assert(coord < Quantity_t::VX);
147 const byte_t * ret = begin(coord);
148 return reinterpret_cast<const real_calc_t*
>(ret);
151template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
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);
158template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
160 mardyn_assert(coord == Quantity_t::UID);
161 const byte_t * ret = begin(coord);
162 return reinterpret_cast<const uid_t*
>(ret);
165template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
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];
175template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
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];
185template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
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];
195template <
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
198 if (nEntriesPerArray == 0 and _numEntriesPerArray == 0)
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;
206 _byteBuffer.resize(totalNumBytes);
208 if (_numEntriesPerArray > nEntriesPerArray) {
209 zero(nEntriesPerArray);
213template<
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
215 if (start_idx == 0) {
216 _byteBuffer.zero(start_idx);
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));
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));
233 size_t startIndex = begin(Quantity_t::UID) - begin(Quantity_t::RX) + start_idx *
sizeof(uid_t);
234 _byteBuffer.zero(startIndex);
238template<
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
240 mardyn_assert(oldNumElements <= _numEntriesPerArray);
242 size_t newNumElements = oldNumElements + additionalElements;
244 if (newNumElements <= _numEntriesPerArray) {
250 if (oldNumElements > 0) {
254 size_t oldNumEntriesPerArray = _numEntriesPerArray;
255 resize(newNumElements);
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));
263 std::memcpy(begin(Quantity_t::UID), &(backupCopy[6*oldNumEntriesPerArray*
sizeof(real_calc_t)]), oldNumElements *
sizeof(uid_t));
266 resize(newNumElements);
270template<
typename real_calc_t,
typename real_accum_t,
typename u
id_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) {
277 increaseStorage(oldNumElements, 1);
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;
288template<
typename real_calc_t,
typename real_accum_t,
typename u
id_t>
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);
295 for (
const byte_t * p = b; p < e; p += stride) {
297 _mm_prefetch(
reinterpret_cast<const char*
>(p), _MM_HINT_T1);
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