Skip to content

Commit a73868b

Browse files
committed
[RF] Make RooAbsCachedPdf's cache lookup key stable across Evaluator paths
In the Evaluator backend, the compile-time analytical-integral construction, doEval, and analyticalIntegralWN each queried `_cacheMgr` with a different (or null/empty) RooArgSet, so the heavy cache content was rebuilt on the first fit step instead of reusing the slot populated during NLL setup. Pin a stable `_compiledNormSet` on the cloned pdf in compileForNormSet for doEval to use, and let analyticalIntegralWN fall back to `anaVars` when the stored `normSet2` is empty so its key mirrors getAnalyticalIntegralWN's. All three paths now hit the same slot. Fixes the stressRooFit -b cpu -n 47 slowdown vs the legacy backend (RooIntegralMorph fit with setCacheAlpha(true)). (cherry picked from commit 50854dc)
1 parent 4751306 commit a73868b

2 files changed

Lines changed: 28 additions & 2 deletions

File tree

roofit/roofitcore/inc/RooAbsCachedPdf.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ class RooAbsCachedPdf : public RooAbsPdf {
134134

135135
bool _disableCache = false; ///< Flag to run object in passthrough (= non-caching mode)
136136

137+
/// Pinned at compileForNormSet() time on the cloned cache pdf, so that
138+
/// doEval() looks up the same _cacheMgr slot that getAnalyticalIntegralWN()
139+
/// populates while the surrounding RooNormalizedPdf is being constructed.
140+
/// Without this, the two paths used different (or null) keys and the cache
141+
/// was rebuilt on the first Evaluator step of every fit.
142+
mutable RooArgSet _compiledNormSet; ///<! stable normalization set for the compiled clone
143+
mutable bool _hasCompiledNormSet = false; ///<! whether _compiledNormSet has been populated
144+
137145
ClassDefOverride(RooAbsCachedPdf,2) // Abstract base class for cached p.d.f.s
138146
};
139147

roofit/roofitcore/src/RooAbsCachedPdf.cxx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,13 @@ double RooAbsCachedPdf::analyticalIntegralWN(int code, const RooArgSet* normSet,
374374
RooArgSet *dummy(nullptr);
375375
const std::vector<int> codeList = _anaReg.retrieve(code-1,allVars,anaVars,normSet2,dummy) ;
376376

377-
PdfCacheElem* cache = getCache(normSet2?normSet2:anaVars,false) ;
377+
// Mirror getAnalyticalIntegralWN's lookup key. If the caller passed a null
378+
// normSet to getAnalyticalIntegralWN, the stored normSet2 is non-null but
379+
// empty; use anaVars (content-equivalent to the original allVars) instead,
380+
// so that analyticalIntegralWN and getAnalyticalIntegralWN both key the
381+
// _cacheMgr lookup on the same content and hit the same slot.
382+
const RooArgSet *cacheNset = (normSet2 && !normSet2->empty()) ? normSet2 : anaVars;
383+
PdfCacheElem *cache = getCache(cacheNset, false);
378384
double ret = cache->pdf()->analyticalIntegralWN(codeList[0],normSet,rangeName) ;
379385

380386
if (codeList[1]>0) {
@@ -391,7 +397,8 @@ double RooAbsCachedPdf::analyticalIntegralWN(int code, const RooArgSet* normSet,
391397

392398
void RooAbsCachedPdf::doEval(RooFit::EvalContext &ctx) const
393399
{
394-
getCachePdf(_normSet)->doEval(ctx);
400+
const RooArgSet *nset = _hasCompiledNormSet ? &_compiledNormSet : _normSet;
401+
getCachePdf(nset)->doEval(ctx);
395402
}
396403

397404

@@ -404,6 +411,17 @@ RooAbsCachedPdf::compileForNormSet(RooArgSet const &normSet, RooFit::Detail::Com
404411
std::unique_ptr<RooAbsPdf> pdfClone(static_cast<RooAbsPdf *>(this->Clone()));
405412
ctx.compileServers(*pdfClone, {});
406413

414+
// Pin a stable normalization set on the clone so that doEval() and the
415+
// analytical integration path triggered inside RooNormalizedPdf below hit
416+
// the same _cacheMgr slot. Otherwise the analytical-integral path keys the
417+
// slot on its own (local) integration variable set while doEval keys it on
418+
// the unset (null) _normSet of the clone, and the heavy cache content is
419+
// rebuilt on the first Evaluator step of every fit.
420+
auto *cachedClone = static_cast<RooAbsCachedPdf *>(pdfClone.get());
421+
cachedClone->_compiledNormSet.removeAll();
422+
cachedClone->_compiledNormSet.add(normSet);
423+
cachedClone->_hasCompiledNormSet = true;
424+
407425
auto newArg = std::make_unique<RooFit::Detail::RooNormalizedPdf>(*pdfClone, normSet);
408426

409427
// The direct servers are the cloned pdf (already compiled above) and the

0 commit comments

Comments
 (0)