CoDiPack  3.1.0
A Code Differentiation Package
SciComp TU Kaiserslautern
Loading...
Searching...
No Matches
identifierCacheOptimizer.hpp
1/*
2 * CoDiPack, a Code Differentiation Package
3 *
4 * Copyright (C) 2015-2026 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 <fstream>
38#include <iostream>
39#include <vector>
40
41#include "../config.h"
42#include "../misc/macros.hpp"
43#include "../tapes/interfaces/fullTapeInterface.hpp"
44#include "../tapes/statementEvaluators/statementEvaluatorInterface.hpp"
45
47namespace codi {
48
65 template<typename T_Tape, typename T_Impl>
66 struct ApplyIdentifierModification : public CallbacksInterface<typename T_Tape::Real, typename T_Tape::Identifier> {
67 using Tape = CODI_DD(T_Tape, CODI_DEFAULT_TAPE);
69
70 using Real = typename Tape::Real;
71 using Identifier = typename Tape::Identifier;
72 using EvalHandle = typename Tape::EvalHandle;
73
74 private:
75
76 Tape& tape;
77 Real* primals = nullptr;
78
79 public:
80
82 ApplyIdentifierModification(Tape& tape) : tape(tape) {
84 primals = tape.getPrimalVector();
85 }
86 }
87
90 CODI_UNUSED(id);
91 // Empty
92 }
93
96 CODI_UNUSED(id);
97 // Empty
98 }
99
102 // Empty
103 }
104
107 // Empty
108 }
109
110 private:
111
113 static void applyToInput_func(Identifier* id, ApplyIdentifierModification* data) {
114 data->cast().applyToInput(*id);
115 }
116
118 static void applyToOutput_func(Identifier* id, ApplyIdentifierModification* data) {
119 data->cast().applyToOutput(*id);
120 }
121
122 public:
123
129 Real const* jacobians, Identifier* rhsIdentifiers) {
130 CODI_UNUSED(jacobians);
131
132 Impl& impl = cast();
133
134 for (codi::Config::ArgumentSize i = 0; i < size; i += 1) {
135 impl.applyToInput(rhsIdentifiers[i]);
136 }
137 impl.applyPostInputLogic();
138
139 impl.applyToOutput(lhsIndex);
140 impl.applyPostOutputLogic();
141 }
142
147 CODI_INLINE void handleStatement(EvalHandle const& evalHandle, codi::Config::ArgumentSize const& nPassiveValues,
148 size_t& linearAdjointPosition, char* stmtData) {
149 using StatementEvaluator = typename Tape::StatementEvaluator;
150
151 Impl& impl = cast();
152
153 codi::WriteInfo writeInfo;
154 StatementEvaluator::template call<codi::StatementCall::WriteInformation, Tape>(evalHandle, writeInfo, primals,
155 nPassiveValues, stmtData);
156
157 StatementEvaluator::template call<codi::StatementCall::IterateInputs, Tape>(
158 evalHandle, linearAdjointPosition, reinterpret_cast<void (*)(Identifier*, void*)>(applyToInput_func), this,
159 nPassiveValues, stmtData);
160 impl.applyPostInputLogic();
161
162 StatementEvaluator::template call<codi::StatementCall::IterateOutputs, Tape>(
163 evalHandle, linearAdjointPosition, reinterpret_cast<void (*)(Identifier*, void*)>(applyToOutput_func), this,
164 nPassiveValues, stmtData);
165 impl.applyPostOutputLogic();
166
167 if (Tape::LinearIndexHandling) {
168 linearAdjointPosition += writeInfo.numberOfOutputArguments;
169 }
170 }
171
177 codi::ByteDataView& llfData) {
178 Impl& impl = cast();
179
180 func.template call<codi::LowLevelFunctionEntryCallKind::IterateInputs>(
181 &tape, llfData, reinterpret_cast<void (*)(Identifier*, void*)>(applyToInput_func), this);
182 impl.applyPostInputLogic();
183
184 llfData.reset();
185 func.template call<codi::LowLevelFunctionEntryCallKind::IterateOutputs>(
186 &tape, llfData, reinterpret_cast<void (*)(Identifier*, void*)>(applyToOutput_func), this);
187 impl.applyPostOutputLogic();
188 }
189
190 private:
191
192 CODI_INLINE Impl& cast() {
193 return static_cast<Impl&>(*this);
194 }
195 };
196
202 template<typename T_Identifier>
204 using Identifier = CODI_DD(T_Identifier, int);
205 using UnsignedIdentifier = std::make_signed_t<Identifier>;
206
207 Identifier start = 0;
208 Identifier nextFree = 0;
209 UnsignedIdentifier nextDirection = 0;
210
211 std::set<Identifier> stack = {};
212
214 CODI_INLINE void init(Identifier start, UnsignedIdentifier dir) {
215 this->start = start;
216 nextFree = start;
217 nextDirection = dir;
218 }
219
221 CODI_INLINE void free(Identifier id) {
222 stack.insert(id);
223 }
224
227 Identifier gen = nextFree;
229
230 return gen;
231 }
232
234 CODI_INLINE Identifier generate() {
235 Identifier gen = {};
236 if (stack.empty()) {
237 gen = generateFresh();
238 } else {
239 gen = *stack.begin();
240 stack.erase(stack.begin());
241 }
242
243 return gen;
244 }
245
247 CODI_INLINE bool isHandledByThis(Identifier id) {
248 if (id == 0) {
249 return false;
250 }
251
252 if (nextDirection < 0) {
253 // Reverse generation
254 return id > nextFree;
255 } else {
256 // Regular generation
257 return id < nextFree;
258 }
259 }
260
263 return (nextFree - start) / nextDirection;
264 }
265 };
266
278 template<typename T_Identifier, typename T_Lifetime = int>
280 private:
281 using Identifier = CODI_DD(T_Identifier, int);
282 using Lifetime = CODI_DD(T_Lifetime, int);
283
284 Identifier invalidId;
285
288 std::vector<Lifetime> stmtLivetime = {};
289
290 std::vector<Lifetime> llfLivetimeOffsets = {};
292 std::vector<Identifier> llfLivetimesId = {};
294 std::vector<Lifetime> llfLivetimes = {};
295
296 Lifetime curLLFOutputPos = 0;
297 Lifetime endLLFOutputPos = 0;
298
299 int outputSize = 0;
300
301 public:
302
304 CODI_INLINE LifetimeManager(Identifier invalidId) : invalidId(invalidId) {
305 llfLivetimeOffsets.push_back(0); // First starting range.
306 }
307
308 /*******************************************************************************/
311
313 CODI_INLINE bool isLLFStatement(Lifetime const& stmtId) {
314 return stmtLivetime[stmtId] < invalidId;
315 }
316
318 CODI_INLINE void prepareStatementRead(Lifetime const& stmtId) {
319 // Check if this is a low level function and perform the setup.
320 if (stmtLivetime[stmtId] < invalidId) {
321 auto [start, end] = getLLFRange(stmtLivetime[stmtId]);
322
323 curLLFOutputPos = start;
324 endLLFOutputPos = end;
325 }
326 }
327
329 CODI_INLINE Lifetime getLifetime(Lifetime const& stmtId, Identifier const& outputId) {
330 CODI_UNUSED(outputId);
331
332 Lifetime r = stmtLivetime[stmtId];
333 if (r < invalidId) {
334 // Low level function entry
335 auto iterPos = std::lower_bound(llfLivetimesId.begin() + curLLFOutputPos,
336 llfLivetimesId.begin() + endLLFOutputPos, outputId);
337 codiAssert(iterPos != llfLivetimesId.end()); // If not found the id references the wrong statement.
338
339 int pos = std::distance(llfLivetimesId.begin(), iterPos);
340 r = llfLivetimes[pos];
341 }
342
343 return r;
344 }
345
347 /*******************************************************************************/
350
352 CODI_INLINE void setLifetime(Lifetime const& stmtId, Identifier const& outputId, Lifetime const& lifetime) {
353 if (stmtLivetime[stmtId] == invalidId) { // Invalid id indicates single output for statement.
354 stmtLivetime[stmtId] = lifetime;
355 } else {
356 // Low level function.
357 codiAssert(stmtLivetime[stmtId] < 0); // If positive a lifetime was already set.
358
359 auto [start, end] = getLLFRange(stmtLivetime[stmtId]);
360
361 auto iterPos = std::lower_bound(llfLivetimesId.begin() + start, llfLivetimesId.begin() + end, outputId);
362 codiAssert(iterPos != llfLivetimesId.end()); // If not found the id references the wrong statement.
363
364 int pos = std::distance(llfLivetimesId.begin(), iterPos);
365 llfLivetimes[pos] = lifetime;
366 }
367 }
368
370 CODI_INLINE void addOutputToStatement(Identifier const& id) {
371 outputSize += 1;
372 llfLivetimesId.push_back(id);
373 llfLivetimes.push_back(invalidId);
374 }
375
379 if (0 == outputSize || outputSize > 1) {
380 sortCurrentRange();
381
382 // Low level function
383 llfLivetimeOffsets.push_back(llfLivetimesId.size());
384 stmtLivetime.push_back(generateLLFRange());
385 } else {
386 // Regular statement
387 stmtLivetime.push_back(invalidId);
388
389 // Discard the low level function lifetime.
390 llfLivetimesId.pop_back();
391 llfLivetimes.pop_back();
392 }
393
394 outputSize = 0;
395 }
396
398
399 private:
400
402 CODI_INLINE std::pair<Lifetime, Lifetime> getLLFRange(Lifetime lifetime) {
403 Lifetime offset = -lifetime - 2;
404 return {llfLivetimeOffsets[offset], llfLivetimeOffsets[offset + 1]};
405 }
406
408 CODI_INLINE Lifetime generateLLFRange() {
409 return -(Identifier)llfLivetimeOffsets.size();
410 }
411
413 void sortCurrentRange() {
414 // Lifetimes are not set yet, so we just need to sort the identifiers.
415 Lifetime start = llfLivetimeOffsets.back();
416 Lifetime end = llfLivetimesId.size();
417
418 // Validate assumption
420 for (Lifetime i = start; i < end; i += 1) {
421 codiAssert(llfLivetimes[i] == invalidId);
422 }
423 }
424
425 std::sort(llfLivetimesId.begin() + start, llfLivetimesId.end());
426 llfLivetimesId.erase(std::unique(llfLivetimesId.begin() + start, llfLivetimesId.end()), llfLivetimesId.end());
427 llfLivetimes.resize(llfLivetimesId.size());
428 }
429 };
430
450 template<typename T_Tape, typename T_Lifetime = int>
452 public:
453 using Tape = CODI_DD(T_Tape, CODI_DEFAULT_TAPE);
454 using Lifetime = CODI_DD(T_Lifetime, int);
455
456 private:
457
458 using Real = typename Tape::Real;
459 using Identifier = typename Tape::Identifier;
460 using EvalHandle = typename Tape::EvalHandle;
461
463 using IdLivetimesMap = std::multimap<Lifetime, std::pair<Identifier, Identifier>>;
464
465 Identifier invalidId = {};
466 Identifier passiveId = {};
467 Tape& tape;
468
469 Lifetime hotLiveTimeThreshold = 500;
470 Identifier idMapSize = {};
471
472 IdentifierGenerator<Identifier> generatorHot = {};
473 IdentifierGenerator<Identifier> generatorCold = {};
474
475 LifetimeManager<Identifier, Lifetime> lifetimes;
476
478 struct Stats {
479 size_t totalHot;
480 size_t totalCold;
481 size_t total;
482 size_t unused;
483 };
484 Stats stats = {};
485
486 public:
487
490 : invalidId(tape.getInvalidIndex()), passiveId(tape.getPassiveIndex()), tape(tape), lifetimes(invalidId) {
491 Identifier startCold = tape.getIndexManager().getLargestCreatedIndex();
492 generatorCold.init(startCold, -1);
493 generatorHot.init(1, 1);
494
495 idMapSize = startCold + 1;
496 }
497
499 CODI_INLINE void setHotLiveTimeThreshold(Lifetime hotLiveTimeThreshold) {
500 this->hotLiveTimeThreshold = hotLiveTimeThreshold;
501 }
502
503 private:
504
511 struct HandleTranslate : public ApplyIdentifierModification<Tape, HandleTranslate> {
513
515 Lifetime curStmtId = 0;
516
517 std::vector<Identifier> translateMap = {};
518
519 IdLivetimesMap currentIdLivetimes = {};
520
522 CODI_INLINE HandleTranslate(IdentifierCacheOptimizerHotCold* p) : Base(p->tape), parent(p) {
523 translateMap.resize(parent->idMapSize, parent->invalidId);
524
525 translateMap[parent->passiveId] = parent->passiveId; // 0 -> 0
526 }
527
529 CODI_INLINE void addProgrammInput(Identifier& id) {
530 applyToOutput(id);
531 }
532
534 CODI_INLINE void applyToInput(Identifier& id) {
535 Identifier& transId = translateMap[id];
536
537 codiAssert(parent->invalidId != transId);
538 id = transId;
539 }
540
542 CODI_INLINE void applyToOutput(Identifier& id) {
543 // Early out for passive id.
544 if (parent->passiveId == id) {
545 if (Config::EnableAssert && parent->lifetimes.isLLFStatement(curStmtId)) {
546 parent->lifetimes.getLifetime(curStmtId, id); // Get lifetime for assert.
547 }
548 return;
549 }
550
551 Lifetime livetime = parent->lifetimes.getLifetime(curStmtId, id);
552 Identifier& transId = translateMap[id];
553
554 codiAssert(-1 != livetime); // There should be no undefined lifetimes.
555
556 if (transId != parent->invalidId) {
557 // Ok, duplicated output detected.
558 } else {
559 // Ok, untranslated id with livetime
560 bool isHot = livetime < parent->hotLiveTimeThreshold;
561
562 // Not yet translated generate an entry.
563 if (isHot) {
564 transId = parent->generatorHot.generate();
565 } else {
566 transId = parent->generatorCold.generate();
567 }
568
569 currentIdLivetimes.emplace(curStmtId + livetime, std::make_pair(id, transId));
570 }
571
572 id = transId;
573 }
574
576 CODI_INLINE void applyPostInputLogic() {
577 using Iter = typename IdLivetimesMap::iterator;
578 Iter cur = currentIdLivetimes.begin();
579 Iter end = currentIdLivetimes.end();
580
581 // Iterate until we find a live time that is after the current statement id.
582 for (; cur != end; cur++) {
583 if (cur->first > curStmtId) {
584 break;
585 }
586
587 bool isHot = parent->generatorHot.isHandledByThis(cur->second.second);
588 if (isHot) {
589 parent->generatorHot.free(cur->second.second);
590 } else {
591 parent->generatorCold.free(cur->second.second);
592 }
593 translateMap[cur->second.first] = parent->invalidId;
594 }
595
596 // Remove all freed lifetimes.
597 currentIdLivetimes.erase(currentIdLivetimes.begin(), cur);
598
599 parent->lifetimes.prepareStatementRead(curStmtId);
600 }
601
603 CODI_INLINE void applyPostOutputLogic() {
604 curStmtId += 1;
605 }
606 };
607
615 struct HandleHotColdAnalysis : public ApplyIdentifierModification<Tape, HandleHotColdAnalysis> {
617
618 IdentifierCacheOptimizerHotCold* parent;
619
620 std::vector<Lifetime> idLastUseInStmt = {};
621 std::vector<Lifetime> idCreatedInStmt = {};
622
623 Lifetime curStmtId = 0;
624
626 CODI_INLINE HandleHotColdAnalysis(IdentifierCacheOptimizerHotCold* p) : Base(p->tape), parent(p) {
627 idLastUseInStmt.resize(parent->idMapSize, parent->invalidId);
628 idCreatedInStmt.resize(parent->idMapSize, parent->invalidId);
629 }
630
632 CODI_INLINE void computeLifetime(Identifier& id) {
633 Lifetime& createStmtId = idCreatedInStmt[id];
634 Lifetime& lastUseStmtId = idLastUseInStmt[id];
635
636 if (parent->invalidId != createStmtId && // ID was created
637 parent->invalidId != lastUseStmtId // ID was actually used
638 ) {
639 Lifetime livetime = lastUseStmtId - createStmtId;
640
641 parent->lifetimes.setLifetime(createStmtId, id, livetime);
642 } else if (parent->invalidId == createStmtId && parent->invalidId == lastUseStmtId) {
643 // New identifier, it is used for the first time.
644 } else if (parent->invalidId == lastUseStmtId && parent->invalidId != createStmtId) {
645 // Identifier was not used.
646 parent->lifetimes.setLifetime(createStmtId, id, 0);
647 } else {
648 CODI_EXCEPTION("Identifier '%d' is used but not created, this is an error in the tape.", (int)id);
649 }
650
651 lastUseStmtId = parent->invalidId; // Reset last use.
652 }
653
655 CODI_INLINE void addProgrammInput(Identifier& id) {
656 if (id != parent->passiveId) {
657 idCreatedInStmt[id] = curStmtId;
658 }
659
660 parent->lifetimes.addOutputToStatement(id);
661 }
662
664 CODI_INLINE void applyToInput(Identifier& id) {
665 if (id != parent->passiveId) {
666 idLastUseInStmt[id] = curStmtId;
667 }
668 }
669
671 CODI_INLINE void applyToOutput(Identifier& id) {
672 if (id != parent->passiveId) {
673 computeLifetime(id);
674 idCreatedInStmt[id] = curStmtId;
675 }
676
677 parent->lifetimes.addOutputToStatement(id);
678 }
679
681 CODI_INLINE void applyPostOutputLogic() {
682 parent->lifetimes.finalizeStatement();
683
684 curStmtId += 1;
685 }
686
689 CODI_INLINE void setOutputLifetime(Identifier& id) {
690 idLastUseInStmt[id] = curStmtId + parent->hotLiveTimeThreshold + 1;
691 }
692
694 CODI_INLINE void finalize() {
695 Identifier curId = 0;
696 for (Lifetime& stmtId : idCreatedInStmt) {
697 if (stmtId != parent->invalidId) {
698 computeLifetime(curId);
699 stmtId = parent->invalidId;
700 }
701 curId += 1;
702 }
703 }
704 };
705
709 struct HandleShift : public ApplyIdentifierModification<Tape, HandleShift> {
711
712 IdentifierCacheOptimizerHotCold* parent;
713 Identifier coldShift;
714
716 CODI_INLINE HandleShift(IdentifierCacheOptimizerHotCold* p)
717 : Base(p->tape), parent(p), coldShift(parent->stats.unused) {}
718
720 CODI_INLINE void applyShift(Identifier& id) {
721 if (0 != id && !parent->generatorHot.isHandledByThis(id)) {
722 id -= coldShift;
723 }
724 }
725
727 CODI_INLINE void applyToInput(Identifier& id) {
728 applyShift(id);
729 }
730
732 CODI_INLINE void applyToOutput(Identifier& id) {
733 applyShift(id);
734 }
735 };
736
738 CODI_INLINE void updateStats() {
739 stats.totalHot = generatorHot.getGeneratedSize() + 1; // +1 for zero index.
740 stats.totalCold = generatorCold.getGeneratedSize();
741 stats.total = stats.totalHot + stats.totalCold;
742 stats.unused = generatorCold.start - stats.total + 1; // +1 since start is included in range.
743 }
744
745 public:
746
748 template<typename FuncIn, typename FuncOut>
749 CODI_NO_INLINE void eval(FuncIn&& iterIn, FuncOut&& iterOut) {
750 // Do hot cold analysis
751 {
752 HandleHotColdAnalysis hotCold = {this};
753
754 // Add inputs as one large low level function.
755 iterIn([&](Identifier& id) {
756 hotCold.addProgrammInput(id);
757 });
758 hotCold.applyPostOutputLogic();
759
760 // Analyze the tape.
761 tape.iterateForward(hotCold);
762
763 iterOut([&](Identifier& id) {
764 hotCold.setOutputLifetime(id);
765 });
766
767 // Finalize the analysis.
768 hotCold.finalize();
769 }
770
771 // Translate tape
772 {
773 HandleTranslate translate = {this};
774
775 // Handle inputs as large low level function.
776 translate.applyPostInputLogic();
777 iterIn([&](Identifier& id) {
778 translate.addProgrammInput(id); // Register the starting use of the global inputs.
779 });
780 translate.applyPostOutputLogic();
781
782 tape.iterateForward(translate);
783
784 iterOut([&](Identifier& id) {
785 translate.applyToInput(id); // Just translate do not generate new translations.
786 });
787 }
788
789 updateStats();
790
791 // Perform identifier shift
792 {
793 HandleShift shift = {this};
794 tape.iterateForward(shift);
795
796 auto doShift = [&](Identifier& id) {
797 shift.applyShift(id);
798 };
799 iterIn(doShift);
800 iterOut(doShift);
801 }
802 }
803
806 return stats.total - 1;
807 }
808
810 template<typename Stream>
811 void writeStatsVerbose(Stream& out) {
812 out << "Hot: " << stats.totalHot << std::endl;
813 out << "Cold: " << stats.totalCold << std::endl;
814 out << "Total: " << stats.total << std::endl;
815 out << "Unused: " << stats.unused << std::endl;
816 }
817
819 template<typename Stream>
820 void writeStatsHeader(Stream& out) {
821 out << "Hot; Cold; Total; Unused;";
822 }
823
825 template<typename Stream>
826 void writeStatsRow(Stream& out) {
827 out << "Hot: " << stats.totalHot << std::endl;
828 out << "Cold: " << stats.totalCold << std::endl;
829 out << "Total: " << stats.total << std::endl;
830 out << "Unused: " << stats.unused << std::endl;
831 }
832 };
833}
#define CODI_NO_INLINE
See codi::Config::AvoidedInlines.
Definition config.h:426
#define CODI_INLINE
See codi::Config::ForcedInlines.
Definition config.h:469
#define codiAssert(x)
See codi::Config::EnableAssert.
Definition config.h:441
#define CODI_DD(Type, Default)
Abbreviation for CODI_DECLARE_DEFAULT.
Definition macros.hpp:97
bool constexpr EnableAssert
Enables asserts in CoDiPack for consistency checking.
Definition config.h:445
uint8_t ArgumentSize
Type for the number of arguments in statements.
Definition config.h:117
bool constexpr isPrimalValueTape
Value entry of IsPrimalValueTape.
Definition tapeTraits.hpp:106
CoDiPack - Code Differentiation Package.
Definition codi.hpp:97
inlinevoid CODI_UNUSED(Args const &...)
Disable unused warnings for an arbitrary number of arguments.
Definition macros.hpp:55
Helper class for iterating or changing the identifiers of a tape.
Definition identifierCacheOptimizer.hpp:66
typename Tape::Real Real
See FullTapeInterface.
Definition identifierCacheOptimizer.hpp:70
inlinevoid handleStatement(EvalHandle const &evalHandle, codi::Config::ArgumentSize const &nPassiveValues, size_t &linearAdjointPosition, char *stmtData)
Definition identifierCacheOptimizer.hpp:147
inlinevoid handleStatement(Identifier &lhsIndex, codi::Config::ArgumentSize const &size, Real const *jacobians, Identifier *rhsIdentifiers)
Definition identifierCacheOptimizer.hpp:128
inlinevoid handleLowLevelFunction(codi::LowLevelFunctionEntry< Tape, Real, Identifier > const &func, codi::ByteDataView &llfData)
Definition identifierCacheOptimizer.hpp:176
T_Tape Tape
See ApplyIdentifierModification.
Definition identifierCacheOptimizer.hpp:67
inlinevoid applyPostOutputLogic()
Called after applyToOutput has been called for all outputs.
Definition identifierCacheOptimizer.hpp:106
inlinevoid applyToInput(Identifier &id)
Called for each input of each statement or low level function.
Definition identifierCacheOptimizer.hpp:89
T_Impl Impl
See ApplyIdentifierModification.
Definition identifierCacheOptimizer.hpp:68
typename Tape::EvalHandle EvalHandle
See FullTapeInterface.
Definition identifierCacheOptimizer.hpp:72
inlinevoid applyPostInputLogic()
Called after applyToInput has been called for all inputs.
Definition identifierCacheOptimizer.hpp:101
ApplyIdentifierModification(Tape &tape)
Constructor.
Definition identifierCacheOptimizer.hpp:82
typename Tape::Identifier Identifier
See FullTapeInterface.
Definition identifierCacheOptimizer.hpp:71
inlinevoid applyToOutput(Identifier &id)
Called for each output of each statement or low level function.
Definition identifierCacheOptimizer.hpp:95
Definition byteDataView.hpp:51
inlinevoid reset()
Reset the data position to the start of the data.
Definition byteDataView.hpp:126
interface for callbacks from an custom tape iteration. See CustomIteratorTapeInterface for details.
Definition customIteratorTapeInterface.hpp:55
T_Identifier Identifier
See ReadWriteTapeInterface.
Definition customIteratorTapeInterface.hpp:58
Reassigns the identifiers in a tape such that the tape evaluation is optimized.
Definition identifierCacheOptimizer.hpp:451
void writeStatsHeader(Stream &out)
Write the header for the statistics to a stream.
Definition identifierCacheOptimizer.hpp:820
T_Tape Tape
See IdentifierCacheOptimizerHotCold.
Definition identifierCacheOptimizer.hpp:453
void writeStatsRow(Stream &out)
Write the data for this optimizer into a row.
Definition identifierCacheOptimizer.hpp:826
void eval(FuncIn &&iterIn, FuncOut &&iterOut)
Perform the tape cache optimization. Se the class description for details.
Definition identifierCacheOptimizer.hpp:749
T_Lifetime Lifetime
See IdentifierCacheOptimizerHotCold.
Definition identifierCacheOptimizer.hpp:454
inlinesize_t getLargestCreatedIndex()
Get the new largest created index.
Definition identifierCacheOptimizer.hpp:805
void writeStatsVerbose(Stream &out)
Write statistics to a stream as a list.
Definition identifierCacheOptimizer.hpp:811
inlinevoid setHotLiveTimeThreshold(Lifetime hotLiveTimeThreshold)
Set the threshold for hot variables. Smaller values will be hot and larger ones cold.
Definition identifierCacheOptimizer.hpp:499
Definition identifierCacheOptimizer.hpp:203
inlinebool isHandledByThis(Identifier id)
Check if the identifier is handled by this generator.
Definition identifierCacheOptimizer.hpp:247
inlinevoid init(Identifier start, UnsignedIdentifier dir)
Initialize the range.
Definition identifierCacheOptimizer.hpp:214
inlineIdentifier generateFresh()
Generate an unused identifier.
Definition identifierCacheOptimizer.hpp:226
inlineIdentifier generate()
Generate an identifier.
Definition identifierCacheOptimizer.hpp:234
UnsignedIdentifier nextDirection
Step for the next generated identifier.
Definition identifierCacheOptimizer.hpp:209
std::set< Identifier > stack
List of all unused identifiers.
Definition identifierCacheOptimizer.hpp:211
Identifier nextFree
Next generated identifier.
Definition identifierCacheOptimizer.hpp:208
Identifier start
Start of the identifier range.
Definition identifierCacheOptimizer.hpp:207
inlinevoid free(Identifier id)
Free an identifier.
Definition identifierCacheOptimizer.hpp:221
inlineIdentifier getGeneratedSize()
Get number of generated identifiers.
Definition identifierCacheOptimizer.hpp:262
Helper class for the lifetime management of the identifiers.
Definition identifierCacheOptimizer.hpp:279
inlinebool isLLFStatement(Lifetime const &stmtId)
Check if the statement has just one output.
Definition identifierCacheOptimizer.hpp:313
inlinevoid finalizeStatement()
Definition identifierCacheOptimizer.hpp:378
inlinevoid setLifetime(Lifetime const &stmtId, Identifier const &outputId, Lifetime const &lifetime)
Set the lifetime for an output of a statement. The statement should already be finalized.
Definition identifierCacheOptimizer.hpp:352
inlinevoid addOutputToStatement(Identifier const &id)
Add an output to the current statement.
Definition identifierCacheOptimizer.hpp:370
inlinevoid prepareStatementRead(Lifetime const &stmtId)
Call before lifetimes are read for a statement.
Definition identifierCacheOptimizer.hpp:318
inlineLifetime getLifetime(Lifetime const &stmtId, Identifier const &outputId)
Get the lifetime of an output of the statement. prepareStatementRead needs to be called first.
Definition identifierCacheOptimizer.hpp:329
Low level function entry on the tape. See LowLevelFunctionTapeInterface for details.
Definition lowLevelFunctionEntry.hpp:69
This class is used during the writing process of a primal value tape. The WriteInfo is returned by St...
Definition tapeReaderWriterInterface.hpp:69
size_t numberOfOutputArguments
Number of output arguments.
Definition tapeReaderWriterInterface.hpp:70