ls1-MarDyn
ls1-MarDyn molecular dynamics code
AlignedArrayTriplet.h
1/*
2 * AlignedArrayTriplet.h
3 *
4 * Created on: Mar 23, 2016
5 * Author: tchipevn
6 */
7
8#ifndef ALIGNEDARRAYTRIPLET_H
9#define ALIGNEDARRAYTRIPLET_H
10
11#include "AlignedArray.h"
12#include "utils/mardyn_assert.h"
13
14template <class T>
16public:
17 enum class Coordinate { X = 0, Y = 1, Z = 2 };
18
19 AlignedArrayTriplet(size_t initialSize = 0) : AlignedArray<T>(0), _numEntriesPerArray(0) {
21 }
22
23 void prefetch(int hint = 1, int n = -1) const {
24 mardyn_assert(n >= -2);
25
26 int endPrefetch;
27 const int stride = this->_round_up(1);
28
29 switch(n) {
30 case -1:
31 // prefetch all up to capacity()
33 return;
34 break;
35 case -2:
36 // prefetch all up to size()
37 endPrefetch = _numEntriesPerArray;
38 break;
39 default:
40 // prefetch only first n elements
41 endPrefetch = n;
42 }
43
44 for (int i = 0; i < endPrefetch; i+= stride) {
45#if defined(__SSE3__)
46 _mm_prefetch((const char*)&(x(i)), _MM_HINT_T1);
47 _mm_prefetch((const char*)&(y(i)), _MM_HINT_T1);
48 _mm_prefetch((const char*)&(z(i)), _MM_HINT_T1);
49#elif defined(__MIC__)
50 _mm_prefetch((const char*)&(x(i)), 2);
51 _mm_prefetch((const char*)&(y(i)), 2);
52 _mm_prefetch((const char*)&(z(i)), 2);
53#else
54#endif
55 }
56 }
57
58 // TODO: remove ternary operator?
59 T* begin(Coordinate coord) {return _numEntriesPerArray > 0 ? this->_vec.data() + (size_t(coord) * _numEntriesPerArray) : nullptr;}
60 T* xBegin() { return begin(Coordinate::X); }
61 T* yBegin() { return begin(Coordinate::Y); }
62 T* zBegin() { return begin(Coordinate::Z); }
63
64 const T* begin(Coordinate coord) const {return _numEntriesPerArray > 0 ? this->_vec.data() + (size_t(coord) * _numEntriesPerArray) : nullptr;}
65 const T* xBegin() const { return begin(Coordinate::X); }
66 const T* yBegin() const { return begin(Coordinate::Y); }
67 const T* zBegin() const { return begin(Coordinate::Z); }
68
69 T& get(Coordinate coord, size_t i) { mardyn_assert(i < _numEntriesPerArray); return this->_vec[i + size_t(coord) * _numEntriesPerArray]; }
70 T& x(size_t i) { return get(Coordinate::X, i); }
71 T& y(size_t i) { return get(Coordinate::Y, i); }
72 T& z(size_t i) { return get(Coordinate::Z, i); }
73
74 const T& get(Coordinate coord, size_t i) const { mardyn_assert(i < _numEntriesPerArray); return this->_vec[i + size_t(coord) * _numEntriesPerArray]; }
75 const T& x(size_t i) const { return get(Coordinate::X, i); }
76 const T& y(size_t i) const { return get(Coordinate::Y, i); }
77 const T& z(size_t i) const { return get(Coordinate::Z, i); }
78
79 size_t dimensionToOffset(int i) const {
80 mardyn_assert(i >= 0 and i < 3);
81 return i * _numEntriesPerArray;
82 }
83
84 T& linearCrossAccess(size_t i) { mardyn_assert(i < 3*_numEntriesPerArray); return this->_vec[i];}
85
86 size_t resize_zero_shrink(size_t exact_size, bool zero_rest_of_CL = false, bool allow_shrink = false) {
87 size_t size_rounded_up = this->_round_up(exact_size);
88 size_t size_rounded_up_x3 = size_rounded_up * 3;
89 _numEntriesPerArray = size_rounded_up;
90
91 bool need_resize = size_rounded_up_x3 > this->_vec.size() or (allow_shrink and size_rounded_up_x3 < this->_vec.size());
92
93 if (need_resize) {
94 AlignedArray<T>::resize(size_rounded_up_x3);
95 // resize zero-s all
96 } else {
97 // we didn't resize, but we might still need to zero the rest of the Cache Line
98 if (zero_rest_of_CL) {
99 zero(exact_size);
100 }
101 }
102
103 return _numEntriesPerArray;
104 }
105
106 void zero(size_t start_idx) {
107 size_t num_to_zero = this->_round_up(start_idx) - start_idx;
108 if (_numEntriesPerArray > 0 and num_to_zero > 0) {
109 std::memset(&(x(start_idx)), 0, num_to_zero * sizeof(T));
110 std::memset(&(y(start_idx)), 0, num_to_zero * sizeof(T));
111 std::memset(&(z(start_idx)), 0, num_to_zero * sizeof(T));
112 }
113 }
114
118 void resize(size_t nEntriesPerArray) {
119 if (nEntriesPerArray == 0 and _numEntriesPerArray == 0)
120 return;
121
122 // make sure that this is divisible by eight, otherwise we break alignment
123 // get the rounded-up number of entries
124 _numEntriesPerArray = this->_round_up(nEntriesPerArray);
125 AlignedArray<T>::resize(3 * _numEntriesPerArray);
126
127 if (_numEntriesPerArray > nEntriesPerArray) {
128 // set elements from nEntriesPerArray to _numEntriesPerArray to zero:
129 size_t elements = _numEntriesPerArray - nEntriesPerArray;
130 std::memset(&(x(nEntriesPerArray)), 0, elements * sizeof(T));
131 std::memset(&(y(nEntriesPerArray)), 0, elements * sizeof(T));
132 std::memset(&(z(nEntriesPerArray)), 0, elements * sizeof(T));
133 }
134 }
135
136 void increaseStorage(size_t oldNumElements, size_t additionalElements) {
137 mardyn_assert(oldNumElements <= _numEntriesPerArray);
138
139 size_t newNumElements = oldNumElements + additionalElements;
140
141 if (newNumElements <= _numEntriesPerArray) {
142 // no need to resize
143 return;
144 }
145
146 // do we need to keep contents?
147 if (oldNumElements > 0) {
148 // yes
149 AlignedArray<T> backupCopy(*this);
150
151 size_t oldNumEntriesPerArray = _numEntriesPerArray;
152 resize_zero_shrink(newNumElements);
153
154 std::memcpy(xBegin(), &(backupCopy[0*oldNumEntriesPerArray]), oldNumElements * sizeof(T));
155 std::memcpy(yBegin(), &(backupCopy[1*oldNumEntriesPerArray]), oldNumElements * sizeof(T));
156 std::memcpy(zBegin(), &(backupCopy[2*oldNumEntriesPerArray]), oldNumElements * sizeof(T));
157 } else {
158 // no
159 resize_zero_shrink(newNumElements);
160 }
161 }
162
163 void appendValueTriplet(T v0, T v1, T v2, size_t oldNumElements) {
164 mardyn_assert(oldNumElements <= _numEntriesPerArray);
165 if (oldNumElements < _numEntriesPerArray) {
166 // no need to resize, baby
167 } else {
168 increaseStorage(oldNumElements, 1);
169 }
170 x(oldNumElements) = v0;
171 y(oldNumElements) = v1;
172 z(oldNumElements) = v2;
173 }
174
175private:
177 size_t _numEntriesPerArray;
178};
179
180#endif /* ALIGNEDARRAYTRIPLET_H */
181
AlignedArray.h.
Definition: AlignedArrayTriplet.h:15
void resize(size_t nEntriesPerArray)
Reallocate the array. All content may be lost.
Definition: AlignedArrayTriplet.h:118
An aligned array.
Definition: AlignedArray.h:75
virtual void resize(size_t n)
Reallocate the array. All content may be lost.
Definition: AlignedArray.h:192