Skip to content

Commit 0a10c2f

Browse files
Dan RileyDan Riley
authored andcommitted
Always use the simple cache w/o the prompt delayed reader for
non-event trees. Add a policy that does not cache at all, and a policy that adds a separate EventAuxiliary cache to the simple policy.
1 parent d12fcd4 commit 0a10c2f

File tree

4 files changed

+92
-76
lines changed

4 files changed

+92
-76
lines changed

IOPool/Input/src/RootTree.cc

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ namespace edm {
4242
return std::make_unique<RootDelayedReader>(tree, filePtr, inputType);
4343
}
4444
} // namespace
45+
constexpr auto kSimpleCache = roottree::CacheManagerBase::CacheStrategy::kSimple;
46+
constexpr auto kSparseCache = roottree::CacheManagerBase::CacheStrategy::kSparse;
4547

4648
// Used for all RootTrees
4749
// All the other constructors delegate to this one
@@ -55,10 +57,14 @@ namespace edm {
5557
: filePtr_(filePtr),
5658
branchType_(branchType),
5759
entryNumberForIndex_(std::make_unique<std::vector<EntryNumber>>(nIndexes, IndexIntoFile::invalidEntry)),
58-
promptRead_(promptRead or not branchType_ == InEvent),
60+
promptRead_(promptRead),
5961
rootDelayedReader_(makeRootDelayedReader(*this, filePtr, inputType, nIndexes, promptRead_)),
60-
treeCacheManager_(roottree::CacheManagerBase::create(
61-
promptRead_ ? "Simple" : "Sparse", filePtr_, learningEntries, enablePrefetching, branchType_)) {}
62+
treeCacheManager_(
63+
roottree::CacheManagerBase::create(promptRead_ or branchType_ != InEvent ? kSimpleCache : kSparseCache,
64+
filePtr_,
65+
learningEntries,
66+
enablePrefetching,
67+
branchType_)) {}
6268

6369
// Used for Event/Lumi/Run RootTrees
6470
RootTree::RootTree(std::shared_ptr<InputFile> filePtr,
@@ -236,15 +242,17 @@ namespace edm {
236242
return returnValue;
237243
}
238244

239-
void RootTree::setEntryNumber(EntryNumber theEntryNumber) {
240-
treeCacheManager_->setEntryNumber(theEntryNumber, entryNumber_, entries_);
241-
entryNumber_ = theEntryNumber;
245+
void RootTree::setEntryNumber(EntryNumber newEntryNumber) {
246+
treeCacheManager_->setEntryNumber(newEntryNumber, entryNumber_, entries_);
247+
entryNumber_ = newEntryNumber;
242248
}
243249

244250
void RootTree::getEntryForAllBranches() const { treeCacheManager_->getEntryForAllBranches(entryNumber_); }
245251

246252
void RootTree::getEntry(TBranch* branch, EntryNumber entryNumber) const {
253+
LogTrace("IOTrace").format("RootTree::getEntry() begin for branch {} entry {}", branch->GetName(), entryNumber);
247254
treeCacheManager_->getEntry(branch, entryNumber);
255+
LogTrace("IOTrace").format("RootTree::getEntry() end for branch {} entry {}", branch->GetName(), entryNumber);
248256
}
249257

250258
bool RootTree::skipEntries(unsigned int& offset) {

IOPool/Input/src/RootTree.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ namespace edm {
144144
EntryNumber const& entryNumber() const { return entryNumber_; }
145145
EntryNumber const& entryNumberForIndex(unsigned int index) const;
146146
EntryNumber const& entries() const { return entries_; }
147-
void setEntryNumber(EntryNumber theEntryNumber);
147+
void setEntryNumber(EntryNumber newEntryNumber);
148148
void insertEntryForIndex(unsigned int index);
149149
std::vector<std::string> const& branchNames() const { return branchNames_; }
150150
RootDelayedReaderBase* rootDelayedReader() const;
@@ -230,6 +230,7 @@ namespace edm {
230230
unsigned long treeAutoFlush_ = 0;
231231
bool promptRead_;
232232
std::unique_ptr<RootDelayedReaderBase> rootDelayedReader_;
233+
//All access to a ROOT file is serialized
233234
CMS_SA_ALLOW mutable std::unique_ptr<roottree::CacheManagerBase> treeCacheManager_;
234235

235236
TBranch* branchEntryInfoBranch_ = nullptr; //backwards compatibility

IOPool/Input/src/RootTreeCacheManager.cc

Lines changed: 63 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,25 @@
1515

1616
#include "oneapi/tbb/task_arena.h"
1717

18-
//#define CACHESTATS
19-
#define PARALLELUNZIP
20-
2118
namespace edm {
2219
namespace roottree {
2320
void CacheManagerBase::getEntry(TBranch* branch, EntryNumber entryNumber) { branch->GetEntry(entryNumber); }
24-
void CacheManagerBase::getAuxEntry(TBranch* branch, EntryNumber entryNumber) { branch->GetEntry(entryNumber); }
21+
void CacheManagerBase::getAuxEntry(TBranch* branch, EntryNumber entryNumber) { getEntry(branch, entryNumber); }
22+
void CacheManagerBase::getEntryForAllBranches(EntryNumber entryNumber) const { tree_->GetEntry(entryNumber); }
23+
24+
// policy with no TTreeCache
25+
class NoCache : public CacheManagerBase {
26+
public:
27+
NoCache(std::shared_ptr<InputFile> filePtr) : CacheManagerBase(filePtr) {}
28+
void createPrimaryCache(unsigned int cacheSize) override {}
29+
void setEntryNumber(EntryNumber nextEntryNumber, EntryNumber entryNumber, EntryNumber entries) override;
30+
};
31+
32+
void NoCache::setEntryNumber(EntryNumber nextEntryNumber, EntryNumber entryNumber, EntryNumber entries) {
33+
if (nextEntryNumber != entryNumber) {
34+
tree_->LoadTree(nextEntryNumber);
35+
}
36+
}
2537

2638
//
2739
// SimpleCache implements a policy that uses the TTreeCache
@@ -38,7 +50,7 @@ namespace edm {
3850
BranchType const& branchType);
3951
void reset() override;
4052
void createPrimaryCache(unsigned int cacheSize) override;
41-
void setEntryNumber(EntryNumber theEntryNumber, EntryNumber entryNumber, EntryNumber entries) override;
53+
void setEntryNumber(EntryNumber nextEntryNumber, EntryNumber entryNumber, EntryNumber entries) override;
4254
void trainCache(char const* branchNames) override;
4355
void resetTraining() override;
4456
void getEntry(TBranch* branch, EntryNumber entryNumber) override;
@@ -59,27 +71,20 @@ namespace edm {
5971
: CacheManagerBase(filePtr),
6072
branchType_(branchType),
6173
learningEntries_(learningEntries),
62-
enablePrefetching_(enablePrefetching) {
63-
#ifdef PARALLELUNZIP
64-
if (branchType_ == InEvent) {
65-
TTreeCacheUnzip::SetParallelUnzip();
66-
}
67-
#endif
68-
}
74+
enablePrefetching_(enablePrefetching) {}
6975

7076
void SimpleCache::reset() {
71-
if (treeCache_) {
72-
#ifdef CACHESTATS
77+
if (cachestats && treeCache_) {
7378
treeCache_->Print("a cachedbranches");
74-
#endif
75-
treeCache_->DropBranch("*");
7679
}
7780
}
7881

79-
void SimpleCache::setEntryNumber(EntryNumber theEntryNumber, EntryNumber entryNumber, EntryNumber entries) {
80-
if (theEntryNumber != entryNumber) {
81-
tree_->LoadTree(theEntryNumber);
82-
oneapi::tbb::this_task_arena::isolate([&]() { treeCache_->FillBuffer(); });
82+
void SimpleCache::setEntryNumber(EntryNumber nextEntryNumber, EntryNumber entryNumber, EntryNumber entries) {
83+
if (nextEntryNumber != entryNumber) {
84+
oneapi::tbb::this_task_arena::isolate([&]() {
85+
tree_->LoadTree(nextEntryNumber);
86+
treeCache_->FillBuffer();
87+
});
8388
}
8489
}
8590

@@ -92,35 +97,25 @@ namespace edm {
9297
}
9398

9499
void SimpleCache::createPrimaryCache(unsigned int cacheSize) {
95-
#ifdef PARALLELUNZIP
96-
tree_->SetParallelUnzip(branchType_ == InEvent);
97-
#endif
98-
99100
tree_->SetCacheSize(static_cast<Long64_t>(cacheSize));
100101
treeCache_ = dynamic_cast<TTreeCache*>(filePtr_->getCacheRead(tree_));
101-
102102
assert(treeCache_);
103103

104104
treeCache_->SetEnablePrefetching(enablePrefetching_);
105105
treeCache_->SetLearnEntries(learningEntries_);
106-
treeCache_->SetOptimizeMisses(true);
107106
}
108107

109108
void SimpleCache::resetTraining() {
110-
reset();
111109
trainCache(nullptr);
112110
treeCache_->SetLearnEntries(learningEntries_);
113111
}
114112

115113
void SimpleCache::trainCache(char const* branchNames) {
116-
if (branchType_ != InEvent) {
117-
tree_->SetParallelUnzip(false);
118-
}
119-
treeCache_->StartLearningPhase();
120114
tree_->LoadTree(0);
121-
tree_->SetCacheEntryRange(0, tree_->GetEntries());
115+
treeCache_->StartLearningPhase();
116+
treeCache_->SetEntryRange(0, tree_->GetEntries());
122117
if (branchNames) {
123-
tree_->AddBranchToCache(branchNames, kTRUE);
118+
treeCache_->AddBranch(branchNames, kTRUE);
124119
}
125120
}
126121

@@ -129,7 +124,7 @@ namespace edm {
129124
// patterns typical of late-stage analysis jobs, which may
130125
// read only a sparse selection of branches from selected
131126
// events. Handles many special cases by swapping between
132-
// different specialized caches. Is not thread safe.
127+
// different specialized caches. Not thread safe.
133128
//
134129
class SparseReadCache : public CacheManagerBase {
135130
public:
@@ -146,14 +141,13 @@ namespace edm {
146141
void createPrimaryCache(unsigned int cacheSize) override;
147142
void resetTraining() override;
148143
void reset() override;
149-
void setEntryNumber(EntryNumber theEntryNumber, EntryNumber entryNumber, EntryNumber entries) override;
144+
void setEntryNumber(EntryNumber nextEntryNumber, EntryNumber entryNumber, EntryNumber entries) override;
150145
void trainCache(char const* branchNames) override;
151146
void getEntry(TBranch* branch, EntryNumber entryNumber) override;
152147
void getAuxEntry(TBranch* auxBranch, EntryNumber entryNumber) override;
153148
void init(TTree* tree, unsigned int treeAutoFlush) override;
154149
void reserve(Int_t branchCount) override;
155150
void getEntryForAllBranches(EntryNumber entryNumber) const override;
156-
;
157151

158152
private:
159153
void getEntryUsingCache(TBranch* branch, EntryNumber entryNumber, TTreeCache* cache);
@@ -413,26 +407,26 @@ namespace edm {
413407
void SparseReadCache::resetTraining() { trainNow_ = true; }
414408

415409
void SparseReadCache::reset() {
416-
#ifdef CACHESTATS
417-
if (treeCache_)
418-
treeCache_->Print("a cachedbranches");
419-
if (rawTreeCache_)
420-
rawTreeCache_->Print("a cachedbranches");
421-
if (triggerTreeCache_)
422-
triggerTreeCache_->Print("a cachedbranches");
423-
if (rawTriggerTreeCache_)
424-
rawTriggerTreeCache_->Print("a cachedbranches");
425-
if (auxCache_)
426-
auxCache_->Print("a cachedbranches");
427-
#endif
410+
if constexpr (cachestats) {
411+
if (treeCache_)
412+
treeCache_->Print("a cachedbranches");
413+
if (rawTreeCache_)
414+
rawTreeCache_->Print("a cachedbranches");
415+
if (triggerTreeCache_)
416+
triggerTreeCache_->Print("a cachedbranches");
417+
if (rawTriggerTreeCache_)
418+
rawTriggerTreeCache_->Print("a cachedbranches");
419+
if (auxCache_)
420+
auxCache_->Print("a cachedbranches");
421+
}
428422
treeCache_.reset();
429423
rawTreeCache_.reset();
430424
triggerTreeCache_.reset();
431425
rawTriggerTreeCache_.reset();
432426
auxCache_.reset();
433427
}
434428

435-
void SparseReadCache::setEntryNumber(EntryNumber theEntryNumber, EntryNumber entryNumber, EntryNumber entries) {
429+
void SparseReadCache::setEntryNumber(EntryNumber nextEntryNumber, EntryNumber entryNumber, EntryNumber entries) {
436430
{
437431
auto guard = filePtr_->setCacheReadTemporarily(treeCache_.get(), tree_);
438432

@@ -441,45 +435,45 @@ namespace edm {
441435
// However, because reading one event in the cluster is supposed to be equivalent to reading all events in the cluster,
442436
// we're not incurring additional over-reading - we're just doing it more efficiently.
443437
// NOTE: Constructor guarantees treeAutoFlush_ is positive, even if TTree->GetAutoFlush() is negative.
444-
if (theEntryNumber < entryNumber and theEntryNumber >= 0) {
438+
if (nextEntryNumber < entryNumber and nextEntryNumber >= 0) {
445439
//We started reading the file near the end, now we need to correct for the learning length
446440
if (switchOverEntry_ > tree_->GetEntries()) {
447441
switchOverEntry_ = switchOverEntry_ - tree_->GetEntries();
448442
if (rawTreeCache_) {
449-
rawTreeCache_->SetEntryRange(theEntryNumber, switchOverEntry_);
443+
rawTreeCache_->SetEntryRange(nextEntryNumber, switchOverEntry_);
450444
rawTreeCache_->FillBuffer();
451445
}
452446
}
453447
if (performedSwitchOver_ and triggerTreeCache_) {
454448
//We are using the triggerTreeCache_ not the rawTriggerTreeCache_.
455449
//The triggerTreeCache was originally told to start from an entry further in the file.
456-
triggerTreeCache_->SetEntryRange(theEntryNumber, tree_->GetEntries());
450+
triggerTreeCache_->SetEntryRange(nextEntryNumber, tree_->GetEntries());
457451
} else if (rawTriggerTreeCache_) {
458-
//move the switch point to the end of the cluster holding theEntryNumber
452+
//move the switch point to the end of the cluster holding nextEntryNumber
459453
rawTriggerSwitchOverEntry_ = -1;
460-
TTree::TClusterIterator clusterIter = tree_->GetClusterIterator(theEntryNumber);
461-
while ((rawTriggerSwitchOverEntry_ < theEntryNumber) || (rawTriggerSwitchOverEntry_ <= 0)) {
454+
TTree::TClusterIterator clusterIter = tree_->GetClusterIterator(nextEntryNumber);
455+
while ((rawTriggerSwitchOverEntry_ < nextEntryNumber) || (rawTriggerSwitchOverEntry_ <= 0)) {
462456
rawTriggerSwitchOverEntry_ = clusterIter();
463457
}
464-
rawTriggerTreeCache_->SetEntryRange(theEntryNumber, rawTriggerSwitchOverEntry_);
458+
rawTriggerTreeCache_->SetEntryRange(nextEntryNumber, rawTriggerSwitchOverEntry_);
465459
}
466460
}
467-
if ((theEntryNumber < static_cast<EntryNumber>(entryNumber - treeAutoFlush_)) && (treeCache_) &&
461+
if ((nextEntryNumber < static_cast<EntryNumber>(entryNumber - treeAutoFlush_)) && (treeCache_) &&
468462
(!treeCache_->IsLearning()) && (entries > 0) && (switchOverEntry_ >= 0)) {
469-
treeCache_->SetEntryRange(theEntryNumber, entries);
463+
treeCache_->SetEntryRange(nextEntryNumber, entries);
470464
treeCache_->FillBuffer();
471465
}
472466

473-
tree_->LoadTree(theEntryNumber);
467+
tree_->LoadTree(nextEntryNumber);
474468
}
475-
if (treeCache_ && trainNow_ && theEntryNumber >= 0) {
476-
startTraining(theEntryNumber);
469+
if (treeCache_ && trainNow_ && nextEntryNumber >= 0) {
470+
startTraining(nextEntryNumber);
477471
trainNow_ = false;
478472
trainedSet_.clear();
479473
triggerSet_.clear();
480474
rawTriggerSwitchOverEntry_ = -1;
481475
}
482-
if (treeCache_ && treeCache_->IsLearning() && switchOverEntry_ >= 0 && theEntryNumber >= switchOverEntry_) {
476+
if (treeCache_ && treeCache_->IsLearning() && switchOverEntry_ >= 0 && nextEntryNumber >= switchOverEntry_) {
483477
stopTraining();
484478
}
485479
}
@@ -530,17 +524,20 @@ namespace edm {
530524
triggerSet_.reserve(branchCount);
531525
}
532526

533-
std::unique_ptr<CacheManagerBase> CacheManagerBase::create(const std::string& strategy,
527+
std::unique_ptr<CacheManagerBase> CacheManagerBase::create(CacheStrategy strategy,
534528
std::shared_ptr<InputFile> filePtr,
535529
unsigned int learningEntries,
536530
bool enablePrefetching,
537531
BranchType const& branchType) {
538-
if (strategy == "Simple") {
532+
if (strategy == CacheStrategy::kSimple) {
539533
return std::make_unique<SimpleCache>(filePtr, learningEntries, enablePrefetching, branchType);
540-
} else if (strategy == "Sparse") {
534+
} else if (strategy == CacheStrategy::kSparse) {
541535
return std::make_unique<SparseReadCache>(filePtr, learningEntries, enablePrefetching, branchType);
536+
} else if (strategy == CacheStrategy::kNone) {
537+
return std::make_unique<NoCache>(filePtr);
542538
}
543-
throw cms::Exception("BadConfig") << "CacheManagerBase: unknown cache strategy requested: " << strategy;
539+
540+
throw cms::Exception("BadConfig") << "CacheManagerBase: unknown cache strategy requested";
544541
}
545542
} // namespace roottree
546543
} // namespace edm

IOPool/Input/src/RootTreeCacheManager.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,19 @@ namespace edm {
3131

3232
class CacheManagerBase {
3333
public:
34+
enum class CacheStrategy {
35+
kNone,
36+
kSimple,
37+
kSparse,
38+
};
39+
3440
CacheManagerBase(std::shared_ptr<InputFile> filePtr) : filePtr_(filePtr) {}
3541
virtual ~CacheManagerBase() = default;
3642

3743
virtual void createPrimaryCache(unsigned int cacheSize) = 0;
38-
virtual void setEntryNumber(EntryNumber theEntryNumber, EntryNumber entryNumber, EntryNumber entries) = 0;
44+
// set the tree to read at nextEntryNumber; the current entryNumber is used when detecting
45+
// non-serial reads, especially skipping backwards in the tree
46+
virtual void setEntryNumber(EntryNumber nextEntryNumber, EntryNumber entryNumber, EntryNumber entries) = 0;
3947

4048
virtual void resetTraining() {}
4149
virtual void reset() {}
@@ -44,9 +52,9 @@ namespace edm {
4452
virtual void reserve(Int_t branchCount) {}
4553
virtual void getEntry(TBranch* branch, EntryNumber entryNumber);
4654
virtual void getAuxEntry(TBranch* auxBranch, EntryNumber entryNumber);
47-
virtual void getEntryForAllBranches(EntryNumber entryNumber) const = 0;
55+
virtual void getEntryForAllBranches(EntryNumber entryNumber) const;
4856

49-
static std::unique_ptr<CacheManagerBase> create(const std::string& strategy,
57+
static std::unique_ptr<CacheManagerBase> create(CacheStrategy strategy,
5058
std::shared_ptr<InputFile> filePtr,
5159
unsigned int learningEntries,
5260
bool enablePrefetching,
@@ -55,6 +63,8 @@ namespace edm {
5563
protected:
5664
std::shared_ptr<InputFile> filePtr_;
5765
TTree* tree_ = nullptr;
66+
67+
static constexpr bool cachestats = false;
5868
};
5969

6070
} // namespace roottree

0 commit comments

Comments
 (0)