CoDiPack  2.3.0
A Code Differentiation Package
SciComp TU Kaiserslautern
Loading...
Searching...
No Matches
reuseIndexManagerBase.hpp
1/*
2 * CoDiPack, a Code Differentiation Package
3 *
4 * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau
5 * Homepage: http://scicomp.rptu.de
6 * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de)
7 *
8 * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau)
9 *
10 * This file is part of CoDiPack (http://scicomp.rptu.de/software/codi).
11 *
12 * CoDiPack is free software: you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * CoDiPack is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty
19 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * See the GNU General Public License for more details.
22 * You should have received a copy of the GNU
23 * General Public License along with CoDiPack.
24 * If not, see <http://www.gnu.org/licenses/>.
25 *
26 * For other licensing options please contact us.
27 *
28 * Authors:
29 * - SciComp, University of Kaiserslautern-Landau:
30 * - Max Sagebaum
31 * - Johannes Blühdorn
32 * - Former members:
33 * - Tim Albring
34 */
35#pragma once
36
37#include <algorithm>
38#include <vector>
39
40#include "../../config.h"
41#include "../../misc/macros.hpp"
42#include "../../misc/mathUtility.hpp"
43#include "../data/emptyData.hpp"
44#include "indexManagerInterface.hpp"
46namespace codi {
47
65 template<typename T_Index, typename T_Impl>
66 struct ReuseIndexManagerBase : public IndexManagerInterface<T_Index>, public EmptyData {
67 public:
68
69 using Index = CODI_DD(T_Index, int);
70 using Impl = CODI_DD(T_Impl, CODI_IMPLEMENTATION);
72
74
75 /*******************************************************************************/
78
79 static bool constexpr CopyNeedsStatement = true;
80 static bool constexpr IsLinear = false;
81 static bool constexpr NeedsStaticStorage = true;
82
84
85 protected:
86
87 std::vector<Index> usedIndices;
89
90 std::vector<Index> unusedIndices;
92
94
95 bool valid;
96
97 private:
98 /*******************************************************************************/
101
103 CODI_INLINE Impl& cast() {
104 return static_cast<Impl&>(*this);
105 }
106
108 CODI_INLINE Impl const& cast() const {
109 return static_cast<Impl const&>(*this);
110 }
111
113 CODI_NO_INLINE void generateNewIndices() {
114 cast().generateNewIndices();
115 }
116
118
119 public:
120
124 : usedIndices(),
128 indexSizeIncrement(Config::SmallChunkSize),
129 valid(true) {
130 increaseIndicesSize(unusedIndices);
131 }
132
135 valid = false;
136 }
137
138 /*******************************************************************************/
141
143 template<typename Tape>
145 bool generatedNewIndex = false;
146
147 if (Base::InactiveIndex == index) {
148 if (0 == usedIndicesPos) {
149 if (0 == unusedIndicesPos) {
150 generateNewIndices();
151 generatedNewIndex = true;
152 }
153
154 unusedIndicesPos -= 1;
156 } else {
157 usedIndicesPos -= 1;
159 }
160 }
161
163
164 return generatedNewIndex;
165 }
166
168 template<typename Tape>
170 freeIndex<Tape>(index); // Zero check is performed inside.
171
172 bool generatedNewIndex = false;
173 if (0 == unusedIndicesPos) {
174 generateNewIndices();
175 generatedNewIndex = true;
176 }
177
178 unusedIndicesPos -= 1;
180
182
183 return generatedNewIndex;
184 }
185
187 template<typename Tape>
188 CODI_INLINE void copyIndex(Index& lhs, Index const& rhs) {
189 if (Base::InactiveIndex == rhs) {
190 freeIndex<Tape>(lhs);
191 } else {
192 assignIndex<Tape>(lhs);
193 }
194 }
195
197 template<typename Tape>
199 if (valid && Base::InactiveIndex != index) { // Do not free the zero index.
200 codiAssert(index <= cast().getLargestCreatedIndex());
201
203
204 if (usedIndicesPos == usedIndices.size()) {
205 increaseIndicesSize(usedIndices);
206 }
207
209 usedIndicesPos += 1;
210
211 index = Base::InactiveIndex;
212 }
213 }
214
217 /* This method calculates the number of new indices that needs to be added to the unusedIndices vector.
218 The length of the unusedIndices vector is adjusted in multiples of indexSizeIncrement.
219 This is done by recursively calling by generateNewIndices. */
220 if (index > cast().getLargestCreatedIndex()) {
221 Index needToGenerate = index - cast().getLargestCreatedIndex();
222 size_t newUnusedIndexSize = this->unusedIndicesPos + needToGenerate;
223
224 // Round up newUnusedIndexSize to a multiple of indexSizeIncrement and then resize.
225 newUnusedIndexSize = getNextMultiple(newUnusedIndexSize, this->indexSizeIncrement);
226 this->unusedIndices.resize(newUnusedIndexSize);
227
228 // Generate the new unusedIndices in steps of indexSizeIncrement.
229 while (index > cast().getLargestCreatedIndex()) {
230 generateNewIndices();
231 }
232 }
233 }
234
237 size_t totalSize = usedIndicesPos + unusedIndicesPos;
238 if (totalSize > unusedIndices.size()) {
239 increaseIndicesSizeTo(unusedIndices, totalSize);
240 }
241
242 for (size_t pos = 0; pos < usedIndicesPos; ++pos) {
244 }
245 unusedIndicesPos = totalSize;
246 usedIndicesPos = 0;
247
249 if (totalSize == unusedIndices.size()) {
250 std::sort(unusedIndices.begin(), unusedIndices.end());
251 } else {
253 }
254 }
255 }
256
259 void addToTapeValues(TapeValues& values) const {
260 unsigned long storedIndices = this->usedIndicesPos + this->unusedIndicesPos;
261 unsigned long allocatedIndices = this->usedIndices.size() + this->unusedIndices.size();
262
263 double memoryStoredIndices = (double)storedIndices * (double)(sizeof(Index));
264 double memoryAllocatedIndices = (double)allocatedIndices * (double)(sizeof(Index));
265
266 TapeValues::LocalReductionOperation constexpr operation = Impl::NeedsStaticStorage
267 ? TapeValues::LocalReductionOperation::Max
268 : TapeValues::LocalReductionOperation::Sum;
269
270 values.addUnsignedLongEntry("Indices stored", storedIndices, operation);
271 values.addDoubleEntry("Memory used", memoryStoredIndices, operation, true, false);
272 values.addDoubleEntry("Memory allocated", memoryAllocatedIndices, operation, false, true);
273 }
274
276
277 private:
278
279 CODI_NO_INLINE void increaseIndicesSize(std::vector<Index>& v) {
280 v.resize(v.size() + indexSizeIncrement);
281 }
282
283 CODI_NO_INLINE void increaseIndicesSizeTo(std::vector<Index>& v, size_t minimalSize) {
284 codiAssert(v.size() < minimalSize);
285
286 size_t increaseMul = (minimalSize - v.size()) / indexSizeIncrement + 1; // +1 always rounds up.
287 v.resize(v.size() + increaseMul * indexSizeIncrement);
288 }
289 };
290}
#define CODI_NO_INLINE
See codi::Config::AvoidedInlines.
Definition config.h:417
#define CODI_INLINE
See codi::Config::ForcedInlines.
Definition config.h:457
#define codiAssert(x)
See codi::Config::EnableAssert.
Definition config.h:432
#define CODI_DD(Type, Default)
Abbreviation for CODI_DECLARE_DEFAULT.
Definition macros.hpp:94
#define CODI_IMPLEMENTATION
Used in interface declarations to indicate the type of the implementing class.
Definition macros.hpp:105
bool constexpr SortIndicesOnReset
Reuse index tapes will sort their indices on a reset.
Definition config.h:264
CoDiPack - Code Differentiation Package.
Definition codi.hpp:91
IntegralType getNextMultiple(IntegralType const &targetSize, IntegralType const &chunkSize)
Helper function for overallocation in multiples of a given chunk size.
Definition mathUtility.hpp:49
No data is stored in this DataInterface implementation. It is used to terminate the recursive nature ...
Definition emptyData.hpp:54
EmptyPosition Position
No positional data.
Definition emptyData.hpp:59
Empty Position with no nested data.
Definition position.hpp:47
static void notifyIndexAssignListeners(Index const &index)
Invoke callbacks for IndexAssign events.
Definition eventSystem.hpp:778
static void notifyIndexFreeListeners(Index const &index)
Invoke callbacks for IndexFree events.
Definition eventSystem.hpp:806
Indices enable the mapping of primal values to their adjoint counterparts.
Definition indexManagerInterface.hpp:78
static Index constexpr InactiveIndex
Default inactive index for all index managers.
Definition indexManagerInterface.hpp:86
Index getLargestCreatedIndex() const
Returns the largest created index.
Identifiers are reused. Freed identifiers are assigned to new variables. Variables keep their indices...
Definition reuseIndexManagerBase.hpp:66
static bool constexpr IsLinear
Identifiers are not coupled to statements.
Definition reuseIndexManagerBase.hpp:80
bool assignUnusedIndex(Index &index)
Call on registering input values.
Definition reuseIndexManagerBase.hpp:169
bool valid
Prevent index free after destruction.
Definition reuseIndexManagerBase.hpp:95
~ReuseIndexManagerBase()
Destructor.
Definition reuseIndexManagerBase.hpp:134
T_Impl Impl
See ReuseIndexManagerBase.
Definition reuseIndexManagerBase.hpp:70
ReuseIndexManagerBase()
Definition reuseIndexManagerBase.hpp:123
bool assignIndex(Index &index)
Call on assignment of a primal value, e.g. on w for w = a + b.
Definition reuseIndexManagerBase.hpp:144
std::vector< Index > unusedIndices
Pool of indices that have not been used in this recording yet.
Definition reuseIndexManagerBase.hpp:90
std::vector< Index > usedIndices
Pool of indices that have already been used in this recording.
Definition reuseIndexManagerBase.hpp:87
static bool constexpr CopyNeedsStatement
No copy optimization is implemented.
Definition reuseIndexManagerBase.hpp:79
void addToTapeValues(TapeValues &values) const
Add storage and other information to the tape values.
Definition reuseIndexManagerBase.hpp:259
static bool constexpr NeedsStaticStorage
Identifiers are managed globally.
Definition reuseIndexManagerBase.hpp:81
T_Index Index
See ReuseIndexManagerBase.
Definition reuseIndexManagerBase.hpp:69
size_t indexSizeIncrement
Block size for index pool enlargement.
Definition reuseIndexManagerBase.hpp:93
size_t unusedIndicesPos
Number of remaining unused indices.
Definition reuseIndexManagerBase.hpp:91
void freeIndex(Index &index)
Call on destruction of a primal value. Usually called from the destructor.
Definition reuseIndexManagerBase.hpp:198
size_t usedIndicesPos
Number of remaining used indices.
Definition reuseIndexManagerBase.hpp:88
void reset()
Reset for a new recording.
Definition reuseIndexManagerBase.hpp:236
void copyIndex(Index &lhs, Index const &rhs)
Call on copy of a primal value, e.g. w = a.
Definition reuseIndexManagerBase.hpp:188
void updateLargestCreatedIndex(Index const &index)
Update the largest generated index.
Definition reuseIndexManagerBase.hpp:216
Tape information that can be printed in a pretty print format or a table format.
Definition tapeValues.hpp:75
void addUnsignedLongEntry(std::string const &name, unsigned long const &value, LocalReductionOperation operation=LocalReductionOperation::Sum)
Add unsigned long entry.
Definition tapeValues.hpp:163
void addDoubleEntry(std::string const &name, double const &value, LocalReductionOperation operation=LocalReductionOperation::Sum, bool usedMem=false, bool allocatedMem=false)
Add double entry. If it is a memory entry, it should be in bytes.
Definition tapeValues.hpp:137