Skip to content

Commit 98a75ad

Browse files
committed
[RF] Refactor ChangeOperModeRAII to work with groups of RooAbsArgs
Several places needed to record a set of operation-mode changes and restore them later as a group, so it's better to have the ChangeOperModeRAII act on groups of RooAbsArg to not have to create one RAII object per arg. (cherry picked from commit d42a27c)
1 parent e2e080e commit 98a75ad

7 files changed

Lines changed: 52 additions & 27 deletions

File tree

roofit/roofitcore/inc/RooEvaluatorWrapper.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
#include <RooRealProxy.h>
2222
#include <RooSetProxy.h>
2323

24+
#include <memory>
2425
#include <stack>
2526

27+
class ChangeOperModeRAII;
2628
class RooAbsArg;
2729
class RooAbsCategory;
2830
class RooAbsPdf;
@@ -73,7 +75,7 @@ class RooEvaluatorWrapper final : public RooAbsReal {
7375
void setUseGeneratedFunctionCode(bool);
7476
void writeDebugMacro(std::string const &) const;
7577

76-
std::stack<std::unique_ptr<ChangeOperModeRAII>> setOperModes(RooAbsArg::OperMode opMode);
78+
std::unique_ptr<ChangeOperModeRAII> setOperModes(RooAbsArg::OperMode opMode);
7779

7880
protected:
7981
double evaluate() const override;

roofit/roofitcore/inc/RooFit/Evaluator.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include <RConfig.h>
2121

2222
#include <memory>
23-
#include <stack>
2423

2524
class ChangeOperModeRAII;
2625
class RooAbsArg;
@@ -45,7 +44,7 @@ class Evaluator {
4544

4645
void setOffsetMode(RooFit::EvalContext::OffsetMode);
4746

48-
std::stack<std::unique_ptr<ChangeOperModeRAII>> setOperModes(RooAbsArg::OperMode opMode);
47+
std::unique_ptr<ChangeOperModeRAII> setOperModes(RooAbsArg::OperMode opMode);
4948

5049
private:
5150
void processVariable(NodeInfo &nodeInfo);
@@ -68,7 +67,7 @@ class Evaluator {
6867
RooFit::EvalContext _evalContextCUDA;
6968
std::vector<NodeInfo> _nodes; // the ordered computation graph
7069
std::unordered_map<TNamed const *, NodeInfo *> _nodesMap; // for quick lookup of nodes
71-
std::stack<std::unique_ptr<ChangeOperModeRAII>> _changeOperModeRAIIs;
70+
std::unique_ptr<ChangeOperModeRAII> _operModeChanges;
7271
};
7372

7473
} // end namespace RooFit

roofit/roofitcore/res/RooFitImplHelpers.h

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,25 +46,51 @@ class DisableCachingRAII {
4646
bool _oldState;
4747
};
4848

49-
/// Struct to temporarily change the operation mode of a RooAbsArg until it
50-
/// goes out of scope.
49+
/// Scope guard that temporarily changes the operation mode of one or more
50+
/// RooAbsArg instances. Each call to change() records the arg's current
51+
/// operMode before flipping it to the requested mode (non-recursively, i.e.
52+
/// value clients are not touched). Destruction (or an explicit clear())
53+
/// restores every recorded mode in LIFO order.
54+
///
55+
/// The class is movable but not copyable, so it can be returned from
56+
/// functions that build up a batch of changes to hand to the caller.
5157
class ChangeOperModeRAII {
5258
public:
53-
ChangeOperModeRAII(RooAbsArg *arg, RooAbsArg::OperMode opMode) : _arg{arg}, _oldOpMode(arg->operMode())
59+
ChangeOperModeRAII() = default;
60+
61+
/// Convenience ctor: behaves like a scope guard for a single arg.
62+
ChangeOperModeRAII(RooAbsArg *arg, RooAbsArg::OperMode opMode) { change(arg, opMode); }
63+
64+
~ChangeOperModeRAII() { clear(); }
65+
66+
ChangeOperModeRAII(ChangeOperModeRAII &&) = default;
67+
ChangeOperModeRAII &operator=(ChangeOperModeRAII &&) = default;
68+
ChangeOperModeRAII(ChangeOperModeRAII const &) = delete;
69+
ChangeOperModeRAII &operator=(ChangeOperModeRAII const &) = delete;
70+
71+
/// Record arg's current operMode and flip it to opMode. If the current
72+
/// mode already equals opMode, this is a no-op (nothing to restore).
73+
void change(RooAbsArg *arg, RooAbsArg::OperMode opMode)
5474
{
55-
arg->setOperMode(opMode, /*recurse=*/false);
75+
if (opMode == arg->operMode())
76+
return;
77+
_entries.emplace_back(arg, arg->operMode());
78+
arg->setOperMode(opMode, /*recurseADirty=*/false);
5679
}
5780

58-
ChangeOperModeRAII(ChangeOperModeRAII const &other) = delete;
59-
ChangeOperModeRAII &operator=(ChangeOperModeRAII const &other) = delete;
60-
ChangeOperModeRAII(ChangeOperModeRAII &&other) = delete;
61-
ChangeOperModeRAII &operator=(ChangeOperModeRAII &&other) = delete;
81+
/// Restore every recorded change right away, emptying this guard.
82+
void clear()
83+
{
84+
for (auto it = _entries.rbegin(); it != _entries.rend(); ++it) {
85+
it->first->setOperMode(it->second, /*recurseADirty=*/false);
86+
}
87+
_entries.clear();
88+
}
6289

63-
~ChangeOperModeRAII() { _arg->setOperMode(_oldOpMode, /*recurse=*/false); }
90+
bool empty() const { return _entries.empty(); }
6491

6592
private:
66-
RooAbsArg *_arg = nullptr;
67-
RooAbsArg::OperMode _oldOpMode;
93+
std::vector<std::pair<RooAbsArg *, RooAbsArg::OperMode>> _entries;
6894
};
6995

7096
namespace RooHelpers {

roofit/roofitcore/src/RooEvaluatorWrapper.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ void RooEvaluatorWrapper::writeDebugMacro(std::string const &filename) const
741741
return _funcWrapper->writeDebugMacro(filename);
742742
}
743743

744-
std::stack<std::unique_ptr<ChangeOperModeRAII>> RooEvaluatorWrapper::setOperModes(RooAbsArg::OperMode opMode)
744+
std::unique_ptr<ChangeOperModeRAII> RooEvaluatorWrapper::setOperModes(RooAbsArg::OperMode opMode)
745745
{
746746
return _evaluator->setOperModes(opMode);
747747
}

roofit/roofitcore/src/RooFit/Evaluator.cxx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -628,9 +628,9 @@ void Evaluator::markGPUNodes()
628628
/// Evaluator gets deleted.
629629
void Evaluator::setOperMode(RooAbsArg *arg, RooAbsArg::OperMode opMode)
630630
{
631-
if (opMode != arg->operMode()) {
632-
_changeOperModeRAIIs.emplace(std::make_unique<ChangeOperModeRAII>(arg, opMode));
633-
}
631+
if (!_operModeChanges)
632+
_operModeChanges = std::make_unique<ChangeOperModeRAII>();
633+
_operModeChanges->change(arg, opMode);
634634
}
635635

636636
// Change the operation modes of all RooAbsArgs in the computation graph.
@@ -646,9 +646,9 @@ void Evaluator::setOperMode(RooAbsArg *arg, RooAbsArg::OperMode opMode)
646646
// like a RooRealVar) would be left permanently in ADirty after the first
647647
// minimization, dramatically slowing down later scalar evaluations (for
648648
// example on pdfs held by the legacy test statistics' internal cache).
649-
std::stack<std::unique_ptr<ChangeOperModeRAII>> Evaluator::setOperModes(RooAbsArg::OperMode opMode)
649+
std::unique_ptr<ChangeOperModeRAII> Evaluator::setOperModes(RooAbsArg::OperMode opMode)
650650
{
651-
std::stack<std::unique_ptr<ChangeOperModeRAII>> out{};
651+
auto out = std::make_unique<ChangeOperModeRAII>();
652652
std::unordered_set<RooAbsArg *> visited;
653653

654654
std::vector<RooAbsArg *> queue;
@@ -663,9 +663,7 @@ std::stack<std::unique_ptr<ChangeOperModeRAII>> Evaluator::setOperModes(RooAbsAr
663663
if (!visited.insert(node).second)
664664
continue;
665665

666-
if (opMode != node->operMode()) {
667-
out.emplace(std::make_unique<ChangeOperModeRAII>(node, opMode));
668-
}
666+
out->change(node, opMode);
669667

670668
// Only follow value-client links: that is exactly the propagation path
671669
// used by RooAbsArg::setOperMode with mode==ADirty.

roofit/roofitcore/src/RooMinimizer.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ void reorderCombinations(std::vector<std::vector<int>> &combos, const std::vecto
131131
//
132132
// This should be called before running any routine via the _minimizer data
133133
// member. The RAII object should only be destructed after the routine is done.
134-
std::stack<std::unique_ptr<ChangeOperModeRAII>> setOperModesDirty(RooAbsReal &function)
134+
std::unique_ptr<ChangeOperModeRAII> setOperModesDirty(RooAbsReal &function)
135135
{
136136
if (auto *wrapper = dynamic_cast<RooFit::Experimental::RooEvaluatorWrapper *>(&function)) {
137137
return wrapper->setOperModes(RooAbsArg::ADirty);

roofit/roofitcore/src/RooRealIntegral.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -841,12 +841,12 @@ double RooRealIntegral::evaluate() const
841841
// from caching subgraph results (e.g. for nested numeric integrals).
842842
RooArgList serverList;
843843
_function->treeNodeServerList(&serverList, nullptr, true, true, false, true);
844-
std::list<ChangeOperModeRAII> operModeRAII;
844+
ChangeOperModeRAII operModeRAII;
845845

846846
for (auto *arg : serverList) {
847847
arg->syncCache();
848848
if (arg->operMode() == RooAbsArg::AClean) {
849-
operModeRAII.emplace_back(arg, RooAbsArg::Auto);
849+
operModeRAII.change(arg, RooAbsArg::Auto);
850850
}
851851
}
852852

0 commit comments

Comments
 (0)