Skip to content

Commit e18ec93

Browse files
sawenzelclaude
andcommitted
Prepare the TPC digitizer for concurrent digitizers
This makes several TPC digitizers usable side by side in one process, as a preparation for MT digitization. - Each DigitContainer keeps its own copy of the dead channel map, because CDBInterface::getDeadChannelMap() rebuilds the shared map on every call. - The one-time settings report moves from the flush path into updateCalibrations(). - Digitizer::setSCDistortionsFrom() shares the distortion maps and their scaling with another digitizer. - digitizeSector() takes an optional mutex for the calls that read calibrations through the CDBInterface. - The output is unchanged. https://its.cern.ch/jira/browse/O2-7309 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent fcda4a9 commit e18ec93

6 files changed

Lines changed: 45 additions & 15 deletions

File tree

‎Detectors/TPC/simulation/include/TPCSimulation/DigitContainer.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ class DigitContainer
9696
std::unique_ptr<DigitTime::PrevDigitInfoArray> mPrevDigArr; ///< Keep track of ToT and ion tail cumul from last time bin
9797
o2::utils::DebugStreamer mStreamer; ///< Debug streamer
9898
const CalPad* mPadParams[3] = {nullptr, nullptr, nullptr}; //!< Ion tail fraction, ion tail slope and common mode k-values per pad
99-
const CalDet<bool>* mDeadMap = nullptr; //!< Dead channel map
99+
const CalDet<bool>* mDeadMap = nullptr; //!< Dead channel map, points to mDeadMapCopy if set
100+
std::unique_ptr<CalDet<bool>> mDeadMapCopy; //!< Own copy of the dead channel map, which the CDBInterface rebuilds on each access
100101
bool mCMCEnabled = false; //!< Common mode correction enabled in the FEE config (DigiMode Auto)
101102
bool mCalibrationsUpdated = false; //!< Whether updateCalibrations was called
102103
SAMPAProcessing* mSAMPAProcessing = nullptr; //!< SAMPAProcessing used for the output, the singleton if not set

‎Detectors/TPC/simulation/include/TPCSimulation/Digitizer.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ class Digitizer
143143
/// in case of scaled distortions, the distortions can be recalculated to ensure consistent distortions and corrections
144144
void recalculateDistortions();
145145

146+
/// Use the distortion maps and scaling of another digitizer, which keeps ownership of the maps
147+
void setSCDistortionsFrom(const Digitizer& other);
148+
146149
/// Use digitizer-owned random rings filled from seed and positioned per sector and timeframe in init(),
147150
/// so that the digits of a sector do not depend on which sectors were processed before
148151
/// \param seed base seed, typically DigiParams.seed

‎Detectors/TPC/simulation/src/DigitContainer.cxx‎

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de
1515

1616
#include "TPCSimulation/DigitContainer.h"
17+
#include <atomic>
1718
#include <memory>
1819
#include <fairlogger/Logger.h>
1920
#include "TPCBase/Mapper.h"
@@ -59,15 +60,6 @@ void DigitContainer::fillOutputContainer(std::vector<Digit>& output,
5960
mPrevDigArr = std::make_unique<DigitTime::PrevDigitInfoArray>();
6061
}
6162

62-
static bool reportedSettings = false;
63-
if (!reportedSettings) {
64-
reportSettings();
65-
if (mDeadMap) {
66-
LOGP(info, "Using dead map with {} masked pads", mDeadMap->getSum<int>());
67-
}
68-
reportedSettings = true;
69-
}
70-
7163
for (auto& time : mTimeBins) {
7264
/// the time bins between the last event and the timing of this event are uncorrelated and can be written out
7365
/// OR the readout is triggered (i.e. not continuous) and we can dump everything in any case, as long it is within one drift time interval
@@ -162,12 +154,25 @@ void DigitContainer::updateCalibrations()
162154
}
163155

164156
// dead channel map
165-
mDeadMap = eleParam.applyDeadMap ? &cdb.getDeadChannelMap() : nullptr;
157+
mDeadMap = nullptr;
158+
mDeadMapCopy.reset();
159+
if (eleParam.applyDeadMap) {
160+
mDeadMapCopy = std::make_unique<CalDet<bool>>(cdb.getDeadChannelMap());
161+
mDeadMap = mDeadMapCopy.get();
162+
}
166163

167164
// common mode correction in the FEE, needed to resolve DigiMode Auto
168165
mCMCEnabled = (eleParam.DigiMode == DigitzationMode::Auto) && cdb.getFEEConfig().isCMCEnabled();
169166

170167
mCalibrationsUpdated = true;
168+
169+
static std::atomic<bool> reportedSettings{false};
170+
if (!reportedSettings.exchange(true)) {
171+
reportSettings();
172+
if (mDeadMap) {
173+
LOGP(info, "Using dead map with {} masked pads", mDeadMap->getSum<int>());
174+
}
175+
}
171176
}
172177

173178
void DigitContainer::reportSettings()

‎Detectors/TPC/simulation/src/Digitizer.cxx‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,16 @@ void Digitizer::setStartTime(double time)
295295
mDigitContainer.setStartTime(starttimebin);
296296
}
297297

298+
void Digitizer::setSCDistortionsFrom(const Digitizer& other)
299+
{
300+
mSpaceChargeOwned.reset();
301+
mSpaceCharge = other.mSpaceCharge;
302+
mSpaceChargeDer = other.mSpaceChargeDer;
303+
mUseSCDistortions = other.mUseSCDistortions;
304+
mLumiScaleFactor = other.mLumiScaleFactor;
305+
mUseScaledDistortions = other.mUseScaledDistortions;
306+
}
307+
298308
void Digitizer::setLumiScaleFactor()
299309
{
300310
mLumiScaleFactor = (CorrMapParam::Instance().lumiInst - mSpaceCharge->getMeanLumi()) / mSpaceChargeDer->getMeanLumi();

‎Steer/DigitizerWorkflow/src/TPCSectorDigitization.cxx‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,23 @@ std::string getBranchNameRight(int sector)
4242

4343
std::vector<dataformats::RangeReference<int, int>> digitizeSector(Digitizer& digitizer, const steer::DigitizationContext& context,
4444
const std::vector<TChain*>& simChains, int sector, ULong64_t timeframe,
45-
SectorFlushBuffers& buffers, const std::function<void()>& onFlush)
45+
SectorFlushBuffers& buffers, const std::function<void()>& onFlush,
46+
std::mutex* cdbMutex)
4647
{
48+
// locks cdbMutex, if given, for calls that read calibrations through the CDBInterface
49+
auto cdbLock = [cdbMutex]() { return cdbMutex ? std::unique_lock<std::mutex>(*cdbMutex) : std::unique_lock<std::mutex>(); };
50+
4751
std::vector<dataformats::RangeReference<int, int>> events;
4852
const bool isContinuous = digitizer.isContinuousReadout();
4953
const auto& irecords = context.getEventRecords();
5054
const auto& eventParts = context.getEventParts();
5155

5256
digitizer.setSector(sector);
5357
digitizer.setSeedingTimeframe(timeframe);
54-
digitizer.init();
58+
{
59+
auto lock = cdbLock();
60+
digitizer.init();
61+
}
5562

5663
size_t digitCounter = 0;
5764
auto flush = [&](bool finalFlush = false) {
@@ -69,6 +76,7 @@ std::vector<dataformats::RangeReference<int, int>> digitizeSector(Digitizer& dig
6976
double time = hbfu.getFirstIRofTF(o2::InteractionRecord(0, hbfu.orbitFirstSampled)).bc2ns() / 1000.;
7077
digitizer.setOutputDigitTimeOffset(time);
7178
if (!irecords.empty()) {
79+
auto lock = cdbLock();
7280
digitizer.setStartTime(irecords[0].getTimeNS() / 1000.f);
7381
}
7482
}
@@ -80,6 +88,7 @@ std::vector<dataformats::RangeReference<int, int>> digitizeSector(Digitizer& dig
8088
LOG(info) << "TPC: Event time " << eventTime << " us";
8189
digitizer.setEventTime(eventTime);
8290
if (!isContinuous) {
91+
auto lock = cdbLock();
8392
digitizer.setStartTime(eventTime);
8493
}
8594
size_t startSize = digitCounter;

‎Steer/DigitizerWorkflow/src/TPCSectorDigitization.h‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define STEER_DIGITIZERWORKFLOW_TPCSECTORDIGITIZATION_H_
1414

1515
#include <functional>
16+
#include <mutex>
1617
#include <vector>
1718
#include <RtypesCore.h>
1819
#include "CommonDataFormat/RangeReference.h"
@@ -43,11 +44,12 @@ struct SectorFlushBuffers {
4344
/// Digitize all collisions of one sector of a timeframe.
4445
/// After each flush the new output is in buffers and onFlush is called on the calling thread.
4546
/// The function makes no DPL calls. Concurrent calls need one Digitizer with sector seeding and one set of chains
46-
/// per thread; Digitizer::init() is called here and is not thread-safe across Digitizer instances.
47+
/// per thread, and a common cdbMutex, which serialises the calls that read calibrations through the CDBInterface.
4748
/// \return the digit groups, one per collision part in triggered mode, one for the timeframe in continuous mode
4849
std::vector<dataformats::RangeReference<int, int>> digitizeSector(Digitizer& digitizer, const steer::DigitizationContext& context,
4950
const std::vector<TChain*>& simChains, int sector, ULong64_t timeframe,
50-
SectorFlushBuffers& buffers, const std::function<void()>& onFlush);
51+
SectorFlushBuffers& buffers, const std::function<void()>& onFlush,
52+
std::mutex* cdbMutex = nullptr);
5153

5254
} // namespace tpc
5355
} // namespace o2

0 commit comments

Comments
 (0)