Peano 4
Loading...
Searching...
No Matches
GlobalContinuousMemoryPool.cpph
Go to the documentation of this file.
2
4
6
7
8template <class T>
9tarch::logging::Log toolbox::particles::memorypool::GlobalContinuousMemoryPool<T>::_log( "toolbox::particles::memorypool::GlobalContinuousMemoryPool<T>" );
10
11
12template <class T>
14
15
16template <class T>
18 _gatheredDataPointer(nullptr),
19 _globalMemoryPage(UndefinedMemoryPage) {
20}
21
22
23template <class T>
25 if (_gatheredDataPointer!=nullptr and not container.empty()) {
26 logDebug( "scatter()", "scatter " << container.size() << " element(s) from heap" );
27
28 const int oldSize = container.size();
29 container.clear();
30 for (int i=0; i<oldSize; i++) {
31 container.push_back( new T( _gatheredDataPointer[i]) );
32 }
33
34 tarch::freeMemory( _gatheredDataPointer, tarch::MemoryLocation::Heap );
35 _gatheredDataPointer = nullptr;
36 }
37 else if (_globalMemoryPage!=UndefinedMemoryPage and not container.empty()) {
38 logDebug( "scatter()", "scatter " << container.size() << " element(s) from large continuous memory" );
39 assertion1( _globalMemory.pages[ _globalMemoryPage ].used, _globalMemoryPage );
40
41 const int size = _globalMemory.pages[ _globalMemoryPage ].size;
42 const int first = _globalMemory.pages[ _globalMemoryPage ].startIndex;
43
44 logDebug( "scatter()", "page size is " << size << " starting at index " << first );
45
46 container.clear();
47 for (int i=0; i<size; i++) {
48 container.push_back( new T( _globalMemory.data[ first+i ] ) );
49 }
50
51 _globalMemory.freePage( _globalMemoryPage );
52 _globalMemoryPage = UndefinedMemoryPage;
53 }
54}
55
56
57template <class T>
59 container.clear();
60 _gatheredDataPointer = nullptr;
61 _globalMemoryPage = UndefinedMemoryPage;
62}
63
64
65template <class T>
68 assertion( not container.empty() or not isGathered() );
69 if (not isGathered()) {
70 return p;
71 }
72 else if (_gatheredDataPointer!=nullptr) {
73 logDebug( "scatterAndUpdateIterator()", "scatter " << container.size() << " element(s) currently held on heap" );
74
75 Container newContainer;
76 typename Container::iterator result;
77
78 for (auto oldContainerIterator: container) {
79 newContainer.push_back( new T(*oldContainerIterator) );
80 if (oldContainerIterator==*p) {
81 result = newContainer.end();
82 result--;
83 }
84 }
85
86 container.clear();
87 container.splice( container.begin(), newContainer );
88
89 tarch::freeMemory( _gatheredDataPointer, tarch::MemoryLocation::Heap );
90 _gatheredDataPointer = nullptr;
91
92 return result;
93 }
94 else {
95 logDebug( "scatterAndUpdateIterator()", "scatter " << container.size() << " element(s) currently held within page of continuous memory" );
96
97 Container newContainer;
98 typename Container::iterator result;
99
100 for (auto oldContainerIterator: container) {
101 newContainer.push_back( new T(*oldContainerIterator) );
102 if (oldContainerIterator==*p) {
103 result = newContainer.end();
104 result--;
105 }
106 }
107
108 container.clear();
109 container.splice( container.begin(), newContainer );
110
111 _globalMemory.freePage(_globalMemoryPage);
112 _globalMemoryPage = UndefinedMemoryPage;
113
114 return result;
115 }
116}
117
118
119template <class T>
121 assertion( not container.empty() or not isGathered() );
122 if ( not isGathered() and not container.empty()) {
123 logDebug( "gather()", "gather " << container.size() << " element(s)" );
124
125 _globalMemoryPage = _globalMemory.addPage( container.size() );
126
127 if ( _globalMemoryPage==UndefinedMemoryPage) {
128 logDebug( "gather()", "have not been able to book page in continuous memory, so gather " << container.size() << " element(s) on heap" );
129 _gatheredDataPointer = tarch::allocateMemory<T>( container.size(), tarch::MemoryLocation::Heap );
130 int entry = 0;
131 for (auto& p: container) {
132 _gatheredDataPointer[entry] = *p;
133 delete p;
134 entry++;
135 }
136
137 typename Container::iterator p = container.begin();
138 for (int entry=0; entry<container.size(); entry++) {
139 *p = _gatheredDataPointer + entry;
140 p++;
141 }
142 }
143 else {
144 logDebug( "gather()", "gather " << container.size() << " element(s) into page " << _globalMemoryPage );
145
146 const int first = _globalMemory.pages[ _globalMemoryPage ].startIndex;
147
148 int entry = 0;
149 for (auto& p: container) {
150 _globalMemory.data[first+entry] = *p;
151 delete p;
152 entry++;
153 }
154
155 typename Container::iterator p = container.begin();
156 for (int entry=0; entry<container.size(); entry++) {
157 assertion( first+entry<_globalMemory.data.size() );
158 *p = &( _globalMemory.data[first+entry] );
159 p++;
160 }
161 }
162 }
163}
164
165
166template <class T>
168 assertion( not( _gatheredDataPointer!=nullptr and _globalMemoryPage!=UndefinedMemoryPage ));
169 return _gatheredDataPointer!=nullptr or _globalMemoryPage!=UndefinedMemoryPage;
170}
171
172
173template <class T>
174void toolbox::particles::memorypool::GlobalContinuousMemoryPool<T>::replace( typename Container::iterator p, T* newCopy ) {
175 assertion( not container.empty() or _gatheredDataPointer==nullptr );
176 if ( isGathered() ) {
177 (**p) = *newCopy;
178 delete newCopy;
179 }
180 else {
181 container.erase(p);
182 container.push_back(newCopy);
183 }
184}
185
186
187template <class T>
189 data(initialCapacity),
190 pages(),
191 additionalEntriesRequested(0) {
192}
193
194
195template <class T>
197 logTraceInWith1Argument( "addPage(int)", size );
198
199 assertion(size>0);
200
201 tarch::multicore::Lock lock( semaphore );
202
203 int freePage = UndefinedMemoryPage;
204 int currentPage = 0;
205 while (currentPage<pages.size() and freePage!=UndefinedMemoryPage) {
206 if ( not pages[currentPage].used and pages[currentPage].size==size ) {
207 freePage = currentPage;
208 }
209 currentPage++;
210 }
211
212 if ( freePage==UndefinedMemoryPage and totalUsedSize()==0 and size>data.size() ) {
213 logInfo( "addPage(int)", "global memory seems not to be used at all, but is to small to accommodate first page of size " << size << ". Increase capacity to be able accommodate page" );
214 data.resize( size );
215 }
216
217 if ( freePage==UndefinedMemoryPage and totalUsedSize()+size<=data.size() ) {
218 logDebug(
219 "addPage(int)", "global memory had no free page of size " << size <<
220 ". Add new page, as capacity is available (used size=" << totalUsedSize() << " vs capacity=" <<
221 data.size() << ")"
222 );
223 Page newPage;
224 newPage.startIndex = totalUsedSize();
225 newPage.size = size;
226 newPage.used = true;
227
228 pages.push_back( newPage );
229
230 freePage = pages.size()-1;
231 }
232 else {
233 if (additionalEntriesRequested==0) {
234 logInfo(
235 "addPage(int)",
236 "global memory had no free page of size " << size << " and we cannot accommodate an additional page of size " <<
237 size << " (currently used size=" << totalUsedSize() << " vs available capacity of " <<
238 data.size() << "). Will not report on further requests unless global memory space has grown"
239 );
240 }
241 additionalEntriesRequested += size;
242 logDebug( "addPage(int)", "additional-entries-requested=" << additionalEntriesRequested );
243 }
244
245 logTraceOutWith1Argument( "addPage(int)", freePage );
246 return freePage;
247}
248
249
250template <class T>
255
256
257template <class T>
259 assertion1( pageNumber>=0, pageNumber );
260 assertion1( pageNumber<pages.size(), pageNumber );
261
262 tarch::multicore::Lock lock( semaphore );
263
264 pages[pageNumber].used = false;
265
266 while ( not pages.empty() and not pages[pages.size()-1].used ) {
267 pages.pop_back();
268 }
269
270 if (pages.empty() and additionalEntriesRequested>0) {
271 logInfo(
272 "freePage(int)",
273 "global memory is completely empty, so use opportunity to increase total size from " <<
274 data.size() << " to " << ( data.size() + additionalEntriesRequested )
275 );
276 assertion3( data.size() + additionalEntriesRequested <= data.max_size(), data.size(), additionalEntriesRequested, data.max_size() );
277 data.resize( data.size() + additionalEntriesRequested );
278 additionalEntriesRequested = 0;
279 }
280}
281
282
283template <class T>
285 return pages.empty()
286 ? 0
287 : pages[pages.size()-1].startIndex + pages[pages.size()-1].size;
288}
289
#define assertion3(expr, param0, param1, param2)
#define assertion1(expr, param)
#define assertion(expr)
#define logDebug(methodName, logMacroMessageStream)
Definition Log.h:50
#define logTraceOutWith1Argument(methodName, argument0)
Definition Log.h:380
#define logTraceInWith1Argument(methodName, argument0)
Definition Log.h:370
#define logInfo(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:411
Log Device.
Definition Log.h:516
Create a lock around a boolean semaphore region.
Definition Lock.h:19
Memory pool offering continuous global memory for a particle species.
Container::iterator scatterAndUpdateIterator(const typename Container::iterator &p)
void replace(typename Container::iterator p, T *newCopy)
Replace particle.
static GlobalMemory _globalMemory
This class attribute represents the global data space for all of the particles.
void freeMemory(void *data, MemoryLocation location)
@ Heap
Create data on the heap of the local device.
int totalUsedSize() const
Take last page's start index, add its size and you get the result.
int additionalEntriesRequested
Number of entries that we would have liked to have.