From c587bac190a5293bbffbb4581dc9e9a24c1ff9f9 Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Tue, 10 Jun 2025 09:46:02 +0200 Subject: [PATCH 001/315] Use typed custom allocator for some thrust containers (#14371) --- .../GPU/ITStrackingGPU/TrackingKernels.h | 5 +- .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 5 +- .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 60 +++++++++++++++---- .../include/ITStracking/ExternalAllocator.h | 2 +- .../tracking/include/ITStracking/TimeFrame.h | 29 +++++---- GPU/GPUTracking/Global/GPUChainITS.cxx | 2 +- 6 files changed, 74 insertions(+), 29 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h index 54aa0e01c8a78..09c8c39725efa 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h @@ -19,6 +19,7 @@ namespace o2::its { class CellSeed; +class ExternalAllocator; namespace gpu { #ifdef GPUCA_GPUCODE // GPUg() global kernels must only when compiled by GPU compiler @@ -178,7 +179,8 @@ void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, int filterCellNeighboursHandler(gpuPair*, int*, - unsigned int); + unsigned int, + o2::its::ExternalAllocator* = nullptr); template void processNeighboursHandler(const int startLayer, @@ -191,6 +193,7 @@ void processNeighboursHandler(const int startLayer, gsl::span neighboursDeviceLUTs, const TrackingFrameInfo** foundTrackingFrameInfo, bounded_vector& seedsHost, + o2::its::ExternalAllocator*, const float bz, const float MaxChi2ClusterAttachment, const float maxChi2NDF, diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index 871fd7a95f890..89d2b5aeffe63 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -18,6 +18,7 @@ #include "ITStrackingGPU/TrackerTraitsGPU.h" #include "ITStrackingGPU/TrackingKernels.h" #include "ITStracking/TrackingConfigParam.h" + namespace o2::its { constexpr int UnusedIndex{-1}; @@ -209,7 +210,8 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) filterCellNeighboursHandler(mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), mTimeFrameGPU->getDeviceNeighbours(iLayer), - nNeigh); + nNeigh, + mTimeFrameGPU->getExternalAllocator()); } mTimeFrameGPU->createNeighboursDeviceArray(); mTimeFrameGPU->unregisterRest(); @@ -236,6 +238,7 @@ void TrackerTraitsGPU::findRoads(const int iteration) mTimeFrameGPU->getDeviceNeighboursLUTs(), mTimeFrameGPU->getDeviceArrayTrackingFrameInfo(), trackSeeds, + mTimeFrameGPU->getExternalAllocator(), this->mBz, this->mTrkParams[0].MaxChi2ClusterAttachment, this->mTrkParams[0].MaxChi2NDF, diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 301f37767c160..18c89d39adda0 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -28,6 +28,7 @@ #include "ITStracking/Constants.h" #include "ITStracking/IndexTableUtils.h" #include "ITStracking/MathUtils.h" +#include "ITStracking/ExternalAllocator.h" #include "DataFormatsITS/TrackITS.h" #include "ReconstructionDataFormats/Vertex.h" @@ -35,8 +36,6 @@ #include "ITStrackingGPU/TrackingKernels.h" #include "ITStrackingGPU/Utils.h" -#include "GPUCommonHelpers.h" - #ifndef __HIPCC__ #define THRUST_NAMESPACE thrust::cuda #else @@ -64,6 +63,37 @@ GPUdii() float Sq(float v) namespace gpu { +template +class TypedAllocator : public thrust::device_allocator +{ + public: + using value_type = T; + using pointer = T*; + + template + struct rebind { + using other = TypedAllocator; + }; + + explicit TypedAllocator(ExternalAllocator* allocPtr) + : mInternalAllocator(allocPtr) {} + + T* allocate(size_t n) + { + return reinterpret_cast(mInternalAllocator->allocate(n * sizeof(T))); + } + + void deallocate(T* p, size_t n) + { + char* raw_ptr = reinterpret_cast(p); + size_t bytes = n * sizeof(T); + mInternalAllocator->deallocate(raw_ptr, bytes); // redundant as internal dealloc is no-op. + } + + private: + ExternalAllocator* mInternalAllocator; +}; + GPUd() const int4 getBinsRect(const Cluster& currentCluster, const int layerIndex, const o2::its::IndexTableUtils& utils, const float z1, const float z2, float maxdeltaz, float maxdeltaphi) @@ -1117,7 +1147,8 @@ void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, int filterCellNeighboursHandler(gpuPair* cellNeighbourPairs, int* cellNeighbours, - unsigned int nNeigh) + unsigned int nNeigh, + o2::its::ExternalAllocator* allocator) { thrust::device_ptr> neighVectorPairs(cellNeighbourPairs); thrust::device_ptr validNeighs(cellNeighbours); @@ -1140,6 +1171,7 @@ void processNeighboursHandler(const int startLayer, gsl::span neighboursDeviceLUTs, const TrackingFrameInfo** foundTrackingFrameInfo, bounded_vector& seedsHost, + o2::its::ExternalAllocator* allocator, const float bz, const float maxChi2ClusterAttachment, const float maxChi2NDF, @@ -1148,8 +1180,10 @@ void processNeighboursHandler(const int startLayer, const int nBlocks, const int nThreads) { - thrust::device_vector foundSeedsTable(nCells[startLayer] + 1); // Shortcut: device_vector skips central memory management, we are relying on the contingency. - // TODO: fix this. + auto allocInt = gpu::TypedAllocator(allocator); + auto allocCellSeed = gpu::TypedAllocator(allocator); + thrust::device_vector> foundSeedsTable(nCells[startLayer] + 1, 0, allocInt); // Shortcut: device_vector skips central memory management, we are relying on the contingency. + // TODO: fix this. gpu::processNeighboursKernel<<>>( @@ -1172,8 +1206,8 @@ void processNeighboursHandler(const int startLayer, matCorrType); gpu::cubExclusiveScanInPlace(foundSeedsTable, nCells[startLayer] + 1); - thrust::device_vector updatedCellId(foundSeedsTable.back()); - thrust::device_vector updatedCellSeed(foundSeedsTable.back()); + thrust::device_vector> updatedCellId(foundSeedsTable.back(), 0, allocInt); + thrust::device_vector> updatedCellSeed(foundSeedsTable.back(), allocCellSeed); gpu::processNeighboursKernel<<>>( startLayer, @@ -1195,13 +1229,13 @@ void processNeighboursHandler(const int startLayer, matCorrType); int level = startLevel; - thrust::device_vector lastCellId; - thrust::device_vector lastCellSeed; + thrust::device_vector> lastCellId(allocInt); + thrust::device_vector> lastCellSeed(allocCellSeed); for (int iLayer{startLayer - 1}; iLayer > 0 && level > 2; --iLayer) { lastCellSeed.swap(updatedCellSeed); lastCellId.swap(updatedCellId); - thrust::device_vector().swap(updatedCellSeed); - thrust::device_vector().swap(updatedCellId); + thrust::device_vector>(allocCellSeed).swap(updatedCellSeed); + thrust::device_vector>(allocInt).swap(updatedCellId); auto lastCellSeedSize{lastCellSeed.size()}; foundSeedsTable.resize(lastCellSeedSize + 1); thrust::fill(foundSeedsTable.begin(), foundSeedsTable.end(), 0); @@ -1253,8 +1287,7 @@ void processNeighboursHandler(const int startLayer, propagator, matCorrType); } - - thrust::device_vector outSeeds(updatedCellSeed.size()); + thrust::device_vector> outSeeds(updatedCellSeed.size(), allocCellSeed); auto end = thrust::copy_if(updatedCellSeed.begin(), updatedCellSeed.end(), outSeeds.begin(), gpu::seed_selector(1.e3, maxChi2NDF * ((startLevel + 2) * 2 - 5))); auto s{end - outSeeds.begin()}; seedsHost.reserve(seedsHost.size() + s); @@ -1367,6 +1400,7 @@ template void processNeighboursHandler<7>(const int startLayer, gsl::span neighboursDeviceLUTs, const TrackingFrameInfo** foundTrackingFrameInfo, bounded_vector& seedsHost, + o2::its::ExternalAllocator*, const float bz, const float maxChi2ClusterAttachment, const float maxChi2NDF, diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ExternalAllocator.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ExternalAllocator.h index 9bdb2905ba9ba..1628bbc52776b 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ExternalAllocator.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ExternalAllocator.h @@ -23,8 +23,8 @@ class ExternalAllocator { public: virtual void* allocate(size_t) = 0; + virtual void deallocate(char*, size_t) = 0; }; - } // namespace o2::its #endif diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h index f6bb9a9b11e66..c3eb25f8d0699 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h @@ -230,7 +230,23 @@ struct TimeFrame { void setBz(float bz) { mBz = bz; } float getBz() const { return mBz; } - virtual void setDevicePropagator(const o2::base::PropagatorImpl*) { return; } + void setExternalAllocator(ExternalAllocator* allocator) + { + if (mIsGPU) { + LOGP(debug, "Setting timeFrame allocator to external"); + mAllocator = allocator; + mExtAllocator = true; // to be removed + } else { + LOGP(fatal, "External allocator is currently only supported for GPU"); + } + } + + ExternalAllocator* getExternalAllocator() { return mAllocator; } + + virtual void setDevicePropagator(const o2::base::PropagatorImpl*) + { + return; + }; const o2::base::PropagatorImpl* getDevicePropagator() const { return mPropagatorDevice; } template @@ -277,17 +293,6 @@ struct TimeFrame { // State if memory will be externally managed. bool mExtAllocator = false; ExternalAllocator* mAllocator = nullptr; - void setExternalAllocator(ExternalAllocator* allocator) - { - if (mIsGPU) { - LOGP(debug, "Setting timeFrame allocator to external"); - mAllocator = allocator; - mExtAllocator = true; // to be removed - } else { - LOGP(fatal, "External allocator is currently only supported for GPU"); - } - } - void setExtAllocator(bool ext) { mExtAllocator = ext; } bool getExtAllocator() const { return mExtAllocator; } std::array, nLayers> mUnsortedClusters; diff --git a/GPU/GPUTracking/Global/GPUChainITS.cxx b/GPU/GPUTracking/Global/GPUChainITS.cxx index bcb99fff87a64..cbc19100fe4fa 100644 --- a/GPU/GPUTracking/Global/GPUChainITS.cxx +++ b/GPU/GPUTracking/Global/GPUChainITS.cxx @@ -30,7 +30,7 @@ class GPUFrameworkExternalAllocator final : public o2::its::ExternalAllocator { return mFWReco->AllocateDirectMemory(size, GPUMemoryResource::MEMORY_GPU); } - + void deallocate(char* ptr, size_t) override {} void setReconstructionFramework(o2::gpu::GPUReconstruction* fwr) { mFWReco = fwr; } private: From 3d2a03c131a498addd742a957ae376d622f11a44 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 10 Jun 2025 10:22:19 +0200 Subject: [PATCH 002/315] ITS: fix Cell reorder --- Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h index 097499c05bd3b..fc3656aef800c 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h @@ -67,7 +67,7 @@ class CellSeed final : public o2::track::TrackParCovF { public: GPUhdDefault() CellSeed() = default; - GPUhd() CellSeed(int innerL, int cl0, int cl1, int cl2, int trkl0, int trkl1, o2::track::TrackParCovF& tpc, float chi2) : o2::track::TrackParCovF{tpc}, mLevel{1}, mChi2{chi2} + GPUhd() CellSeed(int innerL, int cl0, int cl1, int cl2, int trkl0, int trkl1, o2::track::TrackParCovF& tpc, float chi2) : o2::track::TrackParCovF(tpc), mChi2(chi2), mLevel(1) { setUserField(innerL); mClusters[innerL + 0] = cl0; From fdab6dbdadf7b90707ebfbd5c99c932c97fc0f90 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 10 Jun 2025 13:06:55 +0200 Subject: [PATCH 003/315] ITS: make clang-tidy happy (#14372) * ITS: selective clang-tidy finds Signed-off-by: Felix Schlepper * ITS: IOUtils remove obsolte functions --------- Signed-off-by: Felix Schlepper --- .../tracking/include/ITStracking/IOUtils.h | 4 - .../tracking/include/ITStracking/TimeFrame.h | 4 +- .../tracking/include/ITStracking/Tracker.h | 6 +- .../tracking/include/ITStracking/Vertexer.h | 2 +- .../include/ITStracking/VertexerTraits.h | 6 +- Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx | 1 - Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx | 123 ++---------------- .../ITSMFT/ITS/tracking/src/TimeFrame.cxx | 20 ++- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 14 +- .../ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 6 +- .../ITSMFT/ITS/tracking/src/Vertexer.cxx | 1 - .../ITS/tracking/src/VertexerTraits.cxx | 14 +- 12 files changed, 49 insertions(+), 152 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h index 57cc44291ba09..0ada9dfbc6188 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h @@ -72,10 +72,6 @@ inline static const o2::itsmft::ChipMappingITS& getChipMappingITS() return MP; } -std::vector> loadLabels(const int, const std::string&); -void writeRoadsReport(std::ofstream&, std::ofstream&, std::ofstream&, const std::vector>>&, - const std::unordered_map&); - template o2::math_utils::Point3D extractClusterData(const itsmft::CompClusterExt& c, iterator& iter, const itsmft::TopologyDictionary* dict, T& sig2y, T& sig2z) { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h index c3eb25f8d0699..1620350c68034 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h @@ -333,8 +333,8 @@ struct TimeFrame { bounded_vector mBogusClusters; /// keep track of clusters with wild coordinates bounded_vector> mRoadLabels; - int mCutClusterMult; - int mCutVertexMult; + int mCutClusterMult{-999}; + int mCutVertexMult{-999}; // Vertexer std::vector> mNTrackletsPerROF; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index d8236fed51240..b393d743809fd 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -63,8 +63,8 @@ class Tracker void adoptTimeFrame(TimeFrame& tf); void clustersToTracks( - LogFunc = [](const std::string& s) { std::cout << s << '\n'; }, - LogFunc = [](const std::string& s) { std::cerr << s << '\n'; }); + const LogFunc& = [](const std::string& s) { std::cout << s << '\n'; }, + const LogFunc& = [](const std::string& s) { std::cerr << s << '\n'; }); void setParameters(const std::vector& p) { mTrkParams = p; } void setMemoryPool(std::shared_ptr& pool) { mMemoryPool = pool; } @@ -113,7 +113,7 @@ class Tracker Roading, NStates, }; - State mCurState; + State mCurState{TFInit}; static constexpr std::array StateNames{"TimeFrame initialisation", "Tracklet finding", "Cell finding", "Neighbour finding", "Road finding"}; }; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h index 07d9d60243a95..63dd41b4a0a8f 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h @@ -106,7 +106,7 @@ class Vertexer Finding, NStates, }; - State mCurState; + State mCurState{Init}; static constexpr std::array StateNames{"Initialisation", "Tracklet finding", "Tracklet validation", "Vertex finding"}; }; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index 1ec6adc9efab4..e4ecced6d67fb 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -86,9 +86,9 @@ class VertexerTraits bounded_vector*, const int iteration = 0); - const bounded_vector> selectClusters(const int* indexTable, - const std::array& selectedBinsRect, - const IndexTableUtils& utils); + bounded_vector> selectClusters(const int* indexTable, + const std::array& selectedBinsRect, + const IndexTableUtils& utils); // utils auto& getVertexingParameters() { return mVrtParams; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx b/Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx index beac55579656f..78f6683675947 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Cluster.cxx @@ -24,7 +24,6 @@ using namespace o2::its; using math_utils::computePhi; using math_utils::getNormalizedPhi; -using math_utils::hypot; Cluster::Cluster(const float x, const float y, const float z, const int index) : xCoordinate{x}, diff --git a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx index 152d4e1be7d04..2638b437d61f8 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx @@ -15,12 +15,15 @@ #include "ITStracking/IOUtils.h" +#include +#include +#include +#include #include #include #include #include #include -#include #include #include "ITSBase/GeometryTGeo.h" @@ -35,10 +38,7 @@ constexpr int PrimaryVertexLayerId{-1}; constexpr int EventLabelsSeparator{-1}; } // namespace -namespace o2 -{ -namespace its -{ +using namespace o2::its; /// convert compact clusters to 3D spacepoints void ioutils::convertCompactClusters(gsl::span clusters, @@ -57,8 +57,8 @@ void ioutils::convertCompactClusters(gsl::span clu } } - for (auto& c : clusters) { - float sigmaY2, sigmaZ2, sigmaYZ = 0; + for (const auto& c : clusters) { + float sigmaY2{0}, sigmaZ2{0}, sigmaYZ{0}; auto locXYZ = extractClusterData(c, pattIt, dict, sigmaY2, sigmaZ2); auto& cl3d = output.emplace_back(c.getSensorID(), geom->getMatrixT2L(c.getSensorID()) ^ locXYZ); // local --> tracking if (applyMisalignment) { @@ -83,9 +83,9 @@ void ioutils::loadEventData(ROframe& event, gsl::spanfillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); int clusterId{0}; - for (auto& c : clusters) { - int layer = geom->getLayer(c.getSensorID()); - float sigmaY2, sigmaZ2, sigmaYZ = 0; + for (const auto& c : clusters) { + const int layer = geom->getLayer(c.getSensorID()); + float sigmaY2{0}, sigmaZ2{0}, sigmaYZ{0}; auto locXYZ = extractClusterData(c, pattIt, dict, sigmaY2, sigmaZ2); auto sensorID = c.getSensorID(); // Inverse transformation to the local --> tracking @@ -118,9 +118,9 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g auto first = rof.getFirstEntry(); auto clusters_in_frame = rof.getROFData(clusters); - for (auto& c : clusters_in_frame) { - int layer = geom->getLayer(c.getSensorID()); - float sigmaY2, sigmaZ2, sigmaYZ = 0; + for (const auto& c : clusters_in_frame) { + const int layer = geom->getLayer(c.getSensorID()); + float sigmaY2{0}, sigmaZ2{0}, sigmaYZ{0}; auto locXYZ = extractClusterData(c, pattIt, dict, sigmaY2, sigmaZ2); auto sensorID = c.getSensorID(); // Inverse transformation to the local --> tracking @@ -141,100 +141,5 @@ int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, g event.addClusterExternalIndexToLayer(layer, first + clusterId); clusterId++; } - return clusters_in_frame.size(); + return (int)clusters_in_frame.size(); } - -std::vector> ioutils::loadLabels(const int eventsNum, const std::string& fileName) -{ - std::vector> labelsMap{}; - std::unordered_map currentEventLabelsMap{}; - std::ifstream inputStream{}; - std::string line{}; - int monteCarloId{}, pdgCode{}, numberOfClusters{}; - float transverseMomentum{}, phi{}, pseudorapidity{}; - - labelsMap.reserve(eventsNum); - - inputStream.open(fileName); - std::getline(inputStream, line); - - while (std::getline(inputStream, line)) { - - std::istringstream inputStringStream(line); - - if (inputStringStream >> monteCarloId) { - - if (monteCarloId == EventLabelsSeparator) { - - labelsMap.emplace_back(currentEventLabelsMap); - currentEventLabelsMap.clear(); - - } else { - - if (inputStringStream >> transverseMomentum >> phi >> pseudorapidity >> pdgCode >> numberOfClusters) { - - if (std::abs(pdgCode) == constants::pdgcodes::PionCode && numberOfClusters == 7) { - - currentEventLabelsMap.emplace(std::piecewise_construct, std::forward_as_tuple(monteCarloId), - std::forward_as_tuple(monteCarloId, transverseMomentum, phi, - pseudorapidity, pdgCode, numberOfClusters)); - } - } - } - } - } - - labelsMap.emplace_back(currentEventLabelsMap); - - return labelsMap; -} - -// void ioutils::writeRoadsReport(std::ofstream& correctRoadsOutputStream, std::ofstream& duplicateRoadsOutputStream, -// std::ofstream& fakeRoadsOutputStream, const std::vector>>& roads, -// const std::unordered_map& labelsMap) -// { -// const int numVertices{static_cast(roads.size())}; -// std::unordered_set foundMonteCarloIds{}; - -// correctRoadsOutputStream << EventLabelsSeparator << std::endl; -// fakeRoadsOutputStream << EventLabelsSeparator << std::endl; - -// for (int iVertex{0}; iVertex < numVertices; ++iVertex) { - -// const std::vector>& currentVertexRoads{roads[iVertex]}; -// const int numRoads{static_cast(currentVertexRoads.size())}; - -// for (int iRoad{0}; iRoad < numRoads; ++iRoad) { - -// const Road<5>& currentRoad{currentVertexRoads[iRoad]}; -// const int currentRoadLabel{currentRoad.getLabel()}; - -// if (!labelsMap.count(currentRoadLabel)) { - -// continue; -// } - -// const Label& currentLabel{labelsMap.at(currentRoadLabel)}; - -// if (currentRoad.isFakeRoad()) { - -// fakeRoadsOutputStream << currentLabel << std::endl; - -// } else { - -// if (foundMonteCarloIds.count(currentLabel.monteCarloId)) { - -// duplicateRoadsOutputStream << currentLabel << std::endl; - -// } else { - -// correctRoadsOutputStream << currentLabel << std::endl; -// foundMonteCarloIds.emplace(currentLabel.monteCarloId); -// } -// } -// } -// } -// } - -} // namespace its -} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx index 6dd11b2b659c7..34d8967c6a5bb 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx @@ -74,7 +74,7 @@ void TimeFrame::addPrimaryVertices(const bounded_vector& vertic for (const auto& vertex : vertices) { mPrimaryVertices.emplace_back(vertex); if (!isBeamPositionOverridden) { - const int w{vertex.getNContributors()}; + const float w = vertex.getNContributors(); mBeamPos[0] = (mBeamPos[0] * mBeamPosWeight + vertex.getX() * w) / (mBeamPosWeight + w); mBeamPos[1] = (mBeamPos[1] * mBeamPosWeight + vertex.getY() * w) / (mBeamPosWeight + w); mBeamPosWeight += w; @@ -126,7 +126,7 @@ void TimeFrame::addPrimaryVertices(const gsl::span& verti mPrimaryVertices.emplace_back(vertex); // put a copy in the present mTotVertPerIteration[iteration]++; if (!isBeamPositionOverridden) { // beam position is updated only at first occurrence of the vertex. A bit sketchy if we have past/future vertices, it should not impact too much. - const int w{vertex.getNContributors()}; + const float w = vertex.getNContributors(); mBeamPos[0] = (mBeamPos[0] * mBeamPosWeight + vertex.getX() * w) / (mBeamPosWeight + w); mBeamPos[1] = (mBeamPos[1] * mBeamPosWeight + vertex.getY() * w) / (mBeamPosWeight + w); mBeamPosWeight += w; @@ -166,7 +166,7 @@ int TimeFrame::loadROFrameData(gsl::span rofs, clearResizeBoundedVector(mClusterSize, clusters.size(), mMemoryPool.get()); for (auto& rof : rofs) { for (int clusterId{rof.getFirstEntry()}; clusterId < rof.getFirstEntry() + rof.getNEntries(); ++clusterId) { - auto& c = clusters[clusterId]; + const auto& c = clusters[clusterId]; int layer = geom->getLayer(c.getSensorID()); @@ -280,7 +280,7 @@ void TimeFrame::prepareClusters(const TrackingParameters& trkParam, con c.radius = h.r; c.indexTableBinIndex = h.bin; } - for (unsigned int iB{0}; iB < clsPerBin.size(); ++iB) { + for (int iB{0}; iB < (int)clsPerBin.size(); ++iB) { mIndexTables[iLayer][rof * (trkParam.ZBins * trkParam.PhiBins + 1) + iB] = lutPerBin[iB]; } for (auto iB{clsPerBin.size()}; iB < (trkParam.ZBins * trkParam.PhiBins + 1); iB++) { @@ -374,7 +374,7 @@ void TimeFrame::initialise(const int iteration, const TrackingParameter const float cosTheta1half = o2::gpu::CAMath::Sqrt(1.f - Sq(0.5f * r1 * oneOverR)); const float cosTheta2half = o2::gpu::CAMath::Sqrt(1.f - Sq(0.5f * r2 * oneOverR)); float x = r2 * cosTheta1half - r1 * cosTheta2half; - float delta = o2::gpu::CAMath::Sqrt(1. / (1.f - 0.25f * Sq(x * oneOverR)) * (Sq(0.25f * r1 * r2 * Sq(oneOverR) / cosTheta2half + cosTheta1half) * Sq(res1) + Sq(0.25f * r1 * r2 * Sq(oneOverR) / cosTheta1half + cosTheta2half) * Sq(res2))); + float delta = o2::gpu::CAMath::Sqrt(1.f / (1.f - 0.25f * Sq(x * oneOverR)) * (Sq(0.25f * r1 * r2 * Sq(oneOverR) / cosTheta2half + cosTheta1half) * Sq(res1) + Sq(0.25f * r1 * r2 * Sq(oneOverR) / cosTheta1half + cosTheta2half) * Sq(res2))); mPhiCuts[iLayer] = std::min(o2::gpu::CAMath::ASin(0.5f * x * oneOverR) + 2.f * mMSangles[iLayer] + delta, constants::math::Pi * 0.5f); } } @@ -401,13 +401,13 @@ template unsigned long TimeFrame::getArtefactsMemory() const { unsigned long size{0}; - for (auto& trkl : mTracklets) { + for (const auto& trkl : mTracklets) { size += sizeof(Tracklet) * trkl.size(); } - for (auto& cells : mCells) { + for (const auto& cells : mCells) { size += sizeof(CellSeed) * cells.size(); } - for (auto& cellsN : mCellsNeighbours) { + for (const auto& cellsN : mCellsNeighbours) { size += sizeof(int) * cellsN.size(); } return size + sizeof(Road) * mRoads.size(); @@ -422,9 +422,7 @@ void TimeFrame::printArtefactsMemory() const template void TimeFrame::fillPrimaryVerticesXandAlpha() { - if (mPValphaX.size()) { - mPValphaX.clear(); - } + deepVectorClear(mPValphaX); mPValphaX.reserve(mPrimaryVertices.size()); for (auto& pv : mPrimaryVertices) { mPValphaX.emplace_back(std::array{o2::gpu::CAMath::Hypot(pv.getX(), pv.getY()), math_utils::computePhi(pv.getX(), pv.getY())}); diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 5565026ab11cf..75c265dbdb703 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -41,7 +41,7 @@ Tracker::Tracker(TrackerTraits7* traits) : mTraits(traits) mTrkParams.resize(1); } -void Tracker::clustersToTracks(LogFunc logger, LogFunc error) +void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) { LogFunc evalLog = [](const std::string&) {}; @@ -195,7 +195,7 @@ void Tracker::computeRoadsMClabels() bool found{false}; for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) { std::pair& occurrence = occurrences[iOcc]; - for (auto& label : cl0labs) { + for (const auto& label : cl0labs) { if (label == occurrence.first) { ++occurrence.second; found = true; @@ -204,7 +204,7 @@ void Tracker::computeRoadsMClabels() } } if (!found) { - for (auto& label : cl0labs) { + for (const auto& label : cl0labs) { occurrences.emplace_back(label, 1); } } @@ -277,7 +277,7 @@ void Tracker::computeTracksMClabels() bool found{false}; for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) { std::pair& occurrence = occurrences[iOcc]; - for (auto& label : labels) { + for (const auto& label : labels) { if (label == occurrence.first) { ++occurrence.second; found = true; @@ -286,7 +286,7 @@ void Tracker::computeTracksMClabels() } } if (!found) { - for (auto& label : labels) { + for (const auto& label : labels) { occurrences.emplace_back(label, 1); } } @@ -302,7 +302,7 @@ void Tracker::computeTracksMClabels() auto clid = track.getClusterIndex(ic); if (clid != constants::its::UnusedIndex) { auto labelsSpan = mTimeFrame->getClusterLabels(ic, clid); - for (auto& currentLabel : labelsSpan) { + for (const auto& currentLabel : labelsSpan) { if (currentLabel == maxOccurrencesValue) { pattern |= 0x1 << (16 + ic); // set bit if correct break; @@ -335,7 +335,7 @@ void Tracker::rectifyClusterIndices() void Tracker::getGlobalConfiguration() { - auto& tc = o2::its::TrackerParamConfig::Instance(); + const auto& tc = o2::its::TrackerParamConfig::Instance(); if (tc.useMatCorrTGeo) { mTraits->setCorrType(o2::base::PropagatorImpl::MatCorrType::USEMatCorrTGeo); } else if (tc.useFastMaterial) { diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index bdd8578e35d48..766dc25cd6d8e 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -101,7 +101,7 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF const float inverseR0{1.f / currentCluster.radius}; for (int iV{startVtx}; iV < endVtx; ++iV) { - auto& primaryVertex{primaryVertices[iV]}; + const auto& primaryVertex{primaryVertices[iV]}; if (primaryVertex.isFlagSet(2) && iteration != 3) { continue; } @@ -830,8 +830,8 @@ void TrackerTraits::findRoads(const int iteration) mTaskArena.execute([&] { bounded_vector perSeedCount(trackSeeds.size() + 1, 0, mMemoryPool.get()); tbb::parallel_for( - tbb::blocked_range(size_t(0), trackSeeds.size()), - [&](const tbb::blocked_range& Seeds) { + tbb::blocked_range(0, (int)trackSeeds.size()), + [&](const tbb::blocked_range& Seeds) { for (int iSeed = Seeds.begin(); iSeed < Seeds.end(); ++iSeed) { const CellSeed& seed{trackSeeds[iSeed]}; TrackITSExt temporaryTrack{seed}; diff --git a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx index 8ab8c1a9e2e3c..a1a1a90da8963 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx @@ -125,7 +125,6 @@ void Vertexer::printEpilog(LogFunc& logger, const unsigned selectedN, const unsigned int vertexN, const float initT, const float trackletT, const float selecT, const float vertexT) { - float total = initT + trackletT + selecT + vertexT; logger(fmt::format(" - {} Vertexer: found {} | {} tracklets in: {} ms", mTraits->getName(), trackletN01, trackletN12, trackletT)); logger(fmt::format(" - {} Vertexer: selected {} tracklets in: {} ms", mTraits->getName(), selectedN, selecT)); logger(fmt::format(" - {} Vertexer: found {} vertices in: {} ms", mTraits->getName(), vertexN, vertexT)); diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index 6fd3d99ffe58d..fe1619efaa192 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -146,9 +146,9 @@ void trackletSelectionKernelHost( } } -const bounded_vector> VertexerTraits::selectClusters(const int* indexTable, - const std::array& selectedBinsRect, - const IndexTableUtils& utils) +bounded_vector> VertexerTraits::selectClusters(const int* indexTable, + const std::array& selectedBinsRect, + const IndexTableUtils& utils) { bounded_vector> filteredBins{mMemoryPool.get()}; int phiBinsNum{selectedBinsRect[3] - selectedBinsRect[1] + 1}; @@ -270,12 +270,12 @@ void VertexerTraits::computeTracklets(const int iteration) /// Create tracklets labels for L0-L1, information is as flat as in tracklets vector (no rofId) if (mTimeFrame->hasMCinformation()) { - for (auto& trk : mTimeFrame->getTracklets()[0]) { + for (const auto& trk : mTimeFrame->getTracklets()[0]) { o2::MCCompLabel label; int sortedId0{mTimeFrame->getSortedIndex(trk.rof[0], 0, trk.firstClusterIndex)}; int sortedId1{mTimeFrame->getSortedIndex(trk.rof[1], 1, trk.secondClusterIndex)}; - for (auto& lab0 : mTimeFrame->getClusterLabels(0, mTimeFrame->getClusters()[0][sortedId0].clusterId)) { - for (auto& lab1 : mTimeFrame->getClusterLabels(1, mTimeFrame->getClusters()[1][sortedId1].clusterId)) { + for (const auto& lab0 : mTimeFrame->getClusterLabels(0, mTimeFrame->getClusters()[0][sortedId0].clusterId)) { + for (const auto& lab1 : mTimeFrame->getClusterLabels(1, mTimeFrame->getClusters()[1][sortedId1].clusterId)) { if (lab0 == lab1 && lab0.isValid()) { label = lab0; break; @@ -544,7 +544,7 @@ void VertexerTraits::computeVertices(const int iteration) mTimeFrame->addPrimaryVerticesLabelsInROF(polls, rofId); } } - if (!vertices.size() && !(iteration && (int)mTimeFrame->getPrimaryVertices(rofId).size() > mVrtParams[iteration].vertPerRofThreshold)) { + if (vertices.empty() && !(iteration && (int)mTimeFrame->getPrimaryVertices(rofId).size() > mVrtParams[iteration].vertPerRofThreshold)) { mTimeFrame->getNoVertexROF()++; } } From 69bdaa0fc1857aa177529ca4f6c87ba46888e034 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 6 Jun 2025 17:33:26 +0200 Subject: [PATCH 004/315] Standalone CI build must fail with errors --- GPU/GPUTracking/Standalone/cmake/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Standalone/cmake/build.sh b/GPU/GPUTracking/Standalone/cmake/build.sh index d2e4ae08c1575..9fe650fd30905 100755 --- a/GPU/GPUTracking/Standalone/cmake/build.sh +++ b/GPU/GPUTracking/Standalone/cmake/build.sh @@ -3,6 +3,7 @@ if [[ -z $1 ]]; then echo "Please provide Sourcedir as command line argument" exit 1 fi +set -e mkdir -p standalone/build pushd standalone/build cp $1/GPU/GPUTracking/Standalone/cmake/config.cmake . From 84e43136cbd915d903e8ce276bb7dfb8631ca1e1 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 10 Jun 2025 18:02:19 +0200 Subject: [PATCH 005/315] Fix abuse of o2::framework::Output (#14384) This prevents support for std::pmr, because it implies movable outputs (which are not). Use the ConcreteDataTypeMatcher instead, which represents a query (matcher) on the data. --- Detectors/TPC/workflow/src/TrackReaderWorkflow.cxx | 4 ++-- Detectors/TPC/workflow/src/tpc-reco-workflow.cxx | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Detectors/TPC/workflow/src/TrackReaderWorkflow.cxx b/Detectors/TPC/workflow/src/TrackReaderWorkflow.cxx index b51fba091b190..b5f1db99cfc5a 100644 --- a/Detectors/TPC/workflow/src/TrackReaderWorkflow.cxx +++ b/Detectors/TPC/workflow/src/TrackReaderWorkflow.cxx @@ -36,7 +36,7 @@ // we need a global variable to propagate the type the message dispatching of the // publisher will trigger on. This is dependent on the input type -o2::framework::Output gDispatchTrigger{"", ""}; +o2::framework::ConcreteDataTypeMatcher gDispatchTrigger{"", ""}; void customize(std::vector& policies) { @@ -96,7 +96,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // nothing to do we leave the matcher empty which will suppress the dispatch // trigger and all messages will be sent out together at end of computation } else if (inputType == "tracks") { - gDispatchTrigger = o2::framework::Output{"TPC", "TRACKS"}; + gDispatchTrigger = o2::framework::ConcreteDataTypeMatcher{"TPC", "TRACKS"}; } bool doMC = not cfgc.options().get("disable-mc"); diff --git a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx index 4d364e74bb620..9d7ab63b0c2a0 100644 --- a/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx +++ b/Detectors/TPC/workflow/src/tpc-reco-workflow.cxx @@ -39,7 +39,7 @@ // we need a global variable to propagate the type the message dispatching of the // publisher will trigger on. This is dependent on the input type -static o2::framework::Output gDispatchTrigger{"", ""}; +static o2::framework::ConcreteDataTypeMatcher gDispatchTrigger{"", ""}; // Global variable used to transport data to the completion policy static o2::tpc::reco_workflow::CompletionPolicyData gPolicyData; @@ -152,13 +152,13 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // nothing to do we leave the matcher empty which will suppress the dispatch // trigger and all messages will be sent out together at end of computation } else if (inputType == "digits") { - gDispatchTrigger = o2::framework::Output{"TPC", "DIGITS"}; + gDispatchTrigger = o2::framework::ConcreteDataTypeMatcher{"TPC", "DIGITS"}; } else if (inputType == "clustershw") { - gDispatchTrigger = o2::framework::Output{"TPC", "CLUSTERHW"}; + gDispatchTrigger = o2::framework::ConcreteDataTypeMatcher{"TPC", "CLUSTERHW"}; } else if (inputType == "clustersnative") { - gDispatchTrigger = o2::framework::Output{"TPC", "CLUSTERNATIVE"}; + gDispatchTrigger = o2::framework::ConcreteDataTypeMatcher{"TPC", "CLUSTERNATIVE"}; } else if (inputType == "zsraw") { - gDispatchTrigger = o2::framework::Output{"TPC", "RAWDATA"}; + gDispatchTrigger = o2::framework::ConcreteDataTypeMatcher{"TPC", "RAWDATA"}; } // set up configuration o2::conf::ConfigurableParam::updateFromFile(cfgc.options().get("configFile")); From 73b259292c546287874c301d5e84c40afe999c81 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 10 Jun 2025 23:27:51 +0200 Subject: [PATCH 006/315] Fix ClusterDecoderRawSpec to work with std::pmr (#14386) --- .../workflow/src/ClusterDecoderRawSpec.cxx | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx b/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx index 9e2e70e8dde46..c5c444e077703 100644 --- a/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx +++ b/Detectors/TPC/workflow/src/ClusterDecoderRawSpec.cxx @@ -43,6 +43,7 @@ namespace o2 { namespace tpc { + /// create the processor spec for TPC raw cluster decoder converting TPC raw to native clusters /// Input: raw pages of TPC raw clusters /// Output: vector of containers with clusters in ClusterNative format, one container per @@ -79,27 +80,18 @@ DataProcessorSpec getClusterDecoderRawSpec(bool sendMC) // init the stacks for forwarding the sector header // FIXME check if there is functionality in the DPL to forward the stack // FIXME make one function - o2::header::Stack rawHeaderStack; - o2::header::Stack mcHeaderStack; o2::tpc::TPCSectorHeader const* sectorHeaderMC = nullptr; if (DataRefUtils::isValid(mclabelref)) { sectorHeaderMC = DataRefUtils::getHeader(mclabelref); - if (sectorHeaderMC) { - o2::header::Stack actual{*sectorHeaderMC}; - std::swap(mcHeaderStack, actual); - if (sectorHeaderMC->sector() < 0) { - pc.outputs().snapshot(Output{gDataOriginTPC, DataDescription("CLNATIVEMCLBL"), fanSpec, std::move(mcHeaderStack)}, fanSpec); - } - } + } + + if (sectorHeaderMC && sectorHeaderMC->sector() < 0) { + pc.outputs().snapshot(Output{gDataOriginTPC, DataDescription("CLNATIVEMCLBL"), fanSpec, {*sectorHeaderMC}}, fanSpec); } auto const* sectorHeader = DataRefUtils::getHeader(ref); - if (sectorHeader) { - o2::header::Stack actual{*sectorHeader}; - std::swap(rawHeaderStack, actual); - if (sectorHeader->sector() < 0) { - pc.outputs().snapshot(Output{gDataOriginTPC, DataDescription("CLUSTERNATIVE"), fanSpec, std::move(rawHeaderStack)}, fanSpec); - return; - } + if (sectorHeader && sectorHeader->sector() < 0) { + pc.outputs().snapshot(Output{gDataOriginTPC, DataDescription("CLUSTERNATIVE"), fanSpec, {*sectorHeader}}, fanSpec); + return; } assert(sectorHeaderMC == nullptr || sectorHeader->sector() == sectorHeaderMC->sector()); @@ -166,8 +158,8 @@ DataProcessorSpec getClusterDecoderRawSpec(bool sendMC) // output of the decoder is sorted in (sector,globalPadRow) coordinates, individual // containers are created for clusters and MC labels per (sector,globalPadRow) address char* outputBuffer = nullptr; - auto outputAllocator = [&pc, &fanSpec, &outputBuffer, &rawHeaderStack](size_t size) -> char* { - outputBuffer = pc.outputs().newChunk(Output{gDataOriginTPC, DataDescription("CLUSTERNATIVE"), fanSpec, std::move(rawHeaderStack)}, size).data(); + auto outputAllocator = [&pc, &fanSpec, &outputBuffer, sectorHeader](size_t size) -> char* { + outputBuffer = pc.outputs().newChunk(Output{gDataOriginTPC, DataDescription("CLUSTERNATIVE"), fanSpec, sectorHeader ? o2::header::Stack{*sectorHeader} : o2::header::Stack{}}, size).data(); return outputBuffer; }; MCLabelContainer mcout; @@ -188,7 +180,7 @@ DataProcessorSpec getClusterDecoderRawSpec(bool sendMC) // serialize the complete list of MC label containers ConstMCLabelContainer labelsFlat; mcout.flatten_to(labelsFlat); - pc.outputs().snapshot(Output{gDataOriginTPC, DataDescription("CLNATIVEMCLBL"), fanSpec, std::move(mcHeaderStack)}, labelsFlat); + pc.outputs().snapshot(Output{gDataOriginTPC, DataDescription("CLNATIVEMCLBL"), fanSpec, sectorHeaderMC ? o2::header::Stack{*sectorHeaderMC} : o2::header::Stack{}}, labelsFlat); } }; From 136d7dc385cd91ec5b1828b8a09cbe653347ebca Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 10 Jun 2025 15:52:41 +0200 Subject: [PATCH 007/315] Fix MCKinematicsReader for QED events when using collisioncontext --- DataFormats/simulation/src/DigitizationContext.cxx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/DataFormats/simulation/src/DigitizationContext.cxx b/DataFormats/simulation/src/DigitizationContext.cxx index 499a478bc5148..e5b4d6e706732 100644 --- a/DataFormats/simulation/src/DigitizationContext.cxx +++ b/DataFormats/simulation/src/DigitizationContext.cxx @@ -151,6 +151,19 @@ bool DigitizationContext::initSimKinematicsChains(std::vector& simkinem // add signal files simkinematicschains.back()->AddFile(o2::base::NameConf::getMCKinematicsFileName(mSimPrefixes[source].data()).c_str()); } + + // we add QED, if used in the digitization context + if (mEventRecordsWithQED.size() > 0) { + if (mSimPrefixes.size() >= QEDSOURCEID) { + LOG(fatal) << "Too many signal chains; crashes with QED source ID"; + } + + // it might be better to use an unordered_map for the simchains but this requires interface changes + simkinematicschains.resize(QEDSOURCEID + 1, nullptr); + simkinematicschains[QEDSOURCEID] = new TChain("o2sim"); + simkinematicschains[QEDSOURCEID]->AddFile(o2::base::DetectorNameConf::getMCKinematicsFileName(mQEDSimPrefix).c_str()); + } + return true; } From 89020a5507b53590af46a214f3f4902c89b7eabb Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 10 Jun 2025 12:53:06 +0200 Subject: [PATCH 008/315] GPU Math: Suppress compiler warnings about NaN in ffast-math --- GPU/Common/GPUCommonMath.h | 5 +++++ GPU/GPUTracking/Definitions/GPULogging.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 350ef173467d5..01067ca032650 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -99,7 +99,12 @@ class GPUCommonMath GPUhdi() static float Remainderf(float x, float y); GPUd() constexpr static bool Finite(float x); GPUd() constexpr static bool IsNaN(float x); +#pragma GCC diagnostic push +#if defined(__FAST_MATH__) && defined(__clang__) +#pragma GCC diagnostic ignored "-Wnan-infinity-disabled" +#endif GPUd() constexpr static float QuietNaN() { return GPUCA_CHOICE(std::numeric_limits::quiet_NaN(), __builtin_nanf(""), nan(0u)); } +#pragma GCC diagnostic pop GPUd() constexpr static uint32_t Clz(uint32_t val); GPUd() constexpr static uint32_t Popcount(uint32_t val); diff --git a/GPU/GPUTracking/Definitions/GPULogging.h b/GPU/GPUTracking/Definitions/GPULogging.h index c8ba635d1af7a..800890045ec45 100644 --- a/GPU/GPUTracking/Definitions/GPULogging.h +++ b/GPU/GPUTracking/Definitions/GPULogging.h @@ -28,7 +28,12 @@ #define GPUFatal(...) #elif defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE_DEVICE) && !defined(GPUCA_NO_FMT) #include + #pragma GCC diagnostic push + #if defined(__FAST_MATH__) && defined(__clang__) + #pragma GCC diagnostic ignored "-Wnan-infinity-disabled" + #endif #include + #pragma GCC diagnostic pop #define GPUInfo(string, ...) \ { \ fmt::printf(string "\n", ##__VA_ARGS__); \ From 418a85fc58fdd772177a6c22f1fa7267e571f2c9 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 11 Jun 2025 09:31:19 +0200 Subject: [PATCH 009/315] ITS: simplify constants + mathutils (#14383) --- .../GPU/ITStrackingGPU/TrackingKernels.h | 4 + .../GPU/ITStrackingGPU/VertexerTraitsGPU.h | 12 +- .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 30 ++--- .../tracking/GPU/cuda/VertexerTraitsGPU.cxx | 2 +- .../ITS/tracking/GPU/cuda/VertexingKernels.cu | 8 -- .../include/ITStracking/Configuration.h | 6 +- .../tracking/include/ITStracking/Constants.h | 103 ++--------------- .../include/ITStracking/IndexTableUtils.h | 4 +- .../tracking/include/ITStracking/MathUtils.h | 109 +++++++++--------- .../include/ITStracking/TrackerTraits.h | 4 +- .../include/ITStracking/VertexerTraits.h | 2 - .../ITSMFT/ITS/tracking/src/Smoother.cxx | 4 +- .../ITSMFT/ITS/tracking/src/TimeFrame.cxx | 24 +--- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 8 +- .../ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 55 +++------ .../ITS/tracking/src/VertexerTraits.cxx | 12 +- 16 files changed, 122 insertions(+), 265 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h index 09c8c39725efa..b847aacd9bba5 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h @@ -22,7 +22,11 @@ class CellSeed; class ExternalAllocator; namespace gpu { + #ifdef GPUCA_GPUCODE // GPUg() global kernels must only when compiled by GPU compiler + +GPUdi() int4 getEmptyBinsRect() { return int4{0, 0, 0, 0}; } + GPUd() bool fitTrack(TrackITSExt& track, int start, int end, diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/VertexerTraitsGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/VertexerTraitsGPU.h index a5c3709081a82..5b1d9194e1174 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/VertexerTraitsGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/VertexerTraitsGPU.h @@ -18,7 +18,6 @@ #define ITSTRACKINGGPU_VERTEXERTRAITSGPU_H_ #include -#include #include "ITStracking/VertexerTraits.h" #include "ITStracking/Configuration.h" @@ -29,13 +28,8 @@ #include "ITStrackingGPU/TimeFrameGPU.h" -namespace o2 +namespace o2::its { -namespace its -{ -class ROframe; - -using constants::its2::InversePhiBinSize; class VertexerTraitsGPU final : public VertexerTraits { @@ -63,6 +57,6 @@ inline void VertexerTraitsGPU::adoptTimeFrame(TimeFrame<7>* tf) noexcept mTimeFrame = static_cast*>(tf); } -} // namespace its -} // namespace o2 +} // namespace o2::its + #endif diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 18c89d39adda0..2191880374548 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -52,14 +52,8 @@ using namespace o2::track; namespace o2::its { -using namespace constants::its2; using Vertex = o2::dataformats::Vertex>; -GPUdii() float Sq(float v) -{ - return v * v; -} - namespace gpu { @@ -99,9 +93,9 @@ GPUd() const int4 getBinsRect(const Cluster& currentCluster, const int layerInde const float z1, const float z2, float maxdeltaz, float maxdeltaphi) { const float zRangeMin = o2::gpu::CAMath::Min(z1, z2) - maxdeltaz; - const float phiRangeMin = (maxdeltaphi > constants::math::Pi) ? 0.f : currentCluster.phi - maxdeltaphi; + const float phiRangeMin = (maxdeltaphi > o2::constants::math::PI) ? 0.f : currentCluster.phi - maxdeltaphi; const float zRangeMax = o2::gpu::CAMath::Max(z1, z2) + maxdeltaz; - const float phiRangeMax = (maxdeltaphi > constants::math::Pi) ? constants::math::TwoPi : currentCluster.phi + maxdeltaphi; + const float phiRangeMax = (maxdeltaphi > o2::constants::math::PI) ? o2::constants::math::TwoPI : currentCluster.phi + maxdeltaphi; if (zRangeMax < -utils.getLayerZ(layerIndex) || zRangeMin > utils.getLayerZ(layerIndex) || zRangeMin > zRangeMax) { @@ -129,7 +123,7 @@ GPUd() bool fitTrack(TrackITSExt& track, o2::base::PropagatorF::MatCorrType matCorrType) { for (int iLayer{start}; iLayer != end; iLayer += step) { - if (track.getClusterIndex(iLayer) == constants::its::UnusedIndex) { + if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { continue; } const TrackingFrameInfo& trackingHit = tfInfos[iLayer][track.getClusterIndex(iLayer)]; @@ -316,7 +310,7 @@ GPUg() void fitTrackSeedsKernel( temporaryTrack.setChi2(0); int* clusters = seed.getClusters(); for (int iL{0}; iL < 7; ++iL) { - temporaryTrack.setExternalClusterIndex(iL, clusters[iL], clusters[iL] != constants::its::UnusedIndex); + temporaryTrack.setExternalClusterIndex(iL, clusters[iL], clusters[iL] != constants::UnusedIndex); } bool fitSuccess = fitTrack(temporaryTrack, // TrackITSExt& track, 0, // int lastLayer, @@ -422,8 +416,6 @@ GPUg() void computeLayerCellsKernel( const float cellDeltaTanLambdaSigma, const float nSigmaCut) { - constexpr float radl = 9.36f; // Radiation length of Si [cm]. - constexpr float rho = 2.33f; // Density of Si [g/cm^3]. constexpr float layerxX0[7] = {5.e-3f, 5.e-3f, 5.e-3f, 1.e-2f, 1.e-2f, 1.e-2f, 1.e-2f}; // Hardcoded here for the moment. for (int iCurrentTrackletIndex = blockIdx.x * blockDim.x + threadIdx.x; iCurrentTrackletIndex < nTrackletsCurrent; iCurrentTrackletIndex += blockDim.x * gridDim.x) { const Tracklet& currentTracklet = tracklets[layer][iCurrentTrackletIndex]; @@ -462,7 +454,7 @@ GPUg() void computeLayerCellsKernel( break; } - if (!track.correctForMaterial(layerxX0[layer + iC], layerxX0[layer] * radl * rho, true)) { + if (!track.correctForMaterial(layerxX0[layer + iC], layerxX0[layer] * constants::Radl * constants::Rho, true)) { break; } @@ -548,12 +540,12 @@ GPUg() void computeLayerTrackletsMultiROFKernel( if (primaryVertex.isFlagSet(2) && iteration != 3) { continue; } - const float resolution = o2::gpu::CAMath::Sqrt(Sq(resolutionPV) / primaryVertex.getNContributors() + Sq(positionResolution)); + const float resolution = o2::gpu::CAMath::Sqrt(math_utils::Sq(resolutionPV) / primaryVertex.getNContributors() + math_utils::Sq(positionResolution)); const float tanLambda{(currentCluster.zCoordinate - primaryVertex.getZ()) * inverseR0}; const float zAtRmin{tanLambda * (minR - currentCluster.radius) + currentCluster.zCoordinate}; const float zAtRmax{tanLambda * (maxR - currentCluster.radius) + currentCluster.zCoordinate}; - const float sqInverseDeltaZ0{1.f / (Sq(currentCluster.zCoordinate - primaryVertex.getZ()) + 2.e-8f)}; /// protecting from overflows adding the detector resolution - const float sigmaZ{o2::gpu::CAMath::Sqrt(Sq(resolution) * Sq(tanLambda) * ((Sq(inverseR0) + sqInverseDeltaZ0) * Sq(meanDeltaR) + 1.f) + Sq(meanDeltaR * MSAngle))}; + const float sqInverseDeltaZ0{1.f / (math_utils::Sq(currentCluster.zCoordinate - primaryVertex.getZ()) + 2.e-8f)}; /// protecting from overflows adding the detector resolution + const float sigmaZ{o2::gpu::CAMath::Sqrt(math_utils::Sq(resolution) * math_utils::Sq(tanLambda) * ((math_utils::Sq(inverseR0) + sqInverseDeltaZ0) * math_utils::Sq(meanDeltaR) + 1.f) + math_utils::Sq(meanDeltaR * MSAngle))}; const int4 selectedBinsRect{getBinsRect(currentCluster, layerIndex + 1, *utils, zAtRmin, zAtRmax, sigmaZ * NSigmaCut, phiCut)}; if (selectedBinsRect.x == 0 && selectedBinsRect.y == 0 && selectedBinsRect.z == 0 && selectedBinsRect.w == 0) { continue; @@ -587,7 +579,7 @@ GPUg() void computeLayerTrackletsMultiROFKernel( const float deltaPhi{o2::gpu::CAMath::Abs(currentCluster.phi - nextCluster.phi)}; const float deltaZ{o2::gpu::CAMath::Abs(tanLambda * (nextCluster.radius - currentCluster.radius) + currentCluster.zCoordinate - nextCluster.zCoordinate)}; const int nextSortedIndex{ROFClusters[layerIndex + 1][rof1] + nextClusterIndex}; - if (deltaZ / sigmaZ < NSigmaCut && (deltaPhi < phiCut || o2::gpu::CAMath::Abs(deltaPhi - constants::math::TwoPi) < phiCut)) { + if (deltaZ / sigmaZ < NSigmaCut && (deltaPhi < phiCut || o2::gpu::CAMath::Abs(deltaPhi - o2::constants::math::TwoPI) < phiCut)) { if constexpr (initRun) { trackletsLUT[layerIndex][currentSortedIndex]++; // we need l0 as well for usual exclusive sums. } else { @@ -634,8 +626,6 @@ GPUg() void processNeighboursKernel(const int layer, const o2::base::Propagator* propagator, const o2::base::PropagatorF::MatCorrType matCorrType) { - constexpr float radl = 9.36f; // Radiation length of Si [cm]. - constexpr float rho = 2.33f; // Density of Si [g/cm^3]. constexpr float layerxX0[7] = {5.e-3f, 5.e-3f, 5.e-3f, 1.e-2f, 1.e-2f, 1.e-2f, 1.e-2f}; // Hardcoded here for the moment. for (unsigned int iCurrentCell = blockIdx.x * blockDim.x + threadIdx.x; iCurrentCell < nCurrentCells; iCurrentCell += blockDim.x * gridDim.x) { int foundSeeds{0}; @@ -678,7 +668,7 @@ GPUg() void processNeighboursKernel(const int layer, } if (matCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { - if (!seed.correctForMaterial(layerxX0[layer - 1], layerxX0[layer - 1] * radl * rho, true)) { + if (!seed.correctForMaterial(layerxX0[layer - 1], layerxX0[layer - 1] * constants::Radl * constants::Rho, true)) { continue; } } diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cxx index 2a6debe8f652e..90d654a26a43d 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexerTraitsGPU.cxx @@ -40,7 +40,7 @@ void VertexerTraitsGPU::updateVertexingParameters(const std::vector(std::ceil(mIndexTableUtils.getNphiBins() * par.phiCut / constants::math::TwoPi)); + par.phiSpan = static_cast(std::ceil(mIndexTableUtils.getNphiBins() * par.phiCut / o2::constants::math::TwoPI)); par.zSpan = static_cast(std::ceil(par.zCut * mIndexTableUtils.getInverseZCoordinate(0))); } } diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexingKernels.cu index acbd77585df37..126e799efce5d 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/VertexingKernels.cu @@ -20,10 +20,7 @@ namespace o2 { namespace its { -using constants::its::VertexerHistogramVolume; -using constants::math::TwoPi; using math_utils::getNormalizedPhi; -using namespace constants::its2; namespace gpu { @@ -58,11 +55,6 @@ void trackletFinderHandler(const Cluster* clustersNextLayer, // 0 2 maxTrackletsPerCluster); // const unsigned int maxTrackletsPerCluster = 1e2 } /* -GPUd() float smallestAngleDifference(float a, float b) -{ - float diff = fmod(b - a + constants::math::Pi, constants::math::TwoPi) - constants::math::Pi; - return (diff < -constants::math::Pi) ? diff + constants::math::TwoPi : ((diff > constants::math::Pi) ? diff - constants::math::TwoPi : diff); -} GPUd() const int4 getBinsRect(const Cluster& currentCluster, const int layerIndex, const float z1, float maxdeltaz, float maxdeltaphi) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index d3f7597ae314b..14edd0b81e049 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -58,9 +58,9 @@ class Configuration : public Param }; struct TrackingParameters { - int CellMinimumLevel() { return MinTrackLength - constants::its::ClustersPerCell + 1; } - int CellsPerRoad() const { return NLayers - 2; } - int TrackletsPerRoad() const { return NLayers - 1; } + int CellMinimumLevel() const noexcept { return MinTrackLength - constants::ClustersPerCell + 1; } + int CellsPerRoad() const noexcept { return NLayers - 2; } + int TrackletsPerRoad() const noexcept { return NLayers - 1; } std::string asString() const; int NLayers = 7; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h index c29ad2e01c588..48cc45e44cf1c 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h @@ -17,112 +17,25 @@ #define TRACKINGITSU_INCLUDE_CONSTANTS_H_ #include "ITStracking/Definitions.h" -#include "CommonConstants/MathConstants.h" -#include "GPUCommonMath.h" -#include "GPUCommonDef.h" - -#ifndef GPUCA_GPUCODE_DEVICE -#include -#include -#include -#endif - -namespace o2 -{ -namespace its -{ - -namespace constants +namespace o2::its::constants { constexpr float MB = 1024.f * 1024.f; constexpr float GB = 1024.f * 1024.f * 1024.f; constexpr bool DoTimeBenchmarks = true; constexpr bool SaveTimeBenchmarks = false; -namespace math -{ -constexpr float Pi{3.14159265359f}; -constexpr float TwoPi{2.0f * Pi}; -constexpr float FloatMinThreshold{1e-20f}; -} // namespace math - -namespace its -{ -constexpr int LayersNumberVertexer{3}; +constexpr float Tolerance{1e-12}; // numerical tolerance constexpr int ClustersPerCell{3}; constexpr int UnusedIndex{-1}; constexpr float Resolution{0.0005f}; - -GPUhdi() constexpr std::array VertexerHistogramVolume() -{ - return std::array{{1.98, 1.98, 40.f}}; -} -} // namespace its - -namespace its2 -{ -constexpr int LayersNumber{7}; -constexpr int TrackletsPerRoad{LayersNumber - 1}; -constexpr int CellsPerRoad{LayersNumber - 2}; - -GPUhdi() constexpr std::array LayersZCoordinate() -{ - constexpr double s = 1.; // safety margin - return std::array{16.333f + s, 16.333f + s, 16.333f + s, 42.140f + s, 42.140f + s, 73.745f + s, 73.745f + s}; -} - -GPUhdi() constexpr std::array LayersRCoordinate() +constexpr float Radl = 9.36f; // Radiation length of Si [cm] +constexpr float Rho = 2.33f; // Density of Si [g/cm^3] +namespace its // to be removed { - return std::array{{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}}; -} - -constexpr int ZBins{256}; -constexpr int PhiBins{128}; -constexpr float InversePhiBinSize{PhiBins / constants::math::TwoPi}; -GPUhdi() constexpr std::array InverseZBinSize() -{ - constexpr auto zSize = LayersZCoordinate(); - return std::array{0.5f * ZBins / (zSize[0]), 0.5f * ZBins / (zSize[1]), 0.5f * ZBins / (zSize[2]), - 0.5f * ZBins / (zSize[3]), 0.5f * ZBins / (zSize[4]), 0.5f * ZBins / (zSize[5]), - 0.5f * ZBins / (zSize[6])}; -} - -GPUhdi() constexpr float getInverseZCoordinate(const int layerIndex) -{ - return 0.5f * ZBins / LayersZCoordinate()[layerIndex]; -} - -GPUhdi() int getZBinIndex(const int layerIndex, const float zCoordinate) -{ - return (zCoordinate + LayersZCoordinate()[layerIndex]) * - InverseZBinSize()[layerIndex]; -} - -GPUhdi() int getPhiBinIndex(const float currentPhi) -{ - return (currentPhi * InversePhiBinSize); -} - -GPUhdi() int getBinIndex(const int zIndex, const int phiIndex) -{ - return o2::gpu::GPUCommonMath::Min(phiIndex * ZBins + zIndex, - ZBins * PhiBins - 1); -} - -GPUhdi() constexpr int4 getEmptyBinsRect() { return int4{0, 0, 0, 0}; } - -} // namespace its2 - -namespace pdgcodes -{ -constexpr int PionCode{211}; -} -} // namespace constants -#ifndef GPUCA_GPUCODE_DEVICE -typedef std::vector> index_table_t; -#endif +constexpr int UnusedIndex{-1}; +constexpr float Resolution{0.0005f}; } // namespace its -} // namespace o2 +} // namespace o2::its::constants #endif /* TRACKINGITSU_INCLUDE_CONSTANTS_H_ */ diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h index ed4027f77f360..61072cb2410b7 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IndexTableUtils.h @@ -16,9 +16,9 @@ #ifndef TRACKINGITSU_INCLUDE_INDEXTABLEUTILS_H_ #define TRACKINGITSU_INCLUDE_INDEXTABLEUTILS_H_ -#include "ITStracking/Constants.h" #include "ITStracking/Configuration.h" #include "ITStracking/Definitions.h" +#include "CommonConstants/MathConstants.h" #include "GPUCommonMath.h" #include "GPUCommonDef.h" @@ -55,7 +55,7 @@ class IndexTableUtils template inline void IndexTableUtils::setTrackingParameters(const T& params) { - mInversePhiBinSize = params.PhiBins / constants::math::TwoPi; + mInversePhiBinSize = params.PhiBins / o2::constants::math::TwoPI; mNzBins = params.ZBins; mNphiBins = params.PhiBins; for (int iLayer{0}; iLayer < params.LayerZ.size(); ++iLayer) { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h index 9093609144283..c5c1e4a8ce220 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/MathUtils.h @@ -13,92 +13,95 @@ /// \brief /// -#ifndef TRACKINGITSU_INCLUDE_CAUTILS_H_ -#define TRACKINGITSU_INCLUDE_CAUTILS_H_ +#ifndef O2_ITS_TRACKING_MATHUTILS_H_ +#define O2_ITS_TRACKING_MATHUTILS_H_ -#ifndef GPUCA_GPUCODE_DEVICE -#include -#include -#include -#include -#endif - -#include "MathUtils/Utils.h" +#include "CommonConstants/MathConstants.h" #include "ITStracking/Constants.h" +#include "MathUtils/Utils.h" #include "GPUCommonMath.h" #include "GPUCommonDef.h" -namespace o2 -{ -namespace its +namespace o2::its::math_utils { -namespace math_utils +GPUhdi() float computePhi(float x, float y) { -GPUhdni() float computePhi(const float, const float); -GPUhdni() float hypot(const float, const float); -GPUhdni() constexpr float getNormalizedPhi(const float); -GPUhdni() constexpr float3 crossProduct(const float3&, const float3&); -GPUhdni() float computeCurvature(float x1, float y1, float x2, float y2, float x3, float y3); -GPUhdni() float computeCurvatureCentreX(float x1, float y1, float x2, float y2, float x3, float y3); -GPUhdni() float computeTanDipAngle(float x1, float y1, float x2, float y2, float z1, float z2); - -} // namespace math_utils - -GPUhdi() float math_utils::computePhi(const float x, const float y) -{ - //return o2::gpu::CAMath::ATan2(-yCoordinate, -xCoordinate) + constants::math::Pi; - return o2::math_utils::fastATan2(-y, -x) + constants::math::Pi; -} - -GPUhdi() float math_utils::hypot(const float x, const float y) -{ - return o2::gpu::CAMath::Sqrt(x * x + y * y); + return o2::math_utils::fastATan2(-y, -x) + o2::constants::math::PI; } -GPUhdi() constexpr float math_utils::getNormalizedPhi(const float phi) +GPUhdi() constexpr float hypot(float x, float y) { - return (phi < 0) ? phi + constants::math::TwoPi : (phi > constants::math::TwoPi) ? phi - constants::math::TwoPi - : phi; + return o2::gpu::CAMath::Hypot(x, y); } -GPUhdi() constexpr float3 math_utils::crossProduct(const float3& firstVector, const float3& secondVector) +GPUhdi() constexpr float getNormalizedPhi(float phi) { - - return float3{(firstVector.y * secondVector.z) - (firstVector.z * secondVector.y), - (firstVector.z * secondVector.x) - (firstVector.x * secondVector.z), - (firstVector.x * secondVector.y) - (firstVector.y * secondVector.x)}; + phi -= o2::constants::math::TwoPI * o2::gpu::CAMath::Floor(phi * (1.f / o2::constants::math::TwoPI)); + return phi; } -GPUhdi() float math_utils::computeCurvature(float x1, float y1, float x2, float y2, float x3, float y3) +GPUhdi() float computeCurvature(float x1, float y1, float x2, float y2, float x3, float y3) { + // in case the triangle is degenerate we return infinite curvature. const float d = (x2 - x1) * (y3 - y2) - (x3 - x2) * (y2 - y1); + if (o2::gpu::CAMath::Abs(d) < o2::its::constants::Tolerance) { + return 0.f; + } const float a = 0.5f * ((y3 - y2) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1) - (y2 - y1) * (y3 * y3 - y2 * y2 + x3 * x3 - x2 * x2)); const float b = 0.5f * ((x2 - x1) * (y3 * y3 - y2 * y2 + x3 * x3 - x2 * x2) - (x3 - x2) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1)); - const float den2 = (d * x1 - a) * (d * x1 - a) + (d * y1 - b) * (d * y1 - b); - return den2 > 0.f ? -1.f * d / o2::gpu::CAMath::Sqrt(den2) : 0.f; + const float den = o2::gpu::CAMath::Hypot(d * x1 - a, d * y1 - b); + if (den < o2::its::constants::Tolerance) { + return 0.f; + } + return -d / den; } -GPUhdi() float math_utils::computeCurvatureCentreX(float x1, float y1, float x2, float y2, float x3, float y3) +GPUhdi() float computeCurvatureCentreX(float x1, float y1, float x2, float y2, float x3, float y3) { + // in case the triangle is degenerate we return set the centre to infinity. float dx21 = x2 - x1, dx32 = x3 - x2; - if (dx21 == 0.f || dx32 == 0.f) { // add small offset + if (o2::gpu::CAMath::Abs(dx21) < o2::its::constants::Tolerance || + o2::gpu::CAMath::Abs(dx32) < o2::its::constants::Tolerance) { // add small offset x2 += 1e-4; dx21 = x2 - x1; dx32 = x3 - x2; } - float k1 = (y2 - y1) / dx21, k2 = (y3 - y2) / dx32; - return (k1 != k2) ? 0.5f * (k1 * k2 * (y1 - y3) + k2 * (x1 + x2) - k1 * (x2 + x3)) / (k2 - k1) : 1e5; + const float k1 = (y2 - y1) / dx21, k2 = (y3 - y2) / dx32; + if (o2::gpu::CAMath::Abs(k2 - k1) < o2::its::constants::Tolerance) { + return o2::constants::math::VeryBig; + } + return 0.5f * (k1 * k2 * (y1 - y3) + k2 * (x1 + x2) - k1 * (x2 + x3)) / (k2 - k1); } -GPUhdi() float math_utils::computeTanDipAngle(float x1, float y1, float x2, float y2, float z1, float z2) +GPUhdi() float computeTanDipAngle(float x1, float y1, float x2, float y2, float z1, float z2) { - return (z1 - z2) / o2::gpu::CAMath::Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + // in case the points vertically align we go to pos/neg inifinity. + const float d = o2::gpu::CAMath::Hypot(x1 - x2, y1 - y2); + if (o2::gpu::CAMath::Abs(d) < o2::its::constants::Tolerance) { + return ((z1 > z2) ? -1.f : 1.f) * o2::constants::math::VeryBig; + } + return (z1 - z2) / d; } -} // namespace its -} // namespace o2 +GPUhdi() float smallestAngleDifference(float a, float b) +{ + return o2::gpu::CAMath::Remainderf(b - a, o2::constants::math::TwoPI); +} -#endif /* TRACKINGITSU_INCLUDE_CAUTILS_H_ */ +GPUhdi() float Sq(float v) +{ + return v * v; +} + +GPUhdi() float MSangle(float mass, float p, float xX0) +{ + float beta = p / o2::gpu::CAMath::Hypot(mass, p); + return 0.0136f * o2::gpu::CAMath::Sqrt(xX0) * (1.f + 0.038f * o2::gpu::CAMath::Log(xX0)) / (beta * p); +} + +} // namespace o2::its::math_utils + +#endif diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h index 5f4e40b92ba82..36956a5206277 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h @@ -113,9 +113,9 @@ template inline const int4 TrackerTraits::getBinsRect(const int layerIndex, float phi, float maxdeltaphi, float z1, float z2, float maxdeltaz) const noexcept { const float zRangeMin = o2::gpu::GPUCommonMath::Min(z1, z2) - maxdeltaz; - const float phiRangeMin = (maxdeltaphi > constants::math::Pi) ? 0.f : phi - maxdeltaphi; + const float phiRangeMin = (maxdeltaphi > o2::constants::math::PI) ? 0.f : phi - maxdeltaphi; const float zRangeMax = o2::gpu::GPUCommonMath::Max(z1, z2) + maxdeltaz; - const float phiRangeMax = (maxdeltaphi > constants::math::Pi) ? constants::math::TwoPi : phi + maxdeltaphi; + const float phiRangeMax = (maxdeltaphi > o2::constants::math::PI) ? o2::constants::math::TwoPI : phi + maxdeltaphi; if (zRangeMax < -mTrkParams[0].LayerZ[layerIndex] || zRangeMin > mTrkParams[0].LayerZ[layerIndex] || zRangeMin > zRangeMax) { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index e4ecced6d67fb..e1e1d44e8ead9 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -41,8 +41,6 @@ class MCCompLabel; namespace its { -class ROframe; -using constants::its::LayersNumberVertexer; enum class TrackletMode { Layer0Layer1 = 0, diff --git a/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx b/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx index 6259e20a02dfb..9bc65161c3cbb 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx @@ -50,7 +50,7 @@ Smoother::Smoother(TrackITSExt& track, size_t smoothingLayer, const ROframe& ////////////////////// // Outward propagation for (size_t iLayer{0}; iLayer < mLayerToSmooth; ++iLayer) { - if (mOutwardsTrack.getClusterIndex(iLayer) == constants::its::UnusedIndex) { // Shorter tracks + if (mOutwardsTrack.getClusterIndex(iLayer) == constants::UnusedIndex) { // Shorter tracks continue; } const TrackingFrameInfo& tF = event.getTrackingFrameInfoOnLayer(iLayer).at(mOutwardsTrack.getClusterIndex(iLayer)); @@ -78,7 +78,7 @@ Smoother::Smoother(TrackITSExt& track, size_t smoothingLayer, const ROframe& ///////////////////// // Inward propagation for (size_t iLayer{D - 1}; iLayer > mLayerToSmooth; --iLayer) { - if (mInwardsTrack.getClusterIndex(iLayer) == constants::its::UnusedIndex) { // Shorter tracks + if (mInwardsTrack.getClusterIndex(iLayer) == constants::UnusedIndex) { // Shorter tracks continue; } const TrackingFrameInfo& tF = event.getTrackingFrameInfoOnLayer(iLayer).at(mInwardsTrack.getClusterIndex(iLayer)); diff --git a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx index 34d8967c6a5bb..80dbae42fc387 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx @@ -34,18 +34,6 @@ struct ClusterHelper { int bin; int ind; }; - -inline float MSangle(float mass, float p, float xX0) -{ - float beta = p / o2::gpu::CAMath::Hypot(mass, p); - return 0.0136f * o2::gpu::CAMath::Sqrt(xX0) * (1.f + 0.038f * o2::gpu::CAMath::Log(xX0)) / (beta * p); -} - -inline float Sq(float v) -{ - return v * v; -} - } // namespace namespace o2::its @@ -323,7 +311,7 @@ void TimeFrame::initialise(const int iteration, const TrackingParameter for (unsigned int iLayer{0}; iLayer < std::min((int)mClusters.size(), maxLayers); ++iLayer) { clearResizeBoundedVector(mClusters[iLayer], mUnsortedClusters[iLayer].size(), mMemoryPool.get()); clearResizeBoundedVector(mUsedClusters[iLayer], mUnsortedClusters[iLayer].size(), mMemoryPool.get()); - mPositionResolution[iLayer] = o2::gpu::CAMath::Sqrt(0.5 * (trkParam.SystErrorZ2[iLayer] + trkParam.SystErrorY2[iLayer]) + trkParam.LayerResolution[iLayer] * trkParam.LayerResolution[iLayer]); + mPositionResolution[iLayer] = o2::gpu::CAMath::Sqrt(0.5f * (trkParam.SystErrorZ2[iLayer] + trkParam.SystErrorY2[iLayer]) + trkParam.LayerResolution[iLayer] * trkParam.LayerResolution[iLayer]); } clearResizeBoundedArray(mIndexTables, mNrof * (trkParam.ZBins * trkParam.PhiBins + 1), mMemoryPool.get()); clearResizeBoundedVector(mLines, mNrof, mMemoryPool.get()); @@ -364,18 +352,18 @@ void TimeFrame::initialise(const int iteration, const TrackingParameter float oneOverR{0.001f * 0.3f * std::abs(mBz) / trkParam.TrackletMinPt}; for (unsigned int iLayer{0}; iLayer < mClusters.size(); ++iLayer) { - mMSangles[iLayer] = MSangle(0.14f, trkParam.TrackletMinPt, trkParam.LayerxX0[iLayer]); + mMSangles[iLayer] = math_utils::MSangle(0.14f, trkParam.TrackletMinPt, trkParam.LayerxX0[iLayer]); mPositionResolution[iLayer] = o2::gpu::CAMath::Sqrt(0.5f * (trkParam.SystErrorZ2[iLayer] + trkParam.SystErrorY2[iLayer]) + trkParam.LayerResolution[iLayer] * trkParam.LayerResolution[iLayer]); if (iLayer < mClusters.size() - 1) { const float& r1 = trkParam.LayerRadii[iLayer]; const float& r2 = trkParam.LayerRadii[iLayer + 1]; const float res1 = o2::gpu::CAMath::Hypot(trkParam.PVres, mPositionResolution[iLayer]); const float res2 = o2::gpu::CAMath::Hypot(trkParam.PVres, mPositionResolution[iLayer + 1]); - const float cosTheta1half = o2::gpu::CAMath::Sqrt(1.f - Sq(0.5f * r1 * oneOverR)); - const float cosTheta2half = o2::gpu::CAMath::Sqrt(1.f - Sq(0.5f * r2 * oneOverR)); + const float cosTheta1half = o2::gpu::CAMath::Sqrt(1.f - math_utils::Sq(0.5f * r1 * oneOverR)); + const float cosTheta2half = o2::gpu::CAMath::Sqrt(1.f - math_utils::Sq(0.5f * r2 * oneOverR)); float x = r2 * cosTheta1half - r1 * cosTheta2half; - float delta = o2::gpu::CAMath::Sqrt(1.f / (1.f - 0.25f * Sq(x * oneOverR)) * (Sq(0.25f * r1 * r2 * Sq(oneOverR) / cosTheta2half + cosTheta1half) * Sq(res1) + Sq(0.25f * r1 * r2 * Sq(oneOverR) / cosTheta1half + cosTheta2half) * Sq(res2))); - mPhiCuts[iLayer] = std::min(o2::gpu::CAMath::ASin(0.5f * x * oneOverR) + 2.f * mMSangles[iLayer] + delta, constants::math::Pi * 0.5f); + float delta = o2::gpu::CAMath::Sqrt(1.f / (1.f - 0.25f * math_utils::Sq(x * oneOverR)) * (math_utils::Sq(0.25f * r1 * r2 * math_utils::Sq(oneOverR) / cosTheta2half + cosTheta1half) * math_utils::Sq(res1) + math_utils::Sq(0.25f * r1 * r2 * math_utils::Sq(oneOverR) / cosTheta1half + cosTheta2half) * math_utils::Sq(res2))); + mPhiCuts[iLayer] = std::min(o2::gpu::CAMath::ASin(0.5f * x * oneOverR) + 2.f * mMSangles[iLayer] + delta, o2::constants::math::PI * 0.5f); } } diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 75c265dbdb703..f4da1a86818bb 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -178,7 +178,7 @@ void Tracker::computeRoadsMClabels() for (int iCell{0}; iCell < mTrkParams[0].CellsPerRoad(); ++iCell) { const int currentCellIndex{currentRoad[iCell]}; - if (currentCellIndex == constants::its::UnusedIndex) { + if (currentCellIndex == constants::UnusedIndex) { if (isFirstRoadCell) { continue; } else { @@ -270,7 +270,7 @@ void Tracker::computeTracksMClabels() for (int iCluster = 0; iCluster < TrackITSExt::MaxClusters; ++iCluster) { const int index = track.getClusterIndex(iCluster); - if (index == constants::its::UnusedIndex) { + if (index == constants::UnusedIndex) { continue; } auto labels = mTimeFrame->getClusterLabels(iCluster, index); @@ -300,7 +300,7 @@ void Tracker::computeTracksMClabels() // set fake clusters pattern for (int ic{TrackITSExt::MaxClusters}; ic--;) { auto clid = track.getClusterIndex(ic); - if (clid != constants::its::UnusedIndex) { + if (clid != constants::UnusedIndex) { auto labelsSpan = mTimeFrame->getClusterLabels(ic, clid); for (const auto& currentLabel : labelsSpan) { if (currentLabel == maxOccurrencesValue) { @@ -325,7 +325,7 @@ void Tracker::rectifyClusterIndices() for (auto& track : mTimeFrame->getTracks(iROF)) { for (int iCluster = 0; iCluster < TrackITSExt::MaxClusters; ++iCluster) { const int index = track.getClusterIndex(iCluster); - if (index != constants::its::UnusedIndex) { + if (index != constants::UnusedIndex) { track.setExternalClusterIndex(iCluster, mTimeFrame->getClusterExternalIndex(iCluster, index)); } } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index 766dc25cd6d8e..36636069137f3 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -22,7 +22,7 @@ #include #endif -#include +#include #include #include "CommonConstants/MathConstants.h" @@ -38,18 +38,10 @@ using o2::base::PropagatorF; -namespace -{ -inline float Sq(float q) -{ - return q * q; -} -} // namespace - namespace o2::its { -constexpr int debugLevel{0}; +static constexpr int debugLevel{0}; template void TrackerTraits::computeLayerTracklets(const int iteration, int iROFslice, int iVertex) @@ -105,15 +97,15 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF if (primaryVertex.isFlagSet(2) && iteration != 3) { continue; } - const float resolution = o2::gpu::CAMath::Sqrt(Sq(mTrkParams[iteration].PVres) / primaryVertex.getNContributors() + Sq(mTimeFrame->getPositionResolution(iLayer))); + const float resolution = o2::gpu::CAMath::Sqrt(math_utils::Sq(mTrkParams[iteration].PVres) / primaryVertex.getNContributors() + math_utils::Sq(mTimeFrame->getPositionResolution(iLayer))); const float tanLambda{(currentCluster.zCoordinate - primaryVertex.getZ()) * inverseR0}; const float zAtRmin{tanLambda * (mTimeFrame->getMinR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate}; const float zAtRmax{tanLambda * (mTimeFrame->getMaxR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate}; - const float sqInverseDeltaZ0{1.f / (Sq(currentCluster.zCoordinate - primaryVertex.getZ()) + 2.e-8f)}; /// protecting from overflows adding the detector resolution - const float sigmaZ{o2::gpu::CAMath::Sqrt(Sq(resolution) * Sq(tanLambda) * ((Sq(inverseR0) + sqInverseDeltaZ0) * Sq(meanDeltaR) + 1.f) + Sq(meanDeltaR * mTimeFrame->getMSangle(iLayer)))}; + const float sqInverseDeltaZ0{1.f / (math_utils::Sq(currentCluster.zCoordinate - primaryVertex.getZ()) + 2.e-8f)}; /// protecting from overflows adding the detector resolution + const float sigmaZ{o2::gpu::CAMath::Sqrt(math_utils::Sq(resolution) * math_utils::Sq(tanLambda) * ((math_utils::Sq(inverseR0) + sqInverseDeltaZ0) * math_utils::Sq(meanDeltaR) + 1.f) + math_utils::Sq(meanDeltaR * mTimeFrame->getMSangle(iLayer)))}; const int4 selectedBinsRect{getBinsRect(currentCluster, iLayer + 1, zAtRmin, zAtRmax, sigmaZ * mTrkParams[iteration].NSigmaCut, mTimeFrame->getPhiCut(iLayer))}; if (selectedBinsRect.x == 0 && selectedBinsRect.y == 0 && selectedBinsRect.z == 0 && selectedBinsRect.w == 0) { @@ -181,7 +173,7 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF if (deltaZ / sigmaZ < mTrkParams[iteration].NSigmaCut && (deltaPhi < mTimeFrame->getPhiCut(iLayer) || - o2::gpu::GPUCommonMath::Abs(deltaPhi - constants::math::TwoPi) < mTimeFrame->getPhiCut(iLayer))) { + o2::gpu::GPUCommonMath::Abs(deltaPhi - o2::constants::math::TwoPI) < mTimeFrame->getPhiCut(iLayer))) { if (iLayer > 0) { mTimeFrame->getTrackletsLookupTable()[iLayer - 1][currentSortedIndex]++; } @@ -273,9 +265,6 @@ void TrackerTraits::computeLayerCells(const int iteration) std::ofstream off(std::format("cells{}.txt", iter++)); #endif - constexpr float radl = 9.36f; // Radiation length of Si [cm] - constexpr float rho = 2.33f; // Density of Si [g/cm^3] - for (int iLayer = 0; iLayer < mTrkParams[iteration].CellsPerRoad(); ++iLayer) { deepVectorClear(mTimeFrame->getCells()[iLayer]); if (iLayer > 0) { @@ -359,7 +348,7 @@ void TrackerTraits::computeLayerCells(const int iteration) break; } - if (!track.correctForMaterial(mTrkParams[0].LayerxX0[iLayer + iC], mTrkParams[0].LayerxX0[iLayer] * radl * rho, true)) { + if (!track.correctForMaterial(mTrkParams[0].LayerxX0[iLayer + iC], mTrkParams[0].LayerxX0[iLayer] * constants::Radl * constants::Rho, true)) { break; } @@ -441,7 +430,7 @@ void TrackerTraits::computeLayerCells(const int iteration) break; } - if (!track.correctForMaterial(mTrkParams[0].LayerxX0[iLayer + iC], mTrkParams[0].LayerxX0[iLayer] * radl * rho, true)) { + if (!track.correctForMaterial(mTrkParams[0].LayerxX0[iLayer + iC], mTrkParams[0].LayerxX0[iLayer] * constants::Radl * constants::Rho, true)) { break; } @@ -682,9 +671,7 @@ void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bou } if (mCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { - float radl = 9.36f; // Radiation length of Si [cm] - float rho = 2.33f; // Density of Si [g/cm^3] - if (!seed.correctForMaterial(mTrkParams[0].LayerxX0[iLayer - 1], mTrkParams[0].LayerxX0[iLayer - 1] * radl * rho, true)) { + if (!seed.correctForMaterial(mTrkParams[0].LayerxX0[iLayer - 1], mTrkParams[0].LayerxX0[iLayer - 1] * constants::Radl * constants::Rho, true)) { continue; } } @@ -745,9 +732,7 @@ void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bou } if (mCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { - float radl = 9.36f; // Radiation length of Si [cm] - float rho = 2.33f; // Density of Si [g/cm^3] - if (!seed.correctForMaterial(mTrkParams[0].LayerxX0[iLayer - 1], mTrkParams[0].LayerxX0[iLayer - 1] * radl * rho, true)) { + if (!seed.correctForMaterial(mTrkParams[0].LayerxX0[iLayer - 1], mTrkParams[0].LayerxX0[iLayer - 1] * constants::Radl * constants::Rho, true)) { continue; } } @@ -838,7 +823,7 @@ void TrackerTraits::findRoads(const int iteration) temporaryTrack.resetCovariance(); temporaryTrack.setChi2(0); for (int iL{0}; iL < 7; ++iL) { - temporaryTrack.setExternalClusterIndex(iL, seed.getCluster(iL), seed.getCluster(iL) != constants::its::UnusedIndex); + temporaryTrack.setExternalClusterIndex(iL, seed.getCluster(iL), seed.getCluster(iL) != constants::UnusedIndex); } bool fitSuccess = fitTrack(temporaryTrack, 0, mTrkParams[0].NLayers, 1, mTrkParams[0].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF); @@ -874,7 +859,7 @@ void TrackerTraits::findRoads(const int iteration) trk.resetCovariance(); trk.setChi2(0); for (int iL{0}; iL < 7; ++iL) { - trk.setExternalClusterIndex(iL, seed.getCluster(iL), seed.getCluster(iL) != constants::its::UnusedIndex); + trk.setExternalClusterIndex(iL, seed.getCluster(iL), seed.getCluster(iL) != constants::UnusedIndex); } bool fitSuccess = fitTrack(trk, 0, mTrkParams[0].NLayers, 1, mTrkParams[0].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF); @@ -898,7 +883,7 @@ void TrackerTraits::findRoads(const int iteration) int nShared = 0; bool isFirstShared{false}; for (int iLayer{0}; iLayer < mTrkParams[0].NLayers; ++iLayer) { - if (track.getClusterIndex(iLayer) == constants::its::UnusedIndex) { + if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { continue; } nShared += int(mTimeFrame->isClusterUsed(iLayer, track.getClusterIndex(iLayer))); @@ -911,7 +896,7 @@ void TrackerTraits::findRoads(const int iteration) std::array rofs{INT_MAX, INT_MAX, INT_MAX}; for (int iLayer{0}; iLayer < mTrkParams[0].NLayers; ++iLayer) { - if (track.getClusterIndex(iLayer) == constants::its::UnusedIndex) { + if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { continue; } mTimeFrame->markUsedCluster(iLayer, track.getClusterIndex(iLayer)); @@ -977,7 +962,7 @@ void TrackerTraits::extendTracks(const int iteration) track.setPattern(pattern); /// Make sure that the newly attached clusters get marked as used for (int iLayer{0}; iLayer < mTrkParams[iteration].NLayers; ++iLayer) { - if (track.getClusterIndex(iLayer) == constants::its::UnusedIndex) { + if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { continue; } mTimeFrame->markUsedCluster(iLayer, track.getClusterIndex(iLayer)); @@ -1082,7 +1067,7 @@ bool TrackerTraits::fitTrack(TrackITSExt& track, int start, int end, in auto propInstance = o2::base::Propagator::Instance(); for (int iLayer{start}; iLayer != end; iLayer += step) { - if (track.getClusterIndex(iLayer) == constants::its::UnusedIndex) { + if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { continue; } const TrackingFrameInfo& trackingHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer)[track.getClusterIndex(iLayer)]; @@ -1096,9 +1081,7 @@ bool TrackerTraits::fitTrack(TrackITSExt& track, int start, int end, in } if (mCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { - constexpr float radl = 9.36f; // Radiation length of Si [cm] - constexpr float rho = 2.33f; // Density of Si [g/cm^3] - if (!track.correctForMaterial(mTrkParams[0].LayerxX0[iLayer], mTrkParams[0].LayerxX0[iLayer] * radl * rho, true)) { + if (!track.correctForMaterial(mTrkParams[0].LayerxX0[iLayer], mTrkParams[0].LayerxX0[iLayer] * constants::Radl * constants::Rho, true)) { continue; } } @@ -1143,9 +1126,7 @@ bool TrackerTraits::trackFollowing(TrackITSExt* track, int rof, bool ou } if (mTrkParams[iteration].CorrType == PropagatorF::MatCorrType::USEMatCorrNONE) { // account for material affects if propagator does not - constexpr float radl = 9.36f; // Radiation length of Si [cm] - constexpr float rho = 2.33f; // Density of Si [g/cm^3] - if (!hypoParam.correctForMaterial(mTrkParams[iteration].LayerxX0[iLayer], mTrkParams[iteration].LayerxX0[iLayer] * radl * rho, true)) { + if (!hypoParam.correctForMaterial(mTrkParams[iteration].LayerxX0[iLayer], mTrkParams[iteration].LayerxX0[iLayer] * constants::Radl * constants::Rho, true)) { continue; } } diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index fe1619efaa192..37b650c05bd61 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -31,12 +31,6 @@ using namespace o2::its; -float smallestAngleDifference(float a, float b) -{ - float diff = fmod(b - a + constants::math::Pi, constants::math::TwoPi) - constants::math::Pi; - return (diff < -constants::math::Pi) ? diff + constants::math::TwoPi : ((diff > constants::math::Pi) ? diff - constants::math::TwoPi : diff); -} - template void trackleterKernelHost( const gsl::span& clustersNextLayer, // 0 2 @@ -75,7 +69,7 @@ void trackleterKernelHost( continue; } const Cluster& nextCluster{clustersNextLayer[iNextLayerClusterIndex]}; - if (o2::gpu::GPUCommonMath::Abs(smallestAngleDifference(currentCluster.phi, nextCluster.phi)) < phiCut) { + if (o2::gpu::GPUCommonMath::Abs(math_utils::smallestAngleDifference(currentCluster.phi, nextCluster.phi)) < phiCut) { if (storedTracklets < maxTrackletsPerCluster) { if constexpr (!EvalRun) { if constexpr (Mode == TrackletMode::Layer0Layer1) { @@ -128,7 +122,7 @@ void trackletSelectionKernelHost( continue; } const float deltaTanLambda{o2::gpu::GPUCommonMath::Abs(tracklet01.tanLambda - tracklet12.tanLambda)}; - const float deltaPhi{o2::gpu::GPUCommonMath::Abs(smallestAngleDifference(tracklet01.phi, tracklet12.phi))}; + const float deltaPhi{o2::gpu::GPUCommonMath::Abs(math_utils::smallestAngleDifference(tracklet01.phi, tracklet12.phi))}; if (!usedTracklets[iTracklet01] && deltaTanLambda < tanLambdaCut && deltaPhi < phiCut && validTracklets != maxTracklets) { usedClusters0[tracklet01.firstClusterIndex] = true; usedClusters2[tracklet12.secondClusterIndex] = true; @@ -171,7 +165,7 @@ void VertexerTraits::updateVertexingParameters(const std::vector(std::ceil(mIndexTableUtils.getNphiBins() * par.phiCut / constants::math::TwoPi)); + par.phiSpan = static_cast(std::ceil(mIndexTableUtils.getNphiBins() * par.phiCut / o2::constants::math::TwoPI)); par.zSpan = static_cast(std::ceil(par.zCut * mIndexTableUtils.getInverseZCoordinate(0))); } setNThreads(vrtPar[0].nThreads); From bb75239cef8addcc693f52f1f9dcb65b83ce9f21 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:10:51 +0200 Subject: [PATCH 010/315] Export fairlogger/Logger.h to avoid disseminating it everywhere. (#14391) --- Framework/Logger/include/Framework/Logger.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Logger/include/Framework/Logger.h b/Framework/Logger/include/Framework/Logger.h index 5b3cd832d60a1..3bd977d14c735 100644 --- a/Framework/Logger/include/Framework/Logger.h +++ b/Framework/Logger/include/Framework/Logger.h @@ -11,7 +11,7 @@ #ifndef O2_FRAMEWORK_LOGGER_H_ #define O2_FRAMEWORK_LOGGER_H_ -#include +#include // IWYU pragma: export #define O2DEBUG(...) LOGF(debug, __VA_ARGS__) #define O2INFO(...) LOGF(info, __VA_ARGS__) From 892c49cd9f8e0ec5a65061aabfb36a7422c841f3 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:30:45 +0200 Subject: [PATCH 011/315] IWYU: avoid spurious unused include report (#14392) Using WorkflowSpec without an AlgorithmSpec does not make much sense. --- Framework/Core/include/Framework/WorkflowSpec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/WorkflowSpec.h b/Framework/Core/include/Framework/WorkflowSpec.h index bdc4ea6302da1..d778463eeb1d2 100644 --- a/Framework/Core/include/Framework/WorkflowSpec.h +++ b/Framework/Core/include/Framework/WorkflowSpec.h @@ -12,7 +12,7 @@ #define O2_FRAMEWORK_WORKFLOWSPEC_H_ #include "Framework/DataProcessorSpec.h" -#include "Framework/AlgorithmSpec.h" +#include "Framework/AlgorithmSpec.h" // IWYU pragma: export #include #include From 3a8de5599d75cf26c194d4dc23460e9a640c1ad9 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:51:49 +0200 Subject: [PATCH 012/315] IWYU: export commonly used headers (#14393) - Avoid fairlogger/Logger.h suggested everywhere - Avoid exposing WorkflowSpec.h everywhere we have a runDataProcessing.h - Cannot use AnalysisDataModel without ASoA.h --- Framework/Core/include/Framework/AnalysisDataModel.h | 2 +- Framework/Core/include/Framework/runDataProcessing.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index a2b0dc39950d4..e34b8210a0178 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -11,7 +11,7 @@ #ifndef O2_FRAMEWORK_ANALYSISDATAMODEL_H_ #define O2_FRAMEWORK_ANALYSISDATAMODEL_H_ -#include "Framework/ASoA.h" +#include "Framework/ASoA.h" // IWYU pragma: export #include #include diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 07083314af12e..e756c9f4b1d26 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -21,12 +21,12 @@ #include "Framework/DataProcessorSpec.h" #include "Framework/DataAllocator.h" #include "Framework/SendingPolicy.h" -#include "Framework/WorkflowSpec.h" +#include "Framework/WorkflowSpec.h" // IWYU pragma: export #include "Framework/ConfigContext.h" #include "Framework/CustomWorkflowTerminationHook.h" #include "Framework/CommonServices.h" #include "Framework/WorkflowCustomizationHelpers.h" -#include "Framework/Logger.h" +#include "Framework/Logger.h" // IWYU pragma: export #include "Framework/CheckTypes.h" #include "Framework/StructToTuple.h" #include "ResourcePolicy.h" From b9b561d346384f18558c09efd156da2007cbb0e2 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 12 Jun 2025 08:04:04 +0200 Subject: [PATCH 013/315] ITS: tracker shadowed variable (#14390) * ITS: set default mem to high Signed-off-by: Felix Schlepper * ITS: fix output crash if zero tracks where found Signed-off-by: Felix Schlepper * ITS: tracker fix shadowed variable Signed-off-by: Felix Schlepper * ITS: minor adjustments in TF Signed-off-by: Felix Schlepper --------- Signed-off-by: Felix Schlepper --- .../include/ITStracking/Configuration.h | 6 +- .../tracking/include/ITStracking/TimeFrame.h | 4 +- .../include/ITStracking/TrackingConfigParam.h | 5 +- .../ITSMFT/ITS/tracking/src/Configuration.cxx | 8 +- .../ITSMFT/ITS/tracking/src/TimeFrame.cxx | 126 +++++++++--------- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 5 +- .../ITS/tracking/src/TrackingInterface.cxx | 68 +++++----- 7 files changed, 111 insertions(+), 111 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 14edd0b81e049..2a40b817a7005 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -18,7 +18,7 @@ #ifndef GPUCA_GPUCODE_DEVICE #include -#include +#include #include #include #endif @@ -108,7 +108,7 @@ struct TrackingParameters { float TrackFollowerNSigmaCutPhi = 1.f; bool PrintMemory = false; // print allocator usage in epilog report - size_t MaxMemory = 12000000000UL; + size_t MaxMemory = std::numeric_limits::max(); bool DropTFUponFailure = false; }; @@ -142,7 +142,7 @@ struct VertexingParameters { int nThreads = 1; bool PrintMemory = false; // print allocator usage in epilog report - size_t MaxMemory = 12000000000UL; + size_t MaxMemory = std::numeric_limits::max(); bool DropTFUponFailure = false; }; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h index 1620350c68034..248e63aef382c 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h @@ -298,8 +298,6 @@ struct TimeFrame { std::array, nLayers> mUnsortedClusters; std::vector> mTracklets; std::vector> mCells; - std::vector> mCellSeeds; - std::vector> mCellSeedsChi2; bounded_vector> mRoads; std::vector> mTracks; std::vector> mCellsNeighbours; @@ -311,7 +309,7 @@ struct TimeFrame { void wipe(); private: - void prepareClusters(const TrackingParameters& trkParam, const int maxLayers); + void prepareClusters(const TrackingParameters& trkParam, const int maxLayers = nLayers); float mBz = 5.; unsigned int mNTotalLowPtVertices = 0; int mBeamPosWeight = 0; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h index 72301cd2851b3..039fe0756d6f6 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h @@ -12,6 +12,7 @@ #ifndef ALICEO2_ITSDPLTRACKINGPARAM_H_ #define ALICEO2_ITSDPLTRACKINGPARAM_H_ +#include #include "CommonUtils/ConfigurableParam.h" #include "CommonUtils/ConfigurableParamHelper.h" @@ -49,7 +50,7 @@ struct VertexerParamConfig : public o2::conf::ConfigurableParamHelper::max(); bool dropTFUponFailure = false; O2ParamDef(VertexerParamConfig, "ITSVertexerParam"); @@ -94,7 +95,7 @@ struct TrackerParamConfig : public o2::conf::ConfigurableParamHelper::max(); bool dropTFUponFailure = false; bool fataliseUponFailure = true; // granular management of the fatalisation in async mode diff --git a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx index d1cddc1819a0b..9e631ad6afb7f 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx @@ -57,14 +57,18 @@ std::string TrackingParameters::asString() const for (size_t i = 0; i < SystErrorY2.size(); i++) { str += std::format("{:.2e}/{:.2e} ", SystErrorY2[i], SystErrorZ2[i]); } - str += std::format(" MemLimit {:.2f} GB", double(MaxMemory) / constants::GB); + if (std::numeric_limits::max() != MaxMemory) { + str += std::format(" MemLimit {:.2f} GB", double(MaxMemory) / constants::GB); + } return str; } std::string VertexingParameters::asString() const { std::string str = std::format("NZb:{} NPhB:{} DRof:{} ClsCont:{} MaxTrkltCls:{} ZCut:{} PhCut:{}", ZBins, PhiBins, deltaRof, clusterContributorsCut, maxTrackletsPerCluster, zCut, phiCut); - str += std::format(" MemLimit {:.2f} GB", double(MaxMemory) / constants::GB); + if (std::numeric_limits::max() != MaxMemory) { + str += std::format(" MemLimit {:.2f} GB", double(MaxMemory) / constants::GB); + } return str; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx index 80dbae42fc387..dbb1631a4eb10 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx @@ -13,6 +13,10 @@ /// \brief /// +#include +#include + +#include "Framework/Logger.h" #include "ITStracking/TimeFrame.h" #include "ITStracking/MathUtils.h" #include "DataFormatsITSMFT/Cluster.h" @@ -24,8 +28,6 @@ #include "ITStracking/BoundedAllocator.h" #include "ITStracking/TrackingConfigParam.h" -#include - namespace { struct ClusterHelper { @@ -53,7 +55,7 @@ TimeFrame::TimeFrame() template TimeFrame::~TimeFrame() { - resetVectors(); + wipe(); } template @@ -214,34 +216,34 @@ int TimeFrame::loadROFrameData(gsl::span rofs, template void TimeFrame::prepareClusters(const TrackingParameters& trkParam, const int maxLayers) { + const int numBins{trkParam.PhiBins * trkParam.ZBins}; + const int stride{numBins + 1}; bounded_vector cHelper(mMemoryPool.get()); - bounded_vector clsPerBin(trkParam.PhiBins * trkParam.ZBins, 0, mMemoryPool.get()); + bounded_vector clsPerBin(numBins, 0, mMemoryPool.get()); + bounded_vector lutPerBin(numBins, 0, mMemoryPool.get()); for (int rof{0}; rof < mNrof; ++rof) { if ((int)mMultiplicityCutMask.size() == mNrof && !mMultiplicityCutMask[rof]) { continue; } - for (int iLayer{0}; iLayer < std::min(trkParam.NLayers, maxLayers); ++iLayer) { - std::fill(clsPerBin.begin(), clsPerBin.end(), 0); - const auto unsortedClusters{getUnsortedClustersOnLayer(rof, iLayer)}; + for (int iLayer{0}, stopLayer = std::min(trkParam.NLayers, maxLayers); iLayer < stopLayer; ++iLayer) { + const auto& unsortedClusters{getUnsortedClustersOnLayer(rof, iLayer)}; const int clustersNum{static_cast(unsortedClusters.size())}; + auto* tableBase = mIndexTables[iLayer].data() + rof * stride; - deepVectorClear(cHelper); cHelper.resize(clustersNum); for (int iCluster{0}; iCluster < clustersNum; ++iCluster) { - const Cluster& c = unsortedClusters[iCluster]; ClusterHelper& h = cHelper[iCluster]; - float x = c.xCoordinate - mBeamPos[0]; - float y = c.yCoordinate - mBeamPos[1]; - const float& z = c.zCoordinate; + + const float x = c.xCoordinate - mBeamPos[0]; + const float y = c.yCoordinate - mBeamPos[1]; + const float z = c.zCoordinate; + float phi = math_utils::computePhi(x, y); int zBin{mIndexTableUtils.getZBinIndex(iLayer, z)}; - if (zBin < 0) { - zBin = 0; - mBogusClusters[iLayer]++; - } else if (zBin >= trkParam.ZBins) { - zBin = trkParam.ZBins - 1; + if (zBin < 0 || zBin >= trkParam.ZBins) { + zBin = std::clamp(zBin, 0, trkParam.ZBins - 1); mBogusClusters[iLayer]++; } int bin = mIndexTableUtils.getBinIndex(zBin, mIndexTableUtils.getPhiBinIndex(phi)); @@ -252,28 +254,23 @@ void TimeFrame::prepareClusters(const TrackingParameters& trkParam, con h.bin = bin; h.ind = clsPerBin[bin]++; } - bounded_vector lutPerBin(clsPerBin.size(), 0, mMemoryPool.get()); - lutPerBin[0] = 0; - for (unsigned int iB{1}; iB < lutPerBin.size(); ++iB) { - lutPerBin[iB] = lutPerBin[iB - 1] + clsPerBin[iB - 1]; - } + std::exclusive_scan(clsPerBin.begin(), clsPerBin.end(), lutPerBin.begin(), 0); auto clusters2beSorted{getClustersOnLayer(rof, iLayer)}; for (int iCluster{0}; iCluster < clustersNum; ++iCluster) { const ClusterHelper& h = cHelper[iCluster]; - Cluster& c = clusters2beSorted[lutPerBin[h.bin] + h.ind]; + c = unsortedClusters[iCluster]; c.phi = h.phi; c.radius = h.r; c.indexTableBinIndex = h.bin; } - for (int iB{0}; iB < (int)clsPerBin.size(); ++iB) { - mIndexTables[iLayer][rof * (trkParam.ZBins * trkParam.PhiBins + 1) + iB] = lutPerBin[iB]; - } - for (auto iB{clsPerBin.size()}; iB < (trkParam.ZBins * trkParam.PhiBins + 1); iB++) { - mIndexTables[iLayer][rof * (trkParam.ZBins * trkParam.PhiBins + 1) + iB] = clustersNum; - } + std::copy_n(lutPerBin.data(), clsPerBin.size(), tableBase); + std::fill_n(tableBase + clsPerBin.size(), stride - clsPerBin.size(), clustersNum); + + std::fill(clsPerBin.begin(), clsPerBin.end(), 0); + cHelper.clear(); } } } @@ -351,7 +348,7 @@ void TimeFrame::initialise(const int iteration, const TrackingParameter mPhiCuts.resize(mClusters.size() - 1, 0.f); float oneOverR{0.001f * 0.3f * std::abs(mBz) / trkParam.TrackletMinPt}; - for (unsigned int iLayer{0}; iLayer < mClusters.size(); ++iLayer) { + for (unsigned int iLayer{0}; iLayer < nLayers; ++iLayer) { mMSangles[iLayer] = math_utils::MSangle(0.14f, trkParam.TrackletMinPt, trkParam.LayerxX0[iLayer]); mPositionResolution[iLayer] = o2::gpu::CAMath::Sqrt(0.5f * (trkParam.SystErrorZ2[iLayer] + trkParam.SystErrorY2[iLayer]) + trkParam.LayerResolution[iLayer] * trkParam.LayerResolution[iLayer]); if (iLayer < mClusters.size() - 1) { @@ -441,14 +438,14 @@ void TimeFrame::checkTrackletLUTs() auto& trk = getTracklets()[iLayer][iTracklet]; int currentId{trk.firstClusterIndex}; if (currentId < prev) { - std::cout << "First Cluster Index not increasing monotonically on L:T:ID:Prev " << iLayer << "\t" << iTracklet << "\t" << currentId << "\t" << prev << std::endl; + LOG(info) << "First Cluster Index not increasing monotonically on L:T:ID:Prev " << iLayer << "\t" << iTracklet << "\t" << currentId << "\t" << prev; } else if (currentId == prev) { count++; } else { if (iLayer > 0) { auto& lut{getTrackletsLookupTable()[iLayer - 1]}; if (count != lut[prev + 1] - lut[prev]) { - std::cout << "LUT count broken " << iLayer - 1 << "\t" << prev << "\t" << count << "\t" << lut[prev + 1] << "\t" << lut[prev] << std::endl; + LOG(info) << "LUT count broken " << iLayer - 1 << "\t" << prev << "\t" << count << "\t" << lut[prev + 1] << "\t" << lut[prev]; } } count = 1; @@ -457,7 +454,7 @@ void TimeFrame::checkTrackletLUTs() if (iLayer > 0) { auto& lut{getTrackletsLookupTable()[iLayer - 1]}; if (iTracklet >= (uint32_t)(lut[currentId + 1]) || iTracklet < (uint32_t)(lut[currentId])) { - std::cout << "LUT broken: " << iLayer - 1 << "\t" << currentId << "\t" << iTracklet << std::endl; + LOG(info) << "LUT broken: " << iLayer - 1 << "\t" << currentId << "\t" << iTracklet; } } } @@ -495,25 +492,25 @@ void TimeFrame::resetTracklets() template void TimeFrame::printTrackletLUTonLayer(int i) { - std::cout << "--------" << std::endl - << "Tracklet LUT " << i << std::endl; + LOG(info) << "-------- Tracklet LUT " << i; + std::stringstream s; for (int j : mTrackletsLookupTable[i]) { - std::cout << j << "\t"; + s << j << "\t"; } - std::cout << "\n--------" << std::endl - << std::endl; + LOG(info) << s.str(); + LOG(info) << "--------"; } template void TimeFrame::printCellLUTonLayer(int i) { - std::cout << "--------" << std::endl - << "Cell LUT " << i << std::endl; + LOG(info) << "-------- Cell LUT " << i; + std::stringstream s; for (int j : mCellsLookupTable[i]) { - std::cout << j << "\t"; + s << j << "\t"; } - std::cout << "\n--------" << std::endl - << std::endl; + LOG(info) << s.str(); + LOG(info) << "--------"; } template @@ -535,56 +532,58 @@ void TimeFrame::printCellLUTs() template void TimeFrame::printVertices() { - std::cout << "Vertices in ROF (nROF = " << mNrof << ", lut size = " << mROFramesPV.size() << ")" << std::endl; + LOG(info) << "Vertices in ROF (nROF = " << mNrof << ", lut size = " << mROFramesPV.size() << ")"; for (unsigned int iR{0}; iR < mROFramesPV.size(); ++iR) { - std::cout << mROFramesPV[iR] << "\t"; + LOG(info) << mROFramesPV[iR] << "\t"; } - std::cout << "\n\n Vertices:" << std::endl; + LOG(info) << "\n\n Vertices:"; for (unsigned int iV{0}; iV < mPrimaryVertices.size(); ++iV) { - std::cout << mPrimaryVertices[iV].getX() << "\t" << mPrimaryVertices[iV].getY() << "\t" << mPrimaryVertices[iV].getZ() << std::endl; + LOG(info) << mPrimaryVertices[iV].getX() << "\t" << mPrimaryVertices[iV].getY() << "\t" << mPrimaryVertices[iV].getZ(); } - std::cout << "--------" << std::endl; + LOG(info) << "--------"; } template void TimeFrame::printROFoffsets() { - std::cout << "--------" << std::endl; + LOG(info) << "--------"; for (unsigned int iLayer{0}; iLayer < mROFramesClusters.size(); ++iLayer) { - std::cout << "Layer " << iLayer << std::endl; + LOG(info) << "Layer " << iLayer; + std::stringstream s; for (auto value : mROFramesClusters[iLayer]) { - std::cout << value << "\t"; + s << value << "\t"; } - std::cout << std::endl; + LOG(info) << s.str(); } } template void TimeFrame::printNClsPerROF() { - std::cout << "--------" << std::endl; + LOG(info) << "--------"; for (unsigned int iLayer{0}; iLayer < mNClustersPerROF.size(); ++iLayer) { - std::cout << "Layer " << iLayer << std::endl; + LOG(info) << "Layer " << iLayer; + std::stringstream s; for (auto& value : mNClustersPerROF[iLayer]) { - std::cout << value << "\t"; + s << value << "\t"; } - std::cout << std::endl; + LOG(info) << s.str(); } } template void TimeFrame::printSliceInfo(const int startROF, const int sliceSize) { - std::cout << "Dumping slice of " << sliceSize << " rofs:" << std::endl; + LOG(info) << "Dumping slice of " << sliceSize << " rofs:"; for (int iROF{startROF}; iROF < startROF + sliceSize; ++iROF) { - std::cout << "ROF " << iROF << " dump:" << std::endl; + LOG(info) << "ROF " << iROF << " dump:"; for (unsigned int iLayer{0}; iLayer < mClusters.size(); ++iLayer) { - std::cout << "Layer " << iLayer << " has: " << getClustersOnLayer(iROF, iLayer).size() << " clusters." << std::endl; + LOG(info) << "Layer " << iLayer << " has: " << getClustersOnLayer(iROF, iLayer).size() << " clusters."; } - std::cout << "Number of seeding vertices: " << getPrimaryVertices(iROF).size() << std::endl; + LOG(info) << "Number of seeding vertices: " << getPrimaryVertices(iROF).size(); int iVertex{0}; for (auto& v : getPrimaryVertices(iROF)) { - std::cout << "\t vertex " << iVertex++ << ": x=" << v.getX() << " " << " y=" << v.getY() << " z=" << v.getZ() << " has " << v.getNContributors() << " contributors." << std::endl; + LOG(info) << "\t vertex " << iVertex++ << ": x=" << v.getX() << " " << " y=" << v.getY() << " z=" << v.getZ() << " has " << v.getNContributors() << " contributors."; } } } @@ -645,8 +644,6 @@ void TimeFrame::setMemoryPool(std::shared_ptr& p initVectors(mTracks); initVectors(mTracklets); initVectors(mCells); - initVectors(mCellSeeds); - initVectors(mCellSeedsChi2); initVectors(mCellsNeighbours); initVectors(mCellsLookupTable); } @@ -658,8 +655,6 @@ void TimeFrame::wipe() deepVectorClear(mTracks); deepVectorClear(mTracklets); deepVectorClear(mCells); - deepVectorClear(mCellSeeds); - deepVectorClear(mCellSeedsChi2); deepVectorClear(mRoads); deepVectorClear(mCellsNeighbours); deepVectorClear(mCellsLookupTable); @@ -687,6 +682,7 @@ void TimeFrame::wipe() deepVectorClear(mPValphaX); deepVectorClear(mBogusClusters); deepVectorClear(mTrackletsIndexROF); + deepVectorClear(mPrimaryVertices); } template class TimeFrame<7>; diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index f4da1a86818bb..c92d1e8505356 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -79,7 +79,7 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) double timeTracklets{0.}, timeCells{0.}, timeNeighbours{0.}, timeRoads{0.}; int nTracklets{0}, nCells{0}, nNeighbours{0}, nTracks{-static_cast(mTimeFrame->getNumberOfTracks())}; int nROFsIterations = mTrkParams[iteration].nROFsPerIterations > 0 ? mTimeFrame->getNrof() / mTrkParams[iteration].nROFsPerIterations + bool(mTimeFrame->getNrof() % mTrkParams[iteration].nROFsPerIterations) : 1; - int iVertex{std::min(maxNvertices, 0)}; + iVertex = std::min(maxNvertices, 0); logger(std::format("==== ITS {} Tracking iteration {} summary ====", mTraits->getName(), iteration)); total += evaluateTask(&Tracker::initialiseTimeFrame, StateNames[mCurState = TFInit], iteration, logger, iteration); @@ -105,8 +105,7 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) nNeighbours += mTimeFrame->getNumberOfNeighbours(); timeRoads += evaluateTask(&Tracker::findRoads, StateNames[mCurState = Roading], iteration, evalLog, iteration); } - iVertex++; - } while (iVertex < maxNvertices); + } while (++iVertex < maxNvertices); logger(std::format(" - Tracklet finding: {} tracklets found in {:.2f} ms", nTracklets, timeTracklets)); logger(std::format(" - Cell finding: {} cells found in {:.2f} ms", nCells, timeCells)); logger(std::format(" - Neighbours finding: {} neighbours found in {:.2f} ms", nNeighbours, timeNeighbours)); diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index 05b2ec57ecc6d..c70108b4f8a30 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -322,43 +322,45 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) mTracker->clustersToTracks(logger, errorLogger); } size_t totTracks{mTimeFrame->getNumberOfTracks()}, totClusIDs{mTimeFrame->getNumberOfUsedClusters()}; - allTracks.reserve(totTracks); - allClusIdx.reserve(totClusIDs); + if (totTracks) { + allTracks.reserve(totTracks); + allClusIdx.reserve(totClusIDs); - if (mTimeFrame->hasBogusClusters()) { - LOG(warning) << fmt::format(" - The processed timeframe had {} clusters with wild z coordinates, check the dictionaries", mTimeFrame->hasBogusClusters()); - } - - for (unsigned int iROF{0}; iROF < trackROFvec.size(); ++iROF) { - auto& tracksROF{trackROFvec[iROF]}; - auto& vtxROF = vertROFvec[iROF]; - auto& tracks = mTimeFrame->getTracks(iROF); - auto number{tracks.size()}; - auto first{allTracks.size()}; - int offset = -tracksROF.getFirstEntry(); // cluster entry!!! - tracksROF.setFirstEntry(first); - tracksROF.setNEntries(number); - tracksROF.setFlags(vtxROF.getFlags()); // copies 0xffffffff if cosmics - if (processingMask[iROF]) { - irFrames.emplace_back(tracksROF.getBCData(), tracksROF.getBCData() + nBCPerTF - 1).info = tracks.size(); + if (mTimeFrame->hasBogusClusters()) { + LOG(warning) << fmt::format(" - The processed timeframe had {} clusters with wild z coordinates, check the dictionaries", mTimeFrame->hasBogusClusters()); } - allTrackLabels.reserve(mTimeFrame->getTracksLabel(iROF).size()); // should be 0 if not MC - std::copy(mTimeFrame->getTracksLabel(iROF).begin(), mTimeFrame->getTracksLabel(iROF).end(), std::back_inserter(allTrackLabels)); - // Some conversions that needs to be moved in the tracker internals - for (unsigned int iTrk{0}; iTrk < tracks.size(); ++iTrk) { - auto& trc{tracks[iTrk]}; - trc.setFirstClusterEntry(allClusIdx.size()); // before adding tracks, create final cluster indices - int ncl = trc.getNumberOfClusters(), nclf = 0; - for (int ic = TrackITSExt::MaxClusters; ic--;) { // track internally keeps in->out cluster indices, but we want to store the references as out->in!!! - auto clid = trc.getClusterIndex(ic); - if (clid >= 0) { - trc.setClusterSize(ic, mTimeFrame->getClusterSize(clid)); - allClusIdx.push_back(clid); - nclf++; + + for (unsigned int iROF{0}; iROF < trackROFvec.size(); ++iROF) { + auto& tracksROF{trackROFvec[iROF]}; + auto& vtxROF = vertROFvec[iROF]; + auto& tracks = mTimeFrame->getTracks(iROF); + auto number{tracks.size()}; + auto first{allTracks.size()}; + int offset = -tracksROF.getFirstEntry(); // cluster entry!!! + tracksROF.setFirstEntry(first); + tracksROF.setNEntries(number); + tracksROF.setFlags(vtxROF.getFlags()); // copies 0xffffffff if cosmics + if (processingMask[iROF]) { + irFrames.emplace_back(tracksROF.getBCData(), tracksROF.getBCData() + nBCPerTF - 1).info = tracks.size(); + } + allTrackLabels.reserve(mTimeFrame->getTracksLabel(iROF).size()); // should be 0 if not MC + std::copy(mTimeFrame->getTracksLabel(iROF).begin(), mTimeFrame->getTracksLabel(iROF).end(), std::back_inserter(allTrackLabels)); + // Some conversions that needs to be moved in the tracker internals + for (unsigned int iTrk{0}; iTrk < tracks.size(); ++iTrk) { + auto& trc{tracks[iTrk]}; + trc.setFirstClusterEntry(allClusIdx.size()); // before adding tracks, create final cluster indices + int ncl = trc.getNumberOfClusters(), nclf = 0; + for (int ic = TrackITSExt::MaxClusters; ic--;) { // track internally keeps in->out cluster indices, but we want to store the references as out->in!!! + auto clid = trc.getClusterIndex(ic); + if (clid >= 0) { + trc.setClusterSize(ic, mTimeFrame->getClusterSize(clid)); + allClusIdx.push_back(clid); + nclf++; + } } + assert(ncl == nclf); + allTracks.emplace_back(trc); } - assert(ncl == nclf); - allTracks.emplace_back(trc); } } LOGP(info, "ITSTracker pushed {} tracks and {} vertices", allTracks.size(), vertices.size()); From ad4cc98f67cebe5ef7fb56be8ac56dee76ee578b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 12 Jun 2025 09:28:46 +0200 Subject: [PATCH 014/315] Add compatibility with std::pmr (#14379) The move assign operator is deleted is std::pmr::polymorphic_allocator so we cannot iterate anymore at runtime on the headers in the stack and move them. --- .../include/DataSampling/Dispatcher.h | 1 - Utilities/DataSampling/src/Dispatcher.cxx | 54 +++++++++++++------ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/Utilities/DataSampling/include/DataSampling/Dispatcher.h b/Utilities/DataSampling/include/DataSampling/Dispatcher.h index 1d34269f87536..c38ece1436bc0 100644 --- a/Utilities/DataSampling/include/DataSampling/Dispatcher.h +++ b/Utilities/DataSampling/include/DataSampling/Dispatcher.h @@ -65,7 +65,6 @@ class Dispatcher : public framework::Task private: DataSamplingHeader prepareDataSamplingHeader(const DataSamplingPolicy& policy, header::DataHeader const& original); - header::Stack extractAdditionalHeaders(const char* inputHeaderStack) const; void reportStats(monitoring::Monitoring& monitoring) const; void send(framework::DataAllocator& dataAllocator, const framework::DataRef& inputData, const framework::Output& output) const; diff --git a/Utilities/DataSampling/src/Dispatcher.cxx b/Utilities/DataSampling/src/Dispatcher.cxx index 38ad15f5fd752..bc79be2771316 100644 --- a/Utilities/DataSampling/src/Dispatcher.cxx +++ b/Utilities/DataSampling/src/Dispatcher.cxx @@ -29,6 +29,7 @@ #include #include +#include using namespace o2::configuration; using namespace o2::monitoring; @@ -77,6 +78,42 @@ void Dispatcher::init(InitContext& ctx) mDeviceID.runtimeInit(spec.id.substr(0, DataSamplingHeader::deviceIDTypeSize).c_str()); } +header::Stack extractAdditionalHeaders(const char* inputHeaderStack) +{ + std::array headers; + int count = 0; + const auto* first = header::BaseHeader::get(reinterpret_cast(inputHeaderStack)); + for (const auto* current = first; current != nullptr; current = current->next()) { + if (current->description != header::DataHeader::sHeaderType && current->description != DataProcessingHeader::sHeaderType) { + headers[count++] = current; + } + } + + // Poor man runtime pack expansion. + switch (count) { + case 0: + return header::Stack{}; + case 1: + return header::Stack{*headers[0]}; + case 2: + return header::Stack{*headers[0], *headers[1]}; + case 3: + return header::Stack{*headers[0], *headers[1], *headers[2]}; + case 4: + return header::Stack{*headers[0], *headers[1], *headers[2], *headers[3]}; + case 5: + return header::Stack{*headers[0], *headers[1], *headers[2], *headers[3], *headers[4]}; + case 6: + return header::Stack{*headers[0], *headers[1], *headers[2], *headers[3], *headers[4], *headers[5]}; + case 7: + return header::Stack{*headers[0], *headers[1], *headers[2], *headers[3], *headers[4], *headers[5], *headers[6]}; + case 8: + return header::Stack{*headers[0], *headers[1], *headers[2], *headers[3], *headers[4], *headers[5], *headers[6], *headers[7]}; + default: + throw std::runtime_error(fmt::format("Too many headers to copy {}", count)); + } +} + void Dispatcher::run(ProcessingContext& ctx) { // todo: consider matching (and deciding) in completion policy to save some time @@ -106,7 +143,7 @@ void Dispatcher::run(ProcessingContext& ctx) // so that custom data-dependent headers are passed forward, // and we add a DataSamplingHeader. header::Stack headerStack{ - std::move(extractAdditionalHeaders(part.header)), + extractAdditionalHeaders(part.header), dsheader}; const auto* partInputHeader = DataRefUtils::getHeader(part); @@ -156,21 +193,6 @@ DataSamplingHeader Dispatcher::prepareDataSamplingHeader(const DataSamplingPolic original}; } -header::Stack Dispatcher::extractAdditionalHeaders(const char* inputHeaderStack) const -{ - header::Stack headerStack; - - const auto* first = header::BaseHeader::get(reinterpret_cast(inputHeaderStack)); - for (const auto* current = first; current != nullptr; current = current->next()) { - if (current->description != header::DataHeader::sHeaderType && - current->description != DataProcessingHeader::sHeaderType) { - headerStack = std::move(header::Stack{std::move(headerStack), *current}); - } - } - - return headerStack; -} - void Dispatcher::send(DataAllocator& dataAllocator, const DataRef& inputData, const Output& output) const { const auto* inputHeader = DataRefUtils::getHeader(inputData); From dbacf7b1c659b7a18690f2616e20ed9c8f36502b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 12 Jun 2025 17:12:03 +0200 Subject: [PATCH 015/315] Remove references to boost::container::pmr (#14395) Use fair::mq::pmr instead, so that we can then easily migrate fair::mq to std::pmr while still having backward compatibility. --- DataFormats/Headers/include/Headers/Stack.h | 32 ++++++++----------- DataFormats/Headers/test/testDataHeader.cxx | 8 ++--- .../include/MemoryResources/MemoryResources.h | 18 +++++------ .../test/testMemoryResources.cxx | 2 +- Framework/Core/include/Framework/Output.h | 11 ++----- Framework/Core/test/test_FairMQ.cxx | 2 +- 6 files changed, 31 insertions(+), 42 deletions(-) diff --git a/DataFormats/Headers/include/Headers/Stack.h b/DataFormats/Headers/include/Headers/Stack.h index 259a445f18cf8..40987c483e1b8 100644 --- a/DataFormats/Headers/include/Headers/Stack.h +++ b/DataFormats/Headers/include/Headers/Stack.h @@ -14,10 +14,7 @@ #include "MemoryResources/MemoryResources.h" #include "Headers/DataHeader.h" -namespace o2 -{ - -namespace header +namespace o2::header { //__________________________________________________________________________________________________ /// @struct Stack @@ -45,20 +42,20 @@ struct Stack { }; public: - using allocator_type = boost::container::pmr::polymorphic_allocator; + using allocator_type = fair::mq::pmr::polymorphic_allocator; using value_type = std::byte; - using BufferType = std::unique_ptr; //this gives us proper default move semantics for free + using BufferType = std::unique_ptr; // this gives us proper default move semantics for free Stack() = default; Stack(Stack&&) = default; Stack(Stack&) = delete; Stack& operator=(Stack&) = delete; - Stack& operator=(Stack&&) = default; + Stack& operator=(Stack&&) = delete; - value_type* data() const { return buffer.get(); } - size_t size() const { return bufferSize; } + [[nodiscard]] value_type* data() const { return buffer.get(); } + [[nodiscard]] size_t size() const { return bufferSize; } allocator_type get_allocator() const { return allocator; } - const BaseHeader* first() const { return reinterpret_cast(this->data()); } + [[nodiscard]] const BaseHeader* first() const { return reinterpret_cast(this->data()); } static const BaseHeader* firstHeader(std::byte const* buf) { return BaseHeader::get(buf); } static const BaseHeader* lastHeader(std::byte const* buf) { @@ -90,9 +87,9 @@ struct Stack { /// all headers must derive from BaseHeader, in addition also other stacks can be passed to ctor. template >::value, int> = 0> + !std::is_convertible>::value, int> = 0> Stack(FirstArgType&& firstHeader, Headers&&... headers) - : Stack(boost::container::pmr::new_delete_resource(), std::forward(firstHeader), + : Stack(fair::mq::pmr::new_delete_resource(), std::forward(firstHeader), std::forward(headers)...) { } @@ -122,7 +119,7 @@ struct Stack { template constexpr static size_t calculateSize(T&& h) noexcept { - //if it's a pointer (to a stack) traverse it + // if it's a pointer (to a stack) traverse it if constexpr (std::is_convertible_v) { const BaseHeader* next = BaseHeader::get(std::forward(h)); if (!next) { @@ -133,17 +130,17 @@ struct Stack { size += next->size(); } return size; - //otherwise get the size directly + // otherwise get the size directly } else { return h.size(); } } - //recursion terminator + // recursion terminator constexpr static size_t calculateSize() { return 0; } private: - allocator_type allocator{boost::container::pmr::new_delete_resource()}; + allocator_type allocator{fair::mq::pmr::new_delete_resource()}; size_t bufferSize{0}; BufferType buffer{nullptr, freeobj{allocator.resource()}}; @@ -231,7 +228,6 @@ struct Stack { } }; -} // namespace header -} // namespace o2 +} // namespace o2::header #endif // HEADERS_STACK_H diff --git a/DataFormats/Headers/test/testDataHeader.cxx b/DataFormats/Headers/test/testDataHeader.cxx index 0703fc6c3ae71..2403c1a6230be 100644 --- a/DataFormats/Headers/test/testDataHeader.cxx +++ b/DataFormats/Headers/test/testDataHeader.cxx @@ -280,8 +280,8 @@ BOOST_AUTO_TEST_CASE(headerStack_test) Stack s2{s1, meta}; BOOST_CHECK(s2.size() == s1.size() + sizeof(decltype(meta))); - //check dynamic construction - where we don't have the type information and need to - //work with BaseHeader pointers + // check dynamic construction - where we don't have the type information and need to + // work with BaseHeader pointers const test::MetaHeader thead{2}; o2::header::BaseHeader const* bname = reinterpret_cast(&thead); Stack ds2(s1, *bname); @@ -313,8 +313,8 @@ BOOST_AUTO_TEST_CASE(headerStack_test) BOOST_REQUIRE(h3 != nullptr); BOOST_CHECK(h3->secret == 42); - //test constructing from a buffer and an additional header - using namespace boost::container::pmr; + // test constructing from a buffer and an additional header + using namespace fair::mq::pmr; Stack s5(new_delete_resource(), s1.data(), Stack{}, meta); BOOST_CHECK(s5.size() == s1.size() + sizeof(meta)); // check if we can find the header even though there was an empty stack in the middle diff --git a/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h b/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h index 42dd69aff38e3..eba309e38ad83 100644 --- a/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h +++ b/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h @@ -115,7 +115,7 @@ class MessageResource : public FairMQMemoryResource // A spectator pmr memory resource which only watches the memory of the underlying buffer, does not // carry out real allocation. It owns the underlying buffer which is destroyed on deallocation. template -class SpectatorMemoryResource : public boost::container::pmr::memory_resource +class SpectatorMemoryResource : public fair::mq::pmr::memory_resource { public: using buffer_type = BufferType; @@ -183,10 +183,10 @@ class SpectatorMemoryResource : public boost::container::pmr::memory_resource // This in general (as in STL) is a bad idea, but here it is safe to inherit from an allocator since we // have no additional data and only override some methods so we don't get into slicing and other problems. template -class SpectatorAllocator : public boost::container::pmr::polymorphic_allocator +class SpectatorAllocator : public fair::mq::pmr::polymorphic_allocator { public: - using boost::container::pmr::polymorphic_allocator::polymorphic_allocator; + using fair::mq::pmr::polymorphic_allocator::polymorphic_allocator; using propagate_on_container_move_assignment = std::true_type; // skip default construction of empty elements @@ -243,7 +243,7 @@ class OwningMessageSpectatorAllocator return OwningMessageSpectatorAllocator(); } - boost::container::pmr::memory_resource* resource() { return &mResource; } + fair::mq::pmr::memory_resource* resource() { return &mResource; } // skip default construction of empty elements // this is important for two reasons: one: it allows us to adopt an existing buffer (e.g. incoming message) and @@ -269,14 +269,14 @@ class OwningMessageSpectatorAllocator // The NoConstructAllocator behaves like the normal pmr vector but does not call constructors / destructors template -class NoConstructAllocator : public boost::container::pmr::polymorphic_allocator +class NoConstructAllocator : public fair::mq::pmr::polymorphic_allocator { public: - using boost::container::pmr::polymorphic_allocator::polymorphic_allocator; + using fair::mq::pmr::polymorphic_allocator::polymorphic_allocator; using propagate_on_container_move_assignment = std::true_type; template - NoConstructAllocator(Args&&... args) : boost::container::pmr::polymorphic_allocator(std::forward(args)...) + NoConstructAllocator(Args&&... args) : fair::mq::pmr::polymorphic_allocator(std::forward(args)...) { } @@ -302,9 +302,9 @@ class NoConstructAllocator : public boost::container::pmr::polymorphic_allocator //__________________________________________________________________________________________________ using ByteSpectatorAllocator = SpectatorAllocator; -using BytePmrAllocator = boost::container::pmr::polymorphic_allocator; +using BytePmrAllocator = fair::mq::pmr::polymorphic_allocator; template -using vector = std::vector>; +using vector = std::vector>; //__________________________________________________________________________________________________ /// Return a std::vector spanned over the contents of the message, takes ownership of the message diff --git a/DataFormats/MemoryResources/test/testMemoryResources.cxx b/DataFormats/MemoryResources/test/testMemoryResources.cxx index 264fe59b1caac..6bbafa3a82f4f 100644 --- a/DataFormats/MemoryResources/test/testMemoryResources.cxx +++ b/DataFormats/MemoryResources/test/testMemoryResources.cxx @@ -60,7 +60,7 @@ BOOST_AUTO_TEST_CASE(transportallocatormap_test) BOOST_CHECK(_tmp == allocZMQ); } -using namespace boost::container::pmr; +using namespace fair::mq::pmr; BOOST_AUTO_TEST_CASE(allocator_test) { diff --git a/Framework/Core/include/Framework/Output.h b/Framework/Core/include/Framework/Output.h index a2abf5f7600a9..73b04c56f3c4d 100644 --- a/Framework/Core/include/Framework/Output.h +++ b/Framework/Core/include/Framework/Output.h @@ -59,14 +59,7 @@ struct Output { Output& operator=(const Output&) = delete; - Output& operator=(Output&& rhs) - { - origin = rhs.origin; - description = rhs.description; - subSpec = rhs.subSpec; - metaHeader = std::move(rhs.metaHeader); - return *this; - } + Output& operator=(Output&& rhs) = delete; bool operator==(const Output& that) const { @@ -74,5 +67,5 @@ struct Output { } }; -} // namespace o2 +} // namespace o2::framework #endif diff --git a/Framework/Core/test/test_FairMQ.cxx b/Framework/Core/test/test_FairMQ.cxx index 0ccfbf58f7576..f11d98505298f 100644 --- a/Framework/Core/test/test_FairMQ.cxx +++ b/Framework/Core/test/test_FairMQ.cxx @@ -174,7 +174,7 @@ TEST_CASE("addDataBlockForEach_test") int i; int j; }; - using namespace boost::container::pmr; + using namespace fair::mq::pmr; fair::mq::Parts message; std::vector> vec(polymorphic_allocator{allocZMQ}); vec.reserve(100); From c4bca1460aabde0594cc19b6de6715852ff18475 Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 12 Jun 2025 11:36:20 +0200 Subject: [PATCH 016/315] Improve exit handling of O2HitMerger So far, the exit status of O2HitMerger was not analysed. This could lead to situations where O2HitMerger was killed by the OS due to out-of-memory, yet the o2-sim simulator still exited as "successfull". This commit improves the handling. Problems in O2HitMerger will lead to exit code 1 of o2-sim. --- run/O2HitMerger.h | 11 ----------- run/o2sim_parallel.cxx | 27 ++++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/run/O2HitMerger.h b/run/O2HitMerger.h index c2a094bfc9e54..520873e7aaafe 100644 --- a/run/O2HitMerger.h +++ b/run/O2HitMerger.h @@ -87,15 +87,6 @@ namespace o2 namespace devices { -// signal handler -void sighandler(int signal) -{ - if (signal == SIGSEGV) { - LOG(warn) << "segmentation violation ... just exit without coredump in order not to hang"; - raise(SIGKILL); - } -} - class O2HitMerger : public fair::mq::Device { @@ -130,7 +121,6 @@ class O2HitMerger : public fair::mq::Device void InitTask() final { LOG(info) << "INIT HIT MERGER"; - // signal(SIGSEGV, sighandler); ROOT::EnableThreadSafety(); std::string outfilename("o2sim_merged_hits.root"); // default name @@ -764,7 +754,6 @@ class O2HitMerger : public fair::mq::Device eventheader->putInfo("prims_eta_0.8_pi", eta0Point8CounterPi); eventheader->putInfo("prims_total", prims); }; - reorderAndMergeMCTracks(flusheventID, mOutTree, nprimaries, subevOrdered, mcheaderhook, eventheader); if (mOutTree) { diff --git a/run/o2sim_parallel.cxx b/run/o2sim_parallel.cxx index 3e28428938b20..22c6b37e6d9aa 100644 --- a/run/o2sim_parallel.cxx +++ b/run/o2sim_parallel.cxx @@ -732,7 +732,12 @@ int main(int argc, char* argv[]) int status, cpid; // wait just blocks and waits until any child returns; but we make sure to wait until merger is here bool errored = false; - while ((cpid = wait(&status)) != mergerpid) { + // wait at least until mergerpid is reaped + while ((cpid = wait(&status)) != -1) { + if (cpid == mergerpid) { + break; // Defer handling of mergerpid exit status until after the loop + } + if (WEXITSTATUS(status) || WIFSIGNALED(status)) { if (!shutdown_initiated) { LOG(info) << "Process " << cpid << " EXITED WITH CODE " << WEXITSTATUS(status) << " SIGNALED " @@ -753,6 +758,26 @@ int main(int argc, char* argv[]) } } } + + // Handle mergerpid status separately + if (cpid == mergerpid) { + if (WIFEXITED(status)) { + // anything other than 128 is indicative of error + if (WEXITSTATUS(status) != 128) { + LOG(error) << "Merger process exited with abnormal code " << WEXITSTATUS(status); + errored = true; + } + } else if (WIFSIGNALED(status)) { + auto sig = WTERMSIG(status); + if (sig == SIGKILL || sig == SIGBUS || sig == SIGSEGV || sig == SIGABRT) { + LOG(error) << "Merger process terminated through abnormal signal " << WTERMSIG(status); + errored = true; + } + } else { + LOG(warning) << "Merger process exited with unexpected status."; + } + } + // This marks the actual end of the computation (since results are available) LOG(info) << "Merger process " << mergerpid << " returned"; LOG(info) << "Simulation process took " << timer.RealTime() << " s"; From 121ee3ab45981e61fddb850852ff4ace8bcaee73 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 13 Jun 2025 11:05:36 +0200 Subject: [PATCH 017/315] Export tuple to avoid IWYU adding it everywhere (#14403) --- Framework/Core/include/Framework/AnalysisTask.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index b53929f326712..30b31ea4799f5 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -33,6 +33,8 @@ #include #include #include +#include // IWYU pragma: export + namespace o2::framework { /// A more familiar task API for the DPL analysis framework. From 73bc03d1e9d5568983a86d02efa31858cfe9b616 Mon Sep 17 00:00:00 2001 From: Matthias Kleiner Date: Thu, 12 Jun 2025 14:51:40 +0200 Subject: [PATCH 018/315] TPC: changing uint64_t to unsigned long long for compatibility with Mac --- .../Detectors/TPC/include/DataFormatsTPC/DCS.h | 4 ++-- DataFormats/Detectors/TPC/src/DCS.cxx | 2 +- .../TPCCalibration/PressureTemperatureHelper.h | 16 ++++++++-------- .../src/PressureTemperatureHelper.cxx | 8 ++++---- .../workflow/src/TPCPressureTemperatureSpec.cxx | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/DataFormats/Detectors/TPC/include/DataFormatsTPC/DCS.h b/DataFormats/Detectors/TPC/include/DataFormatsTPC/DCS.h index 3608fdc390203..d40b07c48e314 100644 --- a/DataFormats/Detectors/TPC/include/DataFormatsTPC/DCS.h +++ b/DataFormats/Detectors/TPC/include/DataFormatsTPC/DCS.h @@ -557,13 +557,13 @@ struct RobustPressure { Stats cavernAtmosPressure2S; ///< rolling statistics of cavernAtmosPressure2/surfaceAtmosPressure std::vector isOk; ///< bit mask of valid sensors: cavernBit 0, cavern2Bit = 1, surfaceBit = 2 std::vector robustPressure; ///< combined robust pressure value that should be used - std::vector time; ///< time stamps of all pressure values + std::vector time; ///< time stamps of all pressure values TimeStampType timeInterval; ///< time interval used for rolling statistics TimeStampType timeIntervalRef; ///< reference time interval used for normalization of pressure sensors float maxDist{}; ///< maximum allowed time distance between sensors to be accepted for robust pressure calculation float maxDiff{0.2f}; ///< maximum allowed pressure difference between sensors to be accepted for robust pressure calculation - ClassDefNV(RobustPressure, 1); + ClassDefNV(RobustPressure, 2); }; struct Pressure { diff --git a/DataFormats/Detectors/TPC/src/DCS.cxx b/DataFormats/Detectors/TPC/src/DCS.cxx index 3c2524b6ed0fe..14c3887f8e8ae 100644 --- a/DataFormats/Detectors/TPC/src/DCS.cxx +++ b/DataFormats/Detectors/TPC/src/DCS.cxx @@ -357,7 +357,7 @@ void Pressure::makeRobustPressure(TimeStampType timeInterval, TimeStampType time if (nIntervals == 0) { nIntervals = 1; // at least one interval } - std::vector times; + std::vector times; times.reserve(nIntervals); for (int i = 0; i < nIntervals; ++i) { times.emplace_back(tStart + (i + 0.5) * timeInterval); diff --git a/Detectors/TPC/calibration/include/TPCCalibration/PressureTemperatureHelper.h b/Detectors/TPC/calibration/include/TPCCalibration/PressureTemperatureHelper.h index b636fdd2f296d..671c2efb78a8f 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/PressureTemperatureHelper.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/PressureTemperatureHelper.h @@ -49,7 +49,7 @@ class PressureTemperatureHelper static void setOutputs(std::vector& outputs); /// send temperature and pressure for given time stamp - void sendPTForTS(o2::framework::ProcessingContext& pc, const uint64_t timestamp) const; + void sendPTForTS(o2::framework::ProcessingContext& pc, const ULong64_t timestamp) const; /// set fit interval range for temperature in ms void setFitIntervalTemp(const int fitIntervalMS) { mFitIntervalMS = fitIntervalMS; } @@ -58,13 +58,13 @@ class PressureTemperatureHelper /// \param timestamps time stamps of the data /// \param values data points /// \param timestamp time where to interpolate the values - float interpolate(const std::vector& timestamps, const std::vector& values, uint64_t timestamp) const; + float interpolate(const std::vector& timestamps, const std::vector& values, ULong64_t timestamp) const; /// get pressure for given time stamp in ms - float getPressure(const uint64_t timestamp) const { return interpolate(mPressure.second, mPressure.first, timestamp); } + float getPressure(const ULong64_t timestamp) const { return interpolate(mPressure.second, mPressure.first, timestamp); } /// get temperature for given time stamp in ms - dataformats::Pair getTemperature(const uint64_t timestamp) const { return dataformats::Pair{interpolate(mTemperatureA.second, mTemperatureA.first, timestamp), interpolate(mTemperatureC.second, mTemperatureC.first, timestamp)}; } + dataformats::Pair getTemperature(const ULong64_t timestamp) const { return dataformats::Pair{interpolate(mTemperatureA.second, mTemperatureA.first, timestamp), interpolate(mTemperatureC.second, mTemperatureC.first, timestamp)}; } static constexpr o2::header::DataDescription getDataDescriptionPressure() { return o2::header::DataDescription{"pressure"}; } static constexpr o2::header::DataDescription getDataDescriptionTemperature() { return o2::header::DataDescription{"temperature"}; } @@ -73,10 +73,10 @@ class PressureTemperatureHelper static void addInput(std::vector& inputs, o2::framework::InputSpec&& isp); static void addOutput(std::vector& outputs, o2::framework::OutputSpec&& osp); - std::pair, std::vector> mPressure; ///< pressure values for both measurements - std::pair, std::vector> mTemperatureA; ///< temperature values A-side - std::pair, std::vector> mTemperatureC; ///< temperature values C-side - int mFitIntervalMS{5 * 60 * 1000}; ///< fit interval for the temperature + std::pair, std::vector> mPressure; ///< pressure values for both measurements + std::pair, std::vector> mTemperatureA; ///< temperature values A-side + std::pair, std::vector> mTemperatureC; ///< temperature values C-side + int mFitIntervalMS{5 * 60 * 1000}; ///< fit interval for the temperature ClassDefNV(PressureTemperatureHelper, 1); }; diff --git a/Detectors/TPC/calibration/src/PressureTemperatureHelper.cxx b/Detectors/TPC/calibration/src/PressureTemperatureHelper.cxx index 54145f0ecfaf1..d9a55e4aed2b9 100644 --- a/Detectors/TPC/calibration/src/PressureTemperatureHelper.cxx +++ b/Detectors/TPC/calibration/src/PressureTemperatureHelper.cxx @@ -91,13 +91,13 @@ void PressureTemperatureHelper::addOutput(std::vector& outputs, Outp } } -float PressureTemperatureHelper::interpolate(const std::vector& timestamps, const std::vector& values, uint64_t timestamp) const +float PressureTemperatureHelper::interpolate(const std::vector& timestamps, const std::vector& values, ULong64_t timestamp) const { if (auto idxClosest = o2::math_utils::findClosestIndices(timestamps, timestamp)) { auto [idxLeft, idxRight] = *idxClosest; if (idxRight > idxLeft) { - const uint64_t x0 = timestamps[idxLeft]; - const uint64_t x1 = timestamps[idxRight]; + const auto x0 = timestamps[idxLeft]; + const auto x1 = timestamps[idxRight]; const float y0 = values[idxLeft]; const float y1 = values[idxRight]; const float y = (y0 * (x1 - timestamp) + y1 * (timestamp - x0)) / (x1 - x0); @@ -109,7 +109,7 @@ float PressureTemperatureHelper::interpolate(const std::vector& timest return 0; // this should never happen } -void PressureTemperatureHelper::sendPTForTS(o2::framework::ProcessingContext& pc, const uint64_t timestamp) const +void PressureTemperatureHelper::sendPTForTS(o2::framework::ProcessingContext& pc, const ULong64_t timestamp) const { const float pressure = getPressure(timestamp); const auto temp = getTemperature(timestamp); diff --git a/Detectors/TPC/workflow/src/TPCPressureTemperatureSpec.cxx b/Detectors/TPC/workflow/src/TPCPressureTemperatureSpec.cxx index e03a0ffe4308b..4cb25471b55f8 100644 --- a/Detectors/TPC/workflow/src/TPCPressureTemperatureSpec.cxx +++ b/Detectors/TPC/workflow/src/TPCPressureTemperatureSpec.cxx @@ -57,7 +57,7 @@ class PressureTemperatureDevice : public o2::framework::Task mPTHelper.extractCCDBInputs(pc); const auto orbitResetTimeMS = o2::base::GRPGeomHelper::instance().getOrbitResetTimeMS(); const auto firstTFOrbit = pc.services().get().firstTForbit; - const uint64_t timestamp = orbitResetTimeMS + firstTFOrbit * o2::constants::lhc::LHCOrbitMUS * 0.001; + const ULong64_t timestamp = orbitResetTimeMS + firstTFOrbit * o2::constants::lhc::LHCOrbitMUS * 0.001; mPTHelper.sendPTForTS(pc, timestamp); if (mStreamer) { From b0a856379ccf01cbb8cf5ec7ddb6f4cad939c1ca Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 10 Jun 2025 11:48:56 +0200 Subject: [PATCH 019/315] Add some more O2 settings to --setO2Settings of standalone benchmark --- GPU/GPUTracking/Standalone/Benchmark/standalone.cxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx index 95997a30034c9..792f72220e597 100644 --- a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx +++ b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx @@ -223,6 +223,14 @@ int32_t ReadConfiguration(int argc, char** argv) configStandalone.rec.tpc.nWaysOuter = 1; configStandalone.rec.tpc.trackReferenceX = 83; configStandalone.proc.outputSharedClusterMap = 1; + configStandalone.proc.clearO2OutputFromGPU = 1; + configStandalone.QA.clusterRejectionHistograms = 1; + configStandalone.proc.tpcIncreasedMinClustersPerRow = 500000; + configStandalone.proc.ignoreNonFatalGPUErrors = 1; + // TODO: rundEdx=1 + // GPU_proc.qcRunFraction=$TPC_TRACKING_QC_RUN_FRACTION;" + // [[ $CTFINPUT == 1 ]] && GPU_CONFIG_KEY+="GPU_proc.tpcInputWithClusterRejection=1;" + // double pipeline / rtc } if (configStandalone.outputcontrolmem) { From 5ef3da96782ef0bdb971a23c245bedd8e407603e Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 10 Jun 2025 15:35:18 +0200 Subject: [PATCH 020/315] GPU Standalone: No need for warmup iteration of double-pipeline with debugging enabled --- GPU/GPUTracking/Standalone/Benchmark/standalone.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx index 792f72220e597..a624e1e55ed4b 100644 --- a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx +++ b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx @@ -901,7 +901,7 @@ int32_t main(int argc, char** argv) double pipelineWalltime = 1.; if (configStandalone.proc.doublePipeline) { HighResTimer timerPipeline; - if (RunBenchmark(rec, chainTracking, 1, iEvent, &nTracksTotal, &nClustersTotal) || RunBenchmark(recPipeline, chainTrackingPipeline, 2, iEvent, &nTracksTotal, &nClustersTotal)) { + if (configStandalone.proc.debugLevel < 2 && (RunBenchmark(rec, chainTracking, 1, iEvent, &nTracksTotal, &nClustersTotal) || RunBenchmark(recPipeline, chainTrackingPipeline, 2, iEvent, &nTracksTotal, &nClustersTotal))) { goto breakrun; } auto pipeline1 = std::async(std::launch::async, RunBenchmark, rec, chainTracking, configStandalone.runs, iEvent, &nTracksTotal, &nClustersTotal, 0, &timerPipeline); From 6c537d744bd933e32baee2a0a6795e3ca5093aa1 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 11 Jun 2025 09:26:49 +0200 Subject: [PATCH 021/315] GPU Standalone: CI build should use -Werror --- GPU/GPUTracking/Standalone/CMakeLists.txt | 7 ++++++- GPU/GPUTracking/Standalone/cmake/build.sh | 15 +++++++++------ GPU/GPUTracking/Standalone/cmake/config.cmake | 1 + 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/GPU/GPUTracking/Standalone/CMakeLists.txt b/GPU/GPUTracking/Standalone/CMakeLists.txt index 0b37ce38b79f7..48fbd77c62786 100644 --- a/GPU/GPUTracking/Standalone/CMakeLists.txt +++ b/GPU/GPUTracking/Standalone/CMakeLists.txt @@ -65,7 +65,12 @@ if (GPUCA_BUILD_DEBUG_SANITIZE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -shared-libasan") endif() endif() -string(APPEND CMAKE_CXX_FLAGS " -Wno-error -Wall -Wextra -Wshadow -Wno-unused-function -Wno-unused-parameter -Wno-unused-local-typedefs -Wno-unknown-pragmas -Wno-write-strings") +if(GPUCA_CONFIG_WERROR) + string(APPEND CMAKE_CXX_FLAGS " -Werror -Wno-unknown-warning-option") +else() + string(APPEND CMAKE_CXX_FLAGS " -Wno-error") +endif() +string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra -Wshadow -Wno-unused-function -Wno-unused-parameter -Wno-unused-local-typedefs -Wno-unknown-pragmas -Wno-write-strings") string(APPEND CMAKE_SHARED_LINKER_FLAGS " -rdynamic -Wl,--no-undefined") if(CMAKE_CXX_COMPILER MATCHES "clang\\+\\+") string(APPEND CMAKE_CXX_FLAGS " -Wno-vla-cxx-extension") diff --git a/GPU/GPUTracking/Standalone/cmake/build.sh b/GPU/GPUTracking/Standalone/cmake/build.sh index 9fe650fd30905..2698a5bad3950 100755 --- a/GPU/GPUTracking/Standalone/cmake/build.sh +++ b/GPU/GPUTracking/Standalone/cmake/build.sh @@ -7,13 +7,16 @@ set -e mkdir -p standalone/build pushd standalone/build cp $1/GPU/GPUTracking/Standalone/cmake/config.cmake . -cat >> config.cmake << "EOF" -set(ENABLE_CUDA 1) -set(ENABLE_HIP 1) -set(ENABLE_OPENCL 1) -set(GPUCA_CONFIG_ONNX 1) -set(GPUCA_BUILD_EVENT_DISPLAY 0) +if [[ $GPUCA_STANDALONE_CI == 1 ]]; then + cat >> config.cmake << "EOF" + set(ENABLE_CUDA 1) + set(ENABLE_HIP 1) + set(ENABLE_OPENCL 1) + set(GPUCA_CONFIG_ONNX 1) + set(GPUCA_BUILD_EVENT_DISPLAY 0) + set(GPUCA_CONFIG_WERROR 1) EOF +fi cmake -DCMAKE_INSTALL_PREFIX=../ $1/GPU/GPUTracking/Standalone make ${JOBS+-j $JOBS} install popd diff --git a/GPU/GPUTracking/Standalone/cmake/config.cmake b/GPU/GPUTracking/Standalone/cmake/config.cmake index 77ce9c9e77fca..88fe418d40e5b 100644 --- a/GPU/GPUTracking/Standalone/cmake/config.cmake +++ b/GPU/GPUTracking/Standalone/cmake/config.cmake @@ -38,4 +38,5 @@ set(CUDA_COMPUTETARGET "default") # 86 89 #set(GPUCA_RTC_NO_COMPILED_KERNELS 1) #set(GPUCA_KERNEL_RESOURCE_USAGE_VERBOSE 1) #set(GPUCA_CONFIG_COMPILER gcc) # gcc / clang +#set(GPUCA_CONFIG_WERROR 1) #add_definitions(-DGPUCA_GPU_DEBUG_PRINT) From d50b3b029cab92906d63d4714ebd3c8af68d9978 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 11 Jun 2025 15:09:46 +0200 Subject: [PATCH 022/315] GPU: Hide Vc correctly from ROOT --- GPU/Common/GPUCommonDef.h | 2 +- GPU/Common/GPUCommonMath.h | 2 +- GPU/TPCFastTransformation/Spline2D.h | 2 +- GPU/TPCFastTransformation/Spline2DSpec.h | 2 +- GPU/TPCFastTransformation/SplineSpec.h | 2 +- GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h | 4 ++-- GPU/TPCFastTransformation/devtools/SemiregularSpline2D3D.h | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/GPU/Common/GPUCommonDef.h b/GPU/Common/GPUCommonDef.h index d9a5bdf92b6ac..ffe5551f02f1b 100644 --- a/GPU/Common/GPUCommonDef.h +++ b/GPU/Common/GPUCommonDef.h @@ -30,7 +30,7 @@ //Some GPU configuration settings, must be included first #include "GPUCommonDefSettings.h" -#if !(defined(__CLING__) || defined(__ROOTCLING__) || defined(G__ROOT)) // No GPU code for ROOT +#if !defined(__CLING__) && !defined(G__ROOT) // No GPU code for ROOT #if defined(__CUDACC__) || defined(__OPENCL__) || defined(__HIPCC__) || defined(__OPENCL_HOST__) #define GPUCA_GPUCODE // Compiled by GPU compiler #endif diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index 01067ca032650..b448a30107dad 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -521,7 +521,7 @@ GPUdi() void GPUCommonMath::AtomicMinInternal(S* addr, T val) #endif // GPUCA_GPUCODE } -#if (defined(__CUDACC__) || defined(__HIPCC__)) && !defined(G__ROOT) +#if (defined(__CUDACC__) || defined(__HIPCC__)) && !defined(G__ROOT) && !defined(__CLING__) #define GPUCA_HAVE_ATOMIC_MINMAX_FLOAT template <> GPUdii() void GPUCommonMath::AtomicMaxInternal(GPUglobalref() GPUgeneric() GPUAtomic(float) * addr, float val) diff --git a/GPU/TPCFastTransformation/Spline2D.h b/GPU/TPCFastTransformation/Spline2D.h index 788816f73d6dd..19f9fc7b55b91 100644 --- a/GPU/TPCFastTransformation/Spline2D.h +++ b/GPU/TPCFastTransformation/Spline2D.h @@ -22,7 +22,7 @@ #include "FlatObject.h" #include "GPUCommonDef.h" -#if !defined(__ROOTCLING__) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) +#if !defined(__CLING__) && !defined(G__ROOT) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) #include #include #endif diff --git a/GPU/TPCFastTransformation/Spline2DSpec.h b/GPU/TPCFastTransformation/Spline2DSpec.h index e7a9db8e6ae9c..b4d351e8d0407 100644 --- a/GPU/TPCFastTransformation/Spline2DSpec.h +++ b/GPU/TPCFastTransformation/Spline2DSpec.h @@ -22,7 +22,7 @@ #include "GPUCommonDef.h" #include "SplineUtil.h" -#if !defined(__ROOTCLING__) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) +#if !defined(__CLING__) && !defined(G__ROOT) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) #include #include #endif diff --git a/GPU/TPCFastTransformation/SplineSpec.h b/GPU/TPCFastTransformation/SplineSpec.h index 1af427dee503b..744be943181db 100644 --- a/GPU/TPCFastTransformation/SplineSpec.h +++ b/GPU/TPCFastTransformation/SplineSpec.h @@ -22,7 +22,7 @@ #include "GPUCommonDef.h" #include "SplineUtil.h" -#if !defined(__ROOTCLING__) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) +#if !defined(__CLING__) && !defined(G__ROOT) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) #include #include #endif diff --git a/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h b/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h index d60326ddf76ab..33d6874f40aae 100644 --- a/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h +++ b/GPU/TPCFastTransformation/devtools/IrregularSpline2D3D.h @@ -21,7 +21,7 @@ #include "FlatObject.h" #include "GPUCommonDef.h" -#if !defined(__ROOTCLING__) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) +#if !defined(__CLING__) && !defined(G__ROOT) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) #include #include #endif @@ -329,7 +329,7 @@ GPUdi() void IrregularSpline2D3D::getSplineVec(const float* correctedData, float // Same as getSpline, but using vectorized calculation. // \param correctedData should be at least 128-bit aligned -#if !defined(__ROOTCLING__) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) +#if !defined(__CLING__) && !defined(G__ROOT) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) const IrregularSpline1D& gridU = getGridU(); const IrregularSpline1D& gridV = getGridV(); int32_t nu = gridU.getNumberOfKnots(); diff --git a/GPU/TPCFastTransformation/devtools/SemiregularSpline2D3D.h b/GPU/TPCFastTransformation/devtools/SemiregularSpline2D3D.h index 954738fa74f1b..835a525239346 100644 --- a/GPU/TPCFastTransformation/devtools/SemiregularSpline2D3D.h +++ b/GPU/TPCFastTransformation/devtools/SemiregularSpline2D3D.h @@ -23,7 +23,7 @@ #include "RegularSpline1D.h" #include "FlatObject.h" -#if !defined(__ROOTCLING__) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) +#if !defined(__CLING__) && !defined(G__ROOT) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) #include #include #endif @@ -398,7 +398,7 @@ inline void SemiregularSpline2D3D::getSplineVec(const float* correctedData, floa // Same as getSpline, but using vectorized calculation. // \param correctedData should be at least 128-bit aligned -#if !defined(__ROOTCLING__) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) +#if !defined(__CLING__) && !defined(G__ROOT) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC) //&& !defined(__CLING__) /* Idea: There are 16 knots important for (u, v). From 54e61bf02df939c8e54bf2447fa71c15da03a74b Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 12 Jun 2025 07:54:40 +0200 Subject: [PATCH 023/315] GPU: Remove obsolete GPUCA_TPC_RAW_PROPAGATE_PAD_ROW_TIME --- GPU/GPUTracking/DataTypes/GPUTPCGMMergedTrackHit.h | 4 ---- GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h | 1 - GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 4 ---- GPU/GPUTracking/SectorTracker/GPUTPCDef.h | 3 --- GPU/GPUTracking/TPCConvert/GPUTPCConvertKernel.cxx | 4 ---- 5 files changed, 16 deletions(-) diff --git a/GPU/GPUTracking/DataTypes/GPUTPCGMMergedTrackHit.h b/GPU/GPUTracking/DataTypes/GPUTPCGMMergedTrackHit.h index 4ddd70efb5d1c..a5f0c1a55e2b9 100644 --- a/GPU/GPUTracking/DataTypes/GPUTPCGMMergedTrackHit.h +++ b/GPU/GPUTracking/DataTypes/GPUTPCGMMergedTrackHit.h @@ -41,10 +41,6 @@ struct GPUTPCGMMergedTrackHit { struct GPUTPCGMMergedTrackHitXYZ { float x, y, z; uint16_t amp; -#ifdef GPUCA_TPC_RAW_PROPAGATE_PAD_ROW_TIME - float pad; - float time; -#endif }; } // namespace o2::gpu diff --git a/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h b/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h index 48218dd7859e6..9a8b9b8536fb0 100644 --- a/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h +++ b/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h @@ -68,7 +68,6 @@ //#define GPUCA_MERGER_BY_MC_LABEL // Use MC labels for TPC track merging - for performance studies // TODO: Cleanup unneeded options //#define GPUCA_FULL_CLUSTERDATA // Store all cluster information in the cluster data, also those not needed for tracking. -//#define GPUCA_TPC_RAW_PROPAGATE_PAD_ROW_TIME // Propagate Pad, Row, Time cluster information to GM //#define GPUCA_GM_USE_FULL_FIELD // Use offline magnetic field during GMPropagator prolongation // clang-format on diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index ab35e7f9a3c36..338ecae4f9b95 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -1727,10 +1727,6 @@ GPUd() void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThread clXYZ[i].y = c.y; clXYZ[i].z = c.z; clXYZ[i].amp = c.amp; -#ifdef GPUCA_TPC_RAW_PROPAGATE_PAD_ROW_TIME - clXYZ[i].pad = c.mPad; - clXYZ[i].time = c.mTime; -#endif state = c.flags; } else { const ClusterNative& c = GetConstantMem()->ioPtrs.clustersNative->clustersLinear[trackClusters[i].id]; diff --git a/GPU/GPUTracking/SectorTracker/GPUTPCDef.h b/GPU/GPUTracking/SectorTracker/GPUTPCDef.h index 84ea8e836007c..04042bb4a6632 100644 --- a/GPU/GPUTracking/SectorTracker/GPUTPCDef.h +++ b/GPU/GPUTracking/SectorTracker/GPUTPCDef.h @@ -33,9 +33,6 @@ typedef uint32_t cahit; struct cahit2 { cahit x, y; }; } // namespace o2::GPU -#ifdef GPUCA_TPC_RAW_PROPAGATE_PAD_ROW_TIME // Needs full clusterdata - #define GPUCA_FULL_CLUSTERDATA -#endif #if defined(GPUCA_STANDALONE) || defined(GPUCA_GPUCODE) // No support for Full Field Propagator or Statistical errors #ifdef GPUCA_GM_USE_FULL_FIELD diff --git a/GPU/GPUTracking/TPCConvert/GPUTPCConvertKernel.cxx b/GPU/GPUTracking/TPCConvert/GPUTPCConvertKernel.cxx index e17bfc1dff025..806a06dfbbe02 100644 --- a/GPU/GPUTracking/TPCConvert/GPUTPCConvertKernel.cxx +++ b/GPU/GPUTracking/TPCConvert/GPUTPCConvertKernel.cxx @@ -44,9 +44,5 @@ GPUdii() void GPUTPCConvertKernel::Thread<0>(int32_t nBlocks, int32_t nThreads, clout.amp = clin.qTot; clout.flags = clin.getFlags(); clout.id = idOffset + k; -#ifdef GPUCA_TPC_RAW_PROPAGATE_PAD_ROW_TIME - clout.pad = clin.getPad(); - clout.time = clin.getTime(); -#endif } } From 1250d5e8c6aa21dac259189bf7928e4f7e511c01 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 12 Jun 2025 07:55:07 +0200 Subject: [PATCH 024/315] GPU: Remove obsolete GPUCA_FULL_CLUSTERDATA --- GPU/GPUTracking/Definitions/GPUDef.h | 6 +----- GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h | 1 - GPU/GPUTracking/SectorTracker/GPUTPCClusterData.h | 7 ------- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUDef.h b/GPU/GPUTracking/Definitions/GPUDef.h index 69723813d384f..e1b34af55d62d 100644 --- a/GPU/GPUTracking/Definitions/GPUDef.h +++ b/GPU/GPUTracking/Definitions/GPUDef.h @@ -34,11 +34,7 @@ #define GPUPtr2(a, b) b #endif -#ifdef GPUCA_FULL_CLUSTERDATA - #define GPUCA_EVDUMP_FILE "event_full" -#else - #define GPUCA_EVDUMP_FILE "event" -#endif +#define GPUCA_EVDUMP_FILE "event_full" #ifdef GPUCA_GPUCODE #define CA_MAKE_SHARED_REF(vartype, varname, varglobal, varshared) const GPUsharedref() vartype& __restrict__ varname = varshared; diff --git a/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h b/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h index 9a8b9b8536fb0..f33dfad02e7e5 100644 --- a/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h +++ b/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h @@ -67,7 +67,6 @@ #endif //#define GPUCA_MERGER_BY_MC_LABEL // Use MC labels for TPC track merging - for performance studies // TODO: Cleanup unneeded options -//#define GPUCA_FULL_CLUSTERDATA // Store all cluster information in the cluster data, also those not needed for tracking. //#define GPUCA_GM_USE_FULL_FIELD // Use offline magnetic field during GMPropagator prolongation // clang-format on diff --git a/GPU/GPUTracking/SectorTracker/GPUTPCClusterData.h b/GPU/GPUTracking/SectorTracker/GPUTPCClusterData.h index cf269a27bd6a5..fbaeeb294df88 100644 --- a/GPU/GPUTracking/SectorTracker/GPUTPCClusterData.h +++ b/GPU/GPUTracking/SectorTracker/GPUTPCClusterData.h @@ -27,13 +27,6 @@ struct GPUTPCClusterData { float y; float z; float amp; -#ifdef GPUCA_FULL_CLUSTERDATA - float pad; - float time; - float ampMax; - float sigmaPad2; - float sigmaTime2; -#endif }; } // namespace o2::gpu From 5b6fccc8b8d331205d1f60b0031717ec597ad726 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 12 Jun 2025 07:56:07 +0200 Subject: [PATCH 025/315] GPU: Remove obsolete GPUCA_GM_USE_FULL_FIELD --- .../Definitions/GPUDefConstantsAndSettings.h | 1 - GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx | 33 ------------------- GPU/GPUTracking/SectorTracker/GPUTPCDef.h | 7 ---- 3 files changed, 41 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h b/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h index f33dfad02e7e5..46988208256fc 100644 --- a/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h +++ b/GPU/GPUTracking/Definitions/GPUDefConstantsAndSettings.h @@ -67,7 +67,6 @@ #endif //#define GPUCA_MERGER_BY_MC_LABEL // Use MC labels for TPC track merging - for performance studies // TODO: Cleanup unneeded options -//#define GPUCA_GM_USE_FULL_FIELD // Use offline magnetic field during GMPropagator prolongation // clang-format on diff --git a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx index c0dd6cfbcf918..2d612254ba001 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMPropagator.cxx @@ -22,11 +22,6 @@ #include "GPUDebugStreamer.h" #include "GPUTPCGMMerger.h" -#if defined(GPUCA_GM_USE_FULL_FIELD) -#include "AliTracker.h" -#include "AliMagF.h" -#endif - using namespace o2::gpu; GPUd() void GPUTPCGMPropagator::GetBxByBzBase(float cosAlpha, float sinAlpha, float X, float Y, float Z, float B[3]) const @@ -36,24 +31,6 @@ GPUd() void GPUTPCGMPropagator::GetBxByBzBase(float cosAlpha, float sinAlpha, fl float gx = getGlobalX(cosAlpha, sinAlpha, X, Y); float gy = getGlobalY(cosAlpha, sinAlpha, X, Y); -#if defined(GPUCA_GM_USE_FULL_FIELD) - const float kCLight = gpu_common_constants::kCLight; - double r[3] = {gx, gy, Z}; - double bb[3]; - AliTracker::GetBxByBz(r, bb); - bb[0] *= kCLight; - bb[1] *= kCLight; - bb[2] *= kCLight; -/* - cout<<"AliTracker::GetBz()= "<GetField(); - cout<<"Fast field = "<<(void*) fld->GetFastField()<GetMapType() ; - cout<<"Field type: "<GetField(gx, gy, Z, bb); } -#endif - // rotate field to local coordinates B[0] = bb[0] * cosAlpha + bb[1] * sinAlpha; @@ -81,13 +56,6 @@ GPUd() float GPUTPCGMPropagator::GetBzBase(float cosAlpha, float sinAlpha, float float gx = getGlobalX(cosAlpha, sinAlpha, X, Y); float gy = getGlobalY(cosAlpha, sinAlpha, X, Y); -#if defined(GPUCA_GM_USE_FULL_FIELD) - const float kCLight = gpu_common_constants::kCLight; - double r[3] = {gx, gy, Z}; - double bb[3]; - AliTracker::GetBxByBz(r, bb); - return bb[2] * kCLight; -#else switch (mFieldRegion) { case ITS: return mField->GetFieldItsBz(gx, gy, Z); @@ -97,7 +65,6 @@ GPUd() float GPUTPCGMPropagator::GetBzBase(float cosAlpha, float sinAlpha, float default: return mField->GetFieldBz(gx, gy, Z); } -#endif } GPUd() int32_t GPUTPCGMPropagator::RotateToAlpha(float newAlpha) diff --git a/GPU/GPUTracking/SectorTracker/GPUTPCDef.h b/GPU/GPUTracking/SectorTracker/GPUTPCDef.h index 04042bb4a6632..e64937eec0ede 100644 --- a/GPU/GPUTracking/SectorTracker/GPUTPCDef.h +++ b/GPU/GPUTracking/SectorTracker/GPUTPCDef.h @@ -33,12 +33,5 @@ typedef uint32_t cahit; struct cahit2 { cahit x, y; }; } // namespace o2::GPU - -#if defined(GPUCA_STANDALONE) || defined(GPUCA_GPUCODE) // No support for Full Field Propagator or Statistical errors - #ifdef GPUCA_GM_USE_FULL_FIELD - #undef GPUCA_GM_USE_FULL_FIELD - #endif -#endif - #endif //GPUDTPCEF_H // clang-format on From 74db0b59fd7e17ab5cc322b7bc101e8621ae785f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 12 Jun 2025 07:59:33 +0200 Subject: [PATCH 026/315] GPU: Delete obsolete class GPUTPCSectorOutCluster --- GPU/GPUTracking/Base/GPUReconstructionCPU.cxx | 1 - GPU/GPUTracking/CMakeLists.txt | 1 - GPU/GPUTracking/Global/GPUChainTracking.cxx | 1 - GPU/GPUTracking/Global/GPUChainTrackingIO.cxx | 1 - .../SectorTracker/GPUTPCSectorOutCluster.h | 66 ------------------- GPU/GPUTracking/SectorTracker/GPUTPCTrack.h | 6 -- 6 files changed, 76 deletions(-) delete mode 100644 GPU/GPUTracking/SectorTracker/GPUTPCSectorOutCluster.h diff --git a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx index 2d1061616d907..d29fc09f32f63 100644 --- a/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx +++ b/GPU/GPUTracking/Base/GPUReconstructionCPU.cxx @@ -18,7 +18,6 @@ #include "GPUChain.h" #include "GPUDefParametersRuntime.h" #include "GPUTPCClusterData.h" -#include "GPUTPCSectorOutCluster.h" #include "GPUTPCGMMergedTrack.h" #include "GPUTPCGMMergedTrackHit.h" #include "GPUTRDTrackletWord.h" diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 67db16ffe9607..87b202ec607ae 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -155,7 +155,6 @@ set(HDRS_INSTALL SectorTracker/GPUTPCHit.h SectorTracker/GPUTPCHitId.h SectorTracker/GPUTPCMCInfo.h - SectorTracker/GPUTPCSectorOutCluster.h SectorTracker/GPUTPCTracklet.h SectorTracker/GPUTPCTrackLinearisation.h TPCConvert/GPUTPCConvertImpl.h diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index db84050772312..423f0b782d095 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -22,7 +22,6 @@ #include "GPUReconstructionIO.h" #include "GPUChainTrackingDefs.h" #include "GPUTPCClusterData.h" -#include "GPUTPCSectorOutCluster.h" #include "GPUTPCGMMergedTrack.h" #include "GPUTPCGMMergedTrackHit.h" #include "GPUTPCTrack.h" diff --git a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx index 5a141cd08eb65..dd11e9989f684 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingIO.cxx @@ -15,7 +15,6 @@ #include "GPUChainTracking.h" #include "GPUReconstructionIO.h" #include "GPUTPCClusterData.h" -#include "GPUTPCSectorOutCluster.h" #include "GPUTPCGMMergedTrack.h" #include "GPUTPCGMMergedTrackHit.h" #include "GPUTPCTrack.h" diff --git a/GPU/GPUTracking/SectorTracker/GPUTPCSectorOutCluster.h b/GPU/GPUTracking/SectorTracker/GPUTPCSectorOutCluster.h deleted file mode 100644 index 2c62a2ca184b2..0000000000000 --- a/GPU/GPUTracking/SectorTracker/GPUTPCSectorOutCluster.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file GPUTPCSectorOutCluster.h -/// \author Sergey Gorbunov, David Rohr - -#ifndef GPUTPCSECTOROUTCLUSTER_H -#define GPUTPCSECTOROUTCLUSTER_H - -#include "GPUTPCDef.h" - -namespace o2::gpu -{ -/** - * @class GPUTPCSectorOutCluster - * GPUTPCSectorOutCluster class contains clusters which are assigned to sector tracks. - * It is used to send the data from TPC sector trackers to the GlobalMerger - */ -class GPUTPCSectorOutCluster -{ - public: - GPUhd() void Set(uint32_t id, uint8_t row, uint8_t flags, uint16_t amp, float x, float y, float z) - { - mRow = row; - mFlags = flags; - mId = id; - mAmp = amp; - mX = x; - mY = y; - mZ = z; - } - - GPUhd() float GetX() const { return mX; } - GPUhd() float GetY() const { return mY; } - GPUhd() float GetZ() const { return mZ; } - GPUhd() uint16_t GetAmp() const { return mAmp; } - GPUhd() uint32_t GetId() const { return mId; } - GPUhd() uint8_t GetRow() const { return mRow; } - GPUhd() uint8_t GetFlags() const { return mFlags; } - - private: - uint32_t mId; // Id - uint8_t mRow; // row - uint8_t mFlags; // flags - uint16_t mAmp; // amplitude - float mX; // coordinates - float mY; // coordinates - float mZ; // coordinates - -#ifdef GPUCA_TPC_RAW_PROPAGATE_PAD_ROW_TIME - public: - float mPad; - float mTime; -#endif -}; -} // namespace o2::gpu - -#endif diff --git a/GPU/GPUTracking/SectorTracker/GPUTPCTrack.h b/GPU/GPUTracking/SectorTracker/GPUTPCTrack.h index 7306c84cf949c..d67903f00acfa 100644 --- a/GPU/GPUTracking/SectorTracker/GPUTPCTrack.h +++ b/GPU/GPUTracking/SectorTracker/GPUTPCTrack.h @@ -17,7 +17,6 @@ #include "GPUTPCBaseTrackParam.h" #include "GPUTPCDef.h" -#include "GPUTPCSectorOutCluster.h" namespace o2::gpu { @@ -49,11 +48,6 @@ class GPUTPCTrack GPUhd() void SetParam(const GPUTPCBaseTrackParam& v) { mParam = v; } - // Only if used as replacement for SectorOutTrack - GPUhd() static int32_t GetSize(int32_t nClust) { return sizeof(GPUTPCTrack) + nClust * sizeof(GPUTPCSectorOutCluster); } - GPUhd() const GPUTPCTrack* GetNextTrack() const { return (const GPUTPCTrack*)(((char*)this) + GetSize(mNHits)); } - GPUhd() GPUTPCTrack* NextTrack() { return (GPUTPCTrack*)(((char*)this) + GetSize(mNHits)); } - private: int32_t mFirstHitID; // index of the first track cell in the track->cell pointer array int32_t mNHits; // number of track cells From d4fb131cbd800bc825034264d89fed32ce2a578a Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 15 Jun 2025 14:51:24 +0200 Subject: [PATCH 027/315] GPU CMake: Switch from deprecated AMDGPU_TARGETS to GPU_TARGETS --- dependencies/FindO2GPU.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index 20e351a68c271..f9c549905f178 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -234,7 +234,7 @@ endif() if(ENABLE_HIP) if(HIP_AMDGPUTARGET) set(CMAKE_HIP_ARCHITECTURES "${HIP_AMDGPUTARGET}") - set(AMDGPU_TARGETS "${HIP_AMDGPUTARGET}") + set(GPU_TARGETS "${HIP_AMDGPUTARGET}") endif() if(NOT "$ENV{CMAKE_PREFIX_PATH}" MATCHES "rocm" AND NOT CMAKE_PREFIX_PATH MATCHES "rocm" AND EXISTS "/opt/rocm/lib/cmake/") list(APPEND CMAKE_PREFIX_PATH "/opt/rocm/lib/cmake") From 86b1969df0001f1534e16689ad9bb98b20d255ed Mon Sep 17 00:00:00 2001 From: Christian Sonnabend Date: Mon, 16 Jun 2025 09:18:18 +0200 Subject: [PATCH 028/315] NN clusterizer: Bug-fixes and addition of deconvolution kernel (#14378) * First bug-fixes and optimizations for deconvolution flags * Adding publishing logic for deconvolution flags * Adjusting kernels.cmake * Please consider the following formatting changes * Bug-fix for time-position and boundary check in fillInputSingleElement * Fix for kernels.cmake and naming * Changing to uint8_t * Adding kernel definition --------- Co-authored-by: ALICE Action Bot --- .../Definitions/GPUDefParametersDefaults.h | 1 + GPU/GPUTracking/Definitions/GPUSettingsList.h | 1 + .../Global/GPUChainTrackingClusterizer.cxx | 10 ++- .../GPUTPCCFDeconvolution.cxx | 16 +++-- .../TPCClusterFinder/GPUTPCCFDeconvolution.h | 2 +- .../TPCClusterFinder/GPUTPCNNClusterizer.h | 1 + .../GPUTPCNNClusterizerHost.cxx | 1 + .../GPUTPCNNClusterizerKernels.cxx | 65 ++++++++++++++----- .../GPUTPCNNClusterizerKernels.h | 1 + GPU/GPUTracking/kernels.cmake | 17 ++--- 10 files changed, 81 insertions(+), 34 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h b/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h index 7879789bf91c8..8fe8e8ca68e44 100644 --- a/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h +++ b/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h @@ -497,6 +497,7 @@ #define GPUCA_LB_GPUTPCNNClusterizerKernels_determineClass2Labels GPUCA_LB_GPUTPCNNClusterizerKernels #define GPUCA_LB_GPUTPCNNClusterizerKernels_publishClass1Regression GPUCA_LB_GPUTPCNNClusterizerKernels #define GPUCA_LB_GPUTPCNNClusterizerKernels_publishClass2Regression GPUCA_LB_GPUTPCNNClusterizerKernels + #define GPUCA_LB_GPUTPCNNClusterizerKernels_publishDeconvolutionFlags GPUCA_LB_GPUTPCNNClusterizerKernels #define GPUCA_LB_GPUTPCCFStreamCompaction_scanStart GPUCA_PAR_CF_SCAN_WORKGROUP_SIZE #define GPUCA_LB_GPUTPCCFStreamCompaction_scanUp GPUCA_PAR_CF_SCAN_WORKGROUP_SIZE diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index d8173a5b62a35..e75d5a5890e4b 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -269,6 +269,7 @@ AddOption(nnClusterizerBatchedMode, unsigned int, 1, "", 0, "(int, default = 1) AddOption(nnClusterizerVerbosity, int, -1, "", 0, "(int, default = -1) If >0, logging messages of the clusterizer will be displayed") AddOption(nnClusterizerBoundaryFillValue, int, -1, "", 0, "Fill value for the boundary of the input to the NN") AddOption(nnClusterizerApplyNoiseSuppression, int, 1, "", 0, "Applies the NoiseSuppression kernel before the digits to the network are filled") +AddOption(nnClusterizerSetDeconvolutionFlags, int, 1, "", 0, "Runs the deconvolution kernel without overwriting the charge in order to make cluster-to-track attachment identical to heuristic CF") AddOption(nnClassificationPath, std::string, "network_class.onnx", "", 0, "The classification network path") AddOption(nnClassThreshold, float, 0.5, "", 0, "The cutoff at which clusters will be accepted / rejected.") AddOption(nnRegressionPath, std::string, "network_reg.onnx", "", 0, "The regression network path") diff --git a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx index 64e6f5a31aaa7..816ee43d50b15 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx @@ -989,8 +989,10 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) int withMC = (doGPU && propagateMCLabels); if (clustererNNShadow.mNnClusterizerUseCfRegression || (int)(nn_settings.nnClusterizerApplyCfDeconvolution)) { - runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}); + runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}, true); DoDebugAndDump(RecoStep::TPCClusterFinding, GPUChainTrackingDebugFlags::TPCClustererChargeMap, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges"); + } else if (clustererNNShadow.mNnClusterizerSetDeconvolutionFlags) { + runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}, false); } // float time_clusterizer = 0, time_fill = 0, time_networks = 0; @@ -1001,6 +1003,10 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) // auto start0 = std::chrono::high_resolution_clock::now(); runKernel({GetGrid(iSize * clustererNNShadow.mNnClusterizerElementSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, withMC, batchStart); // Filling the data + if (clustererNNShadow.mNnClusterizerSetDeconvolutionFlags) { + runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, withMC, batchStart); // Filling the regression data + } + // auto stop0 = std::chrono::high_resolution_clock::now(); // auto start1 = std::chrono::high_resolution_clock::now(); @@ -1102,7 +1108,7 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) GPUFatal("Project not compiled with neural network clusterization. Aborting."); #endif } else { - runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}); + runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}, true); DoDebugAndDump(RecoStep::TPCClusterFinding, GPUChainTrackingDebugFlags::TPCClustererChargeMap, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges"); runKernel({GetGrid(clusterer.mPmemory->counters.nClusters, lane), {iSector}}, 0); } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx index 429d51685e504..d6b8703a9b35d 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.cxx @@ -22,18 +22,19 @@ using namespace o2::gpu; using namespace o2::gpu::tpccf; template <> -GPUdii() void GPUTPCCFDeconvolution::Thread<0>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& clusterer) +GPUdii() void GPUTPCCFDeconvolution::Thread<0>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& clusterer, uint8_t overwriteCharge) { CfArray2D chargeMap(reinterpret_cast(clusterer.mPchargeMap)); CfArray2D isPeakMap(clusterer.mPpeakMap); - GPUTPCCFDeconvolution::deconvolutionImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, isPeakMap, chargeMap, clusterer.mPpositions, clusterer.mPmemory->counters.nPositions); + GPUTPCCFDeconvolution::deconvolutionImpl(get_num_groups(0), get_local_size(0), get_group_id(0), get_local_id(0), smem, isPeakMap, chargeMap, clusterer.mPpositions, clusterer.mPmemory->counters.nPositions, overwriteCharge); } GPUdii() void GPUTPCCFDeconvolution::deconvolutionImpl(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, const CfArray2D& peakMap, CfArray2D& chargeMap, const CfChargePos* positions, - const uint32_t digitnum) + const uint32_t digitnum, + uint8_t overwriteCharge) { SizeT idx = get_global_id(0); @@ -111,9 +112,14 @@ GPUdii() void GPUTPCCFDeconvolution::deconvolutionImpl(int32_t nBlocks, int32_t peakCount = (peakCount == 0) ? 1 : peakCount; PackedCharge charge = chargeMap[pos]; - PackedCharge p(charge.unpack() / peakCount, has3x3, split); - chargeMap[pos] = p; + if (overwriteCharge) { + PackedCharge p(charge.unpack() / peakCount, has3x3, split); + chargeMap[pos] = p; + } else { + PackedCharge p(charge.unpack(), has3x3, split); + chargeMap[pos] = p; + } } GPUdi() uint8_t GPUTPCCFDeconvolution::countPeaksInner( diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h index e971a042e95a4..902e3a28fd21b 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDeconvolution.h @@ -51,7 +51,7 @@ class GPUTPCCFDeconvolution : public GPUKernelTemplate GPUd() static void Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& clusterer, Args... args); private: - static GPUd() void deconvolutionImpl(int32_t, int32_t, int32_t, int32_t, GPUSharedMemory&, const CfArray2D&, CfArray2D&, const CfChargePos*, const uint32_t); + static GPUd() void deconvolutionImpl(int32_t, int32_t, int32_t, int32_t, GPUSharedMemory&, const CfArray2D&, CfArray2D&, const CfChargePos*, const uint32_t, uint8_t); static GPUdi() uint8_t countPeaksInner(uint16_t, const uint8_t*, uint8_t*); static GPUdi() uint8_t countPeaksOuter(uint16_t, uint8_t, const uint8_t*); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h index f7c2d13407b0e..980c0977aca65 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h @@ -44,6 +44,7 @@ class GPUTPCNNClusterizer : public GPUProcessor bool mNnClusterizerAddIndexData = true; float mNnClassThreshold = 0.01; bool mNnSigmoidTrafoClassThreshold = 1; + bool mNnClusterizerSetDeconvolutionFlags = true; int mNnClusterizerUseCfRegression = 0; int mNnClusterizerBatchedMode = 1; int mNnClusterizerTotalClusters = 1; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx index 90f1d6e27246f..124320396d0d4 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx @@ -92,6 +92,7 @@ void GPUTPCNNClusterizerHost::initClusterizer(const GPUSettingsProcessingNNclust clustererNN.mNnClusterizerBatchedMode = settings.nnClusterizerBatchedMode; clustererNN.mNnClusterizerBoundaryFillValue = settings.nnClusterizerBoundaryFillValue; clustererNN.mNnSigmoidTrafoClassThreshold = settings.nnSigmoidTrafoClassThreshold; + clustererNN.mNnClusterizerSetDeconvolutionFlags = (bool)settings.nnClusterizerSetDeconvolutionFlags; if (clustererNN.mNnSigmoidTrafoClassThreshold) { clustererNN.mNnClassThreshold = (float)std::log(settings.nnClassThreshold / (1.f - settings.nnClassThreshold)); } else { diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx index 8ca61602ab4e9..58dd49630d8e6 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx @@ -51,7 +51,7 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread -GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t onlyMC, uint32_t batchStart) +GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint32_t batchStart) { uint32_t glo_idx = get_global_id(0); auto& clusterer = processors.tpcClusterer[sector]; @@ -111,7 +111,7 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread -GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t onlyMC, uint32_t batchStart) +GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint32_t batchStart) { uint32_t glo_idx = get_global_id(0); auto& clusterer = processors.tpcClusterer[sector]; @@ -126,11 +126,13 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread (o2::tpc::constants::MAXGLOBALPADROW - 1)) || ((row + r) < 0); if (is_row_boundary) { if (dtype == 0) { - clustererNN.mInputData_16[base_idx * clustererNN.mNnClusterizerElementSize + transient_index] = (OrtDataType::Float16_t)(static_cast(clustererNN.mNnClusterizerBoundaryFillValue)); + clustererNN.mInputData_16[glo_idx] = (OrtDataType::Float16_t)(static_cast(clustererNN.mNnClusterizerBoundaryFillValue)); } else { - clustererNN.mInputData_32[base_idx * clustererNN.mNnClusterizerElementSize + transient_index] = static_cast(clustererNN.mNnClusterizerBoundaryFillValue); + clustererNN.mInputData_32[glo_idx] = static_cast(clustererNN.mNnClusterizerBoundaryFillValue); } } else { int32_t row_offset = GPUTPCNNClusterizerKernels::rowOffset(row, clustererNN.mNnClusterizerSizeInputRow); int32_t pad_offset = GPUTPCNNClusterizerKernels::padOffset(row, row + r); int32_t rest_1 = transient_index % ((2 * clustererNN.mNnClusterizerSizeInputPad + 1) * (2 * clustererNN.mNnClusterizerSizeInputTime + 1)); int32_t p = CAMath::Floor(rest_1 / (2 * clustererNN.mNnClusterizerSizeInputTime + 1)) - clustererNN.mNnClusterizerSizeInputPad + pad_offset; - int32_t t = (rest_1 % (2 * clustererNN.mNnClusterizerSizeInputTime + 1)) - clustererNN.mNnClusterizerSizeInputTime; + int32_t time_pos = (rest_1 % (2 * clustererNN.mNnClusterizerSizeInputTime + 1)) - clustererNN.mNnClusterizerSizeInputTime + time; - bool is_boundary = GPUTPCNNClusterizerKernels::isBoundary(row + r + row_offset, pad + p, clustererNN.mNnClusterizerSizeInputRow) && (t < 0 || t >= TPC_MAX_FRAGMENT_LEN_GPU); + bool is_boundary = GPUTPCNNClusterizerKernels::isBoundary(row + r + row_offset, pad + p, clustererNN.mNnClusterizerSizeInputRow) && (time_pos < 0 || time_pos >= TPC_MAX_FRAGMENT_LEN_GPU); if (!is_boundary) { float central_charge = static_cast(chargeMap[peak].unpack()); - CfChargePos tmp_pos(row + r, pad + p, time + t); + CfChargePos tmp_pos(row + r, pad + p, time_pos); if (dtype == 0) { - clustererNN.mInputData_16[base_idx * clustererNN.mNnClusterizerElementSize + transient_index] = (OrtDataType::Float16_t)(static_cast(chargeMap[tmp_pos].unpack()) / central_charge); + clustererNN.mInputData_16[glo_idx] = (OrtDataType::Float16_t)(static_cast(chargeMap[tmp_pos].unpack()) / central_charge); } else if (dtype == 1) { - clustererNN.mInputData_32[base_idx * clustererNN.mNnClusterizerElementSize + transient_index] = static_cast(chargeMap[tmp_pos].unpack()) / central_charge; + clustererNN.mInputData_32[glo_idx] = static_cast(chargeMap[tmp_pos].unpack()) / central_charge; } } else { if (dtype == 0) { - clustererNN.mInputData_16[base_idx * clustererNN.mNnClusterizerElementSize + transient_index] = (OrtDataType::Float16_t)(static_cast(clustererNN.mNnClusterizerBoundaryFillValue)); + clustererNN.mInputData_16[glo_idx] = (OrtDataType::Float16_t)(static_cast(clustererNN.mNnClusterizerBoundaryFillValue)); } else { - clustererNN.mInputData_32[base_idx * clustererNN.mNnClusterizerElementSize + transient_index] = static_cast(clustererNN.mNnClusterizerBoundaryFillValue); + clustererNN.mInputData_32[glo_idx] = static_cast(clustererNN.mNnClusterizerBoundaryFillValue); } } } @@ -180,7 +182,7 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread -GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t onlyMC, uint32_t batchStart) +GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint32_t batchStart) { uint32_t glo_idx = get_global_id(0); if (dtype == 0) { @@ -191,7 +193,7 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread -GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t onlyMC, uint32_t batchStart) +GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint32_t batchStart) { auto& clustererNN = processors.tpcNNClusterer[sector]; uint32_t glo_idx = get_global_id(0); @@ -457,6 +459,33 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread +GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint batchStart) +{ + // Implements identical publishing logic as the heuristic clusterizer and deconvolution kernel + uint32_t idx = get_global_id(0); + auto& clusterer = processors.tpcClusterer[sector]; + auto& clustererNN = processors.tpcNNClusterer[sector]; + CfArray2D chargeMap(reinterpret_cast(clusterer.mPchargeMap)); + CfChargePos peak = clusterer.mPfilteredPeakPositions[idx + batchStart]; + + for (int i = 0; i < 8; i++) { + Delta2 d = cfconsts::InnerNeighbors[i]; + CfChargePos tmp_pos = peak.delta(d); + PackedCharge charge = chargeMap[tmp_pos]; + clustererNN.mClusterFlags[2 * idx] += (d.y != 0 && charge.isSplit()); + clustererNN.mClusterFlags[2 * idx + 1] += (d.x != 0 && charge.isSplit()); + } + for (int i = 0; i < 16; i++) { + Delta2 d = cfconsts::OuterNeighbors[i]; + CfChargePos tmp_pos = peak.delta(d); + PackedCharge charge = chargeMap[tmp_pos]; + clustererNN.mClusterFlags[2 * idx] += (d.y != 0 && charge.isSplit() && !charge.has3x3Peak()); + clustererNN.mClusterFlags[2 * idx + 1] += (d.x != 0 && charge.isSplit() && !charge.has3x3Peak()); + } +} + // THe following arithmetic is done because the network is trained with a split between IROC and OROC boundary GPUd() int32_t GPUTPCNNClusterizerKernels::padOffset(int32_t row_ref, int32_t row_current) { diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h index dac2bf9554849..179eb483cdf6b 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h @@ -65,6 +65,7 @@ class GPUTPCNNClusterizerKernels : public GPUKernelTemplate determineClass2Labels = 4, publishClass1Regression = 5, publishClass2Regression = 6, + publishDeconvolutionFlags = 7 }; template diff --git a/GPU/GPUTracking/kernels.cmake b/GPU/GPUTracking/kernels.cmake index 08d879fbb8e9a..2a59f98a6d5b4 100644 --- a/GPU/GPUTracking/kernels.cmake +++ b/GPU/GPUTracking/kernels.cmake @@ -111,7 +111,7 @@ o2_gpu_add_kernel("GPUTPCCFChargeMapFiller, findFragmentStart" "= TPC o2_gpu_add_kernel("GPUTPCCFPeakFinder" "= TPCCLUSTERFINDER" LB) o2_gpu_add_kernel("GPUTPCCFNoiseSuppression, noiseSuppression" "= TPCCLUSTERFINDER" LB) o2_gpu_add_kernel("GPUTPCCFNoiseSuppression, updatePeaks" "= TPCCLUSTERFINDER" LB) -o2_gpu_add_kernel("GPUTPCCFDeconvolution" "= TPCCLUSTERFINDER" LB) +o2_gpu_add_kernel("GPUTPCCFDeconvolution" "= TPCCLUSTERFINDER" LB uint8_t overwriteCharge) o2_gpu_add_kernel("GPUTPCCFClusterizer" "= TPCCLUSTERFINDER" LB int8_t onlyMC) o2_gpu_add_kernel("GPUTPCCFMCLabelFlattener, setRowOffsets" "= TPCCLUSTERFINDER") o2_gpu_add_kernel("GPUTPCCFMCLabelFlattener, flatten" "= TPCCLUSTERFINDER" NO GPUTPCLinearLabels* out) @@ -127,13 +127,14 @@ o2_gpu_add_kernel("GPUTPCCFGather" "=" o2_gpu_add_kernel("GPUTrackingRefitKernel, mode0asGPU" "= GLOBALREFIT " LB) o2_gpu_add_kernel("GPUTrackingRefitKernel, mode1asTrackParCov" "= GLOBALREFIT " LB) if(onnxruntime_FOUND) -o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, runCfClusterizer" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t onlyMC uint batchStart) -o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, fillInputNN" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t onlyMC uint batchStart) -o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, fillInputNNSingleElement" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t onlyMC uint batchStart) -o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, determineClass1Labels" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t onlyMC uint batchStart) -o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, determineClass2Labels" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t onlyMC uint batchStart) -o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, publishClass1Regression" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t onlyMC uint batchStart) -o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, publishClass2Regression" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t onlyMC uint batchStart) +o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, runCfClusterizer" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) +o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, fillInputNN" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) +o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, fillInputNNSingleElement" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) +o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, determineClass1Labels" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) +o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, determineClass2Labels" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) +o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, publishClass1Regression" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) +o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, publishClass2Regression" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) +o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, publishDeconvolutionFlags" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) endif() o2_gpu_kernel_add_parameter(NEIGHBOURS_FINDER_MAX_NNEIGHUP From 614bce287a8cb2a416f62538f7ccea8dcc80d001 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 10 Jun 2025 11:19:15 +0200 Subject: [PATCH 029/315] ITS: after processing cleanup memory remnants Signed-off-by: Felix Schlepper --- .../ITS/tracking/include/ITStracking/TrackingInterface.h | 1 + Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx | 5 +++++ .../ITS/workflow/include/ITSWorkflow/TrackerSpec.h | 1 + Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 9 +++++++-- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h index cff6d215e5e3b..732efcb9e0861 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h @@ -59,6 +59,7 @@ class ITSTrackingInterface void initialise(); void run(framework::ProcessingContext& pc); void printSummary() const; + void end(); virtual void updateTimeDependentParams(framework::ProcessingContext& pc); virtual void finaliseCCDB(framework::ConcreteDataMatcher& matcher, void* obj); diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index c70108b4f8a30..b6b4796690905 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -449,6 +449,11 @@ void ITSTrackingInterface::printSummary() const mTracker->printSummary(); } +void ITSTrackingInterface::end() +{ + mTimeFrame->wipe(); +} + void ITSTrackingInterface::setTraitsFromProvider(VertexerTraits* vertexerTraits, TrackerTraits7* trackerTraits, TimeFrame7* frame) diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h index 9160df6fc49fd..27c4174fab244 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h @@ -48,6 +48,7 @@ class TrackerDPL : public framework::Task void stop() final; private: + void end(); void updateTimeDependentParams(framework::ProcessingContext& pc); std::unique_ptr mRecChain = nullptr; std::unique_ptr mChainITS = nullptr; diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index abbb88aea42fa..9f84ee6522567 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -48,8 +48,7 @@ void TrackerDPL::init(InitContext& ic) void TrackerDPL::stop() { - mITSTrackingInterface.printSummary(); - LOGF(info, "CPU Reconstruction total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); + end(); } void TrackerDPL::run(ProcessingContext& pc) @@ -70,6 +69,12 @@ void TrackerDPL::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) void TrackerDPL::endOfStream(EndOfStreamContext& ec) { + end(); +} + +void TrackerDPL::end() +{ + mITSTrackingInterface.end(); mITSTrackingInterface.printSummary(); LOGF(info, "ITS CA-Tracker total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } From b911f95c1582dd0cb59afa99022f4b74594290fc Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 16 Jun 2025 10:05:06 +0200 Subject: [PATCH 030/315] Fix typo while adapting for std::pmr (#14408) --- Utilities/DataSampling/src/Dispatcher.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/DataSampling/src/Dispatcher.cxx b/Utilities/DataSampling/src/Dispatcher.cxx index bc79be2771316..3ff0ba661fd93 100644 --- a/Utilities/DataSampling/src/Dispatcher.cxx +++ b/Utilities/DataSampling/src/Dispatcher.cxx @@ -80,7 +80,7 @@ void Dispatcher::init(InitContext& ctx) header::Stack extractAdditionalHeaders(const char* inputHeaderStack) { - std::array headers; + std::array headers; int count = 0; const auto* first = header::BaseHeader::get(reinterpret_cast(inputHeaderStack)); for (const auto* current = first; current != nullptr; current = current->next()) { From 56bfdbe23b8c8d6cde5bf656f9b843691d74d168 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 13 Jun 2025 12:21:47 +0200 Subject: [PATCH 031/315] Optional InteractionSampler sampling overwrite Allow to overwrite InteractionSampler by means of virtualizing sampling function. Used in CollisionContextTool do allow putting collisions at fixed N intervals (export mode) for the purpose of systematic studies / debugging. - To use this feature say `export ALICEO2_ENFORCE_TRIVIAL_BC_SAMPLER="2:5" to put 5 collisions into every 2nd bunch-crossing (within the bunch filling scheme) --- .../SimulationDataFormat/InteractionSampler.h | 21 ++++++++++-- .../simulation/src/InteractionSampler.cxx | 18 ++++++++++ .../simulation/src/SimulationDataLinkDef.h | 1 + Steer/src/CollisionContextTool.cxx | 33 ++++++++++++++----- 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/InteractionSampler.h b/DataFormats/simulation/include/SimulationDataFormat/InteractionSampler.h index 13fe099aa344a..d2ccec147cc4f 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/InteractionSampler.h +++ b/DataFormats/simulation/include/SimulationDataFormat/InteractionSampler.h @@ -67,7 +67,7 @@ class InteractionSampler void print() const; protected: - int simulateInteractingBC(); + virtual int simulateInteractingBC(); void nextCollidingBC(int n); o2::math_utils::RandomRing<10000> mBCJumpGenerator; // generator of random jumps in BC @@ -89,7 +89,7 @@ class InteractionSampler static constexpr float DefIntRate = 50e3; ///< default interaction rate - ClassDefNV(InteractionSampler, 1); + ClassDef(InteractionSampler, 1); }; //_________________________________________________ @@ -113,6 +113,23 @@ inline void InteractionSampler::nextCollidingBC(int n) mIR.bc = mInteractingBCs[mCurrBCIdx]; } +// Special case of InteractionSampler without actual sampling. +// Engineers interaction sequence by putting one in each N-th BC with multiplicity mult. +class FixedSkipBC_InteractionSampler : public InteractionSampler +{ + + public: + FixedSkipBC_InteractionSampler(int every_n, int mult) : mEveryN{every_n}, mMultiplicity{mult}, InteractionSampler() {} + + protected: + int simulateInteractingBC() override; + + private: + int mEveryN; // the skip number ---> fills every N-th BC in the bunch filling scheme + int mMultiplicity; // how many events to put if bc is filled + ClassDef(FixedSkipBC_InteractionSampler, 1); +}; + } // namespace steer } // namespace o2 diff --git a/DataFormats/simulation/src/InteractionSampler.cxx b/DataFormats/simulation/src/InteractionSampler.cxx index 1936bf7dc06a9..5e14e22e5f8db 100644 --- a/DataFormats/simulation/src/InteractionSampler.cxx +++ b/DataFormats/simulation/src/InteractionSampler.cxx @@ -130,6 +130,24 @@ int InteractionSampler::simulateInteractingBC() return ncoll; } +//_________________________________________________ +int FixedSkipBC_InteractionSampler::simulateInteractingBC() +{ + // Returns number of collisions assigned to selected BC + + nextCollidingBC(mEveryN); // we jump regular intervals + int ncoll = mMultiplicity; // well defined pileup + + // assign random time withing a bunch + for (int i = ncoll; i--;) { + mTimeInBC.push_back(mCollTimeGenerator.getNextValue()); + } + if (ncoll > 1) { // sort in DECREASING time order (we are reading vector from the end) + std::sort(mTimeInBC.begin(), mTimeInBC.end(), [](const float a, const float b) { return a > b; }); + } + return ncoll; +} + //_________________________________________________ void InteractionSampler::setBunchFilling(const std::string& bcFillingFile) { diff --git a/DataFormats/simulation/src/SimulationDataLinkDef.h b/DataFormats/simulation/src/SimulationDataLinkDef.h index 8a1e0c536c089..15abe9d50390f 100644 --- a/DataFormats/simulation/src/SimulationDataLinkDef.h +++ b/DataFormats/simulation/src/SimulationDataLinkDef.h @@ -24,6 +24,7 @@ #pragma link off all functions; #pragma link C++ class o2::steer::InteractionSampler + ; +#pragma link C++ class o2::steer::FixedSkipBC_InteractionSampler + ; #pragma link C++ class o2::sim::StackParam + ; #pragma link C++ class o2::conf::ConfigurableParamHelper < o2::sim::StackParam> + ; #pragma link C++ class o2::MCTrackT < double> + ; diff --git a/Steer/src/CollisionContextTool.cxx b/Steer/src/CollisionContextTool.cxx index 6dffdc921d651..e2f7c0fce3d67 100644 --- a/Steer/src/CollisionContextTool.cxx +++ b/Steer/src/CollisionContextTool.cxx @@ -302,17 +302,34 @@ int main(int argc, char* argv[]) for (int id = 0; id < ispecs.size(); ++id) { auto mode = ispecs[id].syncmode; if (mode == InteractionLockMode::NOLOCK) { - o2::steer::InteractionSampler sampler; - sampler.setInteractionRate(ispecs[id].interactionRate); + auto sampler = std::make_unique(); + + // for debug purposes: allows to instantiate trivial sampler + if (const char* env = getenv("ALICEO2_ENFORCE_TRIVIAL_BC_SAMPLER")) { + std::string spec(env); + std::regex re(R"((\d+):(\d+))"); + std::smatch match; + int every_n = 1, mult = 1; + if (std::regex_match(spec, match, re)) { + every_n = std::stoi(match[1]); + mult = std::stoi(match[2]); + } else { + LOG(error) << "ALICEO2_ENFORCE_TRIVIAL_BC_SAMPLER format invalid, expected NUMBER_1:NUMBER_2"; + exit(1); + } + sampler.reset(new o2::steer::FixedSkipBC_InteractionSampler(every_n, mult)); + } + + sampler->setInteractionRate(ispecs[id].interactionRate); if (!options.bcpatternfile.empty()) { - setBCFillingHelper(sampler, options.bcpatternfile); + setBCFillingHelper(*sampler, options.bcpatternfile); } o2::InteractionTimeRecord record; // this loop makes sure that the first collision is within the range of orbits asked (if noEmptyTF is enabled) do { - sampler.setFirstIR(o2::InteractionRecord(options.firstBC, orbitstart)); - sampler.init(); - record = sampler.generateCollisionTime(); + sampler->setFirstIR(o2::InteractionRecord(options.firstBC, orbitstart)); + sampler->init(); + record = sampler->generateCollisionTime(); } while (options.noEmptyTF && usetimeframelength && record.orbit >= orbitstart + orbits_total); int count = 0; do { @@ -325,7 +342,7 @@ int main(int argc, char* argv[]) std::pair> insertvalue(record, parts); auto iter = std::lower_bound(collisions.begin(), collisions.end(), insertvalue, [](std::pair> const& a, std::pair> const& b) { return a.first < b.first; }); collisions.insert(iter, insertvalue); - record = sampler.generateCollisionTime(); + record = sampler->generateCollisionTime(); count++; } while ((ispecs[id].mcnumberasked > 0 && count < ispecs[id].mcnumberasked)); // TODO: this loop should probably be replaced by a condition with usetimeframelength and number of orbits @@ -360,7 +377,7 @@ int main(int argc, char* argv[]) } // keep bunch filling information produced by these samplers - bunchFillings.push_back(sampler.getBunchFilling()); + bunchFillings.push_back(sampler->getBunchFilling()); } else { // we are in some lock/sync mode and modify existing collisions From fe8111b67df30bbec6be873c5bd221a724b1ae91 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 16 Jun 2025 10:08:35 +0200 Subject: [PATCH 032/315] GPU CUDA CMake: Do not print warnings that architectures will be depreacted --- GPU/GPUTracking/Base/cuda/CMakeLists.txt | 4 ++-- dependencies/FindO2GPU.cmake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Base/cuda/CMakeLists.txt b/GPU/GPUTracking/Base/cuda/CMakeLists.txt index 0e9831e26d494..7f595b28a582a 100644 --- a/GPU/GPUTracking/Base/cuda/CMakeLists.txt +++ b/GPU/GPUTracking/Base/cuda/CMakeLists.txt @@ -70,8 +70,8 @@ add_custom_command( COMMAND cp ${GPUDIR}/Base/GPUStdSystemHeaders.h ${GPU_RTC_BIN}.src COMMAND cat ${GPUDIR}/Base/cuda/GPUReconstructionCUDAIncludesSystem.h | grep -v GPUStdSystemHeaders.h >> ${GPU_RTC_BIN}.src COMMAND cat ${GPUDIR}/Base/GPUStdSystemHeaders.h >> ${GPU_RTC_BIN}.src - COMMAND ${CMAKE_CUDA_COMPILER} ${GPU_RTC_DEFINES} ${GPU_RTC_INCLUDES} -std=c++${CMAKE_CUDA_STANDARD} -D__CUDA_ARCH__=${RTC_CUDA_ARCH} -D__CUDACC__ -x c++ -M -MD -MT ${GPU_RTC_BIN}.src -MF ${GPU_RTC_BIN}.src.d ${GPU_RTC_SRC} - COMMAND ${CMAKE_CUDA_COMPILER} ${GPU_RTC_DEFINES} ${GPU_RTC_INCLUDES} -std=c++${CMAKE_CUDA_STANDARD} -D__CUDA_ARCH__=${RTC_CUDA_ARCH} -D__CUDACC__ -x c++ -E -Xcompiler "-nostdinc -P" ${GPU_RTC_SRC} >> ${GPU_RTC_BIN}.src + COMMAND ${CMAKE_CUDA_COMPILER} ${GPU_RTC_DEFINES} ${GPU_RTC_INCLUDES} -std=c++${CMAKE_CUDA_STANDARD} -D__CUDA_ARCH__=${RTC_CUDA_ARCH} -Wno-deprecated-gpu-targets -D__CUDACC__ -x c++ -M -MD -MT ${GPU_RTC_BIN}.src -MF ${GPU_RTC_BIN}.src.d ${GPU_RTC_SRC} + COMMAND ${CMAKE_CUDA_COMPILER} ${GPU_RTC_DEFINES} ${GPU_RTC_INCLUDES} -std=c++${CMAKE_CUDA_STANDARD} -D__CUDA_ARCH__=${RTC_CUDA_ARCH} -Wno-deprecated-gpu-targets -D__CUDACC__ -x c++ -E -Xcompiler "-nostdinc -P" ${GPU_RTC_SRC} >> ${GPU_RTC_BIN}.src DEPENDS ${GPU_RTC_SRC} ${GPUDIR}/Base/GPUStdSystemHeaders.h ${GPUDIR}/Base/cuda/GPUReconstructionCUDAIncludesSystem.h ${GPUDIR}/Base/GPUStdSystemHeaders.h DEPFILE ${GPU_RTC_BIN}.src.d COMMAND_EXPAND_LISTS diff --git a/dependencies/FindO2GPU.cmake b/dependencies/FindO2GPU.cmake index f9c549905f178..633d1220575db 100644 --- a/dependencies/FindO2GPU.cmake +++ b/dependencies/FindO2GPU.cmake @@ -148,7 +148,7 @@ if(ENABLE_CUDA) endif() endif() if(CMAKE_CUDA_COMPILER) - set(CMAKE_CUDA_FLAGS "-Xcompiler \"${O2_GPU_CMAKE_CXX_FLAGS_NOSTD}\" ${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr --extended-lambda -Xcompiler -Wno-attributes ${GPUCA_CUDA_DENORMALS_FLAGS}") + set(CMAKE_CUDA_FLAGS "-Xcompiler \"${O2_GPU_CMAKE_CXX_FLAGS_NOSTD}\" ${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr --extended-lambda -Xcompiler -Wno-attributes -Wno-deprecated-gpu-targets ${GPUCA_CUDA_DENORMALS_FLAGS}") set(CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "-Xcompiler \"${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}\" ${CMAKE_CUDA_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}") if(GPUCA_KERNEL_RESOURCE_USAGE_VERBOSE) string(APPEND CMAKE_CUDA_FLAGS " -Xptxas -v") From d449a51ab3a69fd9f5d41a0c5fff74d9b1b8be9e Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Mon, 16 Jun 2025 14:16:39 +0200 Subject: [PATCH 033/315] DataModel: remove unsupported classes (#14400) The code in question conflicts with the modern / standardized specification of std::pmr where the polymorphic_allocators cannot be moved. Given we are not actually using those classes in any case, I am removing them. If we will need the functionality in the future, we will in any case need to reimplement / rethink / verify them. --- .../include/MemoryResources/MemoryResources.h | 167 ------------------ .../test/testMemoryResources.cxx | 76 -------- 2 files changed, 243 deletions(-) diff --git a/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h b/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h index eba309e38ad83..b52f5c715575e 100644 --- a/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h +++ b/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h @@ -111,162 +111,6 @@ class MessageResource : public FairMQMemoryResource } }; -//__________________________________________________________________________________________________ -// A spectator pmr memory resource which only watches the memory of the underlying buffer, does not -// carry out real allocation. It owns the underlying buffer which is destroyed on deallocation. -template -class SpectatorMemoryResource : public fair::mq::pmr::memory_resource -{ - public: - using buffer_type = BufferType; - - SpectatorMemoryResource() noexcept = delete; - SpectatorMemoryResource(const SpectatorMemoryResource&) noexcept = delete; - SpectatorMemoryResource(SpectatorMemoryResource&&) noexcept = default; - SpectatorMemoryResource& operator=(const SpectatorMemoryResource&) = delete; - SpectatorMemoryResource& operator=(SpectatorMemoryResource&&) = default; - ~SpectatorMemoryResource() noexcept override = default; - - // the resource is the pointer managed by unique_ptr - template - SpectatorMemoryResource(std::unique_ptr&& buffer, size_t size) - : mBuffer{std::move(buffer)}, mPointer{mBuffer.get()}, mSize{size} - { - } - - // the resource is the data of the vector managed by unique ptr - template - SpectatorMemoryResource(std::unique_ptr, typename buffer_type::deleter_type>&& buffer) - : mBuffer{std::move(buffer)}, mPointer{mBuffer->data()}, mSize{mBuffer->size() * sizeof(T)} - { - } - - // TODO: the underlying resource can be directly the vector or the read only buffer - protected: - void* do_allocate(std::size_t bytes, std::size_t /*alignment*/) override - { - if (mSize > 0) { - if (bytes > mSize) { - throw std::bad_alloc(); - } - mSize = 0; - return mPointer; - } - throw std::runtime_error("Can not allocate: this memory resource is only supposed to provide spectator access to external buffer"); - } - - void do_deallocate(void* p, std::size_t /*bytes*/, std::size_t /*alignment*/) override - { - if (p == mPointer) { - mBuffer.reset(); - mPointer = nullptr; - } else if (mPointer == nullptr) { - // there is an error in the logic flow, this should never be called more than once - throw std::logic_error("underlying controlled resource has been released already"); - } else { - throw std::logic_error("this resource can only deallocate the controlled resource pointer"); - } - } - bool do_is_equal(const memory_resource& /*other*/) const noexcept override - { - // uniquely owns the underlying resource, can never be equal to any other instance - return false; - } - - private: - buffer_type mBuffer; - void* mPointer = nullptr; - size_t mSize = 0; -}; - -//__________________________________________________________________________________________________ -// This in general (as in STL) is a bad idea, but here it is safe to inherit from an allocator since we -// have no additional data and only override some methods so we don't get into slicing and other problems. -template -class SpectatorAllocator : public fair::mq::pmr::polymorphic_allocator -{ - public: - using fair::mq::pmr::polymorphic_allocator::polymorphic_allocator; - using propagate_on_container_move_assignment = std::true_type; - - // skip default construction of empty elements - // this is important for two reasons: one: it allows us to adopt an existing buffer (e.g. incoming message) and - // quickly construct large vectors while skipping the element initialization. - template - void construct(U*) - { - } - - // dont try to call destructors, makes no sense since resource is managed externally AND allowed - // types cannot have side effects - template - void destroy(U*) - { - } - - T* allocate(size_t size) { return reinterpret_cast(this->resource()->allocate(size * sizeof(T), 64)); } - void deallocate(T* ptr, size_t size) - { - this->resource()->deallocate(const_cast::type*>(ptr), size); - } -}; - -//__________________________________________________________________________________________________ -/// This allocator has a pmr-like interface, but keeps the unique MessageResource as internal state, -/// allowing full resource (associated message) management internally without any global state. -template -class OwningMessageSpectatorAllocator -{ - public: - using value_type = T; - - MessageResource mResource; - - OwningMessageSpectatorAllocator() noexcept = default; - OwningMessageSpectatorAllocator(const OwningMessageSpectatorAllocator&) noexcept = default; - OwningMessageSpectatorAllocator(OwningMessageSpectatorAllocator&&) noexcept = default; - OwningMessageSpectatorAllocator(MessageResource&& resource) noexcept : mResource{resource} {} - - template - OwningMessageSpectatorAllocator(const OwningMessageSpectatorAllocator& other) noexcept : mResource(other.mResource) - { - } - - OwningMessageSpectatorAllocator& operator=(const OwningMessageSpectatorAllocator& other) - { - mResource = other.mResource; - return *this; - } - - OwningMessageSpectatorAllocator select_on_container_copy_construction() const - { - return OwningMessageSpectatorAllocator(); - } - - fair::mq::pmr::memory_resource* resource() { return &mResource; } - - // skip default construction of empty elements - // this is important for two reasons: one: it allows us to adopt an existing buffer (e.g. incoming message) and - // quickly construct large vectors while skipping the element initialization. - template - void construct(U*) - { - } - - // dont try to call destructors, makes no sense since resource is managed externally AND allowed - // types cannot have side effects - template - void destroy(U*) - { - } - - T* allocate(size_t size) { return reinterpret_cast(mResource.allocate(size * sizeof(T), 64)); } - void deallocate(T* ptr, size_t size) - { - mResource.deallocate(const_cast::type*>(ptr), size); - } -}; - // The NoConstructAllocator behaves like the normal pmr vector but does not call constructors / destructors template class NoConstructAllocator : public fair::mq::pmr::polymorphic_allocator @@ -301,21 +145,10 @@ class NoConstructAllocator : public fair::mq::pmr::polymorphic_allocator //__________________________________________________________________________________________________ //__________________________________________________________________________________________________ -using ByteSpectatorAllocator = SpectatorAllocator; using BytePmrAllocator = fair::mq::pmr::polymorphic_allocator; template using vector = std::vector>; -//__________________________________________________________________________________________________ -/// Return a std::vector spanned over the contents of the message, takes ownership of the message -template -auto adoptVector(size_t nelem, fair::mq::MessagePtr message) -{ - static_assert(std::is_trivially_destructible::value); - return std::vector>( - nelem, OwningMessageSpectatorAllocator(MessageResource{std::move(message)})); -}; - //__________________________________________________________________________________________________ /// Get the allocator associated to a transport factory inline static FairMQMemoryResource* getTransportAllocator(fair::mq::TransportFactory* factory) diff --git a/DataFormats/MemoryResources/test/testMemoryResources.cxx b/DataFormats/MemoryResources/test/testMemoryResources.cxx index 6bbafa3a82f4f..a49cd00d75255 100644 --- a/DataFormats/MemoryResources/test/testMemoryResources.cxx +++ b/DataFormats/MemoryResources/test/testMemoryResources.cxx @@ -88,15 +88,6 @@ BOOST_AUTO_TEST_CASE(allocator_test) } testData::nconstructions = 0; - { - std::vector> v(SpectatorAllocator{allocZMQ}); - v.reserve(3); - BOOST_CHECK(allocZMQ->getNumberOfMessages() == 1); - v.emplace_back(1); - v.emplace_back(2); - v.emplace_back(3); - BOOST_CHECK(testData::nconstructions == 3); - } BOOST_CHECK(allocZMQ->getNumberOfMessages() == 0); } @@ -147,73 +138,6 @@ BOOST_AUTO_TEST_CASE(getMessage_test) messageArray = static_cast(message->GetData()); BOOST_CHECK(messageArray[0] == 4 && messageArray[1] == 5 && messageArray[2] == 6); - { - std::vector> v(SpectatorAllocator{allocSHM}); - } -} - -BOOST_AUTO_TEST_CASE(adoptVector_test) -{ - size_t session{(size_t)getpid() * 1000 + 3}; - fair::mq::ProgOptions config; - config.SetProperty("session", std::to_string(session)); - - auto factoryZMQ = fair::mq::TransportFactory::CreateTransportFactory("zeromq"); - auto factorySHM = fair::mq::TransportFactory::CreateTransportFactory("shmem", "adoptVector_test", &config); - auto allocZMQ = getTransportAllocator(factoryZMQ.get()); - auto allocSHM = getTransportAllocator(factorySHM.get()); - - testData::nconstructions = 0; - - // Create a bogus message - auto message = factoryZMQ->CreateMessage(3 * sizeof(testData)); - auto messageAddr = message.get(); - testData tmpBuf[3] = {3, 2, 1}; - std::memcpy(message->GetData(), tmpBuf, 3 * sizeof(testData)); - - auto adoptedOwner = adoptVector(3, std::move(message)); - BOOST_CHECK(adoptedOwner[0].i == 3); - BOOST_CHECK(adoptedOwner[1].i == 2); - BOOST_CHECK(adoptedOwner[2].i == 1); - - auto reclaimedMessage = o2::pmr::getMessage(std::move(adoptedOwner)); - BOOST_CHECK(reclaimedMessage.get() == messageAddr); - BOOST_CHECK(adoptedOwner.size() == 0); - - auto modified = adoptVector(3, std::move(reclaimedMessage)); - modified.emplace_back(9); - BOOST_CHECK(modified[3].i == 9); - BOOST_CHECK(modified.size() == 4); - BOOST_CHECK(testData::nconstructions == 7); - auto modifiedMessage = getMessage(std::move(modified)); - BOOST_CHECK(modifiedMessage != nullptr); - BOOST_CHECK(modifiedMessage.get() != messageAddr); -} - -BOOST_AUTO_TEST_CASE(test_SpectatorMemoryResource) -{ - constexpr int size = 5; - auto buffer = std::make_unique(size); - auto const* bufferdata = buffer.get(); - SpectatorMemoryResource resource(std::move(buffer), size * sizeof(int)); - std::vector> bufferclone(size, o2::pmr::SpectatorAllocator(&resource)); - BOOST_CHECK(bufferclone.data() == bufferdata); - BOOST_CHECK(bufferclone.size() == size); - BOOST_CHECK_THROW(bufferclone.resize(2 * size), std::runtime_error); - - auto vecbuf = std::make_unique>(size); - auto const* vectordata = vecbuf->data(); - SpectatorMemoryResource vecresource(std::move(vecbuf)); - std::vector> vecclone(size, o2::pmr::SpectatorAllocator(&vecresource)); - BOOST_CHECK(vecclone.data() == vectordata); - BOOST_CHECK(vecclone.size() == size); - BOOST_CHECK_THROW(vecclone.resize(2 * size), std::runtime_error); - - std::vector> vecmove; - vecmove = std::move(vecclone); - BOOST_CHECK(vecclone.size() == 0); - BOOST_CHECK(vecmove.data() == vectordata); - BOOST_CHECK(vecmove.size() == size); } }; // namespace o2::pmr From aaa0cf536b309262cf03ed50fefc55c84e836ae0 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 13 Jun 2025 14:37:42 +0200 Subject: [PATCH 034/315] Make TPC resid.extracton to work in runs w/o TRD or TOF --- .../TPC/calibration/SpacePoints/src/TrackInterpolation.cxx | 2 +- prodtests/full-system-test/calib-workflow.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx index 7c2110fd5b4e7..d13f24ad728fd 100644 --- a/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx +++ b/Detectors/TPC/calibration/SpacePoints/src/TrackInterpolation.cxx @@ -148,7 +148,7 @@ void TrackInterpolation::prepareInputTrackSample(const o2::globaltracking::RecoC auto trackIndex = mRecoCont->getPrimaryVertexMatchedTracks(); // Global ID's for associated tracks auto vtxRefs = mRecoCont->getPrimaryVertexMatchedTrackRefs(); // references from vertex to these track IDs int nv = vtxRefs.size() - 1; - GTrackID::mask_t allowedSources = GTrackID::getSourcesMask("ITS-TPC,ITS-TPC-TRD,ITS-TPC-TOF,ITS-TPC-TRD-TOF"); + GTrackID::mask_t allowedSources = GTrackID::getSourcesMask("ITS-TPC,ITS-TPC-TRD,ITS-TPC-TOF,ITS-TPC-TRD-TOF") & mSourcesConfigured; constexpr std::array SrcFast = {int(GTrackID::ITSTPCTRD), int(GTrackID::ITSTPCTOF), int(GTrackID::ITSTPCTRDTOF)}; for (int iv = 0; iv < nv; iv++) { diff --git a/prodtests/full-system-test/calib-workflow.sh b/prodtests/full-system-test/calib-workflow.sh index 3dcd95fd04b54..94e95eaab6567 100755 --- a/prodtests/full-system-test/calib-workflow.sh +++ b/prodtests/full-system-test/calib-workflow.sh @@ -23,7 +23,7 @@ fi if [[ "${CALIB_TPC_SCDCALIB_SENDTRKDATA:-}" == "1" ]]; then ENABLE_TRKDATA_OUTPUT="--send-track-data"; else ENABLE_TRKDATA_OUTPUT=""; fi # specific calibration workflows -if [[ $CALIB_TPC_SCDCALIB == 1 ]]; then add_W o2-tpc-scdcalib-interpolation-workflow "--vtx-sources $VERTEX_TRACK_MATCHING_SOURCES ${CALIB_TPC_SCDCALIB_SLOTLENGTH:+"--sec-per-slot $CALIB_TPC_SCDCALIB_SLOTLENGTH"} $ENABLE_TRKDATA_OUTPUT $DISABLE_ROOT_OUTPUT --disable-root-input --pipeline $(get_N tpc-track-interpolation TPC REST)"; fi +if [[ $CALIB_TPC_SCDCALIB == 1 ]]; then add_W o2-tpc-scdcalib-interpolation-workflow "--vtx-sources $VERTEX_TRACK_MATCHING_SOURCES --tracking-sources $TRACK_SOURCES ${CALIB_TPC_SCDCALIB_SLOTLENGTH:+"--sec-per-slot $CALIB_TPC_SCDCALIB_SLOTLENGTH"} $ENABLE_TRKDATA_OUTPUT $DISABLE_ROOT_OUTPUT --disable-root-input --pipeline $(get_N tpc-track-interpolation TPC REST)"; fi if [[ $CALIB_TPC_TIMEGAIN == 1 ]]; then : ${SCALEEVENTS_TPC_TIMEGAIN:=40} : ${SCALETRACKS_TPC_TIMEGAIN:=1000} From 9ca2abd0972e87c6193c0bd1543031d4670f3cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Mon, 16 Jun 2025 20:40:31 +0200 Subject: [PATCH 035/315] [ALICE3] Add Copper stabilizers for A3 Magnet (#14410) --- .../Upgrades/ALICE3/Passive/CMakeLists.txt | 2 + .../Alice3DetectorsPassive/PassiveBaseParam.h | 43 +++++++++++++++++++ .../Upgrades/ALICE3/Passive/src/Magnet.cxx | 33 +++++++++++--- .../ALICE3/Passive/src/PassiveBaseParam.cxx | 13 ++++++ .../ALICE3/Passive/src/PassiveLinkDef.h | 1 + 5 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/PassiveBaseParam.h create mode 100644 Detectors/Upgrades/ALICE3/Passive/src/PassiveBaseParam.cxx diff --git a/Detectors/Upgrades/ALICE3/Passive/CMakeLists.txt b/Detectors/Upgrades/ALICE3/Passive/CMakeLists.txt index 2689130c495d9..2bd732dfe3b31 100644 --- a/Detectors/Upgrades/ALICE3/Passive/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/Passive/CMakeLists.txt @@ -12,6 +12,7 @@ o2_add_library(Alice3DetectorsPassive SOURCES src/Pipe.cxx src/PassiveBase.cxx + src/PassiveBaseParam.cxx src/Absorber.cxx src/Magnet.cxx PUBLIC_LINK_LIBRARIES O2::Field O2::DetectorsBase O2::SimConfig) @@ -19,6 +20,7 @@ o2_add_library(Alice3DetectorsPassive o2_target_root_dictionary(Alice3DetectorsPassive HEADERS include/Alice3DetectorsPassive/Pipe.h include/Alice3DetectorsPassive/PassiveBase.h + include/Alice3DetectorsPassive/PassiveBaseParam.h include/Alice3DetectorsPassive/Absorber.h include/Alice3DetectorsPassive/Magnet.h LINKDEF src/PassiveLinkDef.h) diff --git a/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/PassiveBaseParam.h b/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/PassiveBaseParam.h new file mode 100644 index 0000000000000..3ac53c1bfb92b --- /dev/null +++ b/Detectors/Upgrades/ALICE3/Passive/include/Alice3DetectorsPassive/PassiveBaseParam.h @@ -0,0 +1,43 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef ALICEO2_PASSIVE_BASEPARAM_H_ +#define ALICEO2_PASSIVE_BASEPARAM_H_ + +#include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/ConfigurableParamHelper.h" + +namespace o2 +{ +namespace passive +{ + +// ** +// ** Parameters for Passive base configuration +// ** + +enum MagnetLayout : int { + AluminiumStabilizer = 0, + CopperStabilizer = 1 +}; + +struct Alice3PassiveBaseParam : public o2::conf::ConfigurableParamHelper { + // Geometry Builder parameters + + int mLayout = MagnetLayout::AluminiumStabilizer; + + O2ParamDef(Alice3PassiveBaseParam, "Alice3PassiveBase"); +}; + +} // namespace passive +} // end namespace o2 + +#endif // ALICEO2_PASSIVE_BASEPARAM_H_ diff --git a/Detectors/Upgrades/ALICE3/Passive/src/Magnet.cxx b/Detectors/Upgrades/ALICE3/Passive/src/Magnet.cxx index 3e3e6590720cf..5c94c3e31a244 100644 --- a/Detectors/Upgrades/ALICE3/Passive/src/Magnet.cxx +++ b/Detectors/Upgrades/ALICE3/Passive/src/Magnet.cxx @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -54,11 +55,24 @@ void Alice3Magnet::createMaterials() // | Support cylinder | 20 | 8.896 | 0.225 | // | Al-strip | 1 | 8.896 | 0.011 | // | NbTi/Cu | 3 | 1.598 | 0.188 | - // | Insulation | 11 | 17.64 | 0.062 | + // | Insulation | 11 | 17.64 | 0.062 | // | Al-stabiliser | 33 | 8.896 | 0.371 | // | Inner cryostat | 10 | 8.896 | 0.112 | // | Outer cryostat | 30 | 8.896 | 0.337 | // +------------------+-------------------------+----------+--------+ + // Update: 2025-06-16 enabledby setting Alice3PassiveBase.mLayout=1 + // +------------------+-------------------------+----------+--------+ + // | layer | effective thickness [mm]| X0 [cm] | X0 [%] | + // +------------------+-------------------------+----------+--------+ + // | Support cylinder | 20 | 8.896 | 0.225 | + // | Al-strip | 1 | 8.896 | 0.011 | + // | NbTi/Cu | 3 | 1.598 | 0.188 | + // | Insulation | 11 | 17.64 | 0.062 | + // | Cu-stabiliser | 22 | 1.436 | 1.532 | + // | Inner cryostat | 10 | 8.896 | 0.112 | + // | Outer cryostat | 30 | 8.896 | 0.337 | + // | total | | | 2.468 | + // +------------------+-------------------------+----------+--------+ // Geometry will be oversimplified in two wrapping cylindrical Al layers (symmetric for the time being) with a Copper layer in between. // @@ -90,6 +104,15 @@ void Alice3Magnet::ConstructGeometry() { createMaterials(); + // Passive Base configuration parameters + auto& passiveBaseParam = Alice3PassiveBaseParam::Instance(); + const bool doCopperStabilizer = (passiveBaseParam.mLayout == o2::passive::MagnetLayout::CopperStabilizer); + if (doCopperStabilizer) { + mRestMaterialThickness -= 3.3; // cm Remove the Aluminium stabiliser + mRestMaterialThickness += 2.2; // cm Add the Copper stabiliser + LOG(debug) << "Alice 3 magnet: using Copper Stabilizer with thickness " << mRestMaterialThickness << " cm"; + } + TGeoManager* geoManager = gGeoManager; TGeoVolume* barrel = geoManager->GetVolume("barrel"); if (!barrel) { @@ -102,22 +125,22 @@ void Alice3Magnet::ConstructGeometry() auto kMedVac = matmgr.getTGeoMedium("ALICE3_MAGNET_VACUUM"); // inner wrap - LOGP(debug, "Alice 3 magnet: creating inner wrap with inner radius {} and thickness {}", mInnerWrapInnerRadius, mInnerWrapThickness); + LOGP(debug, "Alice 3 magnet: creating inner wrap with inner radius {} cm and thickness {} cm", mInnerWrapInnerRadius, mInnerWrapThickness); TGeoTube* innerLayer = new TGeoTube(mInnerWrapInnerRadius, mInnerWrapInnerRadius + mInnerWrapThickness, mZLength / 2); TGeoTube* innerVacuum = new TGeoTube(mInnerWrapInnerRadius + mInnerWrapThickness, mCoilInnerRadius, mZLength / 2); // coils layer - LOGP(debug, "Alice 3 magnet: creating coils layer with inner radius {} and thickness {}", mCoilInnerRadius, mCoilThickness); + LOGP(debug, "Alice 3 magnet: creating coils layer with inner radius {} cm and thickness {} cm", mCoilInnerRadius, mCoilThickness); TGeoTube* coilsLayer = new TGeoTube(mCoilInnerRadius, mCoilInnerRadius + mCoilThickness, mZLength / 2); TGeoTube* restMaterial = new TGeoTube(mRestMaterialRadius, mRestMaterialRadius + mRestMaterialThickness, mZLength / 2); TGeoTube* outerVacuum = new TGeoTube(mRestMaterialRadius + mRestMaterialThickness, mOuterWrapInnerRadius, mZLength / 2); // outer wrap - LOGP(debug, "Alice 3 magnet: creating outer wrap with inner radius {} and thickness {}", mOuterWrapInnerRadius, mOuterWrapThickness); + LOGP(debug, "Alice 3 magnet: creating outer wrap with inner radius {} cm and thickness {} cm", mOuterWrapInnerRadius, mOuterWrapThickness); TGeoTube* outerLayer = new TGeoTube(mOuterWrapInnerRadius, mOuterWrapInnerRadius + mOuterWrapThickness, mZLength / 2); TGeoVolume* innerWrapVol = new TGeoVolume("innerWrap", innerLayer, kMedAl); TGeoVolume* innerVacuumVol = new TGeoVolume("innerVacuum", innerVacuum, kMedVac); TGeoVolume* coilsVol = new TGeoVolume("coils", coilsLayer, kMedCu); - TGeoVolume* restMaterialVol = new TGeoVolume("restMaterial", restMaterial, kMedAl); + TGeoVolume* restMaterialVol = new TGeoVolume("restMaterial", restMaterial, doCopperStabilizer ? kMedCu : kMedAl); TGeoVolume* outerVacuumVol = new TGeoVolume("outerVacuum", outerVacuum, kMedVac); TGeoVolume* outerWrapVol = new TGeoVolume("outerWrap", outerLayer, kMedAl); diff --git a/Detectors/Upgrades/ALICE3/Passive/src/PassiveBaseParam.cxx b/Detectors/Upgrades/ALICE3/Passive/src/PassiveBaseParam.cxx new file mode 100644 index 0000000000000..6b6a6191f0bf5 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/Passive/src/PassiveBaseParam.cxx @@ -0,0 +1,13 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Alice3DetectorsPassive/PassiveBaseParam.h" +O2ParamImpl(o2::passive::Alice3PassiveBaseParam); diff --git a/Detectors/Upgrades/ALICE3/Passive/src/PassiveLinkDef.h b/Detectors/Upgrades/ALICE3/Passive/src/PassiveLinkDef.h index daac6de56a124..803d308671536 100644 --- a/Detectors/Upgrades/ALICE3/Passive/src/PassiveLinkDef.h +++ b/Detectors/Upgrades/ALICE3/Passive/src/PassiveLinkDef.h @@ -16,6 +16,7 @@ #pragma link off all functions; #pragma link C++ class o2::passive::Alice3PassiveBase + ; +#pragma link C++ class o2::passive::Alice3PassiveBaseParam + ; #pragma link C++ class o2::passive::Alice3Pipe + ; #pragma link C++ class o2::passive::Alice3Absorber + ; #pragma link C++ class o2::passive::Alice3Magnet + ; From 0bbb3da1f6f0ef498ac992f40d09c5d8d3e24a83 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 17 Jun 2025 06:25:11 +0200 Subject: [PATCH 036/315] ITS: fix clusterSize propagation (#14412) --- Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx index dbb1631a4eb10..1a3132413c450 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx @@ -180,7 +180,7 @@ int TimeFrame::loadROFrameData(gsl::span rofs, locXYZ = dict->getClusterCoordinates(c, patt, false); clusterSize = patt.getNPixels(); } - mClusterSize.push_back(std::clamp(clusterSize, 0u, 255u)); + mClusterSize[clusterId] = std::clamp(clusterSize, 0u, 255u); auto sensorID = c.getSensorID(); // Inverse transformation to the local --> tracking auto trkXYZ = geom->getMatrixT2L(sensorID) ^ locXYZ; From d1fa18a7e41cfbc59840eab174bc9e07981feb59 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Tue, 17 Jun 2025 10:31:31 +0200 Subject: [PATCH 037/315] [EMCAL-1154] Adjust CellLabels for cross talk emulation (#14385) - The CellLabel class used gsl::span as its members to store the mcLabels and amplitude fractions. However, when we want to use the cross talk emulation, we want to add new cells which happens inside the cross talk emulation function. Outside of this function the newley added CellLabels would point to dangling memory. That's why the members needed to be changed to std::vectors. Also a move constructor was added. --- .../EMCAL/include/DataFormatsEMCAL/CellLabel.h | 18 ++++++++++++------ DataFormats/Detectors/EMCAL/src/CellLabel.cxx | 11 ++++++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CellLabel.h b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CellLabel.h index 81766a3a59cdc..543e49fb06dd8 100644 --- a/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CellLabel.h +++ b/DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/CellLabel.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace o2 { @@ -34,10 +35,15 @@ class CellLabel public: // CellLabel() = default; - /// \brief Constructor + /// \brief Constructor using std::vector by moving NOT copying /// \param labels list of mc labels /// \param amplitudeFractions list of amplitude fractions - CellLabel(const gsl::span labels, const gsl::span amplitudeFractions); + CellLabel(std::vector labels, std::vector amplitudeFractions); + + /// \brief Constructor using gsl::span + /// \param labels list of mc labels + /// \param amplitudeFractions list of amplitude fractions + CellLabel(gsl::span labels, gsl::span amplitudeFractions); // ~CellLabel() = default; // CellLabel(const CellLabel& clus) = default; @@ -52,21 +58,21 @@ class CellLabel int32_t GetLabel(size_t index) const { return mLabels[index]; } /// \brief Getter for labels - gsl::span GetLabels() const { return mLabels; } + std::vector GetLabels() const { return mLabels; } /// \brief Getter for amplitude fraction /// \param index index which amplitude fraction to get float GetAmplitudeFraction(size_t index) const { return mAmplitudeFraction[index]; } /// \brief Getter for amplitude fractions - gsl::span GetAmplitudeFractions() const { return mAmplitudeFraction; } + std::vector GetAmplitudeFractions() const { return mAmplitudeFraction; } /// \brief Getter for label with leading amplitude fraction int32_t GetLeadingMCLabel() const; protected: - gsl::span mLabels; ///< List of MC particles that generated the cluster, ordered in deposited energy. - gsl::span mAmplitudeFraction; ///< List of the fraction of the cell energy coming from a MC particle. Index aligns with mLabels! + std::vector mLabels; ///< List of MC particles that generated the cluster, ordered in deposited energy. + std::vector mAmplitudeFraction; ///< List of the fraction of the cell energy coming from a MC particle. Index aligns with mLabels! }; } // namespace emcal diff --git a/DataFormats/Detectors/EMCAL/src/CellLabel.cxx b/DataFormats/Detectors/EMCAL/src/CellLabel.cxx index e37368ea181d7..70a1a642c5449 100644 --- a/DataFormats/Detectors/EMCAL/src/CellLabel.cxx +++ b/DataFormats/Detectors/EMCAL/src/CellLabel.cxx @@ -16,10 +16,19 @@ #include #include #include +#include +#include using namespace o2::emcal; -CellLabel::CellLabel(const gsl::span labels, const gsl::span amplitudeFractions) : mLabels(labels), mAmplitudeFraction(amplitudeFractions) +CellLabel::CellLabel(std::vector labels, std::vector amplitudeFractions) : mLabels(std::move(labels)), mAmplitudeFraction(std::move(amplitudeFractions)) +{ + if (labels.size() != amplitudeFractions.size()) { + LOG(error) << "Size of labels " << labels.size() << " does not match size of amplitude fraction " << amplitudeFractions.size() << " !"; + } +} + +CellLabel::CellLabel(gsl::span labels, gsl::span amplitudeFractions) : mLabels(labels.begin(), labels.end()), mAmplitudeFraction(amplitudeFractions.begin(), amplitudeFractions.end()) { if (labels.size() != amplitudeFractions.size()) { LOG(error) << "Size of labels " << labels.size() << " does not match size of amplitude fraction " << amplitudeFractions.size() << " !"; From ace4b6b0b9feae9dfcb6ffd5e7132a811066faa3 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Thu, 5 Jun 2025 08:46:28 +0200 Subject: [PATCH 038/315] full_system_test.sh: allow to set RUNNUMBER and extra SIMOPTKEY options for beam types other than pp or PbPb --- prodtests/full_system_test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index 5c7157f93c652..e8b298cc08d8c 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -67,7 +67,7 @@ if [[ $BEAMTYPE == "PbPb" ]]; then else FST_GENERATOR=${FST_GENERATOR:-pythia8pp} FST_COLRATE=${FST_COLRATE:-400000} - RUNNUMBER=303000 # a default un-anchored pp run number + RUNNUMBER=${RUNNUMBER:-303000} # a default un-anchored pp run number fi FST_MC_ENGINE=${FST_MC_ENGINE:-TGeant4} FST_EMBEDDING_CONFIG=${FST_EMBEDDING_CONFIG:-GeneratorPythia8.config=$O2_ROOT/prodtests/full-system-test/pythia8.cfg} @@ -107,7 +107,7 @@ if [[ $BEAMTYPE == "PbPb" && -z $FST_QED ]]; then FST_QED=1 fi DIGIQED= -SIMOPTKEY="Diamond.width[2]=6.;" +SIMOPTKEY+="Diamond.width[2]=6.;" if [[ $FST_QED == 1 ]]; then mkdir -p qed cd qed From 79f11174e8b97ddca2f2e3a397cf893d4cb47327 Mon Sep 17 00:00:00 2001 From: Andrea Giovanni Riffero Date: Tue, 17 Jun 2025 12:32:10 +0200 Subject: [PATCH 039/315] [MID] Improve the macro for the reject list (#14411) Allow to put custom timestamps in the json used to build the manual reject list. --- .../MUON/MID/Calibration/macros/README.md | 4 ++ .../MID/Calibration/macros/build_rejectlist.C | 45 +++++++++++++++---- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Detectors/MUON/MID/Calibration/macros/README.md b/Detectors/MUON/MID/Calibration/macros/README.md index 83e88f18ecf48..f2cf2aa8bf78b 100644 --- a/Detectors/MUON/MID/Calibration/macros/README.md +++ b/Detectors/MUON/MID/Calibration/macros/README.md @@ -72,6 +72,8 @@ This can be done with a json file in the form: { "startRun": 557251, "endRun": 557926, + "startTT": 1726300235000, + "endTT": 1726324000000, "rejectList": [ { "deId": 4, @@ -99,6 +101,8 @@ This can be done with a json file in the form: } ``` +Where `startTT` and `endTT` are the timestamps in which the manual reject list will be built. To use the timestamps of start/end of the specified runs set `startTT` and `endTT` to 0 (or do not include them in the json). + The path to the file is then given to the macro with: ```shell diff --git a/Detectors/MUON/MID/Calibration/macros/build_rejectlist.C b/Detectors/MUON/MID/Calibration/macros/build_rejectlist.C index 48391b4460687..5cec2c611bcf8 100644 --- a/Detectors/MUON/MID/Calibration/macros/build_rejectlist.C +++ b/Detectors/MUON/MID/Calibration/macros/build_rejectlist.C @@ -316,25 +316,52 @@ RejectListStruct load_from_json(const o2::ccdb::CcdbApi& ccdbApi, const char* fi { // Open the JSON file std::cout << "Reading reject list from file " << filename << std::endl; - RejectListStruct rl; std::ifstream inFile(filename); if (!inFile.is_open()) { std::cerr << "Could not open the file!" << std::endl; - return rl; + return {}; } // Create an IStreamWrapper for file input stream rapidjson::IStreamWrapper isw(inFile); - rapidjson::Document doc; if (doc.ParseStream(isw).HasParseError()) { std::cerr << "Problem parsing " << filename << std::endl; - return rl; + return {}; } - auto startRange = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, doc["startRun"].GetInt()); - auto endRange = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, doc["endRun"].GetInt()); - rl.start = startRange.first; - rl.end = endRange.second; + + // manual-validity interval in ms: + int64_t startTSms = 0; + int64_t endTSms = 0; + + // run numbers from the json + int startRun = doc["startRun"].GetInt(); + int endRun = doc["endRun"].GetInt(); + + // check if there are non-zero timestamps in the json + bool hasStartTT = doc.HasMember("startTT") && doc["startTT"].IsInt64() && doc["startTT"].GetInt64() != 0; + bool hasEndTT = doc.HasMember("endTT") && doc["endTT"].IsInt64() && doc["endTT"].GetInt64() != 0; + if (hasStartTT && hasEndTT) { + startTSms = doc["startTT"].GetInt64(); + endTSms = doc["endTT"].GetInt64(); + + // sanity check against the run boundaries + auto runStart = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, startRun).first; + auto runEnd = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, endRun).second; + if (startTSms < runStart || endTSms > runEnd) { + std::cout + << "\n\nWarning: manual timestamps [" << startTSms << " - " << endTSms + << "] lie outside run interval [" << runStart << " - " << runEnd << "]\n\n\n"; + } + } else { + // use run start/end if there are no timestamps in the json + startTSms = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, startRun).first; + endTSms = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, endRun).second; + } + + RejectListStruct rl; + rl.start = startTSms; + rl.end = endTSms; std::cout << "Manual RL validity: " << timeRangeToString(rl.start, rl.end) << std::endl; auto rlArray = doc["rejectList"].GetArray(); for (auto& ar : rlArray) { @@ -453,4 +480,4 @@ void build_rejectlist(long start, long end, const char* qcdbUrl = "http://ali-qc outCCDBApi.storeAsTFileAny(&rl.rejectList, "MID/Calib/RejectList", metadata, rl.start, rl.end); } } -} \ No newline at end of file +} From d493ded804afcecf95e45565bfca0b48352f7300 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 17 Jun 2025 14:38:25 +0200 Subject: [PATCH 040/315] GPU Display: Use 1-argument Vulkan loader which might be compatible to more Vulkan implementations --- .../display/backend/GPUDisplayBackendOpenGL.cxx | 15 +++++---------- .../display/backend/GPUDisplayBackendVulkan.cxx | 5 ++--- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.cxx b/GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.cxx index b9bd2731ac641..664734fe6dff0 100644 --- a/GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.cxx +++ b/GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.cxx @@ -61,28 +61,23 @@ GPUDisplayBackendOpenGL::GPUDisplayBackendOpenGL() mBackendName = "OpenGL"; } -#ifdef GPUCA_DISPLAY_GL3W int32_t GPUDisplayBackendOpenGL::ExtInit() { +#ifdef GPUCA_DISPLAY_GL3W return gl3wInit(); -} #else -int32_t GPUDisplayBackendOpenGL::ExtInit() -{ return glewInit(); -} #endif -#ifdef GPUCA_DISPLAY_OPENGL_CORE +} + bool GPUDisplayBackendOpenGL::CoreProfile() { +#ifdef GPUCA_DISPLAY_OPENGL_CORE return true; -} #else -bool GPUDisplayBackendOpenGL::CoreProfile() -{ return false; -} #endif +} // #define CHKERR(cmd) {cmd;} #define CHKERR(cmd) \ diff --git a/GPU/GPUTracking/display/backend/GPUDisplayBackendVulkan.cxx b/GPU/GPUTracking/display/backend/GPUDisplayBackendVulkan.cxx index a7e54db725ae0..0c2af55121b7d 100644 --- a/GPU/GPUTracking/display/backend/GPUDisplayBackendVulkan.cxx +++ b/GPU/GPUTracking/display/backend/GPUDisplayBackendVulkan.cxx @@ -340,7 +340,7 @@ double GPUDisplayBackendVulkan::checkDevice(vk::PhysicalDevice device, const std void GPUDisplayBackendVulkan::createDevice() { - VULKAN_HPP_DEFAULT_DISPATCHER.init(); + VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); vk::ApplicationInfo appInfo{}; appInfo.pApplicationName = "GPU CA Standalone display"; appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); @@ -355,8 +355,7 @@ void GPUDisplayBackendVulkan::createDevice() uint32_t frontendExtensionCount = mDisplay->frontend()->getReqVulkanExtensions(frontendExtensions); std::vector reqInstanceExtensions(frontendExtensions, frontendExtensions + frontendExtensionCount); - const std::vector reqValidationLayers = { - "VK_LAYER_KHRONOS_validation"}; + const std::vector reqValidationLayers = {"VK_LAYER_KHRONOS_validation"}; auto debugCallback = [](vk::DebugUtilsMessageSeverityFlagBitsEXT messageSeverity, vk::DebugUtilsMessageTypeFlagsEXT messageType, const vk::DebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) -> VkBool32 { static int32_t throwOnError = getenv("GPUCA_VULKAN_VALIDATION_THROW") ? atoi(getenv("GPUCA_VULKAN_VALIDATION_THROW")) : 0; static bool showVulkanValidationInfo = getenv("GPUCA_VULKAN_VALIDATION_INFO") && atoi(getenv("GPUCA_VULKAN_VALIDATION_INFO")); From e2a6098acc7dc7bc1c9c48d76ff9dbc1d4732726 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 17 Jun 2025 15:45:47 +0200 Subject: [PATCH 041/315] GPU Display: Add CMake option to disable building the display --- GPU/GPUTracking/CMakeLists.txt | 2 +- GPU/GPUTracking/display/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 87b202ec607ae..0560ea2dd12d2 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -27,7 +27,7 @@ set(CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER} "${CMAKE_CXX_FLAGS_${CMAKE_BUILD_T include(cmake/helpers.cmake) -if((ALIGPU_BUILD_TYPE STREQUAL "Standalone" AND GPUCA_BUILD_EVENT_DISPLAY) OR (ALIGPU_BUILD_TYPE STREQUAL "O2" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND TARGET AliceO2::DebugGUI AND OPENGL_FOUND AND GLFW_FOUND)) +if((ALIGPU_BUILD_TYPE STREQUAL "Standalone" AND GPUCA_BUILD_EVENT_DISPLAY) OR (ALIGPU_BUILD_TYPE STREQUAL "O2" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND TARGET AliceO2::DebugGUI AND OPENGL_FOUND AND GLFW_FOUND AND (NOT DEFINED GPUCA_BUILD_EVENT_DISPLAY OR NOT GPUCA_BUILD_EVENT_DISPLAY))) set(GPUCA_EVENT_DISPLAY ON) endif() if(ROOT_FOUND) diff --git a/GPU/GPUTracking/display/CMakeLists.txt b/GPU/GPUTracking/display/CMakeLists.txt index a59d5189d6235..513d9b6122c68 100644 --- a/GPU/GPUTracking/display/CMakeLists.txt +++ b/GPU/GPUTracking/display/CMakeLists.txt @@ -159,7 +159,7 @@ install(FILES ${HDRS} ${HDRS_INSTALL} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GP target_compile_definitions(${targetName} PRIVATE $) -message(STATUS "Building GPU Event Display (Vulkan ${GPUCA_EVENT_DISPLAY_VULKAN}, Wayland ${GPUCA_EVENT_DISPLAY_WAYLAND}, Freetype ${GPUCA_EVENT_DISPLAY_FREETYPE}, Fontconfig ${Fontconfig_FOUND}, Qt ${GPUCA_EVENT_DISPLAY_QT})") +message(STATUS "Building GPU Event Display (Vulkan ${GPUCA_EVENT_DISPLAY_VULKAN} ${Vulkan_VERSION}, Wayland ${GPUCA_EVENT_DISPLAY_WAYLAND}, Freetype ${GPUCA_EVENT_DISPLAY_FREETYPE}, Fontconfig ${Fontconfig_FOUND}, Qt ${GPUCA_EVENT_DISPLAY_QT})") target_link_libraries(${targetName} PUBLIC ${GLFW_LIBRARIES} OpenGL::GL) target_include_directories(${targetName} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) From a1d15805280db0d7f2f3d79771f912049b9499f1 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 17 Jun 2025 20:00:01 +0200 Subject: [PATCH 042/315] ITS: GPU accept mc in config --- Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx index b03d1dccfb8e7..05e873c18b898 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx @@ -63,6 +63,7 @@ framework::WorkflowSpec getWorkflow(bool useMC, cfg.runITSTracking = true; cfg.itsTriggerType = useTrig; cfg.itsOverrBeamEst = overrideBeamPosition; + cfg.processMC = useMC; Inputs ggInputs; auto ggRequest = std::make_shared(false, true, false, true, true, From c978bd4476552065eaf31ae2948add3a13840278 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 18 Jun 2025 09:22:28 +0200 Subject: [PATCH 043/315] Run the workflow json creation with error severity (#14079) --- cmake/O2AddWorkflow.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/O2AddWorkflow.cmake b/cmake/O2AddWorkflow.cmake index b952890921f45..4d47e85420cdf 100644 --- a/cmake/O2AddWorkflow.cmake +++ b/cmake/O2AddWorkflow.cmake @@ -53,7 +53,7 @@ function(o2_add_dpl_workflow baseTargetName) add_custom_command( TARGET ${targetExeName} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E env ASAN_OPTIONS=detect_leaks=0,detect_container_overflow=0,detect_odr_violation=0 "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}:$$LD_LIBRARY_PATH" $ -b --dump-workflow --dump-workflow-file ${jsonFile}) + COMMAND ${CMAKE_COMMAND} -E env ASAN_OPTIONS=detect_leaks=0,detect_container_overflow=0,detect_odr_violation=0 "LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}:$$LD_LIBRARY_PATH" $ --severity error -b --dump-workflow --dump-workflow-file ${jsonFile}) add_dependencies(${targetExeName} O2::FrameworkAnalysisSupport O2::FrameworkCCDBSupport) install( From 3fa3fe8636e2cb5431a55f7513702834cf25e506 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 18 Jun 2025 18:07:36 +0200 Subject: [PATCH 044/315] Add support for ONNXRuntime 1.22.00 (#14419) --- Common/ML/include/ML/OrtInterface.h | 9 ++------- Common/ML/src/OrtInterface.cxx | 6 +++--- .../TPCClusterFinder/GPUTPCNNClusterizerHost.h | 2 -- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Common/ML/include/ML/OrtInterface.h b/Common/ML/include/ML/OrtInterface.h index 7224645425856..0c498e33d2e2c 100644 --- a/Common/ML/include/ML/OrtInterface.h +++ b/Common/ML/include/ML/OrtInterface.h @@ -34,10 +34,7 @@ struct MemoryInfo; struct Env; } // namespace Ort -namespace o2 -{ - -namespace ml +namespace o2::ml { class OrtModel @@ -127,8 +124,6 @@ class OrtModel std::string printShape(const std::vector>&, std::vector&); }; -} // namespace ml - -} // namespace o2 +} // namespace o2::ml #endif // O2_ML_ORTINTERFACE_H diff --git a/Common/ML/src/OrtInterface.cxx b/Common/ML/src/OrtInterface.cxx index 8f31761489997..1cd9913efb6aa 100644 --- a/Common/ML/src/OrtInterface.cxx +++ b/Common/ML/src/OrtInterface.cxx @@ -287,9 +287,9 @@ std::vector OrtModel::inference(std::vector& input) return outputValuesVec; } -template std::vector OrtModel::inference(std::vector&); -template std::vector OrtModel::inference(std::vector&); -template std::vector OrtModel::inference(std::vector&); +template std::vector o2::ml::OrtModel::inference(std::vector&); +template std::vector o2::ml::OrtModel::inference(std::vector&); +template std::vector o2::ml::OrtModel::inference(std::vector&); template void OrtModel::inference(I* input, int64_t input_size, O* output) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h index 4334c3418eb09..a4449165261be 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h @@ -20,8 +20,6 @@ #include #include "ML/OrtInterface.h" -using namespace o2::ml; - class OrtMemoryInfo; class OrtAllocator; struct MockedOrtAllocator; From ad782f93a74ca0d35c0ce31a1896ea0e27a64c24 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 18 Jun 2025 22:35:59 +0200 Subject: [PATCH 045/315] Hide NaN code with -ffast-math --- Common/ML/include/ML/3rdparty/GPUORTFloat16.h | 2 ++ GPU/Common/GPUCommonMath.h | 7 ++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Common/ML/include/ML/3rdparty/GPUORTFloat16.h b/Common/ML/include/ML/3rdparty/GPUORTFloat16.h index 3bf2f465b2a35..75e146d872cd1 100644 --- a/Common/ML/include/ML/3rdparty/GPUORTFloat16.h +++ b/Common/ML/include/ML/3rdparty/GPUORTFloat16.h @@ -568,9 +568,11 @@ GPUdi() uint16_t BFloat16Impl::ToUint16Impl(float v) noexcept template GPUdi() float BFloat16Impl::ToFloatImpl() const noexcept { +#ifndef __FAST_MATH__ if (IsNaN()) { return o2::gpu::CAMath::QuietNaN(); } +#endif float result; char* const first = reinterpret_cast(&result); char* const second = first + sizeof(uint16_t); diff --git a/GPU/Common/GPUCommonMath.h b/GPU/Common/GPUCommonMath.h index b448a30107dad..372e067b14aff 100644 --- a/GPU/Common/GPUCommonMath.h +++ b/GPU/Common/GPUCommonMath.h @@ -99,12 +99,9 @@ class GPUCommonMath GPUhdi() static float Remainderf(float x, float y); GPUd() constexpr static bool Finite(float x); GPUd() constexpr static bool IsNaN(float x); -#pragma GCC diagnostic push -#if defined(__FAST_MATH__) && defined(__clang__) -#pragma GCC diagnostic ignored "-Wnan-infinity-disabled" -#endif +#ifndef __FAST_MATH__ GPUd() constexpr static float QuietNaN() { return GPUCA_CHOICE(std::numeric_limits::quiet_NaN(), __builtin_nanf(""), nan(0u)); } -#pragma GCC diagnostic pop +#endif GPUd() constexpr static uint32_t Clz(uint32_t val); GPUd() constexpr static uint32_t Popcount(uint32_t val); From 1d90dc8f18f27f706ca269958cfe479c0fdab1e9 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 19 Jun 2025 15:48:13 +0200 Subject: [PATCH 046/315] Misc fixes for TrackMCStudy workflow --- .../GlobalTrackingStudy/TrackMCStudyConfig.h | 2 +- .../GlobalTrackingStudy/TrackMCStudyTypes.h | 6 ++++-- .../study/src/TrackMCStudy.cxx | 20 ++++++++++++++----- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyConfig.h b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyConfig.h index 7d89928a20b37..3c04affd99cb2 100644 --- a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyConfig.h +++ b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyConfig.h @@ -28,7 +28,7 @@ struct TrackMCStudyConfig : o2::conf::ConfigurableParamHelper mTPCOcc; ///< TPC occupancy for this interaction time std::vector mITSOcc; //< N ITS clusters in the ROF containing collision bool mCheckSV = false; //< check SV binding (apart from prongs availability) + bool mRecProcStage = false; //< flag that the MC particle was added only at the stage of reco tracks processing int mNTPCOccBinLength = 0; ///< TPC occ. histo bin length in TBs float mNTPCOccBinLengthInv; int mVerbose = 0; @@ -185,6 +186,7 @@ void TrackMCStudy::run(ProcessingContext& pc) recoData.collectData(pc, *mDataRequest.get()); // select tracks of needed type, with minimal cuts, the real selected will be done in the vertexer updateTimeDependentParams(pc); // Make sure this is called after recoData.collectData, which may load some conditions + mRecProcStage = false; process(recoData); } @@ -278,15 +280,21 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData) return patt; }; - auto getLowestPadrow = [&recoData](const o2::tpc::TrackTPC& trc) { + auto getLowestPadrow = [&recoData](const o2::tpc::TrackTPC& trc, RecTrack& tref) { if (recoData.inputsTPCclusters) { uint8_t clSect = 0, clRow = 0; uint32_t clIdx = 0; const auto clRefs = recoData.getTPCTracksClusterRefs(); + const auto tpcClusAcc = recoData.getTPCClusters(); trc.getClusterReference(clRefs, trc.getNClusterReferences() - 1, clSect, clRow, clIdx); - return int(clRow); + const auto& clus = tpcClusAcc.clusters[clSect][clRow][clIdx]; + int padFromEdge = int(clus.getPad()), npads = o2::gpu::GPUTPCGeometry::NPads(clRow); + if (padFromEdge > npads / 2) { + padFromEdge = npads - 1 - padFromEdge; + } + tref.padFromEdge = uint8_t(padFromEdge); + tref.lowestPadRow = clRow; } - return -1; }; auto flagTPCClusters = [&recoData](const o2::tpc::TrackTPC& trc, o2::MCCompLabel lbTrc) { @@ -352,7 +360,7 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData) int nev = mcReader.getNEvents(curSrcMC); bool okAccVtx = true; if (nev != (int)mMCVtVec.size()) { - LOGP(error, "source {} has {} events while {} MC vertices were booked", curSrcMC, nev, mMCVtVec.size()); + LOGP(debug, "source {} has {} events while {} MC vertices were booked", curSrcMC, nev, mMCVtVec.size()); okAccVtx = false; } for (curEvMC = 0; curEvMC < nev; curEvMC++) { @@ -382,6 +390,7 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData) } // add reconstruction info to MC particles. If MC particle was not selected before but was reconstrected, account MC info + mRecProcStage = true; // MC particles accepted only at this stage will be flagged for (int iv = 0; iv < nv; iv++) { if (mVerbose > 1) { LOGP(info, "processing PV {} of {}", iv, nv); @@ -532,7 +541,7 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData) if (msk[DetID::TPC]) { const auto& trtpc = recoData.getTPCTrack(gidSet[GTrackID::TPC]); tref.nClTPC = trtpc.getNClusters(); - tref.lowestPadRow = getLowestPadrow(trtpc); + getLowestPadrow(trtpc, tref); flagTPCClusters(trtpc, entry.first); if (trackFam.entTPC < 0) { trackFam.entTPC = tcnt; @@ -1088,6 +1097,7 @@ bool TrackMCStudy::addMCParticle(const MCTrack& mcPart, const o2::MCCompLabel& l mcEntry.mcTrackInfo.bcInTF = mIntBC[lb.getEventID()]; mcEntry.mcTrackInfo.occTPC = mTPCOcc[lb.getEventID()]; mcEntry.mcTrackInfo.occITS = mITSOcc[lb.getEventID()]; + mcEntry.mcTrackInfo.addedAtRecStage = mRecProcStage; int moth = -1; o2::MCCompLabel mclbPar; if ((moth = mcPart.getMotherTrackId()) >= 0) { From 52d7d5820abf5e051711d4bbd5dea4ac3ee3badf Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Fri, 20 Jun 2025 07:19:08 +0200 Subject: [PATCH 047/315] ITS: allow sharing of arena in Tracker & Vertexer (#14394) --- .../tracking/include/ITStracking/Tracker.h | 5 +- .../include/ITStracking/TrackerTraits.h | 7 +- .../include/ITStracking/TrackingInterface.h | 3 + .../tracking/include/ITStracking/Vertexer.h | 5 + .../include/ITStracking/VertexerTraits.h | 9 +- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 1 - .../ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 891 +++++++++--------- .../ITS/tracking/src/TrackingInterface.cxx | 15 + .../ITS/tracking/src/VertexerTraits.cxx | 26 +- 9 files changed, 467 insertions(+), 495 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index b393d743809fd..5ba9b5039f808 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -27,6 +27,8 @@ #include #include +#include + #include "ITStracking/Configuration.h" #include "CommonConstants/MathConstants.h" #include "ITStracking/Definitions.h" @@ -73,8 +75,7 @@ class Tracker void setBz(float bz) { mTraits->setBz(bz); } void setCorrType(const o2::base::PropagatorImpl::MatCorrType type) { mTraits->setCorrType(type); } bool isMatLUT() const { return mTraits->isMatLUT(); } - void setNThreads(int n) { mTraits->setNThreads(n); } - int getNThreads() const { return mTraits->getNThreads(); } + void setNThreads(int n, std::shared_ptr& arena) { mTraits->setNThreads(n, arena); } void printSummary() const; private: diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h index 36956a5206277..7ba67a01fce13 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h @@ -80,8 +80,8 @@ class TrackerTraits void SetRecoChain(o2::gpu::GPUChainITS* chain) { mChain = chain; } void setSmoothing(bool v) { mApplySmoothing = v; } bool getSmoothing() const { return mApplySmoothing; } - void setNThreads(int n); - int getNThreads() const { return mNThreads; } + void setNThreads(int n, std::shared_ptr& arena); + int getNThreads() { return mTaskArena->max_concurrency(); } o2::gpu::GPUChainITS* getChain() const { return mChain; } @@ -94,10 +94,9 @@ class TrackerTraits track::TrackParCov buildTrackSeed(const Cluster& cluster1, const Cluster& cluster2, const TrackingFrameInfo& tf3); bool fitTrack(TrackITSExt& track, int start, int end, int step, float chi2clcut = o2::constants::math::VeryBig, float chi2ndfcut = o2::constants::math::VeryBig, float maxQoverPt = o2::constants::math::VeryBig, int nCl = 0); - int mNThreads = 1; bool mApplySmoothing = false; std::shared_ptr mMemoryPool; - tbb::task_arena mTaskArena; + std::shared_ptr mTaskArena; protected: o2::base::PropagatorImpl::MatCorrType mCorrType = o2::base::PropagatorImpl::MatCorrType::USEMatCorrNONE; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h index 732efcb9e0861..64fd4f8156cca 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h @@ -28,6 +28,8 @@ #include "GPUO2Interface.h" #include "GPUChainITS.h" +#include + namespace o2::its { class ITSTrackingInterface @@ -98,6 +100,7 @@ class ITSTrackingInterface std::unique_ptr mVertexer = nullptr; const o2::dataformats::MeanVertexObject* mMeanVertex; std::shared_ptr mMemoryPool; + std::shared_ptr mTaskArena; }; } // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h index 63dd41b4a0a8f..98bcb95ef65df 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h @@ -21,6 +21,9 @@ #include #include #include +#include + +#include #include "ITStracking/ROframe.h" #include "ITStracking/Constants.h" @@ -90,6 +93,8 @@ class Vertexer const unsigned selectedN, const unsigned int vertexN, const float initT, const float trackletT, const float selecT, const float vertexT); + void setNThreads(int n, std::shared_ptr& arena) { mTraits->setNThreads(n, arena); } + private: std::uint32_t mTimeFrameCounter = 0; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index e1e1d44e8ead9..6554e53fa2ee8 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -17,6 +17,7 @@ #define O2_ITS_TRACKING_VERTEXER_TRAITS_H_ #include +#include #include #include @@ -93,8 +94,8 @@ class VertexerTraits auto getVertexingParameters() const { return mVrtParams; } void setVertexingParameters(std::vector& vertParams) { mVrtParams = vertParams; } void dumpVertexerTraits(); - void setNThreads(int n); - int getNThreads() const { return mNThreads; } + void setNThreads(int n, std::shared_ptr& arena); + int getNThreads() { return mTaskArena->max_concurrency(); } virtual bool isGPU() const noexcept { return false; } virtual const char* getName() const noexcept { return "CPU"; } virtual bool usesMemoryPool() const noexcept { return true; } @@ -116,8 +117,6 @@ class VertexerTraits } protected: - int mNThreads = 1; - std::vector mVrtParams; IndexTableUtils mIndexTableUtils; @@ -125,7 +124,7 @@ class VertexerTraits TimeFrame7* mTimeFrame = nullptr; // observer ptr private: std::shared_ptr mMemoryPool; - tbb::task_arena mTaskArena; + std::shared_ptr mTaskArena; }; inline void VertexerTraits::initialise(const TrackingParameters& trackingParams, const int iteration) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index c92d1e8505356..09d9cee06d9f9 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -342,7 +342,6 @@ void Tracker::getGlobalConfiguration() } else { mTraits->setCorrType(o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT); } - setNThreads(tc.nThreads); int nROFsPerIterations = tc.nROFsPerIterations > 0 ? tc.nROFsPerIterations : -1; if (tc.nOrbitsPerIterations > 0) { /// code to be used when the number of ROFs per orbit is known, this gets priority over the number of ROFs per iteration diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index 36636069137f3..8dd6b9870115c 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef OPTIMISATION_OUTPUT #include @@ -43,6 +44,12 @@ namespace o2::its static constexpr int debugLevel{0}; +struct PassMode { + using OnePass = std::integral_constant; + using TwoPassCount = std::integral_constant; + using TwoPassInsert = std::integral_constant; +}; + template void TrackerTraits::computeLayerTracklets(const int iteration, int iROFslice, int iVertex) { @@ -64,14 +71,15 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF gsl::span diamondSpan(&diamondVert, 1); int startROF{mTrkParams[iteration].nROFsPerIterations > 0 ? iROFslice * mTrkParams[iteration].nROFsPerIterations : 0}; int endROF{o2::gpu::GPUCommonMath::Min(mTrkParams[iteration].nROFsPerIterations > 0 ? (iROFslice + 1) * mTrkParams[iteration].nROFsPerIterations + mTrkParams[iteration].DeltaROF : mTimeFrame->getNrof(), mTimeFrame->getNrof())}; - for (int rof0{startROF}; rof0 < endROF; ++rof0) { - gsl::span primaryVertices = mTrkParams[iteration].UseDiamond ? diamondSpan : mTimeFrame->getPrimaryVertices(rof0); - const int startVtx{iVertex >= 0 ? iVertex : 0}; - const int endVtx{iVertex >= 0 ? o2::gpu::CAMath::Min(iVertex + 1, static_cast(primaryVertices.size())) : static_cast(primaryVertices.size())}; - int minRof = o2::gpu::CAMath::Max(startROF, rof0 - mTrkParams[iteration].DeltaROF); - int maxRof = o2::gpu::CAMath::Min(endROF - 1, rof0 + mTrkParams[iteration].DeltaROF); - - mTaskArena.execute([&] { + + mTaskArena->execute([&] { + for (int rof0{startROF}; rof0 < endROF; ++rof0) { + gsl::span primaryVertices = mTrkParams[iteration].UseDiamond ? diamondSpan : mTimeFrame->getPrimaryVertices(rof0); + const int startVtx{iVertex >= 0 ? iVertex : 0}; + const int endVtx{iVertex >= 0 ? o2::gpu::CAMath::Min(iVertex + 1, static_cast(primaryVertices.size())) : static_cast(primaryVertices.size())}; + int minRof = o2::gpu::CAMath::Max(startROF, rof0 - mTrkParams[iteration].DeltaROF); + int maxRof = o2::gpu::CAMath::Min(endROF - 1, rof0 + mTrkParams[iteration].DeltaROF); + tbb::parallel_for( tbb::blocked_range(0, mTrkParams[iteration].TrackletsPerRoad()), [&](const tbb::blocked_range& Layers) { @@ -190,49 +198,39 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF } } }); - }); - } - - auto sortTracklets = [](const Tracklet& a, const Tracklet& b) -> bool { - return a.firstClusterIndex < b.firstClusterIndex || (a.firstClusterIndex == b.firstClusterIndex && a.secondClusterIndex < b.secondClusterIndex); - }; - auto equalTracklets = [](const Tracklet& a, const Tracklet& b) -> bool { - return a.firstClusterIndex == b.firstClusterIndex && a.secondClusterIndex == b.secondClusterIndex; - }; + } - mTaskArena.execute([&] { tbb::parallel_for( - tbb::blocked_range(0, mTrkParams[iteration].CellsPerRoad()), + tbb::blocked_range(0, mTrkParams[iteration].TrackletsPerRoad()), [&](const tbb::blocked_range& Layers) { for (int iLayer = Layers.begin(); iLayer < Layers.end(); ++iLayer) { /// Sort tracklets - auto& trkl{mTimeFrame->getTracklets()[iLayer + 1]}; - tbb::parallel_sort(trkl.begin(), trkl.end(), sortTracklets); + auto& trkl{mTimeFrame->getTracklets()[iLayer]}; + tbb::parallel_sort(trkl.begin(), trkl.end(), [](const Tracklet& a, const Tracklet& b) -> bool { + return a.firstClusterIndex < b.firstClusterIndex || (a.firstClusterIndex == b.firstClusterIndex && a.secondClusterIndex < b.secondClusterIndex); + }); /// Remove duplicates - trkl.erase(std::unique(trkl.begin(), trkl.end(), equalTracklets), trkl.end()); + trkl.erase(std::unique(trkl.begin(), trkl.end(), [](const Tracklet& a, const Tracklet& b) -> bool { + return a.firstClusterIndex == b.firstClusterIndex && a.secondClusterIndex == b.secondClusterIndex; + }), + trkl.end()); trkl.shrink_to_fit(); - /// recalculate lut - auto& lut{mTimeFrame->getTrackletsLookupTable()[iLayer]}; - std::fill(lut.begin(), lut.end(), 0); - if (trkl.empty()) { - return; - } - for (const auto& tkl : trkl) { - lut[tkl.firstClusterIndex]++; + if (iLayer > 0) { /// recalculate lut + auto& lut{mTimeFrame->getTrackletsLookupTable()[iLayer - 1]}; + std::fill(lut.begin(), lut.end(), 0); + if (trkl.empty()) { + return; + } + for (const auto& tkl : trkl) { + lut[tkl.firstClusterIndex]++; + } + std::exclusive_scan(lut.begin(), lut.end(), lut.begin(), 0); + lut.push_back(trkl.size()); } - std::exclusive_scan(lut.begin(), lut.end(), lut.begin(), 0); - lut.push_back(trkl.size()); } }); }); - /// Layer 0 is done outside the loop - // in-place deduplication - auto& trklt0 = mTimeFrame->getTracklets()[0]; - mTaskArena.execute([&] { tbb::parallel_sort(trklt0.begin(), trklt0.end(), sortTracklets); }); - trklt0.erase(std::unique(trklt0.begin(), trklt0.end(), equalTracklets), trklt0.end()); - trklt0.shrink_to_fit(); - /// Create tracklets labels if (mTimeFrame->hasMCinformation()) { for (int iLayer{0}; iLayer < mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) { @@ -275,184 +273,134 @@ void TrackerTraits::computeLayerCells(const int iteration) } } - mTaskArena.execute([&] { - tbb::parallel_for( - tbb::blocked_range(0, mTrkParams[iteration].CellsPerRoad()), - [&](const tbb::blocked_range& Layers) { - for (int iLayer = Layers.begin(); iLayer < Layers.end(); ++iLayer) { - - if (mTimeFrame->getTracklets()[iLayer + 1].empty() || - mTimeFrame->getTracklets()[iLayer].empty()) { - continue; - } - -#ifdef OPTIMISATION_OUTPUT - float resolution{o2::gpu::CAMath::Sqrt(0.5f * (mTrkParams[iteration].SystErrorZ2[iLayer] + mTrkParams[iteration].SystErrorZ2[iLayer + 1] + mTrkParams[iteration].SystErrorZ2[iLayer + 2] + mTrkParams[iteration].SystErrorY2[iLayer] + mTrkParams[iteration].SystErrorY2[iLayer + 1] + mTrkParams[iteration].SystErrorY2[iLayer + 2])) / mTrkParams[iteration].LayerResolution[iLayer]}; - resolution = resolution > 1.e-12 ? resolution : 1.f; -#endif - - // count number of cells found - const int currentLayerTrackletsNum{static_cast(mTimeFrame->getTracklets()[iLayer].size())}; - bounded_vector perTrackletCount(currentLayerTrackletsNum + 1, 0, mMemoryPool.get()); - tbb::parallel_for( - tbb::blocked_range(0, currentLayerTrackletsNum), - [&](const tbb::blocked_range& Tracklets) { - for (int iTracklet = Tracklets.begin(); iTracklet < Tracklets.end(); ++iTracklet) { - const Tracklet& currentTracklet{mTimeFrame->getTracklets()[iLayer][iTracklet]}; - const int nextLayerClusterIndex{currentTracklet.secondClusterIndex}; - const int nextLayerFirstTrackletIndex{ - mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex]}; - const int nextLayerLastTrackletIndex{ - mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex + 1]}; - - if (nextLayerFirstTrackletIndex == nextLayerLastTrackletIndex) { - continue; - } - - int foundCells{0}; - for (int iNextTracklet{nextLayerFirstTrackletIndex}; iNextTracklet < nextLayerLastTrackletIndex; ++iNextTracklet) { - if (mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet].firstClusterIndex != nextLayerClusterIndex) { - break; - } - const Tracklet& nextTracklet{mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet]}; - const float deltaTanLambda{std::abs(currentTracklet.tanLambda - nextTracklet.tanLambda)}; + mTaskArena->execute([&] { + auto forTrackletCells = [&](auto Tag, int iLayer, bounded_vector& layerCells, int iTracklet, int offset = 0) -> int { + const Tracklet& currentTracklet{mTimeFrame->getTracklets()[iLayer][iTracklet]}; + const int nextLayerClusterIndex{currentTracklet.secondClusterIndex}; + const int nextLayerFirstTrackletIndex{ + mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex]}; + const int nextLayerLastTrackletIndex{ + mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex + 1]}; + + int foundCells{0}; + for (int iNextTracklet{nextLayerFirstTrackletIndex}; iNextTracklet < nextLayerLastTrackletIndex; ++iNextTracklet) { + if (mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet].firstClusterIndex != nextLayerClusterIndex) { + break; + } + const Tracklet& nextTracklet{mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet]}; + const float deltaTanLambda{std::abs(currentTracklet.tanLambda - nextTracklet.tanLambda)}; #ifdef OPTIMISATION_OUTPUT - bool good{mTimeFrame->getTrackletsLabel(iLayer)[iTracklet] == mTimeFrame->getTrackletsLabel(iLayer + 1)[iNextTracklet]}; - float signedDelta{currentTracklet.tanLambda - nextTracklet.tanLambda}; - off << std::format("{}\t{:d}\t{}\t{}\t{}\t{}", iLayer, good, signedDelta, signedDelta / (mTrkParams[iteration].CellDeltaTanLambdaSigma), tanLambda, resolution) << std::endl; + float resolution{o2::gpu::CAMath::Sqrt(0.5f * (mTrkParams[iteration].SystErrorZ2[iLayer] + mTrkParams[iteration].SystErrorZ2[iLayer + 1] + mTrkParams[iteration].SystErrorZ2[iLayer + 2] + mTrkParams[iteration].SystErrorY2[iLayer] + mTrkParams[iteration].SystErrorY2[iLayer + 1] + mTrkParams[iteration].SystErrorY2[iLayer + 2])) / mTrkParams[iteration].LayerResolution[iLayer]}; + resolution = resolution > 1.e-12 ? resolution : 1.f; + bool good{mTimeFrame->getTrackletsLabel(iLayer)[iTracklet] == mTimeFrame->getTrackletsLabel(iLayer + 1)[iNextTracklet]}; + float signedDelta{currentTracklet.tanLambda - nextTracklet.tanLambda}; + off << std::format("{}\t{:d}\t{}\t{}\t{}\t{}", iLayer, good, signedDelta, signedDelta / (mTrkParams[iteration].CellDeltaTanLambdaSigma), tanLambda, resolution) << std::endl; #endif - if (deltaTanLambda / mTrkParams[iteration].CellDeltaTanLambdaSigma < mTrkParams[iteration].NSigmaCut) { + if (deltaTanLambda / mTrkParams[iteration].CellDeltaTanLambdaSigma < mTrkParams[iteration].NSigmaCut) { - /// Track seed preparation. Clusters are numbered progressively from the innermost going outward. - const int clusId[3]{ - mTimeFrame->getClusters()[iLayer][currentTracklet.firstClusterIndex].clusterId, - mTimeFrame->getClusters()[iLayer + 1][nextTracklet.firstClusterIndex].clusterId, - mTimeFrame->getClusters()[iLayer + 2][nextTracklet.secondClusterIndex].clusterId}; - const auto& cluster1_glo = mTimeFrame->getUnsortedClusters()[iLayer][clusId[0]]; - const auto& cluster2_glo = mTimeFrame->getUnsortedClusters()[iLayer + 1][clusId[1]]; - const auto& cluster3_tf = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer + 2)[clusId[2]]; - auto track{buildTrackSeed(cluster1_glo, cluster2_glo, cluster3_tf)}; + /// Track seed preparation. Clusters are numbered progressively from the innermost going outward. + const int clusId[3]{ + mTimeFrame->getClusters()[iLayer][currentTracklet.firstClusterIndex].clusterId, + mTimeFrame->getClusters()[iLayer + 1][nextTracklet.firstClusterIndex].clusterId, + mTimeFrame->getClusters()[iLayer + 2][nextTracklet.secondClusterIndex].clusterId}; + const auto& cluster1_glo = mTimeFrame->getUnsortedClusters()[iLayer][clusId[0]]; + const auto& cluster2_glo = mTimeFrame->getUnsortedClusters()[iLayer + 1][clusId[1]]; + const auto& cluster3_tf = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer + 2)[clusId[2]]; + auto track{buildTrackSeed(cluster1_glo, cluster2_glo, cluster3_tf)}; - float chi2{0.f}; - bool good{false}; - for (int iC{2}; iC--;) { - const TrackingFrameInfo& trackingHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer + iC)[clusId[iC]]; + float chi2{0.f}; + bool good{false}; + for (int iC{2}; iC--;) { + const TrackingFrameInfo& trackingHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer + iC)[clusId[iC]]; - if (!track.rotate(trackingHit.alphaTrackingFrame)) { - break; - } + if (!track.rotate(trackingHit.alphaTrackingFrame)) { + break; + } - if (!track.propagateTo(trackingHit.xTrackingFrame, getBz())) { - break; - } + if (!track.propagateTo(trackingHit.xTrackingFrame, getBz())) { + break; + } - if (!track.correctForMaterial(mTrkParams[0].LayerxX0[iLayer + iC], mTrkParams[0].LayerxX0[iLayer] * constants::Radl * constants::Rho, true)) { - break; - } + if (!track.correctForMaterial(mTrkParams[0].LayerxX0[iLayer + iC], mTrkParams[0].LayerxX0[iLayer] * constants::Radl * constants::Rho, true)) { + break; + } - const auto predChi2{track.getPredictedChi2Quiet(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)}; - if (!iC && predChi2 > mTrkParams[iteration].MaxChi2ClusterAttachment) { - break; - } + const auto predChi2{track.getPredictedChi2Quiet(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)}; + if (!iC && predChi2 > mTrkParams[iteration].MaxChi2ClusterAttachment) { + break; + } - if (!track.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) { - break; - } + if (!track.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) { + break; + } - good = !iC; - chi2 += predChi2; - } - if (good) { - ++foundCells; - } - } - } - perTrackletCount[iTracklet] = foundCells; - } - }); + good = !iC; + chi2 += predChi2; + } + if (good) { + if constexpr (decltype(Tag)::value == PassMode::OnePass::value) { + layerCells.emplace_back(iLayer, clusId[0], clusId[1], clusId[2], iTracklet, iNextTracklet, track, chi2); + ++foundCells; + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassCount::value) { + ++foundCells; + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassInsert::value) { + layerCells[offset++] = CellSeed(iLayer, clusId[0], clusId[1], clusId[2], iTracklet, iNextTracklet, track, chi2); + } else { + static_assert(false, "Unknown mode!"); + } + } + } + } + return foundCells; + }; - // calculate offset table and check if any cells where found - std::exclusive_scan(perTrackletCount.begin(), perTrackletCount.end(), perTrackletCount.begin(), 0); - auto totalCells{perTrackletCount.back()}; - if (totalCells == 0) { + tbb::parallel_for( + tbb::blocked_range(0, mTrkParams[iteration].CellsPerRoad()), + [&](const tbb::blocked_range& Layers) { + for (int iLayer = Layers.begin(); iLayer < Layers.end(); ++iLayer) { + if (mTimeFrame->getTracklets()[iLayer + 1].empty() || + mTimeFrame->getTracklets()[iLayer].empty()) { continue; } - auto& layerCells = mTimeFrame->getCells()[iLayer]; - layerCells.resize(totalCells); - tbb::parallel_for( - tbb::blocked_range(0, currentLayerTrackletsNum), - [&](const tbb::blocked_range& Tracklets) { - for (int iTracklet = Tracklets.begin(); iTracklet < Tracklets.end(); ++iTracklet) { - if (perTrackletCount[iTracklet] == perTrackletCount[iTracklet + 1]) { - continue; + auto& layerCells = mTimeFrame->getCells()[iLayer]; + const int currentLayerTrackletsNum{static_cast(mTimeFrame->getTracklets()[iLayer].size())}; + bounded_vector perTrackletCount(currentLayerTrackletsNum + 1, 0, mMemoryPool.get()); + if (mTaskArena->max_concurrency() <= 1) { + for (int iTracklet{0}; iTracklet < currentLayerTrackletsNum; ++iTracklet) { + perTrackletCount[iTracklet] = forTrackletCells(PassMode::OnePass{}, iLayer, layerCells, iTracklet); + } + std::exclusive_scan(perTrackletCount.begin(), perTrackletCount.end(), perTrackletCount.begin(), 0); + } else { + tbb::parallel_for( + tbb::blocked_range(0, currentLayerTrackletsNum), + [&](const tbb::blocked_range& Tracklets) { + for (int iTracklet = Tracklets.begin(); iTracklet < Tracklets.end(); ++iTracklet) { + perTrackletCount[iTracklet] = forTrackletCells(PassMode::TwoPassCount{}, iLayer, layerCells, iTracklet); } + }); - const Tracklet& currentTracklet{mTimeFrame->getTracklets()[iLayer][iTracklet]}; - const int nextLayerClusterIndex{currentTracklet.secondClusterIndex}; - const int nextLayerFirstTrackletIndex{ - mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex]}; - const int nextLayerLastTrackletIndex{ - mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex + 1]}; - - int position = perTrackletCount[iTracklet]; - for (int iNextTracklet{nextLayerFirstTrackletIndex}; iNextTracklet < nextLayerLastTrackletIndex; ++iNextTracklet) { - if (mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet].firstClusterIndex != nextLayerClusterIndex) { - break; - } - const Tracklet& nextTracklet{mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet]}; - const float deltaTanLambda{std::abs(currentTracklet.tanLambda - nextTracklet.tanLambda)}; - - if (deltaTanLambda / mTrkParams[iteration].CellDeltaTanLambdaSigma < mTrkParams[iteration].NSigmaCut) { - - /// Track seed preparation. Clusters are numbered progressively from the innermost going outward. - const int clusId[3]{ - mTimeFrame->getClusters()[iLayer][currentTracklet.firstClusterIndex].clusterId, - mTimeFrame->getClusters()[iLayer + 1][nextTracklet.firstClusterIndex].clusterId, - mTimeFrame->getClusters()[iLayer + 2][nextTracklet.secondClusterIndex].clusterId}; - const auto& cluster1_glo = mTimeFrame->getUnsortedClusters()[iLayer][clusId[0]]; - const auto& cluster2_glo = mTimeFrame->getUnsortedClusters()[iLayer + 1][clusId[1]]; - const auto& cluster3_tf = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer + 2)[clusId[2]]; - auto track{buildTrackSeed(cluster1_glo, cluster2_glo, cluster3_tf)}; - - float chi2{0.f}; - bool good{false}; - for (int iC{2}; iC--;) { - const TrackingFrameInfo& trackingHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer + iC)[clusId[iC]]; - - if (!track.rotate(trackingHit.alphaTrackingFrame)) { - break; - } - - if (!track.propagateTo(trackingHit.xTrackingFrame, getBz())) { - break; - } - - if (!track.correctForMaterial(mTrkParams[0].LayerxX0[iLayer + iC], mTrkParams[0].LayerxX0[iLayer] * constants::Radl * constants::Rho, true)) { - break; - } - - const auto predChi2{track.getPredictedChi2Quiet(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)}; - if (!iC && predChi2 > mTrkParams[iteration].MaxChi2ClusterAttachment) { - break; - } - - if (!track.o2::track::TrackParCov::update(trackingHit.positionTrackingFrame, trackingHit.covarianceTrackingFrame)) { - break; - } - - good = !iC; - chi2 += predChi2; - } - if (good) { - layerCells[position++] = CellSeed(iLayer, clusId[0], clusId[1], clusId[2], iTracklet, iNextTracklet, track, chi2); - } + std::exclusive_scan(perTrackletCount.begin(), perTrackletCount.end(), perTrackletCount.begin(), 0); + auto totalCells{perTrackletCount.back()}; + if (totalCells == 0) { + continue; + } + layerCells.resize(totalCells); + + tbb::parallel_for( + tbb::blocked_range(0, currentLayerTrackletsNum), + [&](const tbb::blocked_range& Tracklets) { + for (int iTracklet = Tracklets.begin(); iTracklet < Tracklets.end(); ++iTracklet) { + int offset = perTrackletCount[iTracklet]; + if (offset == perTrackletCount[iTracklet + 1]) { + continue; } + forTrackletCells(PassMode::TwoPassInsert{}, iLayer, layerCells, iTracklet, offset); } - } - }); + }); + } if (iLayer > 0) { auto& lut = mTimeFrame->getCellsLookupTable()[iLayer - 1]; @@ -487,128 +435,132 @@ void TrackerTraits::findCellsNeighbours(const int iteration) #ifdef OPTIMISATION_OUTPUT std::ofstream off(std::format("cellneighs{}.txt", iteration)); #endif - for (int iLayer{0}; iLayer < mTrkParams[iteration].CellsPerRoad() - 1; ++iLayer) { - const int nextLayerCellsNum{static_cast(mTimeFrame->getCells()[iLayer + 1].size())}; - deepVectorClear(mTimeFrame->getCellsNeighbours()[iLayer]); - deepVectorClear(mTimeFrame->getCellsNeighboursLUT()[iLayer]); - if (mTimeFrame->getCells()[iLayer + 1].empty() || - mTimeFrame->getCellsLookupTable()[iLayer].empty()) { - continue; - } - mTaskArena.execute([&] { - int layerCellsNum{static_cast(mTimeFrame->getCells()[iLayer].size())}; + struct Neighbor { + int cell{-1}, nextCell{-1}, level{-1}; + }; - bounded_vector perCellCount(layerCellsNum + 1, 0, mMemoryPool.get()); - tbb::parallel_for( - tbb::blocked_range(0, layerCellsNum), - [&](const tbb::blocked_range& Cells) { - for (int iCell = Cells.begin(); iCell < Cells.end(); ++iCell) { - const auto& currentCellSeed{mTimeFrame->getCells()[iLayer][iCell]}; - const int nextLayerTrackletIndex{currentCellSeed.getSecondTrackletIndex()}; - const int nextLayerFirstCellIndex{mTimeFrame->getCellsLookupTable()[iLayer][nextLayerTrackletIndex]}; - const int nextLayerLastCellIndex{mTimeFrame->getCellsLookupTable()[iLayer][nextLayerTrackletIndex + 1]}; - - int foundNextCells{0}; - for (int iNextCell{nextLayerFirstCellIndex}; iNextCell < nextLayerLastCellIndex; ++iNextCell) { - auto nextCellSeed{mTimeFrame->getCells()[iLayer + 1][iNextCell]}; /// copy - if (nextCellSeed.getFirstTrackletIndex() != nextLayerTrackletIndex) { - break; - } + mTaskArena->execute([&] { + for (int iLayer{0}; iLayer < mTrkParams[iteration].CellsPerRoad() - 1; ++iLayer) { + deepVectorClear(mTimeFrame->getCellsNeighbours()[iLayer]); + deepVectorClear(mTimeFrame->getCellsNeighboursLUT()[iLayer]); + if (mTimeFrame->getCells()[iLayer + 1].empty() || + mTimeFrame->getCellsLookupTable()[iLayer].empty()) { + continue; + } - if (!nextCellSeed.rotate(currentCellSeed.getAlpha()) || - !nextCellSeed.propagateTo(currentCellSeed.getX(), getBz())) { - continue; - } - float chi2 = currentCellSeed.getPredictedChi2(nextCellSeed); /// TODO: switch to the chi2 wrt cluster to avoid correlation + int nCells{static_cast(mTimeFrame->getCells()[iLayer].size())}; + bounded_vector cellsNeighbours(mMemoryPool.get()); + + auto forCellNeighbour = [&](auto Tag, int iCell, int offset = 0) -> int { + const auto& currentCellSeed{mTimeFrame->getCells()[iLayer][iCell]}; + const int nextLayerTrackletIndex{currentCellSeed.getSecondTrackletIndex()}; + const int nextLayerFirstCellIndex{mTimeFrame->getCellsLookupTable()[iLayer][nextLayerTrackletIndex]}; + const int nextLayerLastCellIndex{mTimeFrame->getCellsLookupTable()[iLayer][nextLayerTrackletIndex + 1]}; + int foundNextCells{0}; + for (int iNextCell{nextLayerFirstCellIndex}; iNextCell < nextLayerLastCellIndex; ++iNextCell) { + auto nextCellSeed{mTimeFrame->getCells()[iLayer + 1][iNextCell]}; /// copy + if (nextCellSeed.getFirstTrackletIndex() != nextLayerTrackletIndex) { + break; + } + + if (!nextCellSeed.rotate(currentCellSeed.getAlpha()) || + !nextCellSeed.propagateTo(currentCellSeed.getX(), getBz())) { + continue; + } + float chi2 = currentCellSeed.getPredictedChi2(nextCellSeed); /// TODO: switch to the chi2 wrt cluster to avoid correlation #ifdef OPTIMISATION_OUTPUT - bool good{mTimeFrame->getCellsLabel(iLayer)[iCell] == mTimeFrame->getCellsLabel(iLayer + 1)[iNextCell]}; - off << std::format("{}\t{:d}\t{}", iLayer, good, chi2) << std::endl; + bool good{mTimeFrame->getCellsLabel(iLayer)[iCell] == mTimeFrame->getCellsLabel(iLayer + 1)[iNextCell]}; + off << std::format("{}\t{:d}\t{}", iLayer, good, chi2) << std::endl; #endif - if (chi2 > mTrkParams[0].MaxChi2ClusterAttachment) { - continue; - } - ++foundNextCells; - } - perCellCount[iCell] = foundNextCells; + if (chi2 > mTrkParams[0].MaxChi2ClusterAttachment) { + continue; } - }); - std::exclusive_scan(perCellCount.begin(), perCellCount.end(), perCellCount.begin(), 0); - int totalCellNeighbours = perCellCount.back(); - if (totalCellNeighbours == 0) { - deepVectorClear(mTimeFrame->getCellsNeighbours()[iLayer]); - return; - } - - struct Neighbor { - int cell{-1}, nextCell{-1}, level{-1}; + if constexpr (decltype(Tag)::value == PassMode::OnePass::value) { + cellsNeighbours.emplace_back(iCell, iNextCell, currentCellSeed.getLevel() + 1); + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassCount::value) { + ++foundNextCells; + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassInsert::value) { + cellsNeighbours[offset++] = {iCell, iNextCell, currentCellSeed.getLevel() + 1}; + } else { + static_assert(false, "Unknown mode!"); + } + } + return foundNextCells; }; - bounded_vector cellsNeighbours(mMemoryPool.get()); - cellsNeighbours.resize(totalCellNeighbours); - tbb::parallel_for( - tbb::blocked_range(0, layerCellsNum), - [&](const tbb::blocked_range& Cells) { - for (int iCell = Cells.begin(); iCell < Cells.end(); ++iCell) { - if (perCellCount[iCell] == perCellCount[iCell + 1]) { - continue; + if (mTaskArena->max_concurrency() <= 1) { + for (int iCell{0}; iCell < nCells; ++iCell) { + forCellNeighbour(PassMode::OnePass{}, iCell); + } + } else { + bounded_vector perCellCount(nCells + 1, 0, mMemoryPool.get()); + tbb::parallel_for( + tbb::blocked_range(0, nCells), + [&](const tbb::blocked_range& Cells) { + for (int iCell = Cells.begin(); iCell < Cells.end(); ++iCell) { + perCellCount[iCell] = forCellNeighbour(PassMode::TwoPassCount{}, iCell); } - const auto& currentCellSeed{mTimeFrame->getCells()[iLayer][iCell]}; - const int nextLayerTrackletIndex{currentCellSeed.getSecondTrackletIndex()}; - const int nextLayerFirstCellIndex{mTimeFrame->getCellsLookupTable()[iLayer][nextLayerTrackletIndex]}; - const int nextLayerLastCellIndex{mTimeFrame->getCellsLookupTable()[iLayer][nextLayerTrackletIndex + 1]}; - - int position = perCellCount[iCell]; - for (int iNextCell{nextLayerFirstCellIndex}; iNextCell < nextLayerLastCellIndex; ++iNextCell) { - auto nextCellSeed{mTimeFrame->getCells()[iLayer + 1][iNextCell]}; /// copy - if (nextCellSeed.getFirstTrackletIndex() != nextLayerTrackletIndex) { - break; - } + }); - if (!nextCellSeed.rotate(currentCellSeed.getAlpha()) || - !nextCellSeed.propagateTo(currentCellSeed.getX(), getBz())) { - continue; - } - - float chi2 = currentCellSeed.getPredictedChi2(nextCellSeed); /// TODO: switch to the chi2 wrt cluster to avoid correlation - if (chi2 > mTrkParams[0].MaxChi2ClusterAttachment) { + std::exclusive_scan(perCellCount.begin(), perCellCount.end(), perCellCount.begin(), 0); + int totalCellNeighbours = perCellCount.back(); + if (totalCellNeighbours == 0) { + deepVectorClear(mTimeFrame->getCellsNeighbours()[iLayer]); + continue; + } + cellsNeighbours.resize(totalCellNeighbours); + + tbb::parallel_for( + tbb::blocked_range(0, nCells), + [&](const tbb::blocked_range& Cells) { + for (int iCell = Cells.begin(); iCell < Cells.end(); ++iCell) { + int offset = perCellCount[iCell]; + if (offset == perCellCount[iCell + 1]) { continue; } - - cellsNeighbours[position++] = {iCell, iNextCell, currentCellSeed.getLevel() + 1}; + forCellNeighbour(PassMode::TwoPassInsert{}, iCell, offset); } - } - }); + }); + } + + if (cellsNeighbours.empty()) { + continue; + } tbb::parallel_sort(cellsNeighbours.begin(), cellsNeighbours.end(), [](const auto& a, const auto& b) { return a.nextCell < b.nextCell; }); auto& cellsNeighbourLUT = mTimeFrame->getCellsNeighboursLUT()[iLayer]; - cellsNeighbourLUT.assign(nextLayerCellsNum, 0); + cellsNeighbourLUT.assign(mTimeFrame->getCells()[iLayer + 1].size(), 0); for (const auto& neigh : cellsNeighbours) { ++cellsNeighbourLUT[neigh.nextCell]; } std::inclusive_scan(cellsNeighbourLUT.begin(), cellsNeighbourLUT.end(), cellsNeighbourLUT.begin()); - mTimeFrame->getCellsNeighbours()[iLayer].reserve(totalCellNeighbours); + mTimeFrame->getCellsNeighbours()[iLayer].reserve(cellsNeighbours.size()); std::ranges::transform(cellsNeighbours, std::back_inserter(mTimeFrame->getCellsNeighbours()[iLayer]), [](const auto& neigh) { return neigh.cell; }); auto it = cellsNeighbours.begin(); - while (it != cellsNeighbours.end()) { - const int current_nextCell = it->nextCell; - auto group_end = std::find_if_not(it, cellsNeighbours.end(), - [current_nextCell](const auto& nb) { return nb.nextCell == current_nextCell; }); - const auto max_level_it = std::max_element(it, group_end, - [](const auto& a, const auto& b) { return a.level < b.level; }); - mTimeFrame->getCells()[iLayer + 1][current_nextCell].setLevel(max_level_it->level); - it = group_end; + int current = it->nextCell; + int maxLvl = it->level; + ++it; + for (; it != cellsNeighbours.end(); ++it) { + if (it->nextCell == current) { + maxLvl = std::max(maxLvl, it->level); + } else { + mTimeFrame->getCells()[iLayer + 1][current].setLevel(maxLvl); + current = it->nextCell; + maxLvl = it->level; + } } - }); - } + mTimeFrame->getCells()[iLayer + 1][current].setLevel(maxLvl); + } + }); } template @@ -621,141 +573,128 @@ void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bou int failed[5]{0, 0, 0, 0, 0}, attempts{0}, failedByMismatch{0}; #endif - mTaskArena.execute([&] { - bounded_vector perCellCount(currentCellSeed.size() + 1, 0, mMemoryPool.get()); - tbb::parallel_for( - tbb::blocked_range(0, (int)currentCellSeed.size()), - [&](const tbb::blocked_range& Cells) { - for (int iCell = Cells.begin(); iCell < Cells.end(); ++iCell) { - const CellSeed& currentCell{currentCellSeed[iCell]}; - int foundSeeds{0}; - if (currentCell.getLevel() != iLevel) { - continue; - } - if (currentCellId.empty() && (mTimeFrame->isClusterUsed(iLayer, currentCell.getFirstClusterIndex()) || - mTimeFrame->isClusterUsed(iLayer + 1, currentCell.getSecondClusterIndex()) || - mTimeFrame->isClusterUsed(iLayer + 2, currentCell.getThirdClusterIndex()))) { - continue; /// this we do only on the first iteration, hence the check on currentCellId - } - const int cellId = currentCellId.empty() ? iCell : currentCellId[iCell]; - const int startNeighbourId{cellId ? mTimeFrame->getCellsNeighboursLUT()[iLayer - 1][cellId - 1] : 0}; - const int endNeighbourId{mTimeFrame->getCellsNeighboursLUT()[iLayer - 1][cellId]}; - - for (int iNeighbourCell{startNeighbourId}; iNeighbourCell < endNeighbourId; ++iNeighbourCell) { - CA_DEBUGGER(attempts++); - const int neighbourCellId = mTimeFrame->getCellsNeighbours()[iLayer - 1][iNeighbourCell]; - const CellSeed& neighbourCell = mTimeFrame->getCells()[iLayer - 1][neighbourCellId]; - if (neighbourCell.getSecondTrackletIndex() != currentCell.getFirstTrackletIndex()) { - CA_DEBUGGER(failedByMismatch++); - continue; - } - if (mTimeFrame->isClusterUsed(iLayer - 1, neighbourCell.getFirstClusterIndex())) { - continue; - } - if (currentCell.getLevel() - 1 != neighbourCell.getLevel()) { - CA_DEBUGGER(failed[0]++); - continue; - } - /// Let's start the fitting procedure - CellSeed seed{currentCell}; - auto& trHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer - 1)[neighbourCell.getFirstClusterIndex()]; - - if (!seed.rotate(trHit.alphaTrackingFrame)) { - CA_DEBUGGER(failed[1]++); - continue; - } + mTaskArena->execute([&] { + auto forCellNeighbours = [&](auto Tag, int iCell, int offset = 0) -> int { + const CellSeed& currentCell{currentCellSeed[iCell]}; - if (!propagator->propagateToX(seed, trHit.xTrackingFrame, getBz(), o2::base::PropagatorImpl::MAX_SIN_PHI, o2::base::PropagatorImpl::MAX_STEP, mCorrType)) { - CA_DEBUGGER(failed[2]++); - continue; - } + if constexpr (decltype(Tag)::value != PassMode::TwoPassInsert::value) { + if (currentCell.getLevel() != iLevel) { + return 0; + } + if (currentCellId.empty() && (mTimeFrame->isClusterUsed(iLayer, currentCell.getFirstClusterIndex()) || + mTimeFrame->isClusterUsed(iLayer + 1, currentCell.getSecondClusterIndex()) || + mTimeFrame->isClusterUsed(iLayer + 2, currentCell.getThirdClusterIndex()))) { + return 0; /// this we do only on the first iteration, hence the check on currentCellId + } + } - if (mCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { - if (!seed.correctForMaterial(mTrkParams[0].LayerxX0[iLayer - 1], mTrkParams[0].LayerxX0[iLayer - 1] * constants::Radl * constants::Rho, true)) { - continue; - } - } + const int cellId = currentCellId.empty() ? iCell : currentCellId[iCell]; + const int startNeighbourId{cellId ? mTimeFrame->getCellsNeighboursLUT()[iLayer - 1][cellId - 1] : 0}; + const int endNeighbourId{mTimeFrame->getCellsNeighboursLUT()[iLayer - 1][cellId]}; + int foundSeeds{0}; + for (int iNeighbourCell{startNeighbourId}; iNeighbourCell < endNeighbourId; ++iNeighbourCell) { + CA_DEBUGGER(attempts++); + const int neighbourCellId = mTimeFrame->getCellsNeighbours()[iLayer - 1][iNeighbourCell]; + const CellSeed& neighbourCell = mTimeFrame->getCells()[iLayer - 1][neighbourCellId]; + if (neighbourCell.getSecondTrackletIndex() != currentCell.getFirstTrackletIndex()) { + CA_DEBUGGER(failedByMismatch++); + continue; + } + if (mTimeFrame->isClusterUsed(iLayer - 1, neighbourCell.getFirstClusterIndex())) { + continue; + } + if (currentCell.getLevel() - 1 != neighbourCell.getLevel()) { + CA_DEBUGGER(failed[0]++); + continue; + } + /// Let's start the fitting procedure + CellSeed seed{currentCell}; + const auto& trHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer - 1)[neighbourCell.getFirstClusterIndex()]; - auto predChi2{seed.getPredictedChi2Quiet(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)}; - if ((predChi2 > mTrkParams[0].MaxChi2ClusterAttachment) || predChi2 < 0.f) { - CA_DEBUGGER(failed[3]++); - continue; - } - seed.setChi2(seed.getChi2() + predChi2); - if (!seed.o2::track::TrackParCov::update(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)) { - CA_DEBUGGER(failed[4]++); - continue; - } - ++foundSeeds; - } - perCellCount[iCell] = foundSeeds; + if (!seed.rotate(trHit.alphaTrackingFrame)) { + CA_DEBUGGER(failed[1]++); + continue; } - }); - std::exclusive_scan(perCellCount.begin(), perCellCount.end(), perCellCount.begin(), 0); - auto totalNeighbours{perCellCount.back()}; - if (totalNeighbours == 0) { - return; - } - updatedCellSeeds.resize(totalNeighbours); - updatedCellsIds.resize(totalNeighbours); + if (!propagator->propagateToX(seed, trHit.xTrackingFrame, getBz(), o2::base::PropagatorImpl::MAX_SIN_PHI, o2::base::PropagatorImpl::MAX_STEP, mCorrType)) { + CA_DEBUGGER(failed[2]++); + continue; + } - tbb::parallel_for( - tbb::blocked_range(0, (int)currentCellSeed.size()), - [&](const tbb::blocked_range& Cells) { - for (int iCell = Cells.begin(); iCell < Cells.end(); ++iCell) { - if (perCellCount[iCell] == perCellCount[iCell + 1]) { + if (mCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { + if (!seed.correctForMaterial(mTrkParams[0].LayerxX0[iLayer - 1], mTrkParams[0].LayerxX0[iLayer - 1] * constants::Radl * constants::Rho, true)) { continue; } - // no need for further checks on cell level - - const CellSeed& currentCell{currentCellSeed[iCell]}; - const int cellId = currentCellId.empty() ? iCell : currentCellId[iCell]; - const int startNeighbourId{cellId ? mTimeFrame->getCellsNeighboursLUT()[iLayer - 1][cellId - 1] : 0}; - const int endNeighbourId{mTimeFrame->getCellsNeighboursLUT()[iLayer - 1][cellId]}; - - int offset = perCellCount[iCell]; - for (int iNeighbourCell{startNeighbourId}; iNeighbourCell < endNeighbourId; ++iNeighbourCell) { - const int neighbourCellId = mTimeFrame->getCellsNeighbours()[iLayer - 1][iNeighbourCell]; - const CellSeed& neighbourCell = mTimeFrame->getCells()[iLayer - 1][neighbourCellId]; - if (neighbourCell.getSecondTrackletIndex() != currentCell.getFirstTrackletIndex() || - mTimeFrame->isClusterUsed(iLayer - 1, neighbourCell.getFirstClusterIndex()) || - currentCell.getLevel() - 1 != neighbourCell.getLevel()) { - continue; - } + } - auto seed = currentCell; + auto predChi2{seed.getPredictedChi2Quiet(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)}; + if ((predChi2 > mTrkParams[0].MaxChi2ClusterAttachment) || predChi2 < 0.f) { + CA_DEBUGGER(failed[3]++); + continue; + } + seed.setChi2(seed.getChi2() + predChi2); + if (!seed.o2::track::TrackParCov::update(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)) { + CA_DEBUGGER(failed[4]++); + continue; + } - const auto& trHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer - 1)[neighbourCell.getFirstClusterIndex()]; - if (!seed.rotate(trHit.alphaTrackingFrame) || !propagator->propagateToX(seed, trHit.xTrackingFrame, getBz(), o2::base::PropagatorImpl::MAX_SIN_PHI, o2::base::PropagatorImpl::MAX_STEP, mCorrType)) { - continue; - } + if constexpr (decltype(Tag)::value != PassMode::TwoPassCount::value) { + seed.getClusters()[iLayer - 1] = neighbourCell.getFirstClusterIndex(); + seed.setLevel(neighbourCell.getLevel()); + seed.setFirstTrackletIndex(neighbourCell.getFirstTrackletIndex()); + seed.setSecondTrackletIndex(neighbourCell.getSecondTrackletIndex()); + } - if (mCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { - if (!seed.correctForMaterial(mTrkParams[0].LayerxX0[iLayer - 1], mTrkParams[0].LayerxX0[iLayer - 1] * constants::Radl * constants::Rho, true)) { - continue; - } - } + if constexpr (decltype(Tag)::value == PassMode::OnePass::value) { + updatedCellSeeds.push_back(seed); + updatedCellsIds.push_back(neighbourCellId); + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassCount::value) { + ++foundSeeds; + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassInsert::value) { + updatedCellSeeds[offset] = seed; + updatedCellsIds[offset++] = neighbourCellId; + } else { + static_assert(false, "Unknown mode!"); + } + } + return foundSeeds; + }; - auto predChi2{seed.getPredictedChi2Quiet(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)}; - if ((predChi2 > mTrkParams[0].MaxChi2ClusterAttachment) || predChi2 < 0.f) { - continue; - } - seed.setChi2(seed.getChi2() + predChi2); - if (!seed.o2::track::TrackParCov::update(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)) { - continue; - } + const int nCells = static_cast(currentCellSeed.size()); + if (mTaskArena->max_concurrency() <= 1) { + for (int iCell{0}; iCell < nCells; ++iCell) { + forCellNeighbours(PassMode::OnePass{}, iCell); + } + } else { + bounded_vector perCellCount(nCells + 1, 0, mMemoryPool.get()); + tbb::parallel_for( + tbb::blocked_range(0, nCells), + [&](const tbb::blocked_range& Cells) { + for (int iCell = Cells.begin(); iCell < Cells.end(); ++iCell) { + perCellCount[iCell] = forCellNeighbours(PassMode::TwoPassCount{}, iCell); + } + }); - seed.getClusters()[iLayer - 1] = neighbourCell.getFirstClusterIndex(); - seed.setLevel(neighbourCell.getLevel()); - seed.setFirstTrackletIndex(neighbourCell.getFirstTrackletIndex()); - seed.setSecondTrackletIndex(neighbourCell.getSecondTrackletIndex()); + std::exclusive_scan(perCellCount.begin(), perCellCount.end(), perCellCount.begin(), 0); + auto totalNeighbours{perCellCount.back()}; + if (totalNeighbours == 0) { + return; + } + updatedCellSeeds.resize(totalNeighbours); + updatedCellsIds.resize(totalNeighbours); - updatedCellSeeds[offset] = seed; - updatedCellsIds[offset++] = neighbourCellId; + tbb::parallel_for( + tbb::blocked_range(0, nCells), + [&](const tbb::blocked_range& Cells) { + for (int iCell = Cells.begin(); iCell < Cells.end(); ++iCell) { + int offset = perCellCount[iCell]; + if (offset == perCellCount[iCell + 1]) { + continue; + } + forCellNeighbours(PassMode::TwoPassInsert{}, iCell, offset); } - } - }); + }); + } }); #ifdef CA_DEBUG @@ -812,66 +751,74 @@ void TrackerTraits::findRoads(const int iteration) } bounded_vector tracks(mMemoryPool.get()); - mTaskArena.execute([&] { - bounded_vector perSeedCount(trackSeeds.size() + 1, 0, mMemoryPool.get()); - tbb::parallel_for( - tbb::blocked_range(0, (int)trackSeeds.size()), - [&](const tbb::blocked_range& Seeds) { - for (int iSeed = Seeds.begin(); iSeed < Seeds.end(); ++iSeed) { - const CellSeed& seed{trackSeeds[iSeed]}; - TrackITSExt temporaryTrack{seed}; - temporaryTrack.resetCovariance(); - temporaryTrack.setChi2(0); - for (int iL{0}; iL < 7; ++iL) { - temporaryTrack.setExternalClusterIndex(iL, seed.getCluster(iL), seed.getCluster(iL) != constants::UnusedIndex); - } + mTaskArena->execute([&] { + auto forSeed = [&](auto Tag, int iSeed, int offset = 0) { + const CellSeed& seed{trackSeeds[iSeed]}; + TrackITSExt temporaryTrack{seed}; + temporaryTrack.resetCovariance(); + temporaryTrack.setChi2(0); + for (int iL{0}; iL < 7; ++iL) { + temporaryTrack.setExternalClusterIndex(iL, seed.getCluster(iL), seed.getCluster(iL) != constants::UnusedIndex); + } - bool fitSuccess = fitTrack(temporaryTrack, 0, mTrkParams[0].NLayers, 1, mTrkParams[0].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF); - if (!fitSuccess) { - continue; - } - temporaryTrack.getParamOut() = temporaryTrack.getParamIn(); - temporaryTrack.resetCovariance(); - temporaryTrack.setChi2(0); - fitSuccess = fitTrack(temporaryTrack, mTrkParams[0].NLayers - 1, -1, -1, mTrkParams[0].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF, 50.f); - if (!fitSuccess || temporaryTrack.getPt() < mTrkParams[iteration].MinPt[mTrkParams[iteration].NLayers - temporaryTrack.getNClusters()]) { - continue; - } - ++perSeedCount[iSeed]; - } - }); - std::exclusive_scan(perSeedCount.begin(), perSeedCount.end(), perSeedCount.begin(), 0); - auto totalTracks{perSeedCount.back()}; - if (totalTracks == 0) { - return; - } - tracks.resize(totalTracks); + bool fitSuccess = fitTrack(temporaryTrack, 0, mTrkParams[0].NLayers, 1, mTrkParams[0].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF); + if (!fitSuccess) { + return 0; + } - tbb::parallel_for( - tbb::blocked_range(0, (int)trackSeeds.size()), - [&](const tbb::blocked_range& Seeds) { - for (int iSeed = Seeds.begin(); iSeed < Seeds.end(); ++iSeed) { - if (perSeedCount[iSeed] == perSeedCount[iSeed + 1]) { - continue; - } - const CellSeed& seed{trackSeeds[iSeed]}; - auto& trk = tracks[perSeedCount[iSeed]] = TrackITSExt(seed); - trk.resetCovariance(); - trk.setChi2(0); - for (int iL{0}; iL < 7; ++iL) { - trk.setExternalClusterIndex(iL, seed.getCluster(iL), seed.getCluster(iL) != constants::UnusedIndex); + temporaryTrack.getParamOut() = temporaryTrack.getParamIn(); + temporaryTrack.resetCovariance(); + temporaryTrack.setChi2(0); + fitSuccess = fitTrack(temporaryTrack, mTrkParams[0].NLayers - 1, -1, -1, mTrkParams[0].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF, 50.f); + if (!fitSuccess || temporaryTrack.getPt() < mTrkParams[iteration].MinPt[mTrkParams[iteration].NLayers - temporaryTrack.getNClusters()]) { + return 0; + } + + if constexpr (decltype(Tag)::value == PassMode::OnePass::value) { + tracks.push_back(temporaryTrack); + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassCount::value) { + // nothing to do + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassInsert::value) { + tracks[offset] = temporaryTrack; + } else { + static_assert(false, "Unknown mode!"); + } + return 1; + }; + + const int nSeeds = static_cast(trackSeeds.size()); + if (mTaskArena->max_concurrency() <= 1) { + for (int iSeed{0}; iSeed < nSeeds; ++iSeed) { + forSeed(PassMode::OnePass{}, iSeed); + } + } else { + bounded_vector perSeedCount(nSeeds + 1, 0, mMemoryPool.get()); + tbb::parallel_for( + tbb::blocked_range(0, nSeeds), + [&](const tbb::blocked_range& Seeds) { + for (int iSeed = Seeds.begin(); iSeed < Seeds.end(); ++iSeed) { + perSeedCount[iSeed] = forSeed(PassMode::TwoPassCount{}, iSeed); } + }); - bool fitSuccess = fitTrack(trk, 0, mTrkParams[0].NLayers, 1, mTrkParams[0].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF); - if (!fitSuccess) { - continue; + std::exclusive_scan(perSeedCount.begin(), perSeedCount.end(), perSeedCount.begin(), 0); + auto totalTracks{perSeedCount.back()}; + if (totalTracks == 0) { + return; + } + tracks.resize(totalTracks); + + tbb::parallel_for( + tbb::blocked_range(0, nSeeds), + [&](const tbb::blocked_range& Seeds) { + for (int iSeed = Seeds.begin(); iSeed < Seeds.end(); ++iSeed) { + if (perSeedCount[iSeed] == perSeedCount[iSeed + 1]) { + continue; + } + forSeed(PassMode::TwoPassInsert{}, iSeed, perSeedCount[iSeed]); } - trk.getParamOut() = trk.getParamIn(); - trk.resetCovariance(); - trk.setChi2(0); - fitTrack(trk, mTrkParams[0].NLayers - 1, -1, -1, mTrkParams[0].MaxChi2ClusterAttachment, mTrkParams[0].MaxChi2NDF, 50.f); - } - }); + }); + } deepVectorClear(trackSeeds); tbb::parallel_sort(tracks.begin(), tracks.end(), [](const auto& a, const auto& b) { @@ -1258,17 +1205,19 @@ bool TrackerTraits::isMatLUT() const } template -void TrackerTraits::setNThreads(int n) +void TrackerTraits::setNThreads(int n, std::shared_ptr& arena) { - if (mNThreads == n && mTaskArena.is_active()) { - return; - } - mNThreads = n > 0 ? n : 1; #if defined(OPTIMISATION_OUTPUT) || defined(CA_DEBUG) - mNThreads = 1; // only works while serial + mTaskArena = std::make_shared(1); +#else + if (arena == nullptr) { + mTaskArena = std::make_shared(std::abs(n)); + LOGP(info, "Setting tracker with {} threads.", n); + } else { + mTaskArena = arena; + LOGP(info, "Attaching tracker to calling thread's arena"); + } #endif - mTaskArena.initialize(mNThreads); - LOGP(info, "Setting tracker with {} threads.", mNThreads); } template class TrackerTraits<7>; diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index b6b4796690905..15348bca9fde7 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -16,6 +16,7 @@ #include "ITSReconstruction/FastMultEst.h" #include "ITStracking/TrackingInterface.h" +#include #include #include "DataFormatsITSMFT/ROFRecord.h" @@ -148,6 +149,20 @@ void ITSTrackingInterface::initialise() } mTracker->setParameters(trackParams); mVertexer->setParameters(vertParams); + if (trackConf.nThreads == vertConf.nThreads) { + bool clamped{false}; + int nThreads = trackConf.nThreads; + if (nThreads > 0) { + const int hw = std::thread::hardware_concurrency(); + const int maxThreads = (hw == 0 ? 1 : hw); + nThreads = std::clamp(nThreads, 1, maxThreads); + clamped = trackConf.nThreads > maxThreads; + } + LOGP(info, "Tracker and Vertexer will share the task arena with {} thread(s){}", nThreads, (clamped) ? " (clamped)" : ""); + mTaskArena = std::make_shared(std::abs(nThreads)); + } + mVertexer->setNThreads(vertConf.nThreads, mTaskArena); + mTracker->setNThreads(trackConf.nThreads, mTaskArena); } void ITSTrackingInterface::run(framework::ProcessingContext& pc) diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index 37b650c05bd61..51cd98aa1366d 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -11,6 +11,7 @@ /// #include +#include #include #include @@ -168,13 +169,12 @@ void VertexerTraits::updateVertexingParameters(const std::vector(std::ceil(mIndexTableUtils.getNphiBins() * par.phiCut / o2::constants::math::TwoPI)); par.zSpan = static_cast(std::ceil(par.zCut * mIndexTableUtils.getInverseZCoordinate(0))); } - setNThreads(vrtPar[0].nThreads); } // Main functions void VertexerTraits::computeTracklets(const int iteration) { - mTaskArena.execute([&] { + mTaskArena->execute([&] { tbb::parallel_for( tbb::blocked_range(0, (short)mTimeFrame->getNrof()), [&](const tbb::blocked_range& Rofs) { @@ -220,7 +220,7 @@ void VertexerTraits::computeTracklets(const int iteration) mTimeFrame->getTracklets()[0].resize(mTimeFrame->getTotalTrackletsTF(0)); mTimeFrame->getTracklets()[1].resize(mTimeFrame->getTotalTrackletsTF(1)); - mTaskArena.execute([&] { + mTaskArena->execute([&] { tbb::parallel_for( tbb::blocked_range(0, (short)mTimeFrame->getNrof()), [&](const tbb::blocked_range& Rofs) { @@ -329,7 +329,7 @@ void VertexerTraits::computeTracklets(const int iteration) void VertexerTraits::computeTrackletMatching(const int iteration) { - mTaskArena.execute([&] { + mTaskArena->execute([&] { tbb::parallel_for( tbb::blocked_range(0, (short)mTimeFrame->getNrof()), [&](const tbb::blocked_range& Rofs) { @@ -687,15 +687,17 @@ void VertexerTraits::computeVerticesInRof(int rofId, verticesInRof.push_back(foundVertices); } -void VertexerTraits::setNThreads(int n) +void VertexerTraits::setNThreads(int n, std::shared_ptr& arena) { - if (mNThreads == n && mTaskArena.is_active()) { - return; - } - mNThreads = n > 0 ? n : 1; #if defined(VTX_DEBUG) - mNThreads = 1; + mTaskArena = std::make_shared(1); +#else + if (arena == nullptr) { + mTaskArena = std::make_shared(std::abs(n)); + LOGP(info, "Setting seeding vertexer with {} threads.", n); + } else { + mTaskArena = arena; + LOGP(info, "Attaching vertexer to calling thread's arena"); + } #endif - mTaskArena.initialize(mNThreads); - LOGP(info, "Setting seeding vertexer with {} threads.", mNThreads); } From b8829ab72db3a170dad0ba0f7c6ff77d5d81fff7 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 20 Jun 2025 01:27:37 +0200 Subject: [PATCH 048/315] Add more info to MCStudy w-flow --- .../GlobalTrackingStudy/TrackMCStudyConfig.h | 2 + .../GlobalTrackingStudy/TrackMCStudyTypes.h | 25 ++++++++-- .../study/src/TrackMCStudy.cxx | 48 ++++++++++++++----- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyConfig.h b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyConfig.h index 3c04affd99cb2..74d77eb3d53de 100644 --- a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyConfig.h +++ b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyConfig.h @@ -28,6 +28,8 @@ struct TrackMCStudyConfig : o2::conf::ConfigurableParamHelper occTPCV{}; o2::track::TrackPar track{}; o2::MCCompLabel label{}; float occTPC = -1.f; @@ -52,8 +52,24 @@ struct MCTrackInfo { uint8_t maxTPCRowSect = -1; int8_t nITSCl = 0; int8_t pattITSCl = 0; - bool addedAtRecStage = false; - ClassDefNV(MCTrackInfo, 5); + uint8_t flags = 0; + + enum Flags : uint32_t { Primary = 0, + AddedAtRecStage = 2, + BitMask = 0xff }; + + bool isPrimary() const { return isBitSet(Primary); } + bool isAddedAtRecStage() const { return isBitSet(AddedAtRecStage); } + void setPrimary() { setBit(Primary); } + void setAddedAtRecStage() { setBit(AddedAtRecStage); } + + uint8_t getBits() const { return flags; } + bool isBitSet(int bit) const { return flags & (0xff & (0x1 << bit)); } + void setBits(std::uint8_t b) { flags = b; } + void setBit(int bit) { flags |= BitMask & (0x1 << bit); } + void resetBit(int bit) { flags &= ~(BitMask & (0x1 << bit)); } + + ClassDefNV(MCTrackInfo, 7); }; struct RecTrack { @@ -272,7 +288,8 @@ struct MCVertex { int nTrackSel = 0; // number of selected MC charged tracks int ID = -1; std::vector recVtx{}; - ClassDefNV(MCVertex, 1); + std::vector occTPCV{}; + ClassDefNV(MCVertex, 2); }; } // namespace o2::trackstudy diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx index 7c53cf1467494..fa8cadf3a115c 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx @@ -109,7 +109,7 @@ class TrackMCStudy : public Task void updateTimeDependentParams(ProcessingContext& pc); float getDCAYCut(float pt) const; - gsl::span mCurrMCTracks; + const std::vector* mCurrMCTracks = nullptr; TVector3 mCurrMCVertex; o2::tpc::VDriftHelper mTPCVDriftHelper{}; o2::tpc::CorrectionMapsLoader mTPCCorrMapsLoader{}; @@ -124,7 +124,7 @@ class TrackMCStudy : public Task bool mCheckSV = false; //< check SV binding (apart from prongs availability) bool mRecProcStage = false; //< flag that the MC particle was added only at the stage of reco tracks processing int mNTPCOccBinLength = 0; ///< TPC occ. histo bin length in TBs - float mNTPCOccBinLengthInv; + float mNTPCOccBinLengthInv = -1.f; int mVerbose = 0; float mITSTimeBiasMUS = 0.f; float mITSROFrameLengthMUS = 0.f; ///< ITS RO frame in mus @@ -182,7 +182,7 @@ void TrackMCStudy::run(ProcessingContext& pc) } mDecProdLblPool.clear(); mMCVtVec.clear(); - mCurrMCTracks = {}; + mCurrMCTracks = nullptr; recoData.collectData(pc, *mDataRequest.get()); // select tracks of needed type, with minimal cuts, the real selected will be done in the vertexer updateTimeDependentParams(pc); // Make sure this is called after recoData.collectData, which may load some conditions @@ -346,6 +346,21 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData) } break; } + if (mNTPCOccBinLengthInv > 0.f) { + mcVtx.occTPCV.resize(params.nOccBinsDrift); + int grp = TMath::Max(1, TMath::Nint(params.nTBPerOccBin * mNTPCOccBinLengthInv)); + for (int ib = 0; ib < params.nOccBinsDrift; ib++) { + float smb = 0; + int tbs = occBin + TMath::Nint(ib * params.nTBPerOccBin * mNTPCOccBinLengthInv); + for (int ig = 0; ig < grp; ig++) { + if (tbs >= 0 && tbs < int(mTBinClOccHist.size())) { + smb += mTBinClOccHist[tbs]; + } + tbs++; + } + mcVtx.occTPCV[ib] = smb; + } + } if (rofCount >= ITSClusROFRec.size()) { mITSOcc.push_back(0); // IR after the last ROF } @@ -362,13 +377,15 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData) if (nev != (int)mMCVtVec.size()) { LOGP(debug, "source {} has {} events while {} MC vertices were booked", curSrcMC, nev, mMCVtVec.size()); okAccVtx = false; + if (nev > (int)mMCVtVec.size()) { // QED + continue; + } } for (curEvMC = 0; curEvMC < nev; curEvMC++) { if (mVerbose > 1) { LOGP(info, "Event {}", curEvMC); } - const auto& mt = mcReader.getTracks(curSrcMC, curEvMC); - mCurrMCTracks = gsl::span(mt.data(), mt.size()); + mCurrMCTracks = &mcReader.getTracks(curSrcMC, curEvMC); const_cast(mcReader.getMCEventHeader(curSrcMC, curEvMC)).GetVertex(mCurrMCVertex); if (okAccVtx) { auto& pos = mMCVtVec[curEvMC].pos; @@ -378,7 +395,7 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData) pos[2] = mCurrMCVertex.Z(); } } - for (int itr = 0; itr < mCurrMCTracks.size(); itr++) { + for (int itr = 0; itr < mCurrMCTracks->size(); itr++) { processMCParticle(curSrcMC, curEvMC, itr); } } @@ -425,11 +442,10 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData) if (lbl.getSourceID() != curSrcMC || lbl.getEventID() != curEvMC) { curSrcMC = lbl.getSourceID(); curEvMC = lbl.getEventID(); - const auto& mt = mcReader.getTracks(curSrcMC, curEvMC); - mCurrMCTracks = gsl::span(mt.data(), mt.size()); + mCurrMCTracks = &mcReader.getTracks(curSrcMC, curEvMC); const_cast(mcReader.getMCEventHeader(curSrcMC, curEvMC)).GetVertex(mCurrMCVertex); } - if (!acceptMCCharged(mCurrMCTracks[lbl.getTrackID()], lbl)) { + if (!acceptMCCharged((*mCurrMCTracks)[lbl.getTrackID()], lbl)) { continue; } entry = mSelMCTracks.find(lbl); @@ -977,7 +993,7 @@ float TrackMCStudy::getDCAYCut(float pt) const bool TrackMCStudy::processMCParticle(int src, int ev, int trid) { - const auto& mcPart = mCurrMCTracks[trid]; + const auto& mcPart = (*mCurrMCTracks)[trid]; int pdg = mcPart.GetPdgCode(); bool res = false; while (true) { @@ -999,7 +1015,7 @@ bool TrackMCStudy::processMCParticle(int src, int ev, int trid) break; } for (int idd = idd0; idd <= idd1; idd++) { - const auto& product = mCurrMCTracks[idd]; + const auto& product = (*mCurrMCTracks)[idd]; auto lbld = o2::MCCompLabel(idd, ev, src); if (!acceptMCCharged(product, lbld, decay)) { decay = -1; // discard decay @@ -1097,11 +1113,17 @@ bool TrackMCStudy::addMCParticle(const MCTrack& mcPart, const o2::MCCompLabel& l mcEntry.mcTrackInfo.bcInTF = mIntBC[lb.getEventID()]; mcEntry.mcTrackInfo.occTPC = mTPCOcc[lb.getEventID()]; mcEntry.mcTrackInfo.occITS = mITSOcc[lb.getEventID()]; - mcEntry.mcTrackInfo.addedAtRecStage = mRecProcStage; + mcEntry.mcTrackInfo.occTPCV = mMCVtVec[lb.getEventID()].occTPCV; + if (mRecProcStage) { + mcEntry.mcTrackInfo.setAddedAtRecStage(); + } + if (o2::mcutils::MCTrackNavigator::isPhysicalPrimary(mcPart, *mCurrMCTracks)) { + mcEntry.mcTrackInfo.setPrimary(); + } int moth = -1; o2::MCCompLabel mclbPar; if ((moth = mcPart.getMotherTrackId()) >= 0) { - const auto& mcPartPar = mCurrMCTracks[moth]; + const auto& mcPartPar = (*mCurrMCTracks)[moth]; mcEntry.mcTrackInfo.pdgParent = mcPartPar.GetPdgCode(); } if (mcPart.isPrimary() && mcReader.getNEvents(lb.getSourceID()) == mMCVtVec.size()) { From b71ab71489436b1d57c807d6a04557b0eb4a6f7a Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 19 Jun 2025 14:11:51 +0200 Subject: [PATCH 049/315] GPU TPC QA: Ignore fake tracks for clone track computation --- GPU/GPUTracking/qa/GPUQA.cxx | 16 +++++++++++----- GPU/GPUTracking/qa/GPUQA.h | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/GPU/GPUTracking/qa/GPUQA.cxx b/GPU/GPUTracking/qa/GPUQA.cxx index 45ccdc783891c..e65246968cefa 100644 --- a/GPU/GPUTracking/qa/GPUQA.cxx +++ b/GPU/GPUTracking/qa/GPUQA.cxx @@ -165,7 +165,7 @@ static constexpr bool CLUST_HIST_INT_SUM = false; static constexpr const int32_t COLORCOUNT = 12; -static const constexpr char* EFF_TYPES[4] = {"Rec", "Clone", "Fake", "All"}; +static const constexpr char* EFF_TYPES[5] = {"Rec", "Clone", "Fake", "All", "RecAndClone"}; static const constexpr char* FINDABLE_NAMES[2] = {"", "Findable"}; static const constexpr char* PRIM_NAMES[2] = {"Prim", "Sec"}; static const constexpr char* PARAMETER_NAMES[5] = {"Y", "Z", "#Phi", "#lambda", "Relative #it{p}_{T}"}; @@ -439,7 +439,7 @@ int32_t GPUQA::InitQACreateHistograms() char name[2048], fname[1024]; if (mQATasks & taskTrackingEff) { // Create Efficiency Histograms - for (int32_t i = 0; i < 4; i++) { + for (int32_t i = 0; i < 5; i++) { for (int32_t j = 0; j < 2; j++) { for (int32_t k = 0; k < 2; k++) { for (int32_t l = 0; l < 5; l++) { @@ -454,7 +454,9 @@ int32_t GPUQA::InitQACreateHistograms() mEff[i][j][k][l]->Sumw2(); } strcat(name, "_eff"); - createHist(mEffResult[i][j][k][l], name); + if (i < 4) { + createHist(mEffResult[i][j][k][l], name); + } } } } @@ -2122,15 +2124,18 @@ int32_t GPUQA::DrawQAHistograms(TObjArray* qcout) gErrorIgnoreLevel = kError; mEffResult[0][j / 2][j % 2][i]->Divide(mEff[l][j / 2][j % 2][i], mEff[3][j / 2][j % 2][i], "cl=0.683 b(1,1) mode"); gErrorIgnoreLevel = oldLevel; - mEff[3][j / 2][j % 2][i]->Reset(); // Sum up rec + clone + fake for clone/fake rate + mEff[3][j / 2][j % 2][i]->Reset(); // Sum up rec + clone + fake for fake rate mEff[3][j / 2][j % 2][i]->Add(mEff[0][j / 2][j % 2][i]); mEff[3][j / 2][j % 2][i]->Add(mEff[1][j / 2][j % 2][i]); mEff[3][j / 2][j % 2][i]->Add(mEff[2][j / 2][j % 2][i]); + mEff[4][j / 2][j % 2][i]->Reset(); // Sum up rec + clone for clone rate + mEff[4][j / 2][j % 2][i]->Add(mEff[0][j / 2][j % 2][i]); + mEff[4][j / 2][j % 2][i]->Add(mEff[1][j / 2][j % 2][i]); } else { // Divide fake/clone auto oldLevel = gErrorIgnoreLevel; gErrorIgnoreLevel = kError; - mEffResult[l][j / 2][j % 2][i]->Divide(mEff[l][j / 2][j % 2][i], mEff[3][j / 2][j % 2][i], "cl=0.683 b(1,1) mode"); + mEffResult[l][j / 2][j % 2][i]->Divide(mEff[l][j / 2][j % 2][i], mEff[l == 1 ? 4 : 3][j / 2][j % 2][i], "cl=0.683 b(1,1) mode"); gErrorIgnoreLevel = oldLevel; } } @@ -2143,6 +2148,7 @@ int32_t GPUQA::DrawQAHistograms(TObjArray* qcout) e->Write(); if (l == 2) { mEff[3][j / 2][j % 2][i]->Write(); // Store also all histogram! + mEff[4][j / 2][j % 2][i]->Write(); // Store also all histogram! } } } else if (GetHist(e, tin, k, nNewInput) == nullptr) { diff --git a/GPU/GPUTracking/qa/GPUQA.h b/GPU/GPUTracking/qa/GPUQA.h index 87900b5279ec0..3d5030e20dba5 100644 --- a/GPU/GPUTracking/qa/GPUQA.h +++ b/GPU/GPUTracking/qa/GPUQA.h @@ -258,7 +258,7 @@ class GPUQA std::vector mClusterParam; int32_t mNTotalFakes = 0; - TH1F* mEff[4][2][2][5]; // eff,clone,fake,all - findable - secondaries - y,z,phi,eta,pt - work,result + TH1F* mEff[5][2][2][5]; // eff,clone,fake,all,all-fake - findable - secondaries - y,z,phi,eta,pt - work,result TGraphAsymmErrors* mEffResult[4][2][2][5]; TCanvas* mCEff[6]; TPad* mPEff[6][4]; From 269941bd68af8bbd1d72ab48569867ddc55686eb Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 17 Jun 2025 14:13:20 +0200 Subject: [PATCH 050/315] gpu-reco-workflow should never add readers, remove leftover when copying from tpc-reco-workflow --- GPU/Workflow/src/gpu-reco-workflow.cxx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/GPU/Workflow/src/gpu-reco-workflow.cxx b/GPU/Workflow/src/gpu-reco-workflow.cxx index 4583e138b7579..0e7ec38962b11 100644 --- a/GPU/Workflow/src/gpu-reco-workflow.cxx +++ b/GPU/Workflow/src/gpu-reco-workflow.cxx @@ -220,12 +220,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) taskPrepare->options()}); } - if (!cfgc.options().get("ignore-dist-stf")) { - GlobalTrackID::mask_t srcTrk = GlobalTrackID::getSourcesMask("none"); - GlobalTrackID::mask_t srcCl = GlobalTrackID::getSourcesMask("TPC"); - o2::globaltracking::InputHelper::addInputSpecs(cfgc, specs, srcCl, srcTrk, srcTrk, doMC); - } - // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit o2::raw::HBFUtilsInitializer hbfIni(cfgc, specs); From de3063cf8200c0e83b353f417578eeb0bf6b99c6 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 17 Jun 2025 14:14:28 +0200 Subject: [PATCH 051/315] GPUWorkflow: fix decompressTPCFromROOT option --- GPU/Workflow/src/gpu-reco-workflow.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Workflow/src/gpu-reco-workflow.cxx b/GPU/Workflow/src/gpu-reco-workflow.cxx index 0e7ec38962b11..561d537b5c251 100644 --- a/GPU/Workflow/src/gpu-reco-workflow.cxx +++ b/GPU/Workflow/src/gpu-reco-workflow.cxx @@ -166,8 +166,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) cfg.lumiScaleMode = sclOpt.lumiMode; cfg.enableMShape = sclOpt.enableMShapeCorrection; cfg.enableCTPLumi = sclOpt.requestCTPLumi; - cfg.decompressTPC = isEnabled(inputTypes, ioType::CompClustCTF); cfg.decompressTPCFromROOT = isEnabled(inputTypes, ioType::CompClustROOT); + cfg.decompressTPC = isEnabled(inputTypes, ioType::CompClustCTF) || cfg.decompressTPCFromROOT; cfg.zsDecoder = isEnabled(inputTypes, ioType::ZSRaw); cfg.zsOnTheFly = isEnabled(inputTypes, ioType::ZSRawOTF); cfg.caClusterer = cfg.zsDecoder || cfg.zsOnTheFly || isEnabled(inputTypes, ioType::Digits); From bef11c6b01f476c798e763a011f18fb2295fd67d Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 19 Jun 2025 16:03:06 +0200 Subject: [PATCH 052/315] GPU Workflow: Do not request TPC Cluster MC labels if we do not run TPC tracking --- GPU/Workflow/src/GPUWorkflowSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Workflow/src/GPUWorkflowSpec.cxx b/GPU/Workflow/src/GPUWorkflowSpec.cxx index 8a755a703705f..6293fce842231 100644 --- a/GPU/Workflow/src/GPUWorkflowSpec.cxx +++ b/GPU/Workflow/src/GPUWorkflowSpec.cxx @@ -1193,7 +1193,7 @@ Inputs GPURecoWorkflowSpec::inputs() inputs.emplace_back(InputSpec{"mclblin", ConcreteDataTypeMatcher{gDataOriginTPC, "DIGITSMCTR"}, Lifetime::Timeframe}); mPolicyData->emplace_back(o2::framework::InputSpec{"digitsmc", o2::framework::ConcreteDataTypeMatcher{"TPC", "DIGITSMCTR"}}); } - } else { + } else if (mSpecConfig.runTPCTracking) { inputs.emplace_back(InputSpec{"mclblin", ConcreteDataTypeMatcher{gDataOriginTPC, "CLNATIVEMCLBL"}, Lifetime::Timeframe}); mPolicyData->emplace_back(o2::framework::InputSpec{"clustersmc", o2::framework::ConcreteDataTypeMatcher{"TPC", "CLNATIVEMCLBL"}}); } From 4f406ccad4cafa9afc201cda81b9232a2bd517c8 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 20 Jun 2025 09:45:23 +0200 Subject: [PATCH 053/315] GPU Display Vulkan: Workaround for bogus old Vulkan versions that report the patch version as vulkan version --- GPU/GPUTracking/display/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/display/CMakeLists.txt b/GPU/GPUTracking/display/CMakeLists.txt index 513d9b6122c68..3280a0655ce9f 100644 --- a/GPU/GPUTracking/display/CMakeLists.txt +++ b/GPU/GPUTracking/display/CMakeLists.txt @@ -31,7 +31,8 @@ if(ALIGPU_BUILD_TYPE STREQUAL "O2") endif() if(Vulkan_FOUND) - if(NOT ${Vulkan_VERSION} VERSION_GREATER_EQUAL "1.3.0" OR Vulkan_GLSLC_EXECUTABLE STREQUAL "Vulkan_GLSLC_EXECUTABLE-NOTFOUND") + string(FIND "${Vulkan_VERSION}" "." vulkan_dot_index) + if(NOT ${Vulkan_VERSION} VERSION_GREATER_EQUAL "1.3.0" OR dot_index EQUAL -1 OR Vulkan_GLSLC_EXECUTABLE STREQUAL "Vulkan_GLSLC_EXECUTABLE-NOTFOUND") set(Vulkan_FOUND 0) endif() endif() From ece12c56cf83a7be9e4b92d8c1b7721820b0aef9 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 20 Jun 2025 15:31:23 +0200 Subject: [PATCH 054/315] GPU Standalone: Fix typo for event dump file name --- GPU/GPUTracking/Definitions/GPUDef.h | 2 +- GPU/GPUTracking/Standalone/Benchmark/standalone.cxx | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUDef.h b/GPU/GPUTracking/Definitions/GPUDef.h index e1b34af55d62d..8ca361dd5003a 100644 --- a/GPU/GPUTracking/Definitions/GPUDef.h +++ b/GPU/GPUTracking/Definitions/GPUDef.h @@ -34,7 +34,7 @@ #define GPUPtr2(a, b) b #endif -#define GPUCA_EVDUMP_FILE "event_full" +#define GPUCA_EVDUMP_FILE "event" #ifdef GPUCA_GPUCODE #define CA_MAKE_SHARED_REF(vartype, varname, varglobal, varshared) const GPUsharedref() vartype& __restrict__ varname = varshared; diff --git a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx index a624e1e55ed4b..ae02f9e9051c4 100644 --- a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx +++ b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx @@ -522,10 +522,9 @@ int32_t ReadEvent(int32_t n) if ((configStandalone.proc.runQA || configStandalone.eventDisplay) && !configStandalone.QA.noMC) { chainTracking->ForceInitQA(); chainTracking->GetQA()->UpdateChain(chainTracking); - if (chainTracking->GetQA()->ReadO2MCData((eventsDir + "mc." + std::to_string(n) + ".dump").c_str())) { - if (chainTracking->GetQA()->ReadO2MCData((eventsDir + "mc.0.dump").c_str()) && configStandalone.proc.runQA) { - throw std::runtime_error("Error reading O2 MC dump"); - } + if (chainTracking->GetQA()->ReadO2MCData((eventsDir + "mc." + std::to_string(n) + ".dump").c_str()) && + chainTracking->GetQA()->ReadO2MCData((eventsDir + "mc.0.dump").c_str()) && configStandalone.proc.runQA) { + throw std::runtime_error("Error reading O2 MC dump"); } } #endif @@ -817,6 +816,9 @@ int32_t main(int argc, char** argv) } nEvents = nEventsInDirectory; } + if (nEvents == 0 && !configStandalone.noEvents) { + printf("No event data found in event folder\n"); + } if (configStandalone.TF.nMerge > 1) { nEvents /= configStandalone.TF.nMerge; } From f2417fb6a6f7da32f544a820825664ffe35fe165 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 23 Jun 2025 09:53:51 +0200 Subject: [PATCH 055/315] ITS3: fix tracking after refactor (#14433) --- .../tracking/include/ITStracking/TimeFrame.h | 3 +- .../ITSMFT/ITS/tracking/src/TimeFrame.cxx | 30 +++++++++++-------- .../ITS3/reconstruction/src/IOUtils.cxx | 2 ++ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h index 248e63aef382c..8b857df7cdd80 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h @@ -91,6 +91,7 @@ struct TimeFrame { gsl::span::iterator& pattIt, const itsmft::TopologyDictionary* dict, const dataformats::MCTruthContainer* mcLabels = nullptr); + void resetROFrameData(); int getTotalClusters() const; auto& getTotVertIteration() { return mTotVertPerIteration; } @@ -138,7 +139,7 @@ struct TimeFrame { gsl::span getClusterLabels(int layerId, const int clId) const { return mClusterLabels->getLabels(mClusterExternalIndices[layerId][clId]); } int getClusterExternalIndex(int layerId, const int clId) const { return mClusterExternalIndices[layerId][clId]; } int getClusterSize(int clusterId) const { return mClusterSize[clusterId]; } - void setClusterSize(const bounded_vector& v) { mClusterSize = v; } + void setClusterSize(bounded_vector& v) { mClusterSize = std::move(v); } auto& getTrackletsLabel(int layer) { return mTrackletLabels[layer]; } auto& getCellsLabel(int layer) { return mCellLabels[layer]; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx index 1a3132413c450..9c683112791ab 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx @@ -136,18 +136,7 @@ int TimeFrame::loadROFrameData(gsl::span rofs, const itsmft::TopologyDictionary* dict, const dataformats::MCTruthContainer* mcLabels) { - for (int iLayer{0}; iLayer < nLayers; ++iLayer) { - deepVectorClear(mUnsortedClusters[iLayer], mMemoryPool.get()); - deepVectorClear(mTrackingFrameInfo[iLayer], mMemoryPool.get()); - deepVectorClear(mClusterExternalIndices[iLayer], mMemoryPool.get()); - clearResizeBoundedVector(mROFramesClusters[iLayer], 1, mMemoryPool.get(), 0); - - if (iLayer < 2) { - deepVectorClear(mTrackletsIndexROF[iLayer], mMemoryPool.get()); - deepVectorClear(mNTrackletsPerCluster[iLayer], mMemoryPool.get()); - deepVectorClear(mNTrackletsPerClusterSum[iLayer], mMemoryPool.get()); - } - } + resetROFrameData(); GeometryTGeo* geom = GeometryTGeo::Instance(); geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); @@ -213,6 +202,23 @@ int TimeFrame::loadROFrameData(gsl::span rofs, return mNrof; } +template +void TimeFrame::resetROFrameData() +{ + for (int iLayer{0}; iLayer < nLayers; ++iLayer) { + deepVectorClear(mUnsortedClusters[iLayer], mMemoryPool.get()); + deepVectorClear(mTrackingFrameInfo[iLayer], mMemoryPool.get()); + deepVectorClear(mClusterExternalIndices[iLayer], mMemoryPool.get()); + clearResizeBoundedVector(mROFramesClusters[iLayer], 1, mMemoryPool.get(), 0); + + if (iLayer < 2) { + deepVectorClear(mTrackletsIndexROF[iLayer], mMemoryPool.get()); + deepVectorClear(mNTrackletsPerCluster[iLayer], mMemoryPool.get()); + deepVectorClear(mNTrackletsPerClusterSum[iLayer], mMemoryPool.get()); + } + } +} + template void TimeFrame::prepareClusters(const TrackingParameters& trkParam, const int maxLayers) { diff --git a/Detectors/Upgrades/ITS3/reconstruction/src/IOUtils.cxx b/Detectors/Upgrades/ITS3/reconstruction/src/IOUtils.cxx index a01eb77af1677..acba8022e376f 100644 --- a/Detectors/Upgrades/ITS3/reconstruction/src/IOUtils.cxx +++ b/Detectors/Upgrades/ITS3/reconstruction/src/IOUtils.cxx @@ -64,6 +64,8 @@ int loadROFrameDataITS3(its::TimeFrame<7>* tf, const its3::TopologyDictionary* dict, const dataformats::MCTruthContainer* mcLabels) { + tf->resetROFrameData(); + auto geom = its::GeometryTGeo::Instance(); geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); From ead329bb619c79251b1b2aba50556364198ecfe5 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Thu, 5 Jun 2025 11:04:27 +0200 Subject: [PATCH 056/315] EPNstderrMonitor: remove static declaration of InfoLoggerMessageOption when sending messages to IL --- Utilities/EPNMonitoring/src/EPNstderrMonitor.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/EPNMonitoring/src/EPNstderrMonitor.cxx b/Utilities/EPNMonitoring/src/EPNstderrMonitor.cxx index d7a7282a78684..035cbd705d769 100644 --- a/Utilities/EPNMonitoring/src/EPNstderrMonitor.cxx +++ b/Utilities/EPNMonitoring/src/EPNstderrMonitor.cxx @@ -133,7 +133,7 @@ void EPNMonitor::sendLog(const std::string& file, const std::string& message, co if (mInfoLoggerActive) { mLoggerContext->setField(InfoLogger::InfoLoggerContext::FieldName::Facility, ("stderr/" + file).substr(0, 31)); mLoggerContext->setField(InfoLogger::InfoLoggerContext::FieldName::Run, mRunNumber != 0 ? std::to_string(mRunNumber) : "unspecified"); - static const InfoLogger::InfoLogger::InfoLoggerMessageOption opt = {severity, level, InfoLogger::InfoLogger::undefinedMessageOption.errorCode, InfoLogger::InfoLogger::undefinedMessageOption.sourceFile, InfoLogger::InfoLogger::undefinedMessageOption.sourceLine}; + const InfoLogger::InfoLogger::InfoLoggerMessageOption opt = {severity, level, InfoLogger::InfoLogger::undefinedMessageOption.errorCode, InfoLogger::InfoLogger::undefinedMessageOption.sourceFile, InfoLogger::InfoLogger::undefinedMessageOption.sourceLine}; mLogger->log(opt, *mLoggerContext, "stderr: %s", file == "SYSLOG" ? (std::string("[GLOBAL SYSLOG]: ") + message).c_str() : message.c_str()); } else { printf("stderr: [%c] %s: %s\n", severity, file.c_str(), message.c_str()); From 3c55949a494894a76e5ef22efddfe251e37bb176 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 24 Jun 2025 10:15:07 +0200 Subject: [PATCH 057/315] ITS: GPU add needed synchronization (#14439) --- Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 2191880374548..8c6367c221583 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -1217,6 +1217,8 @@ void processNeighboursHandler(const int startLayer, maxChi2ClusterAttachment, propagator, matCorrType); + GPUChkErrS(cudaPeekAtLastError()); + GPUChkErrS(cudaDeviceSynchronize()); int level = startLevel; thrust::device_vector> lastCellId(allocInt); @@ -1276,6 +1278,8 @@ void processNeighboursHandler(const int startLayer, maxChi2ClusterAttachment, propagator, matCorrType); + GPUChkErrS(cudaPeekAtLastError()); + GPUChkErrS(cudaDeviceSynchronize()); } thrust::device_vector> outSeeds(updatedCellSeed.size(), allocCellSeed); auto end = thrust::copy_if(updatedCellSeed.begin(), updatedCellSeed.end(), outSeeds.begin(), gpu::seed_selector(1.e3, maxChi2NDF * ((startLevel + 2) * 2 - 5))); From e1a32f71dac4b04be3f4001d864b641e554a76f3 Mon Sep 17 00:00:00 2001 From: ehellbar Date: Tue, 24 Jun 2025 14:29:58 +0200 Subject: [PATCH 058/315] DPL: enable new EoS by default and set data processing and exit transition timeouts (#14429) * DPL: set data processing and exit transition timeouts by default to enable new EoS * adjust data processing and exit transition timeouts in O2Control test --- Framework/Core/src/O2ControlHelpers.cxx | 4 ++-- Framework/Core/src/runDataProcessing.cxx | 6 ++++-- .../test/test_FrameworkDataFlowToO2Control.cxx | 16 ++++++++-------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Framework/Core/src/O2ControlHelpers.cxx b/Framework/Core/src/O2ControlHelpers.cxx index 48d564e4ee4f0..273950e5047f0 100644 --- a/Framework/Core/src/O2ControlHelpers.cxx +++ b/Framework/Core/src/O2ControlHelpers.cxx @@ -369,8 +369,8 @@ void dumpTask(std::ostream& dumpOut, const DeviceSpec& spec, const DeviceExecuti dumpOut << indLevel << "defaults:\n"; dumpOut << indLevel << indScheme << "log_task_stdout: none\n"; dumpOut << indLevel << indScheme << "log_task_stderr: none\n"; - std::string exitTransitionTimeout = "15"; // Allow 15 seconds to finish processing and calibrations - std::string dataProcessingTimeout = "10"; // Allow only ten seconds to finish processing + std::string exitTransitionTimeout = "25"; // Allow 25 seconds to finish processing and calibrations + std::string dataProcessingTimeout = "20"; // Allow only 20 seconds to finish processing if (execution.args.size() > 2) { for (size_t i = 0; i < execution.args.size() - 1; ++i) { if (strcmp(execution.args[i], "--exit-transition-timeout") == 0) { diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index a7e80134a2cc0..f1111da79edd5 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1033,10 +1033,12 @@ int doChild(int argc, char** argv, ServiceRegistry& serviceRegistry, std::string defaultInfologgerMode = ""; o2::framework::DeploymentMode deploymentMode = o2::framework::DefaultsHelpers::deploymentMode(); if (deploymentMode == o2::framework::DeploymentMode::OnlineDDS) { - defaultExitTransitionTimeout = "20"; + defaultExitTransitionTimeout = "40"; + defaultDataProcessingTimeout = "20"; defaultInfologgerMode = "infoLoggerD"; } else if (deploymentMode == o2::framework::DeploymentMode::OnlineECS) { - defaultExitTransitionTimeout = "20"; + defaultExitTransitionTimeout = "25"; + defaultDataProcessingTimeout = "20"; } boost::program_options::options_description optsDesc; ConfigParamsHelper::populateBoostProgramOptions(optsDesc, spec.options, gHiddenDeviceOptions); diff --git a/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx b/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx index 9cdbc357f9674..32dd0b5922a4f 100644 --- a/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx +++ b/Framework/Core/test/test_FrameworkDataFlowToO2Control.cxx @@ -138,8 +138,8 @@ const std::vector expectedTasks{ defaults: log_task_stdout: none log_task_stderr: none - exit_transition_timeout: 15 - data_processing_timeout: 10 + exit_transition_timeout: 25 + data_processing_timeout: 20 _module_cmdline: >- source /etc/profile.d/modules.sh && MODULEPATH={{ modulepath }} module load O2 QualityControl Control-OCCPlugin && {{ dpl_command }} | bcsadc/foo @@ -236,8 +236,8 @@ const std::vector expectedTasks{ defaults: log_task_stdout: none log_task_stderr: none - exit_transition_timeout: 15 - data_processing_timeout: 10 + exit_transition_timeout: 25 + data_processing_timeout: 20 _module_cmdline: >- source /etc/profile.d/modules.sh && MODULEPATH={{ modulepath }} module load O2 QualityControl Control-OCCPlugin && {{ dpl_command }} | foo @@ -336,8 +336,8 @@ const std::vector expectedTasks{ defaults: log_task_stdout: none log_task_stderr: none - exit_transition_timeout: 15 - data_processing_timeout: 10 + exit_transition_timeout: 25 + data_processing_timeout: 20 _module_cmdline: >- source /etc/profile.d/modules.sh && MODULEPATH={{ modulepath }} module load O2 QualityControl Control-OCCPlugin && {{ dpl_command }} | foo @@ -436,8 +436,8 @@ const std::vector expectedTasks{ defaults: log_task_stdout: none log_task_stderr: none - exit_transition_timeout: 15 - data_processing_timeout: 10 + exit_transition_timeout: 25 + data_processing_timeout: 20 _module_cmdline: >- source /etc/profile.d/modules.sh && MODULEPATH={{ modulepath }} module load O2 QualityControl Control-OCCPlugin && {{ dpl_command }} | foo From 0d55348cf853b6bdab626f20890f48d99695210e Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 24 Jun 2025 10:28:43 +0200 Subject: [PATCH 059/315] DigiContext: Bugfix for start of history effect Under certain circumstances, we got a wrong interactions included for the timeframe history effect. This was essentially due to wrong variable initialization and is now fixed. --- DataFormats/simulation/src/DigitizationContext.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DataFormats/simulation/src/DigitizationContext.cxx b/DataFormats/simulation/src/DigitizationContext.cxx index e5b4d6e706732..d840809a4c446 100644 --- a/DataFormats/simulation/src/DigitizationContext.cxx +++ b/DataFormats/simulation/src/DigitizationContext.cxx @@ -452,18 +452,18 @@ std::vector> getTimeFrameBoundaries(std::vector(std::floor(orbit_timeframe_early_fractional)); auto bc_early = (uint32_t)((orbit_timeframe_early_fractional - orbit_timeframe_early_integral) * o2::constants::lhc::LHCMaxBunches); // this is the interaction record of the ti-th timeframe start - o2::InteractionRecord timeframe_start_record(0, orbit_timeframe_early_integral); + o2::InteractionRecord timeframe_start_record(0, orbit_timeframe_start); // this is the interaction record in some previous timeframe after which interactions could still // influence the ti-th timeframe according to orbitsEarly o2::InteractionRecord timeframe_early_record(bc_early, orbit_timeframe_early_integral); From 41279c2f65c0d7c8cba2d50dfde764e4f809f26d Mon Sep 17 00:00:00 2001 From: Chunzheng Wang <83008337+ChunzhengLab@users.noreply.github.com> Date: Tue, 24 Jun 2025 18:29:12 +0200 Subject: [PATCH 060/315] ITS3: move the energy deposition wrt. centre of response (#14415) * move the energy deposition wrt. centre of response * fix the order of IB/OB for noise seeding * print out the resp centre in the CheckChipResponseFile * find the real centre * should use the total eff but not only seed --- .../ITS3/macros/test/CheckChipResponseFile.C | 68 ++++++++++------- .../simulation/src/ChipDigitsContainer.cxx | 8 +- .../ITS3/simulation/src/ChipSimResponse.cxx | 76 +++++++++++++------ 3 files changed, 97 insertions(+), 55 deletions(-) diff --git a/Detectors/Upgrades/ITS3/macros/test/CheckChipResponseFile.C b/Detectors/Upgrades/ITS3/macros/test/CheckChipResponseFile.C index 996a99d87ecbc..32d5bad87ce21 100644 --- a/Detectors/Upgrades/ITS3/macros/test/CheckChipResponseFile.C +++ b/Detectors/Upgrades/ITS3/macros/test/CheckChipResponseFile.C @@ -24,6 +24,7 @@ #define ENABLE_UPGRADES #include "ITSMFTSimulation/AlpideSimResponse.h" +#include "ITS3Simulation/ChipSimResponse.h" #include "ITS3Base/SegmentationMosaix.h" #include "fairlogger/Logger.h" @@ -34,21 +35,21 @@ using SegmentationMosaix = o2::its3::SegmentationMosaix; double um2cm(double um) { return um * 1e-4; } double cm2um(double cm) { return cm * 1e+4; } -o2::itsmft::AlpideSimResponse *mAlpSimResp0 = nullptr, - *mAlpSimResp1 = nullptr, - *mAptSimResp1 = nullptr; +std::unique_ptr mAlpSimResp0, mAlpSimResp1, mAptSimResp1; -o2::itsmft::AlpideSimResponse* loadResponse(const std::string& fileName, const std::string& respName) +std::unique_ptr loadResponse(const std::string& fileName, const std::string& respName) { TFile* f = TFile::Open(fileName.data()); if (!f) { std::cerr << fileName << " not found" << std::endl; return nullptr; } - auto resp = (o2::itsmft::AlpideSimResponse*)f->Get(respName.data()); - if (!resp) + auto base = f->Get(respName.c_str()); + if (!base) { std::cerr << respName << " not found in " << fileName << std::endl; - return resp; + return nullptr; + } + return std::make_unique(base); } void LoadRespFunc() @@ -56,39 +57,49 @@ void LoadRespFunc() std::string AptsFile = "$(O2_ROOT)/share/Detectors/Upgrades/ITS3/data/ITS3ChipResponseData/APTSResponseData.root"; std::string AlpideFile = "$(O2_ROOT)/share/Detectors/ITSMFT/data/AlpideResponseData/AlpideResponseData.root"; + std::cout << "=====================\n"; + LOGP(info, "ALPIDE Vbb=0V response"); mAlpSimResp0 = loadResponse(AlpideFile, "response0"); // Vbb=0V - LOG(info) << "ALPIDE Vbb=0V response" << std::endl; + mAlpSimResp0->computeCentreFromData(); mAlpSimResp0->print(); + LOGP(info, "Response Centre {}", mAlpSimResp0->getRespCentreDep()); + std::cout << "=====================\n"; + LOGP(info, "ALPIDE Vbb=-3V response"); mAlpSimResp1 = loadResponse(AlpideFile, "response1"); // Vbb=-3V - LOG(info) << "ALPIDE Vbb=-3V response" << std::endl; + mAlpSimResp1->computeCentreFromData(); mAlpSimResp1->print(); + LOGP(info, "Response Centre {}", mAlpSimResp1->getRespCentreDep()); + std::cout << "=====================\n"; + LOGP(info, "APTS response"); mAptSimResp1 = loadResponse(AptsFile, "response1"); // APTS - LOG(info) << "APTS response" << std::endl; + mAptSimResp1->computeCentreFromData(); mAptSimResp1->print(); + LOGP(info, "Response Centre {}", mAptSimResp1->getRespCentreDep()); + std::cout << "=====================\n"; } -std::vector getCollectionSeediciencies(o2::itsmft::AlpideSimResponse* resp, +std::vector getCollectionSeediciencies(o2::its3::ChipSimResponse* resp, const std::vector& depths) { std::vector seed; bool flipRow = false, flipCol = false; for (auto depth : depths) { auto rspmat = resp->getResponse(0.0, 0.0, - um2cm(depth) + resp->getDepthMin() + 1.e-9, + um2cm(depth) + 1.e-9, flipRow, flipCol); seed.push_back(rspmat ? rspmat->getValue(2, 2) : 0.f); } return seed; } -std::vector getShareValues(o2::itsmft::AlpideSimResponse* resp, +std::vector getShareValues(o2::its3::ChipSimResponse* resp, const std::vector& depths) { std::vector share; bool flipRow = false, flipCol = false; for (auto depth : depths) { auto rspmat = resp->getResponse(0.0, 0.0, - um2cm(depth) + resp->getDepthMin() + 1.e-9, + um2cm(depth) + 1.e-9, flipRow, flipCol); float s = 0; int npix = resp->getNPix(); @@ -103,14 +114,14 @@ std::vector getShareValues(o2::itsmft::AlpideSimResponse* resp, return share; } -std::vector getEffValues(o2::itsmft::AlpideSimResponse* resp, +std::vector getEffValues(o2::its3::ChipSimResponse* resp, const std::vector& depths) { std::vector all; bool flipRow = false, flipCol = false; for (auto depth : depths) { auto rspmat = resp->getResponse(0.0, 0.0, - um2cm(depth) + resp->getDepthMin() + 1.e-9, + um2cm(depth) + 1.e-9, flipRow, flipCol); float s = 0; int npix = resp->getNPix(); @@ -129,13 +140,16 @@ void CheckChipResponseFile() LoadRespFunc(); LOG(info) << "Response function loaded" << std::endl; - std::vector vecDepth(50); - for (int i = 0; i < 50; ++i) - vecDepth[i] = i; + std::vector vecDepth; + int numPoints = 100; + for (int i = 0; i < numPoints; ++i) { + float value = -50 + i * (100.0f / (numPoints - 1)); + vecDepth.push_back(value); + } int colors[] = {kOrange + 7, kRed + 1, kAzure + 4}; struct RespInfo { - o2::itsmft::AlpideSimResponse* resp; + std::unique_ptr& resp; std::string title; int color; }; @@ -145,7 +159,7 @@ void CheckChipResponseFile() {mAlpSimResp1, "ALPIDE Vbb=-3V", colors[2]}}; TCanvas* c1 = new TCanvas("c1", "c1", 800, 600); - TH1* frame = c1->DrawFrame(-1, -0.049, 50, 1.049); + TH1* frame = c1->DrawFrame(-50, -0.049, 50, 1.049); frame->SetTitle(";Depth(um);Charge Collection Seed / Share / Eff"); TLegend* leg = new TLegend(0.15, 0.5, 0.4, 0.85); leg->SetFillStyle(0); @@ -154,11 +168,11 @@ void CheckChipResponseFile() for (auto& r : responses) { if (!r.resp) continue; - auto seed = getCollectionSeediciencies(r.resp, vecDepth); - auto shr = getShareValues(r.resp, vecDepth); - auto all = getEffValues(r.resp, vecDepth); + auto seed = getCollectionSeediciencies(r.resp.get(), vecDepth); + auto shr = getShareValues(r.resp.get(), vecDepth); + auto all = getEffValues(r.resp.get(), vecDepth); - TGraph* grSeed = new TGraph(vecDepth.size(), vecDepth.data(), seed.data()); + auto grSeed = new TGraph(vecDepth.size(), vecDepth.data(), seed.data()); grSeed->SetTitle(Form("%s seed", r.title.c_str())); grSeed->SetLineColor(r.color); grSeed->SetLineWidth(2); @@ -168,7 +182,7 @@ void CheckChipResponseFile() grSeed->Draw("SAME LP"); leg->AddEntry(grSeed, Form("%s seed", r.title.c_str()), "lp"); - TGraph* grShare = new TGraph(vecDepth.size(), vecDepth.data(), shr.data()); + auto grShare = new TGraph(vecDepth.size(), vecDepth.data(), shr.data()); grShare->SetLineColor(r.color); grShare->SetLineWidth(2); grShare->SetMarkerColor(r.color); @@ -177,7 +191,7 @@ void CheckChipResponseFile() grShare->Draw("SAME LP"); leg->AddEntry(grShare, Form("%s share", r.title.c_str()), "p"); - TGraph* grEff = new TGraph(vecDepth.size(), vecDepth.data(), all.data()); + auto grEff = new TGraph(vecDepth.size(), vecDepth.data(), all.data()); grEff->SetLineColor(r.color); grEff->SetLineWidth(2); grEff->SetMarkerColor(r.color); diff --git a/Detectors/Upgrades/ITS3/simulation/src/ChipDigitsContainer.cxx b/Detectors/Upgrades/ITS3/simulation/src/ChipDigitsContainer.cxx index 102b15863683e..efe878536687d 100644 --- a/Detectors/Upgrades/ITS3/simulation/src/ChipDigitsContainer.cxx +++ b/Detectors/Upgrades/ITS3/simulation/src/ChipDigitsContainer.cxx @@ -31,12 +31,12 @@ void ChipDigitsContainer::addNoise(UInt_t rofMin, UInt_t rofMax, const o2::its3: int nel = 0; if (isIB()) { - // Inner barrel: use ITS3-specific noise interface with OB segmentation. - mean = params->getIBNoisePerPixel() * SegmentationOB::NPixels; + // Inner barrel: use ITS3-specific noise interface with IB segmentation. + mean = params->getIBNoisePerPixel() * SegmentationIB::NPixels; nel = static_cast(params->getIBChargeThreshold() * 1.1); } else { - // Outer barrel: use base class noise interface with IB segmentation. - mean = params->getNoisePerPixel() * SegmentationIB::NPixels; + // Outer barrel: use base class noise interface with OB segmentation. + mean = params->getNoisePerPixel() * SegmentationOB::NPixels; nel = static_cast(params->getChargeThreshold() * 1.1); } diff --git a/Detectors/Upgrades/ITS3/simulation/src/ChipSimResponse.cxx b/Detectors/Upgrades/ITS3/simulation/src/ChipSimResponse.cxx index 1c482983f0d0a..72b291fb0d653 100644 --- a/Detectors/Upgrades/ITS3/simulation/src/ChipSimResponse.cxx +++ b/Detectors/Upgrades/ITS3/simulation/src/ChipSimResponse.cxx @@ -25,38 +25,66 @@ void ChipSimResponse::initData(int tableNumber, std::string dataPath, const bool void ChipSimResponse::computeCentreFromData() { - std::vector zVec, qVec; const int npix = o2::itsmft::AlpideRespSimMat::getNPix(); + std::vector zVec, effVec; + zVec.reserve(mNBinDpt); + effVec.reserve(mNBinDpt); for (int iz = 0; iz < mNBinDpt; ++iz) { - size_t bin = iz + mNBinDpt * (0 + mNBinRow * 0); - const auto& mat = mData[bin]; - float val = mat.getValue(npix / 2, npix / 2); - float gz = mDptMin + iz / mStepInvDpt; - zVec.push_back(gz); - qVec.push_back(val); + int rev = mNBinDpt - 1 - iz; + float z = mDptMin + iz / mStepInvDpt; + float sum = 0.f; + const auto& mat = mData[rev]; + for (int ix = 0; ix < npix; ++ix) { + for (int iy = 0; iy < npix; ++iy) { + sum += mat.getValue(ix, iy); + } + } + zVec.push_back(z); + effVec.push_back(sum); } - std::vector> zqPairs; - for (size_t i = 0; i < zVec.size(); ++i) { - zqPairs.emplace_back(zVec[i], qVec[i]); - } - std::sort(zqPairs.begin(), zqPairs.end()); - zVec.clear(); - qVec.clear(); - for (auto& p : zqPairs) { - zVec.push_back(p.first); - qVec.push_back(p.second); - } + struct Bin { + float z0, z1, q0, q1, dq; + }; + std::vector bins; + bins.reserve(zVec.size() - 1); - float intQ = 0.f, intZQ = 0.f; + float totQ = 0.f; for (size_t i = 0; i + 1 < zVec.size(); ++i) { float z0 = zVec[i], z1 = zVec[i + 1]; - float q0 = qVec[i], q1 = qVec[i + 1]; - float dz = z1 - z0; - intQ += 0.5f * (q0 + q1) * dz; - intZQ += 0.5f * (z0 * q0 + z1 * q1) * dz; + float q0 = effVec[i], q1 = effVec[i + 1]; + float dq = 0.5f * (q0 + q1) * (z1 - z0); + bins.push_back({z0, z1, q0, q1, dq}); + totQ += dq; + } + + if (totQ <= 0.f) { + mRespCentreDep = mDptMin; + return; + } + + float halfQ = 0.5f * totQ; + float cumQ = 0.f; + for (auto& b : bins) { + if (cumQ + b.dq < halfQ) { + cumQ += b.dq; + continue; + } + float dz = b.z1 - b.z0; + float slope = (b.q1 - b.q0) / dz; + float disc = b.q0 * b.q0 - 2.f * slope * (cumQ - halfQ); + + float x; + if (disc >= 0.f && std::abs(slope) > 1e-6f) { + x = (-b.q0 + std::sqrt(disc)) / slope; + } else { + x = (halfQ - cumQ) / b.q0; + } + x = std::clamp(x, 0.f, dz); + mRespCentreDep = b.z0 + x; + return; } - mRespCentreDep = (intQ > 0.f) ? intZQ / intQ : 0.f; + mRespCentreDep = mDptMax; } From 2008bc4e50ef7e927242bc1a74c7b81156a7122e Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 24 Jun 2025 19:04:36 +0200 Subject: [PATCH 061/315] ITS: GPU report found neighbours (#14438) --- .../GPU/ITStrackingGPU/TimeFrameGPU.h | 21 +++++++++++++++++-- .../ITS/tracking/GPU/cuda/TimeFrameGPU.cu | 3 +++ .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 11 +++++----- .../tracking/include/ITStracking/TimeFrame.h | 6 +++--- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h index 82101dba4c02d..d41591e6ff25c 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h @@ -130,7 +130,9 @@ class TimeFrameGPU : public TimeFrame // Host-specific getters gsl::span getNTracklets() { return mNTracklets; } gsl::span getNCells() { return mNCells; } - std::array& getArrayNCells() { return mNCells; } + auto& getArrayNCells() { return mNCells; } + gsl::span getNNeighbours() { return mNNeighbours; } + auto& getArrayNNeighbours() { return mNNeighbours; } // Host-available device getters gsl::span getDeviceTrackletsLUTs() { return mTrackletsLUTDevice; } @@ -139,7 +141,9 @@ class TimeFrameGPU : public TimeFrame gsl::span getDeviceCells() { return mCellsDevice; } // Overridden getters - int getNumberOfCells() const; + int getNumberOfTracklets() const final; + int getNumberOfCells() const final; + int getNumberOfNeighbours() const final; private: void allocMemAsync(void**, size_t, Stream*, bool); // Abstract owned and unowned memory allocations @@ -149,6 +153,7 @@ class TimeFrameGPU : public TimeFrame // Host-available device buffer sizes std::array mNTracklets; std::array mNCells; + std::array mNNeighbours; // Device pointers IndexTableUtils* mIndexTableUtilsDevice; @@ -218,12 +223,24 @@ inline std::vector TimeFrameGPU::getClusterSizes() return sizes; } +template +inline int TimeFrameGPU::getNumberOfTracklets() const +{ + return std::accumulate(mNTracklets.begin(), mNTracklets.end(), 0); +} + template inline int TimeFrameGPU::getNumberOfCells() const { return std::accumulate(mNCells.begin(), mNCells.end(), 0); } +template +inline int TimeFrameGPU::getNumberOfNeighbours() const +{ + return std::accumulate(mNNeighbours.begin(), mNNeighbours.end(), 0); +} + } // namespace o2::its::gpu #endif diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu index 8380533a28e04..b336073604b62 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu @@ -342,6 +342,9 @@ void TimeFrameGPU::createNeighboursIndexTablesDevice() LOGP(debug, "gpu-transfer: loading neighbours LUT for {} elements on layer {}, for {} MB.", mNCells[iLayer], iLayer, mNCells[iLayer] * sizeof(CellSeed) / MB); allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (mNCells[iLayer] + 1) * sizeof(int), nullptr, this->getExtAllocator()); GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (mNCells[iLayer] + 1) * sizeof(int), mGpuStreams[0]->get())); + if (iLayer < nLayers - 3) { + mNNeighbours[iLayer] = 0; + } } STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); } diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index 89d2b5aeffe63..b32189f3fabe3 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -169,7 +169,7 @@ template void TrackerTraitsGPU::findCellsNeighbours(const int iteration) { mTimeFrameGPU->createNeighboursIndexTablesDevice(); - auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); + const auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); for (int iLayer{0}; iLayer < this->mTrkParams[iteration].CellsPerRoad() - 1; ++iLayer) { const int nextLayerCellsNum{static_cast(mTimeFrameGPU->getNCells()[iLayer + 1])}; @@ -208,10 +208,11 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) conf.nBlocks, conf.nThreads); - filterCellNeighboursHandler(mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), - mTimeFrameGPU->getDeviceNeighbours(iLayer), - nNeigh, - mTimeFrameGPU->getExternalAllocator()); + nNeigh = filterCellNeighboursHandler(mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), + mTimeFrameGPU->getDeviceNeighbours(iLayer), + nNeigh, + mTimeFrameGPU->getExternalAllocator()); + mTimeFrameGPU->getArrayNNeighbours()[iLayer] = nNeigh; } mTimeFrameGPU->createNeighboursDeviceArray(); mTimeFrameGPU->unregisterRest(); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h index 8b857df7cdd80..230a46681385d 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h @@ -175,9 +175,9 @@ struct TimeFrame { auto& getVerticesMCRecInfo() { return mVerticesMCRecInfo; } int getNumberOfClusters() const; - int getNumberOfCells() const; - int getNumberOfTracklets() const; - int getNumberOfNeighbours() const; + virtual int getNumberOfCells() const; + virtual int getNumberOfTracklets() const; + virtual int getNumberOfNeighbours() const; size_t getNumberOfTracks() const; size_t getNumberOfUsedClusters() const; auto getNumberOfExtendedTracks() const { return mNExtendedTracks; } From 2ca4db7b14535d5fe17397367baa54849ecbde2b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 24 Jun 2025 19:51:50 +0200 Subject: [PATCH 062/315] DPL: make sure Lifetime::Sporadic is kept (#14434) --- Framework/Core/include/Framework/FairMQDeviceProxy.h | 2 ++ Framework/Core/src/DataAllocator.cxx | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/FairMQDeviceProxy.h b/Framework/Core/include/Framework/FairMQDeviceProxy.h index 46b35f54f21ba..ab0d094c18486 100644 --- a/Framework/Core/include/Framework/FairMQDeviceProxy.h +++ b/Framework/Core/include/Framework/FairMQDeviceProxy.h @@ -40,6 +40,8 @@ class FairMQDeviceProxy void bind(std::vector const& outputs, std::vector const& inputs, std::vector const& forwards, fair::mq::Device& device); + /// Retrieve the transport associated to a given route. + [[nodiscard]] OutputRoute const& getOutputRoute(RouteIndex routeIndex) const { return mOutputs.at(routeIndex.value); } /// Retrieve the transport associated to a given route. [[nodiscard]] fair::mq::TransportFactory* getOutputTransport(RouteIndex routeIndex) const; /// Retrieve the transport associated to a given route. diff --git a/Framework/Core/src/DataAllocator.cxx b/Framework/Core/src/DataAllocator.cxx index ca35089fdfaab..4b559ef26191e 100644 --- a/Framework/Core/src/DataAllocator.cxx +++ b/Framework/Core/src/DataAllocator.cxx @@ -9,6 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include "Framework/CompilerBuiltins.h" +#include "Framework/Lifetime.h" #include "Framework/TableBuilder.h" #include "Framework/TableTreeHelpers.h" #include "Framework/DataAllocator.h" @@ -121,8 +122,12 @@ fair::mq::MessagePtr DataAllocator::headerMessageFromOutput(Output const& spec, dh.runNumber = timingInfo.runNumber; DataProcessingHeader dph{timingInfo.timeslice, 1, timingInfo.creation}; - static_cast(dph).flagsDerivedHeader |= timingInfo.keepAtEndOfStream ? DataProcessingHeader::KEEP_AT_EOS_FLAG : 0; auto& proxy = mRegistry.get(); + auto lifetime = proxy.getOutputRoute(routeIndex).matcher.lifetime; + static_cast(dph).flagsDerivedHeader |= timingInfo.keepAtEndOfStream ? DataProcessingHeader::KEEP_AT_EOS_FLAG : 0; + // Messages associated to sporatic output we always keep, since they are most likely histograms / condition + // objects which need to be kept at the end of stream. + static_cast(dph).flagsDerivedHeader |= (lifetime == Lifetime::Sporadic) ? DataProcessingHeader::KEEP_AT_EOS_FLAG : 0; auto* transport = proxy.getOutputTransport(routeIndex); auto channelAlloc = o2::pmr::getTransportAllocator(transport); From 907144be68eda1c0a4d1a9f6be4ef6283a6fe4d7 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 25 Jun 2025 00:43:34 +0200 Subject: [PATCH 063/315] Fix using namespace arrow, arrow::io (#14442) --- .../include/Framework/FairMQResizableBuffer.h | 25 ++++++++----------- Framework/Core/src/FairMQResizableBuffer.cxx | 14 ++++++----- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/Framework/Core/include/Framework/FairMQResizableBuffer.h b/Framework/Core/include/Framework/FairMQResizableBuffer.h index cdf2a22a2a56b..fc86d8d5dd753 100644 --- a/Framework/Core/include/Framework/FairMQResizableBuffer.h +++ b/Framework/Core/include/Framework/FairMQResizableBuffer.h @@ -24,13 +24,10 @@ namespace o2::framework { -using namespace arrow; -using namespace arrow::io; - -class FairMQOutputStream : public OutputStream +class FairMQOutputStream : public arrow::io::OutputStream { public: - explicit FairMQOutputStream(const std::shared_ptr& buffer); + explicit FairMQOutputStream(const std::shared_ptr& buffer); /// \brief Create in-memory output stream with indicated capacity using a /// memory pool @@ -38,8 +35,8 @@ class FairMQOutputStream : public OutputStream /// the OutputStream /// \param[in,out] pool a MemoryPool to use for allocations /// \return the created stream - static Result> Create( - int64_t initial_capacity = 4096, MemoryPool* pool = default_memory_pool()); + static arrow::Result> Create( + int64_t initial_capacity = 4096, arrow::MemoryPool* pool = arrow::default_memory_pool()); // By the time we call the destructor, the contents // of the buffer are already moved to fairmq @@ -49,24 +46,24 @@ class FairMQOutputStream : public OutputStream // Implement the OutputStream interface /// Close the stream, preserving the buffer (retrieve it with Finish()). - Status Close() override; + arrow::Status Close() override; [[nodiscard]] bool closed() const override; - [[nodiscard]] Result Tell() const override; - Status Write(const void* data, int64_t nbytes) override; + [[nodiscard]] arrow::Result Tell() const override; + arrow::Status Write(const void* data, int64_t nbytes) override; /// \cond FALSE using OutputStream::Write; /// \endcond /// Close the stream and return the buffer - Result> Finish(); + arrow::Result> Finish(); /// \brief Initialize state of OutputStream with newly allocated memory and /// set position to 0 /// \param[in] initial_capacity the starting allocated capacity /// \param[in,out] pool the memory pool to use for allocations /// \return Status - Status Reset(int64_t initial_capacity = 1024, MemoryPool* pool = default_memory_pool()); + arrow::Status Reset(int64_t initial_capacity = 1024, arrow::MemoryPool* pool = arrow::default_memory_pool()); [[nodiscard]] int64_t capacity() const { return capacity_; } @@ -74,9 +71,9 @@ class FairMQOutputStream : public OutputStream FairMQOutputStream(); // Ensures there is sufficient space available to write nbytes - Status Reserve(int64_t nbytes); + arrow::Status Reserve(int64_t nbytes); - std::shared_ptr buffer_; + std::shared_ptr buffer_; bool is_open_; int64_t capacity_; int64_t position_; diff --git a/Framework/Core/src/FairMQResizableBuffer.cxx b/Framework/Core/src/FairMQResizableBuffer.cxx index 9fe1cc882b6ae..592dfcb4376e9 100644 --- a/Framework/Core/src/FairMQResizableBuffer.cxx +++ b/Framework/Core/src/FairMQResizableBuffer.cxx @@ -16,6 +16,8 @@ #include #include +using arrow::Status; + namespace arrow::io::internal { void CloseFromDestructor(FileInterface* file); @@ -28,15 +30,15 @@ static constexpr int64_t kBufferMinimumSize = 256; FairMQOutputStream::FairMQOutputStream() : is_open_(false), capacity_(0), position_(0), mutable_data_(nullptr) {} -FairMQOutputStream::FairMQOutputStream(const std::shared_ptr& buffer) +FairMQOutputStream::FairMQOutputStream(const std::shared_ptr& buffer) : buffer_(buffer), is_open_(true), capacity_(buffer->size()), position_(0), mutable_data_(buffer->mutable_data()) {} -Result> FairMQOutputStream::Create( - int64_t initial_capacity, MemoryPool* pool) +arrow::Result> FairMQOutputStream::Create( + int64_t initial_capacity, arrow::MemoryPool* pool) { // ctor is private, so cannot use make_shared auto ptr = std::shared_ptr(new FairMQOutputStream); @@ -44,7 +46,7 @@ Result> FairMQOutputStream::Create( return ptr; } -Status FairMQOutputStream::Reset(int64_t initial_capacity, MemoryPool* pool) +Status FairMQOutputStream::Reset(int64_t initial_capacity, arrow::MemoryPool* pool) { ARROW_ASSIGN_OR_RAISE(buffer_, AllocateResizableBuffer(initial_capacity, pool)); is_open_ = true; @@ -67,7 +69,7 @@ Status FairMQOutputStream::Close() bool FairMQOutputStream::closed() const { return !is_open_; } -Result> FairMQOutputStream::Finish() +arrow::Result> FairMQOutputStream::Finish() { RETURN_NOT_OK(Close()); buffer_->ZeroPadding(); @@ -75,7 +77,7 @@ Result> FairMQOutputStream::Finish() return std::move(buffer_); } -Result FairMQOutputStream::Tell() const { return position_; } +arrow::Result FairMQOutputStream::Tell() const { return position_; } Status FairMQOutputStream::Write(const void* data, int64_t nbytes) { From 19e73ce40c0dfa6fc33cfc373e572049c98aa43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Wed, 25 Jun 2025 10:23:32 +0200 Subject: [PATCH 064/315] IWYU: BinningPolicy.h (#14323) --- Framework/Core/include/Framework/BinningPolicy.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/BinningPolicy.h b/Framework/Core/include/Framework/BinningPolicy.h index b5e9ba546c4d9..73548cbd6c6ed 100644 --- a/Framework/Core/include/Framework/BinningPolicy.h +++ b/Framework/Core/include/Framework/BinningPolicy.h @@ -12,8 +12,13 @@ #ifndef FRAMEWORK_BINNINGPOLICY_H #define FRAMEWORK_BINNINGPOLICY_H +#include "Framework/ASoA.h" #include "Framework/HistogramSpec.h" // only for VARIABLE_WIDTH -#include "Framework/Pack.h" + +#include +#include +#include +#include namespace o2::framework { From 92f546664861cb867defb425cde8f17cec686518 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 25 Jun 2025 16:22:00 +0200 Subject: [PATCH 065/315] Avoid missing dictionary (#14443) --- DataFormats/simulation/test/testBasicHits.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/simulation/test/testBasicHits.cxx b/DataFormats/simulation/test/testBasicHits.cxx index e81c173fedae8..ccd16ae7a3671 100644 --- a/DataFormats/simulation/test/testBasicHits.cxx +++ b/DataFormats/simulation/test/testBasicHits.cxx @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(BasicXYZHit_ROOTIO) } // same for double valued hits - using HitTypeD = BasicXYZEHit; + using HitTypeD = BasicXYZEHit; HitTypeD hitD(1., 2., 3., 0.01, -1.1, -1, 1); // try writing hit to a TBuffer From fa3dd7bc0eec6c3faf34bb8fdca6010c07609d97 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 24 Jun 2025 21:29:36 +0200 Subject: [PATCH 066/315] ITS: redefine seeding vertex label Signed-off-by: Felix Schlepper --- .../include/ITStracking/VertexerTraits.h | 20 ++++++++++++------- .../ITS/tracking/src/VertexerTraits.cxx | 18 ++++++++--------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index 6554e53fa2ee8..a842f04abfc62 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -101,19 +101,25 @@ class VertexerTraits virtual bool usesMemoryPool() const noexcept { return true; } void setMemoryPool(std::shared_ptr& pool) { mMemoryPool = pool; } - template - static std::pair computeMain(const bounded_vector& elements) + static std::pair computeMain(const bounded_vector& elements) { - T elem; + // we only care about the source&event of the tracks, not the trackId + auto composeVtxLabel = [](const o2::MCCompLabel& lbl) -> o2::MCCompLabel { + return {o2::MCCompLabel::maxTrackID(), lbl.getEventID(), lbl.getSourceID(), lbl.isFake()}; + }; + std::unordered_map frequency; + for (const auto& element : elements) { + ++frequency[composeVtxLabel(element)]; + } + o2::MCCompLabel elem{}; size_t maxCount = 0; - for (auto& element : elements) { - size_t count = std::count(elements.begin(), elements.end(), element); + for (const auto& [key, count] : frequency) { if (count > maxCount) { maxCount = count; - elem = element; + elem = key; } } - return std::make_pair(elem, static_cast(maxCount) / elements.size()); + return std::make_pair(elem, static_cast(maxCount) / static_cast(elements.size())); } protected: diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index 51cd98aa1366d..11304e17d234a 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -506,18 +506,18 @@ void VertexerTraits::computeVertices(const int iteration) if (beamDistance2 < nsigmaCut && o2::gpu::GPUCommonMath::Abs(mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[2]) < mVrtParams[iteration].maxZPositionAllowed) { atLeastOneFound = true; - vertices.emplace_back(o2::math_utils::Point3D(mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[0], - mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[1], - mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[2]), - mTimeFrame->getTrackletClusters(rofId)[iCluster].getRMS2(), // Symm matrix. Diagonal: RMS2 components, - // off-diagonal: square mean of projections on planes. - mTimeFrame->getTrackletClusters(rofId)[iCluster].getSize(), // Contributors - mTimeFrame->getTrackletClusters(rofId)[iCluster].getAvgDistance2()); // In place of chi2 + auto& vertex = vertices.emplace_back(o2::math_utils::Point3D(mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[0], + mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[1], + mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[2]), + mTimeFrame->getTrackletClusters(rofId)[iCluster].getRMS2(), // Symm matrix. Diagonal: RMS2 components, + // off-diagonal: square mean of projections on planes. + mTimeFrame->getTrackletClusters(rofId)[iCluster].getSize(), // Contributors + mTimeFrame->getTrackletClusters(rofId)[iCluster].getAvgDistance2()); // In place of chi2 if (iteration) { - vertices.back().setFlags(Vertex::UPCMode); + vertex.setFlags(Vertex::UPCMode); } - vertices.back().setTimeStamp(mTimeFrame->getTrackletClusters(rofId)[iCluster].getROF()); + vertex.setTimeStamp(mTimeFrame->getTrackletClusters(rofId)[iCluster].getROF()); if (mTimeFrame->hasMCinformation()) { bounded_vector labels(mMemoryPool.get()); for (auto& index : mTimeFrame->getTrackletClusters(rofId)[iCluster].getLabels()) { From ecb7932a38cc2ba37066efc3a8899b60d189df07 Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 23 Jun 2025 15:27:53 +0200 Subject: [PATCH 067/315] Move bulk of the code to cxx to not expose extra headers --- .../Detectors/ITSMFT/common/CMakeLists.txt | 9 +- .../include/DataFormatsITSMFT/TimeDeadMap.h | 95 ++--------------- .../ITSMFT/common/src/TimeDeadMap.cxx | 100 ++++++++++++++++++ 3 files changed, 113 insertions(+), 91 deletions(-) create mode 100644 DataFormats/Detectors/ITSMFT/common/src/TimeDeadMap.cxx diff --git a/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt b/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt index 62fc09ffcad00..96d376526a1a4 100644 --- a/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt +++ b/DataFormats/Detectors/ITSMFT/common/CMakeLists.txt @@ -18,6 +18,7 @@ o2_add_library(DataFormatsITSMFT src/ClusterPattern.cxx src/ClusterTopology.cxx src/TopologyDictionary.cxx + src/TimeDeadMap.cxx src/CTF.cxx PUBLIC_LINK_LIBRARIES O2::ITSMFTBase O2::ReconstructionDataFormats @@ -25,10 +26,10 @@ o2_add_library(DataFormatsITSMFT o2_target_root_dictionary(DataFormatsITSMFT HEADERS include/DataFormatsITSMFT/ROFRecord.h - include/DataFormatsITSMFT/Digit.h - include/DataFormatsITSMFT/GBTCalibData.h - include/DataFormatsITSMFT/NoiseMap.h - include/DataFormatsITSMFT/TimeDeadMap.h + include/DataFormatsITSMFT/Digit.h + include/DataFormatsITSMFT/GBTCalibData.h + include/DataFormatsITSMFT/NoiseMap.h + include/DataFormatsITSMFT/TimeDeadMap.h include/DataFormatsITSMFT/Cluster.h include/DataFormatsITSMFT/CompCluster.h include/DataFormatsITSMFT/ClusterPattern.h diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h index a0b214f705d7c..5a93cbb712931 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h @@ -15,8 +15,6 @@ #define ALICEO2_ITSMFT_TIMEDEADMAP_H #include "Rtypes.h" -#include "DetectorsCommonDataFormats/DetID.h" -#include #include #include @@ -26,6 +24,8 @@ namespace o2 namespace itsmft { +class NoiseMap; + class TimeDeadMap { public: @@ -56,96 +56,17 @@ class TimeDeadMap mStaticDeadMap.clear(); } - void decodeMap(o2::itsmft::NoiseMap& noisemap) - { // for static part only - if (mMAP_VERSION == "3") { - LOG(error) << "Trying to decode static part of deadmap version " << mMAP_VERSION << ". Not implemented, doing nothing."; - return; - } - for (int iel = 0; iel < mStaticDeadMap.size(); iel++) { - uint16_t w = mStaticDeadMap[iel]; - noisemap.maskFullChip(w & 0x7FFF); - if (w & 0x8000) { - for (int w2 = (w & 0x7FFF) + 1; w2 < mStaticDeadMap.at(iel + 1); w2++) { - noisemap.maskFullChip(w2); - } - } - } - } - - void decodeMap(unsigned long orbit, o2::itsmft::NoiseMap& noisemap, bool includeStaticMap = true, long orbitGapAllowed = 330000) - { // for time-dependent and (optionally) static part. Use orbitGapAllowed = -1 to ignore check on orbit difference - - if (mMAP_VERSION != "3" && mMAP_VERSION != "4") { - LOG(error) << "Trying to decode time-dependent deadmap version " << mMAP_VERSION << ". Not implemented, doing nothing."; - return; - } - - if (mEvolvingDeadMap.empty()) { - LOG(warning) << "Time-dependent dead map is empty. Doing nothing."; - return; - } - - std::vector closestVec; - long dT = getMapAtOrbit(orbit, closestVec); - - if (orbitGapAllowed >= 0 && std::abs(dT) > orbitGapAllowed) { - LOG(warning) << "Requested orbit " << orbit << ", found " << orbit - dT << ". Orbit gap is too high, skipping time-dependent map."; - closestVec.clear(); - } - - // add static part if requested. something may be masked twice - if (includeStaticMap && mMAP_VERSION != "3") { - closestVec.insert(closestVec.end(), mStaticDeadMap.begin(), mStaticDeadMap.end()); - } - - // vector encoding: if 1<<15 = 0x8000 is set, the word encodes the first element of a range, with mask (1<<15)-1 = 0x7FFF. The last element of the range is the next in the vector. - - for (int iel = 0; iel < closestVec.size(); iel++) { - uint16_t w = closestVec.at(iel); - noisemap.maskFullChip(w & 0x7FFF); - if (w & 0x8000) { - for (int w2 = (w & 0x7FFF) + 1; w2 < closestVec.at(iel + 1); w2++) { - noisemap.maskFullChip(w2); - } - } - } - }; - + void decodeMap(NoiseMap& noisemap) const; + void decodeMap(unsigned long orbit, o2::itsmft::NoiseMap& noisemap, bool includeStaticMap = true, long orbitGapAllowed = 330000) const; std::string getMapVersion() const { return mMAP_VERSION; }; unsigned long getEvolvingMapSize() const { return mEvolvingDeadMap.size(); }; - - std::vector getEvolvingMapKeys() - { - std::vector keys; - std::transform(mEvolvingDeadMap.begin(), mEvolvingDeadMap.end(), std::back_inserter(keys), - [](const auto& O) { return O.first; }); - return keys; - } - - void getStaticMap(std::vector& mmap) { mmap = mStaticDeadMap; }; - - long getMapAtOrbit(unsigned long orbit, std::vector& mmap) - { // fills mmap and returns requested_orbit - found_orbit. Found orbit is the highest key lower or equal to the requested one - if (mEvolvingDeadMap.empty()) { - LOG(warning) << "Requested orbit " << orbit << "from an empty time-dependent map. Doing nothing"; - return (long)orbit; - } - auto closest = mEvolvingDeadMap.upper_bound(orbit); - if (closest != mEvolvingDeadMap.begin()) { - --closest; - mmap = closest->second; - return (long)orbit - closest->first; - } else { - mmap = mEvolvingDeadMap.begin()->second; - return (long)(orbit)-mEvolvingDeadMap.begin()->first; - } - } - + std::vector getEvolvingMapKeys() const; + void getStaticMap(std::vector& mmap) const { mmap = mStaticDeadMap; }; + long getMapAtOrbit(unsigned long orbit, std::vector& mmap) const; void setMapVersion(std::string version) { mMAP_VERSION = version; }; - bool isDefault() { return mIsDefaultObject; }; + bool isDefault() const { return mIsDefaultObject; }; void setAsDefault(bool isdef = true) { mIsDefaultObject = isdef; }; private: diff --git a/DataFormats/Detectors/ITSMFT/common/src/TimeDeadMap.cxx b/DataFormats/Detectors/ITSMFT/common/src/TimeDeadMap.cxx new file mode 100644 index 0000000000000..e3df8e7f91f86 --- /dev/null +++ b/DataFormats/Detectors/ITSMFT/common/src/TimeDeadMap.cxx @@ -0,0 +1,100 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file TimeDeadMap.cxx +/// \brief Implementation of the time-dependent map + +#include "DataFormatsITSMFT/TimeDeadMap.h" +#include "DataFormatsITSMFT/NoiseMap.h" +#include "Framework/Logger.h" + +using namespace o2::itsmft; + +void TimeDeadMap::decodeMap(o2::itsmft::NoiseMap& noisemap) const +{ // for static part only + if (mMAP_VERSION == "3") { + LOG(error) << "Trying to decode static part of deadmap version " << mMAP_VERSION << ". Not implemented, doing nothing."; + return; + } + for (int iel = 0; iel < mStaticDeadMap.size(); iel++) { + uint16_t w = mStaticDeadMap[iel]; + noisemap.maskFullChip(w & 0x7FFF); + if (w & 0x8000) { + for (int w2 = (w & 0x7FFF) + 1; w2 < mStaticDeadMap.at(iel + 1); w2++) { + noisemap.maskFullChip(w2); + } + } + } +} + +void TimeDeadMap::decodeMap(unsigned long orbit, o2::itsmft::NoiseMap& noisemap, bool includeStaticMap, long orbitGapAllowed) const +{ // for time-dependent and (optionally) static part. Use orbitGapAllowed = -1 to ignore check on orbit difference + + if (mMAP_VERSION != "3" && mMAP_VERSION != "4") { + LOG(error) << "Trying to decode time-dependent deadmap version " << mMAP_VERSION << ". Not implemented, doing nothing."; + return; + } + + if (mEvolvingDeadMap.empty()) { + LOG(warning) << "Time-dependent dead map is empty. Doing nothing."; + return; + } + + std::vector closestVec; + long dT = getMapAtOrbit(orbit, closestVec); + + if (orbitGapAllowed >= 0 && std::abs(dT) > orbitGapAllowed) { + LOG(warning) << "Requested orbit " << orbit << ", found " << orbit - dT << ". Orbit gap is too high, skipping time-dependent map."; + closestVec.clear(); + } + + // add static part if requested. something may be masked twice + if (includeStaticMap && mMAP_VERSION != "3") { + closestVec.insert(closestVec.end(), mStaticDeadMap.begin(), mStaticDeadMap.end()); + } + + // vector encoding: if 1<<15 = 0x8000 is set, the word encodes the first element of a range, with mask (1<<15)-1 = 0x7FFF. The last element of the range is the next in the vector. + + for (int iel = 0; iel < closestVec.size(); iel++) { + uint16_t w = closestVec.at(iel); + noisemap.maskFullChip(w & 0x7FFF); + if (w & 0x8000) { + for (int w2 = (w & 0x7FFF) + 1; w2 < closestVec.at(iel + 1); w2++) { + noisemap.maskFullChip(w2); + } + } + } +} + +std::vector TimeDeadMap::getEvolvingMapKeys() const +{ + std::vector keys; + std::transform(mEvolvingDeadMap.begin(), mEvolvingDeadMap.end(), std::back_inserter(keys), + [](const auto& O) { return O.first; }); + return keys; +} + +long TimeDeadMap::getMapAtOrbit(unsigned long orbit, std::vector& mmap) const +{ // fills mmap and returns requested_orbit - found_orbit. Found orbit is the highest key lower or equal to the requested one + if (mEvolvingDeadMap.empty()) { + LOG(warning) << "Requested orbit " << orbit << "from an empty time-dependent map. Doing nothing"; + return (long)orbit; + } + auto closest = mEvolvingDeadMap.upper_bound(orbit); + if (closest != mEvolvingDeadMap.begin()) { + --closest; + mmap = closest->second; + return (long)orbit - closest->first; + } else { + mmap = mEvolvingDeadMap.begin()->second; + return (long)(orbit)-mEvolvingDeadMap.begin()->first; + } +} From a096a62bb2c719f93ab6be6600d48e015ffc0f4d Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer Date: Fri, 20 Jun 2025 16:28:14 +0200 Subject: [PATCH 068/315] GPU/TPCClusterFinder: Fix out-of-bounds write. --- .../TPCClusterFinder/GPUTPCCFStreamCompaction.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx index d43e96b19c5d0..0f2fd235dc0d0 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFStreamCompaction.cxx @@ -55,8 +55,9 @@ GPUdii() void GPUTPCCFStreamCompaction::Thread int32_t iThreadGlobal = get_global_id(0); int32_t offsetInBlock = work_group_scan_inclusive_add((iThreadGlobal < nElems) ? scanOffset[iThreadGlobal] : 0); - // TODO: This write isn't needed?? - scanOffset[iThreadGlobal] = offsetInBlock; + if (iThreadGlobal < nElems) { + scanOffset[iThreadGlobal] = offsetInBlock; + } int32_t lastThread = nThreads - 1; if (iThread == lastThread) { From 53b81b8262ec8c1d428fe66d5180a488d7c50013 Mon Sep 17 00:00:00 2001 From: Christian Sonnabend Date: Wed, 25 Jun 2025 22:23:23 +0200 Subject: [PATCH 069/315] Fix for cluster flags --- .../TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx index 58dd49630d8e6..bc8d26954b5dc 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx @@ -127,6 +127,8 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread chargeMap(reinterpret_cast(clusterer.mPchargeMap)); CfChargePos peak = clusterer.mPfilteredPeakPositions[idx + batchStart]; + clustererNN.mClusterFlags[2 * idx] = 0; + clustererNN.mClusterFlags[2 * idx + 1] = 0; for (int i = 0; i < 8; i++) { Delta2 d = cfconsts::InnerNeighbors[i]; CfChargePos tmp_pos = peak.delta(d); From 312ae1311c7629d37f972bbcf3deaa95ab7f16ed Mon Sep 17 00:00:00 2001 From: Christian Sonnabend Date: Wed, 25 Jun 2025 22:32:07 +0200 Subject: [PATCH 070/315] Cleanup + handling of deconvolution --- .../Global/GPUChainTrackingClusterizer.cxx | 53 +++---------------- 1 file changed, 6 insertions(+), 47 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx index 816ee43d50b15..b85505ccf5fda 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx @@ -977,20 +977,10 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) GPUTPCNNClusterizer& clustererNNShadow = doGPU ? processorsShadow()->tpcNNClusterer[lane] : clustererNN; GPUTPCNNClusterizerHost& nnApplication = nnApplications[lane]; - // // bool recreateMemoryAllocator = false; - // if (lane == 0) { - // (nnApplications[lane].mModelClass).initEnvironment(); - // nnApplications[lane].directOrtAllocator((nnApplications[lane].mModelClass).getEnv(), (nnApplications[lane].mModelClass).getMemoryInfo(), mRec, 0); - // } - // // recreateMemoryAllocator = true; - // (nnApplications[lane].mModelClass).initSession(); - // (nnApplications[lane].mModelReg1).initSession(); - int withMC = (doGPU && propagateMCLabels); - if (clustererNNShadow.mNnClusterizerUseCfRegression || (int)(nn_settings.nnClusterizerApplyCfDeconvolution)) { + if (nn_settings.nnClusterizerApplyCfDeconvolution) { runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}, true); - DoDebugAndDump(RecoStep::TPCClusterFinding, GPUChainTrackingDebugFlags::TPCClustererChargeMap, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges"); } else if (clustererNNShadow.mNnClusterizerSetDeconvolutionFlags) { runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}, false); } @@ -1007,9 +997,6 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, withMC, batchStart); // Filling the regression data } - // auto stop0 = std::chrono::high_resolution_clock::now(); - // auto start1 = std::chrono::high_resolution_clock::now(); - // NN evaluations if (clustererNNShadow.mNnInferenceInputDType == 0) { if (clustererNNShadow.mNnInferenceOutputDType == 0) { @@ -1055,8 +1042,6 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } } - // auto stopNNs = std::chrono::high_resolution_clock::now(); - // Publishing kernels if (nnApplication.mModelClass.getNumOutputNodes()[0][1] == 1) { runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, withMC, batchStart); // Assigning class labels @@ -1069,41 +1054,15 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, withMC, batchStart); // Publishing class 2 regression results } } - - // for(int i = 0; i < iSize; ++i) { - // if(clustererNNShadow.mOutputDataClass[i + batchStart] > 1) { - // LOG(info) << "WARNING ORT: Output of " << i + batchStart << " / " << clusterer.mPmemory->counters.nClusters << " is " << clustererNNShadow.mModelProbabilities_16[i].ToFloat() << " and " << clustererNNShadow.mOutputDataClass[i + batchStart] << " thresh " << clustererNNShadow.mNnClassThreshold << " instead of 0 or 1. Please check the model and the input data."; - // // std::string input = "["; - // // for(int j = 0; j < clustererNNShadow.mNnClusterizerElementSize; j++){ - // // input += std::to_string(clustererNNShadow.mInputData_16[i * clustererNNShadow.mNnClusterizerElementSize + j].ToFloat()) + ", "; - // // } - // // input += "]"; - // // LOG(info) << "Input is: " << input; - // } - // } - - // auto stop1 = std::chrono::high_resolution_clock::now(); - - // time_networks += std::chrono::duration_cast(stopNNs - start1).count() / 1e9; - // time_clusterizer += std::chrono::duration_cast(stop1 - start1).count() / 1e9; - // time_fill += std::chrono::duration_cast(stop0 - start0).count() / 1e9; } + if (clustererNNShadow.mNnClusterizerUseCfRegression) { - // auto start1 = std::chrono::high_resolution_clock::now(); + if(!nn_settings.nnClusterizerApplyCfDeconvolution) { + runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}, true); + } + DoDebugAndDump(RecoStep::TPCClusterFinding, GPUChainTrackingDebugFlags::TPCClustererChargeMap, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges"); runKernel({GetGrid(clusterer.mPmemory->counters.nClusters, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, withMC, 0); // Running the CF regression kernel - no batching needed: batchStart = 0 - // auto stop1 = std::chrono::high_resolution_clock::now(); - // time_clusterizer += std::chrono::duration_cast(stop1 - start1).count() / 1e9; } - // if (clustererNNShadow.mNnClusterizerVerbosity < 3) { - // int acceptedClusters = 0; - // for (size_t i = 0; i < clusterer.mPmemory->counters.nClusters; ++i) { - // if(clustererNNShadow.mOutputDataClass[i] > 1 || clustererNNShadow.mOutputDataClass[i] < 0) { - // LOG(info) << "WARNING ORT 2: " << clustererNNShadow.mOutputDataClass[i] << " for index " << i << " / " << clusterer.mPmemory->counters.nClusters; - // } - // acceptedClusters += clustererNNShadow.mOutputDataClass[i]; - // } - // LOG(info) << "[NN CF] Apply NN (fragment " << fragment.index << ", lane: " << lane << ", sector: " << iSector << "): filling data " << time_fill << "s ; networks: " << time_networks << "s ; clusterizer: " << time_clusterizer << "s ; " << clusterer.mPmemory->counters.nClusters << " clusters, " << acceptedClusters << " accepted. --> " << (int32_t)clusterer.mPmemory->counters.nClusters / (time_fill + time_clusterizer) << " clusters/s"; - // } #else GPUFatal("Project not compiled with neural network clusterization. Aborting."); #endif From eb292d802118b31a7afbe0670565da4f558efd5e Mon Sep 17 00:00:00 2001 From: Christian Sonnabend Date: Wed, 25 Jun 2025 22:33:58 +0200 Subject: [PATCH 071/315] Using only propagateMcLabels --- .../Global/GPUChainTrackingClusterizer.cxx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx index b85505ccf5fda..dd4cd6ef0be96 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx @@ -977,7 +977,7 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) GPUTPCNNClusterizer& clustererNNShadow = doGPU ? processorsShadow()->tpcNNClusterer[lane] : clustererNN; GPUTPCNNClusterizerHost& nnApplication = nnApplications[lane]; - int withMC = (doGPU && propagateMCLabels); + // int withMC = (doGPU && propagateMCLabels); if (nn_settings.nnClusterizerApplyCfDeconvolution) { runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}, true); @@ -991,10 +991,10 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) size_t iSize = CAMath::Min((uint)clustererNNShadow.mNnClusterizerBatchedMode, (uint)(clusterer.mPmemory->counters.nClusters - batchStart)); // auto start0 = std::chrono::high_resolution_clock::now(); - runKernel({GetGrid(iSize * clustererNNShadow.mNnClusterizerElementSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, withMC, batchStart); // Filling the data + runKernel({GetGrid(iSize * clustererNNShadow.mNnClusterizerElementSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, batchStart); // Filling the data if (clustererNNShadow.mNnClusterizerSetDeconvolutionFlags) { - runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, withMC, batchStart); // Filling the regression data + runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, batchStart); // Filling the regression data } // NN evaluations @@ -1044,14 +1044,14 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) // Publishing kernels if (nnApplication.mModelClass.getNumOutputNodes()[0][1] == 1) { - runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, withMC, batchStart); // Assigning class labels + runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, propagateMCLabels, batchStart); // Assigning class labels } else { - runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, withMC, batchStart); // Assigning class labels + runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, propagateMCLabels, batchStart); // Assigning class labels } if (!clustererNNShadow.mNnClusterizerUseCfRegression) { - runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, withMC, batchStart); // Publishing class 1 regression results + runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, propagateMCLabels, batchStart); // Publishing class 1 regression results if (nnApplication.mModelClass.getNumOutputNodes()[0][1] > 1 && nnApplication.mModelReg2.isInitialized()) { - runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, withMC, batchStart); // Publishing class 2 regression results + runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, propagateMCLabels, batchStart); // Publishing class 2 regression results } } } @@ -1061,7 +1061,7 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}, true); } DoDebugAndDump(RecoStep::TPCClusterFinding, GPUChainTrackingDebugFlags::TPCClustererChargeMap, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges"); - runKernel({GetGrid(clusterer.mPmemory->counters.nClusters, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, withMC, 0); // Running the CF regression kernel - no batching needed: batchStart = 0 + runKernel({GetGrid(clusterer.mPmemory->counters.nClusters, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, 0); // Running the CF regression kernel - no batching needed: batchStart = 0 } #else GPUFatal("Project not compiled with neural network clusterization. Aborting."); From d8dbc60590cb60cbe3398b20da6bb714bf28c4a4 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 23 Jun 2025 10:12:48 +0200 Subject: [PATCH 072/315] ITS: cleanup unused GPU code --- .../ITS/tracking/include/ITStracking/Cell.h | 16 -- .../tracking/include/ITStracking/Constants.h | 5 - .../ITS/tracking/include/ITStracking/Road.h | 7 +- GPU/GPUTracking/Base/GPUConstantMem.h | 2 - GPU/GPUTracking/CMakeLists.txt | 4 - .../Definitions/GPUDefParametersConstants.h | 1 - .../Definitions/GPUDefParametersDefaults.h | 3 - GPU/GPUTracking/Global/GPUChainITS.cxx | 17 +- GPU/GPUTracking/Global/GPUChainITS.h | 13 +- GPU/GPUTracking/ITS/GPUITSFitter.cxx | 64 ------ GPU/GPUTracking/ITS/GPUITSFitter.h | 102 --------- GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx | 201 ------------------ GPU/GPUTracking/ITS/GPUITSFitterKernels.h | 42 ---- GPU/GPUTracking/ITS/GPUITSTrack.h | 32 --- .../Standalone/Benchmark/standalone.cxx | 4 +- GPU/GPUTracking/kernels.cmake | 1 - 16 files changed, 12 insertions(+), 502 deletions(-) delete mode 100644 GPU/GPUTracking/ITS/GPUITSFitter.cxx delete mode 100644 GPU/GPUTracking/ITS/GPUITSFitter.h delete mode 100644 GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx delete mode 100644 GPU/GPUTracking/ITS/GPUITSFitterKernels.h delete mode 100644 GPU/GPUTracking/ITS/GPUITSTrack.h diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h index fc3656aef800c..d81ba4426ca55 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h @@ -29,22 +29,6 @@ namespace o2::its class Cell final { public: - GPUhdDefault() Cell() = default; - GPUhd() Cell(const int firstClusterIndex, const int secondClusterIndex, const int thirdClusterIndex, - const int firstTrackletIndex, const int secondTrackletIndex) - : mFirstClusterIndex(firstClusterIndex), - mSecondClusterIndex(secondClusterIndex), - mThirdClusterIndex(thirdClusterIndex), - mFirstTrackletIndex(firstTrackletIndex), - mSecondTrackletIndex(secondTrackletIndex), - mLevel(1) {} - GPUhdDefault() Cell(const Cell&) = default; - GPUhdDefault() Cell(Cell&&) = default; - GPUhdDefault() ~Cell() = default; - - GPUhdDefault() Cell& operator=(const Cell&) = default; - GPUhdDefault() Cell& operator=(Cell&&) noexcept = default; - GPUhd() int getFirstClusterIndex() const { return mFirstClusterIndex; }; GPUhd() int getSecondClusterIndex() const { return mSecondClusterIndex; }; GPUhd() int getThirdClusterIndex() const { return mThirdClusterIndex; }; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h index 48cc45e44cf1c..ab9d0c2e4d1a6 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Constants.h @@ -31,11 +31,6 @@ constexpr int UnusedIndex{-1}; constexpr float Resolution{0.0005f}; constexpr float Radl = 9.36f; // Radiation length of Si [cm] constexpr float Rho = 2.33f; // Density of Si [g/cm^3] -namespace its // to be removed -{ -constexpr int UnusedIndex{-1}; -constexpr float Resolution{0.0005f}; -} // namespace its } // namespace o2::its::constants #endif /* TRACKINGITSU_INCLUDE_CONSTANTS_H_ */ diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h index e9cd306e63bc5..75f187f31652b 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Road.h @@ -45,14 +45,14 @@ class Road final GPUhd() void resetRoad() { for (int i = 0; i < maxRoadSize; i++) { - mCellIds[i] = constants::its::UnusedIndex; + mCellIds[i] = constants::UnusedIndex; } mRoadSize = 0; } GPUhd() void addCell(int cellLayer, int cellId) { - if (mCellIds[cellLayer] == constants::its::UnusedIndex) { + if (mCellIds[cellLayer] == constants::UnusedIndex) { ++mRoadSize; } @@ -60,8 +60,7 @@ class Road final } private: - int mCellIds[maxRoadSize]{constants::its::UnusedIndex}; - // int mLabel; + int mCellIds[maxRoadSize]{constants::UnusedIndex}; unsigned char mRoadSize{0}; bool mIsFakeRoad{false}; }; diff --git a/GPU/GPUTracking/Base/GPUConstantMem.h b/GPU/GPUTracking/Base/GPUConstantMem.h index 532c270431d99..ffb17997b9190 100644 --- a/GPU/GPUTracking/Base/GPUConstantMem.h +++ b/GPU/GPUTracking/Base/GPUConstantMem.h @@ -26,7 +26,6 @@ #include "GPUTPCConvert.h" #include "GPUTPCCompression.h" #include "GPUTPCDecompression.h" -#include "GPUITSFitter.h" #include "GPUTPCClusterFinder.h" #include "GPUTrackingRefit.h" @@ -50,7 +49,6 @@ struct GPUConstantMem { GPUTRDTrackerGPU trdTrackerGPU; GPUTRDTracker trdTrackerO2; GPUTPCClusterFinder tpcClusterer[GPUCA_NSECTORS]; - GPUITSFitter itsFitter; GPUTrackingRefitProcessor trackingRefit; GPUTrackingInOutPointers ioPtrs; GPUCalibObjectsConst calibObjects; diff --git a/GPU/GPUTracking/CMakeLists.txt b/GPU/GPUTracking/CMakeLists.txt index 0560ea2dd12d2..a7159549322a0 100644 --- a/GPU/GPUTracking/CMakeLists.txt +++ b/GPU/GPUTracking/CMakeLists.txt @@ -173,8 +173,6 @@ set(SRCS_NO_CINT ${SRCS_NO_CINT} display/GPUDisplayInterface.cxx) set(SRCS_NO_CINT ${SRCS_NO_CINT} Global/GPUChainITS.cxx - ITS/GPUITSFitter.cxx - ITS/GPUITSFitterKernels.cxx dEdx/GPUdEdx.cxx TPCConvert/GPUTPCConvert.cxx TPCConvert/GPUTPCConvertKernel.cxx @@ -220,7 +218,6 @@ set(SRCS_NO_H ${SRCS_NO_H} TPCClusterFinder/GPUTPCClusterFinderDump.cxx) set(HDRS_INSTALL ${HDRS_INSTALL} - ITS/GPUITSTrack.h TPCClusterFinder/CfArray2D.h TPCClusterFinder/CfConsts.h TPCClusterFinder/CfFragment.h @@ -298,7 +295,6 @@ set(INCDIRS ${CMAKE_CURRENT_SOURCE_DIR}/SectorTracker ${CMAKE_CURRENT_SOURCE_DIR}/TPCConvert ${CMAKE_CURRENT_SOURCE_DIR}/dEdx - ${CMAKE_CURRENT_SOURCE_DIR}/ITS ${CMAKE_CURRENT_SOURCE_DIR}/TRDTracking ${CMAKE_CURRENT_SOURCE_DIR}/qa ${CMAKE_CURRENT_SOURCE_DIR}/Global diff --git a/GPU/GPUTracking/Definitions/GPUDefParametersConstants.h b/GPU/GPUTracking/Definitions/GPUDefParametersConstants.h index 78036e47fc49d..747ee84a906a6 100644 --- a/GPU/GPUTracking/Definitions/GPUDefParametersConstants.h +++ b/GPU/GPUTracking/Definitions/GPUDefParametersConstants.h @@ -32,7 +32,6 @@ // Default maximum numbers #define GPUCA_MAX_CLUSTERS ((size_t) 1024 * 1024 * 1024) // Maximum number of TPC clusters #define GPUCA_MAX_TRD_TRACKLETS ((size_t) 128 * 1024) // Maximum number of TRD tracklets -#define GPUCA_MAX_ITS_FIT_TRACKS ((size_t) 96 * 1024) // Max number of tracks for ITS track fit #define GPUCA_MEMORY_SIZE ((size_t) 6 * 1024 * 1024 * 1024) // Size of memory allocated on Device #define GPUCA_HOST_MEMORY_SIZE ((size_t) 1 * 1024 * 1024 * 1024) // Size of memory allocated on Host #define GPUCA_GPU_STACK_SIZE ((size_t) 8 * 1024) // Stack size per GPU thread diff --git a/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h b/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h index 8fe8e8ca68e44..0591ac8c58630 100644 --- a/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h +++ b/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h @@ -438,9 +438,6 @@ #ifndef GPUCA_LB_GPUTPCGMO2Output_output #define GPUCA_LB_GPUTPCGMO2Output_output 256 #endif - #ifndef GPUCA_LB_GPUITSFitterKernels - #define GPUCA_LB_GPUITSFitterKernels 256 - #endif #ifndef GPUCA_LB_GPUTPCStartHitsFinder #define GPUCA_LB_GPUTPCStartHitsFinder 256 #endif diff --git a/GPU/GPUTracking/Global/GPUChainITS.cxx b/GPU/GPUTracking/Global/GPUChainITS.cxx index cbc19100fe4fa..18fb5ff1de939 100644 --- a/GPU/GPUTracking/Global/GPUChainITS.cxx +++ b/GPU/GPUTracking/Global/GPUChainITS.cxx @@ -44,22 +44,7 @@ GPUChainITS::~GPUChainITS() mITSVertexerTraits.reset(); } -GPUChainITS::GPUChainITS(GPUReconstruction* rec, uint32_t maxTracks) : GPUChain(rec), mMaxTracks(maxTracks) {} - -void GPUChainITS::RegisterPermanentMemoryAndProcessors() { mRec->RegisterGPUProcessor(&processors()->itsFitter, GetRecoStepsGPU() & RecoStep::ITSTracking); } - -void GPUChainITS::RegisterGPUProcessors() -{ - if (GetRecoStepsGPU() & RecoStep::ITSTracking) { - mRec->RegisterGPUDeviceProcessor(&processorsShadow()->itsFitter, &processors()->itsFitter); - } -} - -void GPUChainITS::MemorySize(size_t& gpuMem, size_t& pageLockedHostMem) -{ - gpuMem = mMaxTracks * sizeof(GPUITSTrack) + GPUCA_MEMALIGN; - pageLockedHostMem = gpuMem; -} +GPUChainITS::GPUChainITS(GPUReconstruction* rec) : GPUChain(rec) {} int32_t GPUChainITS::Init() { return 0; } diff --git a/GPU/GPUTracking/Global/GPUChainITS.h b/GPU/GPUTracking/Global/GPUChainITS.h index 150d66031d084..6821f63845b95 100644 --- a/GPU/GPUTracking/Global/GPUChainITS.h +++ b/GPU/GPUTracking/Global/GPUChainITS.h @@ -29,32 +29,31 @@ class GPUFrameworkExternalAllocator; namespace o2::gpu { -class GPUChainITS : public GPUChain +class GPUChainITS final : public GPUChain { friend class GPUReconstruction; public: ~GPUChainITS() override; - void RegisterPermanentMemoryAndProcessors() override; - void RegisterGPUProcessors() override; int32_t Init() override; int32_t PrepareEvent() override; int32_t Finalize() override; int32_t RunChain() override; - void MemorySize(size_t& gpuMem, size_t& pageLockedHostMem) override; + + void RegisterPermanentMemoryAndProcessors() final {}; + void RegisterGPUProcessors() final {}; + void MemorySize(size_t&, size_t&) final {}; o2::its::TrackerTraits<7>* GetITSTrackerTraits(); o2::its::VertexerTraits* GetITSVertexerTraits(); o2::its::TimeFrame<7>* GetITSTimeframe(); protected: - GPUChainITS(GPUReconstruction* rec, uint32_t maxTracks = GPUCA_MAX_ITS_FIT_TRACKS); + GPUChainITS(GPUReconstruction* rec); std::unique_ptr> mITSTrackerTraits; std::unique_ptr mITSVertexerTraits; std::unique_ptr> mITSTimeFrame; std::unique_ptr mFrameworkAllocator; - - uint32_t mMaxTracks; }; } // namespace o2::gpu diff --git a/GPU/GPUTracking/ITS/GPUITSFitter.cxx b/GPU/GPUTracking/ITS/GPUITSFitter.cxx deleted file mode 100644 index a954d430f7ac3..0000000000000 --- a/GPU/GPUTracking/ITS/GPUITSFitter.cxx +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file GPUITSFitter.cxx -/// \author David Rohr, Maximiliano Puccio - -#include "GPUITSFitter.h" - -#include "ITStracking/Road.h" -#include "ITStracking/Cluster.h" -#include "GPUITSTrack.h" -#include "GPUReconstruction.h" - -using namespace o2::gpu; - -#ifndef GPUCA_GPUCODE -void GPUITSFitter::InitializeProcessor() -{ -} - -void* GPUITSFitter::SetPointersInput(void* mem) -{ - computePointerWithAlignment(mem, mRoads, mNumberOfRoads); - for (int32_t i = 0; i < 7; i++) { - computePointerWithAlignment(mem, mTF[i], mNTF[i]); - } - return mem; -} - -void* GPUITSFitter::SetPointersTracks(void* mem) -{ - computePointerWithAlignment(mem, mTracks, mNMaxTracks); - return mem; -} - -void* GPUITSFitter::SetPointersMemory(void* mem) -{ - computePointerWithAlignment(mem, mMemory, 1); - return mem; -} - -void GPUITSFitter::RegisterMemoryAllocation() -{ - AllocateAndInitializeLate(); - mMemoryResInput = mRec->RegisterMemoryAllocation(this, &GPUITSFitter::SetPointersInput, GPUMemoryResource::MEMORY_INPUT, "ITSInput"); - mMemoryResTracks = mRec->RegisterMemoryAllocation(this, &GPUITSFitter::SetPointersTracks, GPUMemoryResource::MEMORY_OUTPUT, "ITSTracks"); - mMemoryResMemory = mRec->RegisterMemoryAllocation(this, &GPUITSFitter::SetPointersMemory, GPUMemoryResource::MEMORY_PERMANENT, "ITSMemory"); -} - -void GPUITSFitter::SetMaxData(const GPUTrackingInOutPointers& io) { mNMaxTracks = mNumberOfRoads; } -#endif - -void GPUITSFitter::clearMemory() -{ - new (mMemory) Memory; -} diff --git a/GPU/GPUTracking/ITS/GPUITSFitter.h b/GPU/GPUTracking/ITS/GPUITSFitter.h deleted file mode 100644 index 9c0995a80749f..0000000000000 --- a/GPU/GPUTracking/ITS/GPUITSFitter.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file GPUITSFitter.h -/// \author David Rohr, Maximiliano Puccio - -#ifndef GPUITSFITTER_H -#define GPUITSFITTER_H - -#include "GPUProcessor.h" -#include "GPUITSTrack.h" - -namespace o2::its -{ -template -class Road; -struct TrackingFrameInfo; -struct Cluster; -class Cell; -} // namespace o2::its - -namespace o2::gpu -{ -class GPUITSTrack; - -class GPUITSFitter : public GPUProcessor -{ - public: -#ifndef GPUCA_GPUCODE - void InitializeProcessor(); - void RegisterMemoryAllocation(); - void SetMaxData(const GPUTrackingInOutPointers& io); - - void* SetPointersInput(void* mem); - void* SetPointersTracks(void* mem); - void* SetPointersMemory(void* mem); -#endif - - GPUd() o2::its::Road<5>* roads() - { - return mRoads; - } - GPUd() void SetNumberOfRoads(int32_t v) { mNumberOfRoads = v; } - GPUd() int32_t NumberOfRoads() { return mNumberOfRoads; } - GPUd() GPUITSTrack* tracks() - { - return mTracks; - } - GPUd() GPUAtomic(uint32_t) & NumberOfTracks() - { - return mMemory->mNumberOfTracks; - } - GPUd() void SetNumberOfLayers(int32_t i) { mNumberOfLayers = i; } - GPUd() int32_t NumberOfLayers() { return mNumberOfLayers; } - GPUd() void SetNumberTF(int32_t i, int32_t v) { mNTF[i] = v; } - GPUd() o2::its::TrackingFrameInfo** trackingFrame() - { - return mTF; - } - GPUd() const o2::its::Cluster** clusters() - { - return mClusterPtrs; - } - GPUd() const o2::its::Cell** cells() - { - return mCellPtrs; - } - - void clearMemory(); - - struct Memory { - GPUAtomic(uint32_t) mNumberOfTracks = 0; - }; - - protected: - int32_t mNumberOfLayers; - int32_t mNumberOfRoads = 0; - int32_t mNMaxTracks = 0; - int32_t* mNTF = nullptr; - Memory* mMemory = nullptr; - o2::its::Road<5>* mRoads = nullptr; - o2::its::TrackingFrameInfo** mTF = {nullptr}; - GPUITSTrack* mTracks = nullptr; - - const o2::its::Cluster** mClusterPtrs; - const o2::its::Cell** mCellPtrs; - - int16_t mMemoryResInput = -1; - int16_t mMemoryResTracks = -1; - int16_t mMemoryResMemory = -1; -}; -} // namespace o2::gpu - -#endif diff --git a/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx b/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx deleted file mode 100644 index 798efb7d7964e..0000000000000 --- a/GPU/GPUTracking/ITS/GPUITSFitterKernels.cxx +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file GPUITSFitterKernels.cxx -/// \author David Rohr, Maximiliano Puccio - -#include "GPUITSFitterKernels.h" -#include "GPUConstantMem.h" - -#include "ITStracking/Constants.h" -#include "ITStracking/MathUtils.h" -#include "ITStracking/Road.h" -#include "ITStracking/Cluster.h" -#include "ITStracking/Cell.h" -#include "CommonConstants/MathConstants.h" - -#if defined(CA_DEBUG) && !defined(GPUCA_GPUCODE_DEVICE) -#include -#endif - -using namespace o2::gpu; -using namespace o2; -using namespace o2::its; - -GPUdii() bool GPUITSFitterKernels::fitTrack(GPUITSFitter& GPUrestrict() Fitter, GPUTPCGMPropagator& GPUrestrict() prop, GPUITSTrack& GPUrestrict() track, int32_t start, int32_t end, int32_t step) -{ - for (int32_t iLayer{start}; iLayer != end; iLayer += step) { - if (track.mClusters[iLayer] == o2::its::constants::its::UnusedIndex) { - continue; - } - const TrackingFrameInfo& GPUrestrict() trackingHit = Fitter.trackingFrame()[iLayer][track.mClusters[iLayer]]; - - if (prop.PropagateToXAlpha(trackingHit.xTrackingFrame, trackingHit.alphaTrackingFrame, step > 0)) { - return false; - } - - if (prop.Update(trackingHit.positionTrackingFrame[0], trackingHit.positionTrackingFrame[1], 0, false, trackingHit.covarianceTrackingFrame[0], trackingHit.covarianceTrackingFrame[2])) { - return false; - } - - /*const float xx0 = (iLayer > 2) ? 0.008f : 0.003f; // Rough layer thickness //FIXME - constexpr float radiationLength = 9.36f; // Radiation length of Si [cm] - constexpr float density = 2.33f; // Density of Si [g/cm^3] - if (!track.correctForMaterial(xx0, xx0 * radiationLength * density, true)) - return false;*/ - } - return true; -} - -template <> -GPUdii() void GPUITSFitterKernels::Thread<0>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUsharedref() GPUSharedMemory& smem, processorType& GPUrestrict() processors) -{ - GPUITSFitter& Fitter = processors.itsFitter; - - GPUTPCGMPropagator prop; - prop.SetPolynomialField(&processors.param.polynomialField); - prop.SetMaxSinPhi(GPUCA_MAX_SIN_PHI); - prop.SetFitInProjections(1); - float bz = -5.f; // FIXME - -#ifdef CA_DEBUG - int32_t roadCounters[4]{0, 0, 0, 0}; - int32_t fitCounters[4]{0, 0, 0, 0}; - int32_t backpropagatedCounters[4]{0, 0, 0, 0}; - int32_t refitCounters[4]{0, 0, 0, 0}; -#endif - for (int32_t iRoad = get_global_id(0); iRoad < Fitter.NumberOfRoads(); iRoad += get_global_size(0)) { - Road<5>& road = Fitter.roads()[iRoad]; - int32_t clusters[7] = {o2::its::constants::its::UnusedIndex, o2::its::constants::its::UnusedIndex, o2::its::constants::its::UnusedIndex, o2::its::constants::its::UnusedIndex, o2::its::constants::its::UnusedIndex, o2::its::constants::its::UnusedIndex, o2::its::constants::its::UnusedIndex}; - int32_t lastCellLevel = o2::its::constants::its::UnusedIndex; - CA_DEBUGGER(int32_t nClusters = 2); - - for (int32_t iCell{0}; iCell < Fitter.NumberOfLayers() - 2; ++iCell) { - const int32_t cellIndex = road[iCell]; - if (cellIndex == o2::its::constants::its::UnusedIndex) { - continue; - } else { - clusters[iCell] = Fitter.cells()[iCell][cellIndex].getFirstClusterIndex(); - clusters[iCell + 1] = Fitter.cells()[iCell][cellIndex].getSecondClusterIndex(); - clusters[iCell + 2] = Fitter.cells()[iCell][cellIndex].getThirdClusterIndex(); - lastCellLevel = iCell; - CA_DEBUGGER(nClusters++); - } - } - - CA_DEBUGGER(roadCounters[nClusters - 4]++); - - if (lastCellLevel == o2::its::constants::its::UnusedIndex) { - continue; - } - - /// From primary vertex context index to event index (== the one used as input of the tracking code) - for (int32_t iC{0}; iC < 7; iC++) { - if (clusters[iC] != o2::its::constants::its::UnusedIndex) { - clusters[iC] = Fitter.clusters()[iC][clusters[iC]].clusterId; - } - } - /// Track seed preparation. Clusters are numbered progressively from the outermost to the innermost. - const auto& cluster1 = Fitter.trackingFrame()[lastCellLevel + 2][clusters[lastCellLevel + 2]]; - const auto& cluster2 = Fitter.trackingFrame()[lastCellLevel + 1][clusters[lastCellLevel + 1]]; - const auto& cluster3 = Fitter.trackingFrame()[lastCellLevel][clusters[lastCellLevel]]; - - GPUITSTrack temporaryTrack; - { - const float ca = CAMath::Cos(cluster3.alphaTrackingFrame), sa = CAMath::Sin(cluster3.alphaTrackingFrame); - const float x1 = cluster1.xCoordinate * ca + cluster1.yCoordinate * sa; - const float y1 = -cluster1.xCoordinate * sa + cluster1.yCoordinate * ca; - const float z1 = cluster1.zCoordinate; - const float x2 = cluster2.xCoordinate * ca + cluster2.yCoordinate * sa; - const float y2 = -cluster2.xCoordinate * sa + cluster2.yCoordinate * ca; - const float z2 = cluster2.zCoordinate; - const float x3 = cluster3.xTrackingFrame; - const float y3 = cluster3.positionTrackingFrame[0]; - const float z3 = cluster3.positionTrackingFrame[1]; - - const float crv = o2::its::math_utils::computeCurvature(x1, y1, x2, y2, x3, y3); - const float x0 = o2::its::math_utils::computeCurvatureCentreX(x1, y1, x2, y2, x3, y3); - const float tgl12 = o2::its::math_utils::computeTanDipAngle(x1, y1, x2, y2, z1, z2); - const float tgl23 = o2::its::math_utils::computeTanDipAngle(x2, y2, x3, y3, z2, z3); - - const float r2 = CAMath::Sqrt(cluster2.xCoordinate * cluster2.xCoordinate + cluster2.yCoordinate * cluster2.yCoordinate); - const float r3 = CAMath::Sqrt(cluster3.xCoordinate * cluster3.xCoordinate + cluster3.yCoordinate * cluster3.yCoordinate); - const float fy = 1.f / (r2 - r3); - const float& tz = fy; - const float cy = (o2::its::math_utils::computeCurvature(x1, y1, x2, y2 + o2::its::constants::its::Resolution, x3, y3) - crv) / (o2::its::constants::its::Resolution * bz * constants::math::B2C) * 20.f; // FIXME: MS contribution to the cov[14] (*20 added) - constexpr float s2 = o2::its::constants::its::Resolution * o2::its::constants::its::Resolution; - - temporaryTrack.X() = cluster3.xTrackingFrame; - temporaryTrack.Y() = y3; - temporaryTrack.Z() = z3; - temporaryTrack.SinPhi() = crv * (x3 - x0); - temporaryTrack.DzDs() = 0.5f * (tgl12 + tgl23); - temporaryTrack.QPt() = CAMath::Abs(bz) < constants::math::Almost0 ? constants::math::Almost0 : crv / (bz * constants::math::B2C); - temporaryTrack.TZOffset() = 0; - temporaryTrack.Cov()[0] = s2; - temporaryTrack.Cov()[1] = 0.f; - temporaryTrack.Cov()[2] = s2; - temporaryTrack.Cov()[3] = s2 * fy; - temporaryTrack.Cov()[4] = 0.f; - temporaryTrack.Cov()[5] = s2 * fy * fy; - temporaryTrack.Cov()[6] = 0.f; - temporaryTrack.Cov()[7] = s2 * tz; - temporaryTrack.Cov()[8] = 0.f; - temporaryTrack.Cov()[9] = s2 * tz * tz; - temporaryTrack.Cov()[10] = s2 * cy; - temporaryTrack.Cov()[11] = 0.f; - temporaryTrack.Cov()[12] = s2 * fy * cy; - temporaryTrack.Cov()[13] = 0.f; - temporaryTrack.Cov()[14] = s2 * cy * cy; - temporaryTrack.SetChi2(0); - temporaryTrack.SetNDF(-5); - - prop.SetTrack(&temporaryTrack, cluster3.alphaTrackingFrame); - } - - for (size_t iC = 0; iC < 7; ++iC) { - temporaryTrack.mClusters[iC] = clusters[iC]; - } - bool fitSuccess = fitTrack(Fitter, prop, temporaryTrack, Fitter.NumberOfLayers() - 4, -1, -1); - if (!fitSuccess) { - continue; - } - CA_DEBUGGER(fitCounters[nClusters - 4]++); - temporaryTrack.ResetCovariance(); - fitSuccess = fitTrack(Fitter, prop, temporaryTrack, 0, Fitter.NumberOfLayers(), 1); - if (!fitSuccess) { - continue; - } - CA_DEBUGGER(backpropagatedCounters[nClusters - 4]++); - for (int32_t k = 0; k < 5; k++) { - temporaryTrack.mOuterParam.P[k] = temporaryTrack.Par()[k]; - } - for (int32_t k = 0; k < 15; k++) { - temporaryTrack.mOuterParam.C[k] = temporaryTrack.Cov()[k]; - } - temporaryTrack.mOuterParam.X = temporaryTrack.X(); - temporaryTrack.mOuterParam.alpha = prop.GetAlpha(); - temporaryTrack.ResetCovariance(); - fitSuccess = fitTrack(Fitter, prop, temporaryTrack, Fitter.NumberOfLayers() - 1, -1, -1); - if (!fitSuccess) { - continue; - } - CA_DEBUGGER(refitCounters[nClusters - 4]++); - int32_t trackId = CAMath::AtomicAdd(&Fitter.NumberOfTracks(), 1u); - Fitter.tracks()[trackId] = temporaryTrack; - } -#ifdef CA_DEBUG - GPUInfo("Roads: %i %i %i %i", roadCounters[0], roadCounters[1], roadCounters[2], roadCounters[3]); - GPUInfo("Fitted tracks: %i %i %i %i", fitCounters[0], fitCounters[1], fitCounters[2], fitCounters[3]); - GPUInfo("Backpropagated tracks: %i %i %i %i", backpropagatedCounters[0], backpropagatedCounters[1], backpropagatedCounters[2], backpropagatedCounters[3]); - GPUInfo("Refitted tracks: %i %i %i %i", refitCounters[0], refitCounters[1], refitCounters[2], refitCounters[3]); -#endif -} diff --git a/GPU/GPUTracking/ITS/GPUITSFitterKernels.h b/GPU/GPUTracking/ITS/GPUITSFitterKernels.h deleted file mode 100644 index 5a2a30de28823..0000000000000 --- a/GPU/GPUTracking/ITS/GPUITSFitterKernels.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file GPUITSFitterKernels.h -/// \author David Rohr, Maximiliano Puccio - -#ifndef GPUITSFITTERKERNELS_H -#define GPUITSFITTERKERNELS_H - -#include "GPUGeneralKernels.h" -namespace o2::its -{ -struct TrackingFrameInfo; -} // namespace o2::its - -namespace o2::gpu -{ -class GPUTPCGMPropagator; -class GPUITSFitter; -class GPUITSTrack; - -class GPUITSFitterKernels : public GPUKernelTemplate -{ - public: - GPUhdi() constexpr static GPUDataTypes::RecoStep GetRecoStep() { return GPUDataTypes::RecoStep::ITSTracking; } - template - GPUd() static void Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUsharedref() GPUSharedMemory& smem, processorType& processors); - - protected: - GPUd() static bool fitTrack(GPUITSFitter& Fitter, GPUTPCGMPropagator& prop, GPUITSTrack& track, int32_t start, int32_t end, int32_t step); -}; -} // namespace o2::gpu - -#endif diff --git a/GPU/GPUTracking/ITS/GPUITSTrack.h b/GPU/GPUTracking/ITS/GPUITSTrack.h deleted file mode 100644 index 5063985692a43..0000000000000 --- a/GPU/GPUTracking/ITS/GPUITSTrack.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file GPUITSTrack.h -/// \author David Rohr, Maximiliano Puccio - -#ifndef GPUITSTRACK_H -#define GPUITSTRACK_H - -#include "GPUTPCGMMergerTypes.h" -#include "GPUTPCGMTrackParam.h" - -namespace o2::gpu -{ -class GPUITSTrack : public GPUTPCGMTrackParam -{ - public: - gputpcgmmergertypes::GPUTPCOuterParam mOuterParam; - float mAlpha; - int32_t mClusters[7]; -}; -} // namespace o2::gpu - -#endif diff --git a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx index ae02f9e9051c4..fed4610b2f13a 100644 --- a/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx +++ b/GPU/GPUTracking/Standalone/Benchmark/standalone.cxx @@ -765,9 +765,9 @@ int32_t main(int argc, char** argv) chainTrackingPipeline->SetQAFromForeignChain(chainTracking); } if (!configStandalone.proc.doublePipeline) { - chainITS = rec->AddChain(0); + chainITS = rec->AddChain(); if (configStandalone.testSyncAsync) { - chainITSAsync = recAsync->AddChain(0); + chainITSAsync = recAsync->AddChain(); } } diff --git a/GPU/GPUTracking/kernels.cmake b/GPU/GPUTracking/kernels.cmake index 2a59f98a6d5b4..52cda3e8ff416 100644 --- a/GPU/GPUTracking/kernels.cmake +++ b/GPU/GPUTracking/kernels.cmake @@ -90,7 +90,6 @@ o2_gpu_add_kernel("GPUTPCGMO2Output, output" "= TPC o2_gpu_add_kernel("GPUTPCGMO2Output, mc" "= TPCMERGER") o2_gpu_add_kernel("GPUTRDTrackerKernels, gpuVersion" "= TRDTRACKER MATLUT TPCMERGER" LB GPUTRDTrackerGPU* externalInstance) o2_gpu_add_kernel("GPUTRDTrackerKernels, o2Version" "= TRDTRACKER MATLUT O2PROPAGATOR" LB GPUTRDTracker* externalInstance) -o2_gpu_add_kernel("GPUITSFitterKernels" "= TPCMERGER MATLUT" LB) o2_gpu_add_kernel("GPUTPCConvertKernel" "=" LB) o2_gpu_add_kernel("GPUTPCCompressionKernels, step0attached" "= TPCCOMPRESSION" LB) o2_gpu_add_kernel("GPUTPCCompressionKernels, step1unattached" "= ERRORS" LB) From 96dafaa247e464c3f611bd5c306fe6d13fa76c87 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 19 Jun 2025 21:02:18 +0200 Subject: [PATCH 073/315] ITS: GPU add missing output to GPUWorkflowSpec was missed initially. compliments #14425 and should now allow ITS MC to be run standalone on gpu. thanks @davidrohr! --- GPU/Workflow/src/GPUWorkflowSpec.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/Workflow/src/GPUWorkflowSpec.cxx b/GPU/Workflow/src/GPUWorkflowSpec.cxx index 6293fce842231..6aa4b753f9300 100644 --- a/GPU/Workflow/src/GPUWorkflowSpec.cxx +++ b/GPU/Workflow/src/GPUWorkflowSpec.cxx @@ -1305,6 +1305,7 @@ Outputs GPURecoWorkflowSpec::outputs() if (mSpecConfig.processMC) { outputSpecs.emplace_back(gDataOriginITS, "VERTICESMCTR", 0, Lifetime::Timeframe); + outputSpecs.emplace_back(gDataOriginITS, "VERTICESMCPUR", 0, Lifetime::Timeframe); outputSpecs.emplace_back(gDataOriginITS, "TRACKSMCTR", 0, Lifetime::Timeframe); outputSpecs.emplace_back(gDataOriginITS, "ITSTrackMC2ROF", 0, Lifetime::Timeframe); } From 38acc6f71a196ebdf8494d7b56c402dcaa299cde Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Thu, 26 Jun 2025 13:14:30 +0200 Subject: [PATCH 074/315] DPL Analysis: add `DefinesDelayed` Add `DefinesDelayed` allowing to set the expressions in a process function, e.g. after calculating some required input values --- .../Core/include/Framework/AnalysisHelpers.h | 16 +++++++- .../Core/include/Framework/AnalysisManagers.h | 37 +++++++++++++++++++ .../Core/include/Framework/AnalysisTask.h | 2 + Framework/Core/test/test_Concepts.cxx | 14 +++++++ 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/Framework/Core/include/Framework/AnalysisHelpers.h b/Framework/Core/include/Framework/AnalysisHelpers.h index 95be6c7e407b3..6e9b1e211bb76 100644 --- a/Framework/Core/include/Framework/AnalysisHelpers.h +++ b/Framework/Core/include/Framework/AnalysisHelpers.h @@ -340,8 +340,9 @@ concept is_spawns = requires(T t) { /// The actual expressions have to be set in init() for the configurable expression /// columns, used to define the table -template +template struct Defines : decltype(transformBase()) { + static constexpr bool delayed = DELAYED; using spawnable_t = T; using metadata = decltype(transformBase())::metadata; using extension_t = typename metadata::extension_table_t; @@ -373,13 +374,26 @@ struct Defines : decltype(transformBase()) { std::array projectors; std::shared_ptr projector = nullptr; std::shared_ptr schema = std::make_shared(o2::soa::createFieldsFromColumns(placeholders_pack_t{})); + std::shared_ptr inputSchema = nullptr; + + bool needRecompilation = false; + + void recompile() + { + projector = framework::expressions::createProjectorHelper(N, projectors.data(), inputSchema, schema->fields()); + } }; +template +using DefinesDelayed = Defines; + template concept is_defines = requires(T t) { typename T::metadata; requires std::same_as; requires std::same_as>; + requires std::same_as; + &T::recompile; }; /// Policy to control index building diff --git a/Framework/Core/include/Framework/AnalysisManagers.h b/Framework/Core/include/Framework/AnalysisManagers.h index 2a052c0b07218..7717d5cb3a6a2 100644 --- a/Framework/Core/include/Framework/AnalysisManagers.h +++ b/Framework/Core/include/Framework/AnalysisManagers.h @@ -307,6 +307,7 @@ bool prepareOutput(ProcessingContext& context, T& builds) template bool prepareOutput(ProcessingContext& context, T& defines) + requires(T::delayed == false) { using metadata = o2::aod::MetadataTrait>::metadata; auto originalTable = soa::ArrowHelpers::joinTables(extractOriginals(context), std::span{metadata::base_table_t::originalLabels}); @@ -314,6 +315,42 @@ bool prepareOutput(ProcessingContext& context, T& defines) using base_table_t = typename T::base_table_t::table_t; originalTable = makeEmptyTable(o2::aod::label()); } + if (defines.inputSchema == nullptr) { + defines.inputSchema = originalTable->schema(); + } + using D = o2::aod::Hash; + + defines.extension = std::make_shared(o2::framework::spawner(originalTable, + o2::aod::label(), + defines.projectors.data(), + defines.projector, + defines.schema)); + defines.table = std::make_shared(soa::ArrowHelpers::joinTables({defines.extension->asArrowTable(), originalTable}, std::span{T::spawnable_t::table_t::originalLabels})); + return true; +} + +template +bool prepareDelayedOutput(ProcessingContext&, T&) +{ + return false; +} + +template + requires(T::delayed == true) +bool prepareDelayedOutput(ProcessingContext& context, T& defines) +{ + if (defines.needRecompilation) { + defines.recompile(); + } + using metadata = o2::aod::MetadataTrait>::metadata; + auto originalTable = soa::ArrowHelpers::joinTables(extractOriginals(context), std::span{metadata::base_table_t::originalLabels}); + if (originalTable->schema()->fields().empty() == true) { + using base_table_t = typename T::base_table_t::table_t; + originalTable = makeEmptyTable(o2::aod::label()); + } + if (defines.inputSchema == nullptr) { + defines.inputSchema = originalTable->schema(); + } using D = o2::aod::Hash; defines.extension = std::make_shared(o2::framework::spawner(originalTable, diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 30b31ea4799f5..892948582b3cc 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -645,6 +645,8 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args) return false; }, *task.get()); + // prepare delayed outputs + homogeneous_apply_refs([&pc](auto& element) { return analysis_task_parsers::prepareDelayedOutput(pc, element); }, *task.get()); // finalize outputs homogeneous_apply_refs([&pc](auto& element) { return analysis_task_parsers::finalizeOutput(pc, element); }, *task.get()); }; diff --git a/Framework/Core/test/test_Concepts.cxx b/Framework/Core/test/test_Concepts.cxx index 4bf4f977ec3a8..5e2ad6d96b30f 100644 --- a/Framework/Core/test/test_Concepts.cxx +++ b/Framework/Core/test/test_Concepts.cxx @@ -32,6 +32,15 @@ struct P { PROCESS_SWITCH(P, process1, "", true); }; +namespace o2::aod +{ +namespace ct +{ +DECLARE_SOA_CONFIGURABLE_EXPRESSION_COLUMN(Test, test, float, "test"); +} +DECLARE_SOA_CONFIGURABLE_EXTENDED_TABLE(TracksMore, TracksIU, "TRKMORE", ct::Test); +} // namespace o2::aod + TEST_CASE("IdentificationConcepts") { // ASoA @@ -122,6 +131,11 @@ TEST_CASE("IdentificationConcepts") Builds bld; REQUIRE(is_builds); + Defines def; + DefinesDelayed ddef; + REQUIRE(is_defines); + REQUIRE(is_defines); + OutputObj oo{"test"}; REQUIRE(is_outputobj); From aa1ca7a221450cd6e36825c6f23bb61fb2b869de Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 26 Jun 2025 15:08:35 +0200 Subject: [PATCH 075/315] DPL: improve logs for new calibration scheme (#14030) - Report correct timeout for readers. - Improve message when dropping data which is not going to be processed by the CalibrationOnly mode. --- Framework/Core/src/DataProcessingDevice.cxx | 11 ++++++++--- Framework/Core/src/DataRelayer.cxx | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index c303af4858234..ba3fc2cd1bedd 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -1400,10 +1400,15 @@ void DataProcessingDevice::Run() O2_SIGNPOST_EVENT_EMIT(calibration, lid, "timer_setup", "Starting %d s timer for exitTransitionTimeout.", deviceContext.exitTransitionTimeout); uv_timer_start(deviceContext.gracePeriodTimer, on_transition_requested_expired, deviceContext.exitTransitionTimeout * 1000, 0); - if (mProcessingPolicies.termination == TerminationPolicy::QUIT) { - O2_SIGNPOST_EVENT_EMIT_INFO(device, lid, "run_loop", "New state requested. Waiting for %d seconds before quitting.", (int)deviceContext.exitTransitionTimeout); + bool onlyGenerated = hasOnlyGenerated(spec); + int timeout = onlyGenerated ? deviceContext.dataProcessingTimeout : deviceContext.exitTransitionTimeout; + if (mProcessingPolicies.termination == TerminationPolicy::QUIT && DefaultsHelpers::onlineDeploymentMode() == false) { + O2_SIGNPOST_EVENT_EMIT_INFO(device, lid, "run_loop", "New state requested. Waiting for %d seconds before quitting.", timeout); } else { - O2_SIGNPOST_EVENT_EMIT_INFO(device, lid, "run_loop", "New state requested. Waiting for %d seconds before switching to READY state.", (int)deviceContext.exitTransitionTimeout); + O2_SIGNPOST_EVENT_EMIT_INFO(device, lid, "run_loop", + "New state requested. Waiting for %d seconds before %{public}s", + timeout, + onlyGenerated ? "dropping remaining input and switching to READY state." : "switching to READY state."); } } else { state.transitionHandling = TransitionHandlingState::Expired; diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index 6ddfa7597f7f6..dc820fb5232d1 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -8,6 +8,7 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "Framework/DeviceState.h" #include "Framework/RootSerializationSupport.h" #include "Framework/DataRelayer.h" #include "Framework/DataProcessingStats.h" @@ -43,6 +44,7 @@ #include #include +#include #include #include #if __has_include() @@ -347,9 +349,21 @@ void DataRelayer::setOldestPossibleInput(TimesliceId proposed, ChannelIndex chan if (element.size() == 0) { auto& state = mContext.get(); if (state.transitionHandling != TransitionHandlingState::NoTransition && DefaultsHelpers::onlineDeploymentMode()) { - LOGP(warning, "Missing {} (lifetime:{}) while dropping incomplete data in slot {} with timestamp {} < {}.", DataSpecUtils::describe(input), input.lifetime, si, timestamp.value, newOldest.timeslice.value); + if (state.allowedProcessing == DeviceState::CalibrationOnly) { + O2_SIGNPOST_ID_GENERATE(cid, calibration); + O2_SIGNPOST_EVENT_EMIT(calibration, cid, "expected_missing_data", "Expected missing %{public}s (lifetime:%d) while dropping non-calibration data in slot %zu with timestamp %zu < %zu.", + DataSpecUtils::describe(input).c_str(), (int)input.lifetime, si, timestamp.value, newOldest.timeslice.value); + } else { + LOGP(info, "Missing {} (lifetime:{}) while dropping incomplete data in slot {} with timestamp {} < {}.", DataSpecUtils::describe(input), input.lifetime, si, timestamp.value, newOldest.timeslice.value); + } } else { - LOGP(error, "Missing {} (lifetime:{}) while dropping incomplete data in slot {} with timestamp {} < {}.", DataSpecUtils::describe(input), input.lifetime, si, timestamp.value, newOldest.timeslice.value); + if (state.allowedProcessing == DeviceState::CalibrationOnly) { + O2_SIGNPOST_ID_GENERATE(cid, calibration); + O2_SIGNPOST_EVENT_EMIT_INFO(calibration, cid, "expected_missing_data", "Not processing in calibration mode: missing %s (lifetime:%d) while dropping incomplete data in slot %zu with timestamp %zu < %zu.", + DataSpecUtils::describe(input).c_str(), (int)input.lifetime, si, timestamp.value, newOldest.timeslice.value); + } else { + LOGP(error, "Missing {} (lifetime:{}) while dropping incomplete data in slot {} with timestamp {} < {}.", DataSpecUtils::describe(input), input.lifetime, si, timestamp.value, newOldest.timeslice.value); + } } } } From cc7a23dc59e8e99857850ab740f978fb4553e6ca Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 26 Jun 2025 12:50:04 +0200 Subject: [PATCH 076/315] jobutils: Sanitize return code treatment hopefully fixing a bug where the return code seems to have contained additional characters (hidden) which confused the return code analysis and provides printouts (or bash errors) like: ``` line 336: [: 0 0: integer expression expected ``` --- Utilities/Tools/jobutils2.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Utilities/Tools/jobutils2.sh b/Utilities/Tools/jobutils2.sh index eec71c33ffea5..ba96b97da090b 100644 --- a/Utilities/Tools/jobutils2.sh +++ b/Utilities/Tools/jobutils2.sh @@ -328,9 +328,14 @@ EOF # ?? should directly exit here? wait $PID || QUERY_RC_FROM_LOG="ON" - # query return code from log (seems to be safer as sometimes the wait issues "PID" not a child of this shell) - RC=$(awk '/TASK-EXIT-CODE:/{print $2}' ${logfile}) - if [ ! "${RC}" ]; then + # query return code from log and sanitize (seems to be safer as sometimes the wait issues "PID" not a child of this shell) + RC=$(awk '/TASK-EXIT-CODE:/{print $2; exit}' "${logfile}" | tr -d '[:space:]' | tr -d '\r') + if [ -z "${RC}" ]; then + RC=1 + fi + # check that RC is an integer + if ! [[ "$RC" =~ ^[0-9]+$ ]]; then + echo "Malformed TASK-EXIT-CODE: '${RC}'" RC=1 fi if [ "${RC}" -eq "0" ]; then From e4108ce9fe092b28bead4cbbf3a0d0c8f69a4081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Thu, 26 Jun 2025 22:12:08 +0200 Subject: [PATCH 077/315] A3: Add sensitive RICH layers to geometry (#14450) --- .../ALICE3/RICH/base/src/GeometryTGeo.cxx | 2 +- .../include/RICHSimulation/RICHRing.h | 2 + .../ALICE3/RICH/simulation/src/Detector.cxx | 57 +++++++++++-------- .../ALICE3/RICH/simulation/src/RICHRing.cxx | 2 +- 4 files changed, 36 insertions(+), 27 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/RICH/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/RICH/base/src/GeometryTGeo.cxx index ebe6dcfbdc79a..01d242d6c64cd 100644 --- a/Detectors/Upgrades/ALICE3/RICH/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/RICH/base/src/GeometryTGeo.cxx @@ -21,7 +21,7 @@ std::unique_ptr GeometryTGeo::sInstance; std::string GeometryTGeo::sVolumeName = "RICHV"; std::string GeometryTGeo::sRingName = "RICHRing"; std::string GeometryTGeo::sChipName = "RICHChip"; -std::string GeometryTGeo::sSensorName = "RICHSensor"; +std::string GeometryTGeo::sSensorName = "RICHPhotoTile"; std::string GeometryTGeo::sSensorFWDName = "FWDRICHSensor"; // only one big sensor for now std::string GeometryTGeo::sSensorBWDName = "BWDRICHSensor"; // only one big sensor for now diff --git a/Detectors/Upgrades/ALICE3/RICH/simulation/include/RICHSimulation/RICHRing.h b/Detectors/Upgrades/ALICE3/RICH/simulation/include/RICHSimulation/RICHRing.h index a7892c210e310..296e24cbd8f06 100644 --- a/Detectors/Upgrades/ALICE3/RICH/simulation/include/RICHSimulation/RICHRing.h +++ b/Detectors/Upgrades/ALICE3/RICH/simulation/include/RICHSimulation/RICHRing.h @@ -54,6 +54,8 @@ class Ring auto getDeltaPhiPos() const { return TMath::TwoPi() / mNTiles; } void createRing(TGeoVolume* motherVolume); + int getPosId() const { return mPosId; } + int getNTiles() const { return mNTiles; } private: int mPosId; // id of the ring diff --git a/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx index de5c1817a515a..02719d6f93a00 100644 --- a/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/RICH/simulation/src/Detector.cxx @@ -145,29 +145,29 @@ void Detector::createGeometry() vRICH->SetTitle(vstrng); auto& richPars = RICHBaseParam::Instance(); - prepareLayout(); + prepareLayout(); // Preparing the positions of the rings and tiles for (int iRing{0}; iRing < richPars.nRings; ++iRing) { if (!richPars.oddGeom && iRing == (richPars.nRings / 2)) { continue; } - mRings[iRing] = Ring{iRing, - richPars.nTiles, - richPars.rMin, - richPars.rMax, - richPars.radiatorThickness, - (float)mVTile1[iRing], - (float)mVTile2[iRing], - (float)mLAerogelZ[iRing], - richPars.detectorThickness, - (float)mVMirror1[iRing], - (float)mVMirror2[iRing], - richPars.zBaseSize, - (float)mR0Radiator[iRing], - (float)mR0PhotoDet[iRing], - (float)mTRplusG[iRing], - (float)mThetaBi[iRing], - GeometryTGeo::getRICHVolPattern()}; + mRings[iRing] = o2::rich::Ring{iRing, + richPars.nTiles, + richPars.rMin, + richPars.rMax, + richPars.radiatorThickness, + (float)mVTile1[iRing], + (float)mVTile2[iRing], + (float)mLAerogelZ[iRing], + richPars.detectorThickness, + (float)mVMirror1[iRing], + (float)mVMirror2[iRing], + richPars.zBaseSize, + (float)mR0Radiator[iRing], + (float)mR0PhotoDet[iRing], + (float)mTRplusG[iRing], + (float)mThetaBi[iRing], + GeometryTGeo::getRICHVolPattern()}; } if (richPars.enableFWDRich) { @@ -182,7 +182,7 @@ void Detector::InitializeO2Detector() { LOG(info) << "Initialize RICH O2Detector"; mGeometryTGeo = GeometryTGeo::Instance(); - // defineSensitiveVolumes(); + defineSensitiveVolumes(); } void Detector::defineSensitiveVolumes() @@ -194,12 +194,19 @@ void Detector::defineSensitiveVolumes() LOGP(info, "Adding RICH Sensitive Volumes"); // The names of the RICH sensitive volumes have the format: Ring(0...mRings.size()-1) - for (int j{0}; j < mRings.size(); j++) { - volumeName = GeometryTGeo::getRICHSensorPattern() + TString::Itoa(j, 10); - LOGP(info, "Trying {}", volumeName.Data()); - v = geoManager->GetVolume(volumeName.Data()); - LOGP(info, "Adding RICH Sensitive Volume {}", v->GetName()); - AddSensitiveVolume(v); + for (auto ring : mRings) { + for (int j = 0; j < ring.getNTiles(); j++) { + volumeName = Form("%s_%d_%d", GeometryTGeo::getRICHSensorPattern(), ring.getPosId(), j); + LOGP(info, "Trying {}", volumeName.Data()); + v = geoManager->GetVolume(volumeName.Data()); + if (!v) { + LOG(error) << "Geometry does not contain volume " << volumeName.Data(); + geoManager->GetListOfVolumes()->Print(); + LOG(fatal) << "Could not find volume " << volumeName.Data() << " in the geometry"; + } + LOGP(info, "Adding RICH Sensitive Volume {}", v->GetName()); + AddSensitiveVolume(v); + } } } diff --git a/Detectors/Upgrades/ALICE3/RICH/simulation/src/RICHRing.cxx b/Detectors/Upgrades/ALICE3/RICH/simulation/src/RICHRing.cxx index 27890dc0c4c06..1c6c9612795a0 100644 --- a/Detectors/Upgrades/ALICE3/RICH/simulation/src/RICHRing.cxx +++ b/Detectors/Upgrades/ALICE3/RICH/simulation/src/RICHRing.cxx @@ -106,7 +106,7 @@ Ring::Ring(int rPosId, photoTile->SetVertex(6, photThick / 2, photYmax / 2); photoTile->SetVertex(7, photThick / 2, -photYmax / 2); - TGeoVolume* photoTileVol = new TGeoVolume(Form("photoTile_%d_%d", rPosId, photTileCount), photoTile, medSi); + TGeoVolume* photoTileVol = new TGeoVolume(Form("%s_%d_%d", GeometryTGeo::getRICHSensorPattern(), rPosId, photTileCount), photoTile, medSi); photoTileVol->SetLineColor(kOrange - 8); photoTileVol->SetLineWidth(1); From 8d6b1cc999f4ec7dd49841655c52970ff08e5ae9 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 26 Jun 2025 23:44:09 +0200 Subject: [PATCH 078/315] DPL: avoid unintialised member (#14449) Not actually used in this particular case, however better safe than sorry. --- Framework/Core/src/DataRelayer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/DataRelayer.cxx b/Framework/Core/src/DataRelayer.cxx index dc820fb5232d1..092e8340a934a 100644 --- a/Framework/Core/src/DataRelayer.cxx +++ b/Framework/Core/src/DataRelayer.cxx @@ -692,7 +692,7 @@ DataRelayer::RelayChoice } index.publishSlot(slot); index.markAsDirty(slot, true); - return RelayChoice{.type = RelayChoice::Type::WillRelay}; + return RelayChoice{.type = RelayChoice::Type::WillRelay, .timeslice = timeslice}; } O2_BUILTIN_UNREACHABLE(); } From bb740a43b7a42b06e721658399e5fe927fa890a3 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Thu, 26 Jun 2025 23:45:52 +0200 Subject: [PATCH 079/315] Replace type name hash with a different string hash in preparation for string-based expressions (#14398) --- Framework/Core/include/Framework/ASoA.h | 415 +++++++++--------- .../Core/include/Framework/StringHelpers.h | 13 + .../include/Framework/TypeIdHelpers.h | 5 +- 3 files changed, 232 insertions(+), 201 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 592864528244c..0e4c2b82ffa8f 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -34,6 +34,7 @@ #include #include // IWYU pragma: export #include +#include namespace o2::framework { @@ -694,6 +695,7 @@ struct DynamicColumn { template struct IndexColumn { using inherited_t = INHERIT; + static constexpr const uint32_t hash = 0; static constexpr const char* const& columnLabel() { return INHERIT::mLabel; } }; @@ -701,6 +703,7 @@ struct IndexColumn { template struct MarkerColumn { using inherited_t = INHERIT; + static constexpr const uint32_t hash = 0; static constexpr const char* const& columnLabel() { return INHERIT::mLabel; } }; @@ -1907,7 +1910,7 @@ class Table static constexpr auto hashes() { - return [](framework::pack) { return std::set{{o2::framework::TypeIdHelpers::uniqueId()...}}; }(columns_t{}); + return [](framework::pack) { return std::set{{C::hash...}}; }(columns_t{}); } Table(std::shared_ptr table, uint64_t offset = 0) @@ -2279,6 +2282,17 @@ O2ORIGIN("TEST"); O2HASH("TEST/0"); } // namespace o2::aod +namespace +{ +template +consteval static std::string_view namespace_prefix() +{ + constexpr auto name = o2::framework::type_name(); + const auto pos = name.rfind(std::string_view{":"}); + return name.substr(0, pos - 1); +} +} // namespace + #define DECLARE_EQUIVALENT_FOR_INDEX(_Base_, _Equiv_) \ template <> \ struct EquivalentIndexNG, o2::aod::Hash<_Equiv_::ref.desc_hash>> { \ @@ -2294,6 +2308,7 @@ O2HASH("TEST/0"); #define DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) \ struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ static constexpr const char* mLabel = _Label_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ static_assert(!((*(mLabel + 1) == 'I' && *(mLabel + 2) == 'n' && *(mLabel + 3) == 'd' && *(mLabel + 4) == 'e' && *(mLabel + 5) == 'x')), "Index is not a valid column name"); \ using base = o2::soa::Column<_Type_, _Name_>; \ using type = _Type_; \ @@ -2317,8 +2332,7 @@ O2HASH("TEST/0"); return _Getter_(); \ } \ }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ - o2::framework::expressions::selectArrowType<_Type_>() } + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_COLUMN(_Name_, _Getter_, _Type_) \ DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, "f" #_Name_) @@ -2330,6 +2344,7 @@ O2HASH("TEST/0"); #define DECLARE_SOA_BITMAP_COLUMN_FULL(_Name_, _Getter_, _Size_, _Label_) \ struct _Name_ : o2::soa::Column { \ static constexpr const char* mLabel = _Label_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ static_assert(!((*(mLabel + 1) == 'I' && *(mLabel + 2) == 'n' && *(mLabel + 3) == 'd' && *(mLabel + 4) == 'e' && *(mLabel + 5) == 'x')), "Index is not a valid column name"); \ using base = o2::soa::Column; \ using type = MAKEINT(_Size_); \ @@ -2352,82 +2367,81 @@ O2HASH("TEST/0"); return (*mColumnIterator & (static_cast(1) << bit)) >> bit; \ } \ }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ - o2::framework::expressions::selectArrowType() } + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType() } #define DECLARE_SOA_BITMAP_COLUMN(_Name_, _Getter_, _Size_) \ DECLARE_SOA_BITMAP_COLUMN_FULL(_Name_, _Getter_, _Size_, "f" #_Name_) /// An 'expression' column. i.e. a column that can be calculated from other /// columns with gandiva based on static C++ expression. -#define DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_, _Expression_) \ - struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ - static constexpr const char* mLabel = _Label_; \ - using base = o2::soa::Column<_Type_, _Name_>; \ - using type = _Type_; \ - using column_t = _Name_; \ - using spawnable_t = std::true_type; \ - _Name_(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_() = default; \ - _Name_(_Name_ const& other) = default; \ - _Name_& operator=(_Name_ const& other) = default; \ - \ - decltype(auto) _Getter_() const \ - { \ - return *mColumnIterator; \ - } \ - \ - decltype(auto) get() const \ - { \ - return _Getter_(); \ - } \ - \ - static o2::framework::expressions::Projector Projector() \ - { \ - return _Expression_; \ - } \ - }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_, _Expression_) \ + struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ + static constexpr const char* mLabel = _Label_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ + using base = o2::soa::Column<_Type_, _Name_>; \ + using type = _Type_; \ + using column_t = _Name_; \ + using spawnable_t = std::true_type; \ + _Name_(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_() = default; \ + _Name_(_Name_ const& other) = default; \ + _Name_& operator=(_Name_ const& other) = default; \ + \ + decltype(auto) _Getter_() const \ + { \ + return *mColumnIterator; \ + } \ + \ + decltype(auto) get() const \ + { \ + return _Getter_(); \ + } \ + \ + static o2::framework::expressions::Projector Projector() \ + { \ + return _Expression_; \ + } \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Expression_) \ DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, "f" #_Name_, _Expression_); /// A configurable 'expression' column. i.e. a column that can be calculated from other /// columns with gandiva based on dynamically supplied C++ expression or a string definition. -#define DECLARE_SOA_CONFIGURABLE_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Label_) \ - struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ - static constexpr const char* mLabel = _Label_; \ - static constexpr const int32_t mHash = _Label_ ""_h; \ - using base = o2::soa::Column<_Type_, _Name_>; \ - using type = _Type_; \ - using column_t = _Name_; \ - using spawnable_t = std::true_type; \ - _Name_(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_() = default; \ - _Name_(_Name_ const& other) = default; \ - _Name_& operator=(_Name_ const& other) = default; \ - \ - decltype(auto) _Getter_() const \ - { \ - return *mColumnIterator; \ - } \ - \ - decltype(auto) get() const \ - { \ - return _Getter_(); \ - } \ - }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_>(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_CONFIGURABLE_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Label_) \ + struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ + static constexpr const char* mLabel = _Label_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ + static constexpr const int32_t mHash = _Label_ ""_h; \ + using base = o2::soa::Column<_Type_, _Name_>; \ + using type = _Type_; \ + using column_t = _Name_; \ + using spawnable_t = std::true_type; \ + _Name_(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_() = default; \ + _Name_(_Name_ const& other) = default; \ + _Name_& operator=(_Name_ const& other) = default; \ + \ + decltype(auto) _Getter_() const \ + { \ + return *mColumnIterator; \ + } \ + \ + decltype(auto) get() const \ + { \ + return _Getter_(); \ + } \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() } /// An index column is a column of indices to elements / of another table named /// _Name_##s. The column name will be _Name_##Id and will always be stored in @@ -2461,6 +2475,7 @@ consteval auto getIndexTargets() static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ static constexpr const char* mLabel = "fIndexSlice" _Label_ _Suffix_; \ + static constexpr const uint32_t hash = 0; \ using base = o2::soa::Column<_Type_[2], _Name_##IdSlice>; \ using type = _Type_[2]; \ using column_t = _Name_##IdSlice; \ @@ -2547,6 +2562,7 @@ consteval auto getIndexTargets() static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ static constexpr const char* mLabel = "fIndexArray" _Label_ _Suffix_; \ + static constexpr const uint32_t hash = 0; \ using base = o2::soa::Column, _Name_##Ids>; \ using type = std::vector<_Type_>; \ using column_t = _Name_##Ids; \ @@ -2697,143 +2713,143 @@ consteval auto getIndexTargets() #define DECLARE_SOA_ARRAY_INDEX_COLUMN_CUSTOM(_Name_, _Getter_, _Label_) DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, int32_t, _Name_##s, _Label_, "") /// NORMAL -#define DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, _Label_, _Suffix_) \ - struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ - static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ - static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ - static constexpr const char* mLabel = "fIndex" _Label_ _Suffix_; \ - using base = o2::soa::Column<_Type_, _Name_##Id>; \ - using type = _Type_; \ - using column_t = _Name_##Id; \ - using binding_t = _Table_; \ - static constexpr auto index_targets = getIndexTargets<_Table_>(); \ - _Name_##Id(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_##Id() = default; \ - _Name_##Id(_Name_##Id const& other) = default; \ - _Name_##Id& operator=(_Name_##Id const& other) = default; \ - type inline getId() const \ - { \ - return _Getter_##Id(); \ - } \ - \ - type _Getter_##Id() const \ - { \ - return *mColumnIterator; \ - } \ - \ - bool has_##_Getter_() const \ - { \ - return *mColumnIterator >= 0; \ - } \ - \ - template \ - auto _Getter_##_as() const \ - { \ - if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \ - o2::soa::notBoundTable(#_Table_); \ - } \ - if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ - o2::soa::accessingInvalidIndexFor(#_Getter_); \ - } \ - auto t = mBinding.get(); \ - if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ - o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \ - } \ - return t->rawIteratorAt(*mColumnIterator); \ - } \ - \ - auto _Getter_() const \ - { \ - return _Getter_##_as(); \ - } \ - \ - template \ - bool setCurrent(T* current) \ - { \ - if constexpr (o2::soa::is_binding_compatible_v()) { \ - assert(current != nullptr); \ - this->mBinding.bind(current); \ - return true; \ - } \ - return false; \ - } \ - \ - bool setCurrentRaw(o2::soa::Binding current) \ - { \ - this->mBinding = current; \ - return true; \ - } \ - binding_t const* getCurrent() const { return mBinding.get(); } \ - o2::soa::Binding getCurrentRaw() const { return mBinding; } \ - o2::soa::Binding mBinding; \ - }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" #_Table_ _Suffix_, o2::framework::TypeIdHelpers::uniqueId<_Name_##Id>(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, _Label_, _Suffix_) \ + struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ + static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ + static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ + static constexpr const char* mLabel = "fIndex" _Label_ _Suffix_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_##Id>(), std::string_view{#_Getter_ "Id"}); \ + using base = o2::soa::Column<_Type_, _Name_##Id>; \ + using type = _Type_; \ + using column_t = _Name_##Id; \ + using binding_t = _Table_; \ + static constexpr auto index_targets = getIndexTargets<_Table_>(); \ + _Name_##Id(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_##Id() = default; \ + _Name_##Id(_Name_##Id const& other) = default; \ + _Name_##Id& operator=(_Name_##Id const& other) = default; \ + type inline getId() const \ + { \ + return _Getter_##Id(); \ + } \ + \ + type _Getter_##Id() const \ + { \ + return *mColumnIterator; \ + } \ + \ + bool has_##_Getter_() const \ + { \ + return *mColumnIterator >= 0; \ + } \ + \ + template \ + auto _Getter_##_as() const \ + { \ + if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \ + o2::soa::notBoundTable(#_Table_); \ + } \ + if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ + o2::soa::accessingInvalidIndexFor(#_Getter_); \ + } \ + auto t = mBinding.get(); \ + if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ + o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \ + } \ + return t->rawIteratorAt(*mColumnIterator); \ + } \ + \ + auto _Getter_() const \ + { \ + return _Getter_##_as(); \ + } \ + \ + template \ + bool setCurrent(T* current) \ + { \ + if constexpr (o2::soa::is_binding_compatible_v()) { \ + assert(current != nullptr); \ + this->mBinding.bind(current); \ + return true; \ + } \ + return false; \ + } \ + \ + bool setCurrentRaw(o2::soa::Binding current) \ + { \ + this->mBinding = current; \ + return true; \ + } \ + binding_t const* getCurrent() const { return mBinding.get(); } \ + o2::soa::Binding getCurrentRaw() const { return mBinding; } \ + o2::soa::Binding mBinding; \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" #_Table_ _Suffix_, _Name_##Id::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Table_, _Suffix_) DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, #_Table_, _Suffix_) #define DECLARE_SOA_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, _Name_##s, "") #define DECLARE_SOA_INDEX_COLUMN_CUSTOM(_Name_, _Getter_, _Label_) DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, int32_t, _Name_##s, _Label_, "") /// SELF -#define DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, _IndexTarget_) \ - struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ - static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ - static constexpr const char* mLabel = "fIndex" _Label_; \ - using base = o2::soa::Column<_Type_, _Name_##Id>; \ - using type = _Type_; \ - using column_t = _Name_##Id; \ - using self_index_t = std::true_type; \ - using compatible_signature = std::conditional, _IndexTarget_, void>; \ - _Name_##Id(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_##Id() = default; \ - _Name_##Id(_Name_##Id const& other) = default; \ - _Name_##Id& operator=(_Name_##Id const& other) = default; \ - type inline getId() const \ - { \ - return _Getter_##Id(); \ - } \ - \ - type _Getter_##Id() const \ - { \ - return *mColumnIterator; \ - } \ - \ - bool has_##_Getter_() const \ - { \ - return *mColumnIterator >= 0; \ - } \ - \ - template \ - auto _Getter_##_as() const \ - { \ - if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ - o2::soa::accessingInvalidIndexFor(#_Getter_); \ - } \ - auto t = mBinding.get(); \ - if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ - o2::soa::dereferenceWithWrongType(#_Getter_, "self"); \ - } \ - return t->rawIteratorAt(*mColumnIterator); \ - } \ - \ - bool setCurrentRaw(o2::soa::Binding current) \ - { \ - this->mBinding = current; \ - return true; \ - } \ - o2::soa::Binding getCurrentRaw() const { return mBinding; } \ - o2::soa::Binding mBinding; \ - }; \ - [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" _Label_, o2::framework::TypeIdHelpers::uniqueId<_Name_##Id>(), \ - o2::framework::expressions::selectArrowType<_Type_>() } +#define DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, _IndexTarget_) \ + struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ + static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ + static constexpr const char* mLabel = "fIndex" _Label_; \ + static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_##Id>(), std::string_view{#_Getter_ "Id"}); \ + using base = o2::soa::Column<_Type_, _Name_##Id>; \ + using type = _Type_; \ + using column_t = _Name_##Id; \ + using self_index_t = std::true_type; \ + using compatible_signature = std::conditional, _IndexTarget_, void>; \ + _Name_##Id(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_##Id() = default; \ + _Name_##Id(_Name_##Id const& other) = default; \ + _Name_##Id& operator=(_Name_##Id const& other) = default; \ + type inline getId() const \ + { \ + return _Getter_##Id(); \ + } \ + \ + type _Getter_##Id() const \ + { \ + return *mColumnIterator; \ + } \ + \ + bool has_##_Getter_() const \ + { \ + return *mColumnIterator >= 0; \ + } \ + \ + template \ + auto _Getter_##_as() const \ + { \ + if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ + o2::soa::accessingInvalidIndexFor(#_Getter_); \ + } \ + auto t = mBinding.get(); \ + if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ + o2::soa::dereferenceWithWrongType(#_Getter_, "self"); \ + } \ + return t->rawIteratorAt(*mColumnIterator); \ + } \ + \ + bool setCurrentRaw(o2::soa::Binding current) \ + { \ + this->mBinding = current; \ + return true; \ + } \ + o2::soa::Binding getCurrentRaw() const { return mBinding; } \ + o2::soa::Binding mBinding; \ + }; \ + [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" _Label_, _Name_##Id::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_SELF_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, void) #define DECLARE_SOA_SELF_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_SELF_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, #_Name_) @@ -2842,6 +2858,7 @@ consteval auto getIndexTargets() struct _Name_##IdSlice : o2::soa::Column<_Type_[2], _Name_##IdSlice> { \ static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ static constexpr const char* mLabel = "fIndexSlice" _Label_; \ + static constexpr const uint32_t hash = 0; \ using base = o2::soa::Column<_Type_[2], _Name_##IdSlice>; \ using type = _Type_[2]; \ using column_t = _Name_##IdSlice; \ @@ -2905,6 +2922,7 @@ consteval auto getIndexTargets() struct _Name_##Ids : o2::soa::Column, _Name_##Ids> { \ static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ static constexpr const char* mLabel = "fIndexArray" _Label_; \ + static constexpr const uint32_t hash = 0; \ using base = o2::soa::Column, _Name_##Ids>; \ using type = std::vector<_Type_>; \ using column_t = _Name_##Ids; \ @@ -3021,6 +3039,7 @@ consteval auto getIndexTargets() using callback_holder_t = _Name_##Callback; \ using callable_t = helper::callable_t; \ using callback_t = callable_t::type; \ + static constexpr const uint32_t hash = 0; \ \ _Name_(arrow::ChunkedArray const*) \ { \ diff --git a/Framework/Core/include/Framework/StringHelpers.h b/Framework/Core/include/Framework/StringHelpers.h index 3da10fb0f561d..e450764576c29 100644 --- a/Framework/Core/include/Framework/StringHelpers.h +++ b/Framework/Core/include/Framework/StringHelpers.h @@ -13,9 +13,11 @@ #define O2_FRAMEWORK_STRINGHELPERS_H_ #include +#include #include #include #include +#include // CRC32 Table (zlib polynomial) static constexpr uint32_t crc_table[256] = {0x0L, 0x77073096L, 0xee0e612cL, @@ -72,6 +74,17 @@ consteval uint32_t crc32(char const* str, int length) return crc; } +template + requires(std::same_as && ...) +consteval uint32_t crc32(Ts... Vs) +{ + uint32_t crc = 0xFFFFFFFF; + for (auto& c : std::vector{Vs...} | std::ranges::views::join) { + crc = (crc >> 8) ^ crc_table[(crc ^ static_cast(c)) & 0x000000FF]; + } + return crc; +} + consteval uint32_t compile_time_hash(char const* str) { return crc32(str, static_cast(__builtin_strlen(str)) - 1) ^ 0xFFFFFFFF; diff --git a/Framework/Foundation/include/Framework/TypeIdHelpers.h b/Framework/Foundation/include/Framework/TypeIdHelpers.h index d4f72b8f3f7ff..5eaac2151b909 100644 --- a/Framework/Foundation/include/Framework/TypeIdHelpers.h +++ b/Framework/Foundation/include/Framework/TypeIdHelpers.h @@ -75,10 +75,9 @@ struct TypeIdHelpers { constexpr static uint32_t uniqueId() { #ifdef __CLING__ - constexpr uint32_t r = crc32(unique_type_id_v.data(), unique_type_id_v.size()); - return r; + return crc32(unique_type_id_v.data(), unique_type_id_v.size()); #else - return compile_time_hash(type_name().data()); + return crc32(type_name().data(), type_name().size()); #endif } }; From e2c787371e4385e13feadb2605f9b9fa21c18dc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 14:57:18 +0200 Subject: [PATCH 080/315] Bump actions/setup-python from 2 to 5 (#14299) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/datamodel-doc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/datamodel-doc.yml b/.github/workflows/datamodel-doc.yml index 294fc2e50f50b..dc8facb307409 100644 --- a/.github/workflows/datamodel-doc.yml +++ b/.github/workflows/datamodel-doc.yml @@ -40,7 +40,7 @@ jobs: git checkout -B auto-datamodel-doc - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.x From 6df9860cd7d8e488e0fcaf936f71de98bc32e5ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 09:20:27 +0000 Subject: [PATCH 081/315] Bump actions/stale from 1 to 9 Bumps [actions/stale](https://github.com/actions/stale) from 1 to 9. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v1...v9) --- updated-dependencies: - dependency-name: actions/stale dependency-version: '9' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 1f1387d4868ae..b1be426cdfc77 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v1 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: 'This PR did not have any update in the last 30 days. Is it still needed? Unless further action in will be closed in 5 days.' From f3a41fc59d80d750596aad2f32427945525db00f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 09:20:22 +0000 Subject: [PATCH 082/315] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/code-transformations.yml | 2 +- .github/workflows/datamodel-doc.yml | 6 +++--- .github/workflows/doxygen.yml | 2 +- .github/workflows/release.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/code-transformations.yml b/.github/workflows/code-transformations.yml index 4b5e55fcc2941..bfc60fdfcbe44 100644 --- a/.github/workflows/code-transformations.yml +++ b/.github/workflows/code-transformations.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} persist-credentials: false diff --git a/.github/workflows/datamodel-doc.yml b/.github/workflows/datamodel-doc.yml index dc8facb307409..51789c9697196 100644 --- a/.github/workflows/datamodel-doc.yml +++ b/.github/workflows/datamodel-doc.yml @@ -10,20 +10,20 @@ jobs: steps: - name: Checkout O2 - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: O2 persist-credentials: false - name: Checkout O2Physics - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: AliceO2Group/O2Physics path: O2Physics persist-credentials: false - name: Checkout documentation - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: AliceO2Group/analysis-framework path: analysis-framework diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index 38da67c793799..ae867739eba62 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -13,7 +13,7 @@ jobs: run: | sudo apt-get update -y sudo apt-get install -y doxygen doxygen-doc doxygen-latex doxygen-gui graphviz cmake - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "dev" persist-credentials: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 894ff2e0bb49b..a401af1ba39e2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: branch=$(echo ${{ github.event.inputs.tag }}-patches | tr . - | sed -e's/-[0-9]*-patches$/-patches/') EOF id: decide_release_branch - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "dev" - name: Tag branch (or create one before tagging if does not exists) From cddd9286104d04bb1b259a7e738ba886af514190 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 27 Jun 2025 10:21:58 +0200 Subject: [PATCH 083/315] Fix vertex copying for last timeframe in collisioncontext When construction individual-TF collisioncontexts, there was a problem copying assigned vertices for the last timeframe due to a simple index comparison error. This is fixed in this commit. --- DataFormats/simulation/src/DigitizationContext.cxx | 2 +- Steer/src/CollisionContextTool.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DataFormats/simulation/src/DigitizationContext.cxx b/DataFormats/simulation/src/DigitizationContext.cxx index d840809a4c446..dc3c560a1485b 100644 --- a/DataFormats/simulation/src/DigitizationContext.cxx +++ b/DataFormats/simulation/src/DigitizationContext.cxx @@ -705,7 +705,7 @@ DigitizationContext DigitizationContext::extractSingleTimeframe(int timeframeid, } std::copy(mEventRecords.begin() + startindex, mEventRecords.begin() + endindex, std::back_inserter(r.mEventRecords)); std::copy(mEventParts.begin() + startindex, mEventParts.begin() + endindex, std::back_inserter(r.mEventParts)); - if (mInteractionVertices.size() > endindex) { + if (mInteractionVertices.size() >= endindex) { std::copy(mInteractionVertices.begin() + startindex, mInteractionVertices.begin() + endindex, std::back_inserter(r.mInteractionVertices)); } diff --git a/Steer/src/CollisionContextTool.cxx b/Steer/src/CollisionContextTool.cxx index e2f7c0fce3d67..9fc3e548ff213 100644 --- a/Steer/src/CollisionContextTool.cxx +++ b/Steer/src/CollisionContextTool.cxx @@ -594,7 +594,7 @@ int main(int argc, char* argv[]) std::stringstream str; str << path_prefix << tf_output_counter++ << "/collisioncontext.root"; copy.saveToFile(str.str()); - LOG(info) << "----"; + LOG(info) << "---- CollisionContext for timeframe " << tf_id << " -----"; copy.printCollisionSummary(); } } From 50d26e30079bfa5be388b7aaf511c367ca66d350 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 27 Jun 2025 10:25:47 +0200 Subject: [PATCH 084/315] o2-sim: Fix for merger exit status analysis --- run/o2sim_parallel.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/run/o2sim_parallel.cxx b/run/o2sim_parallel.cxx index 22c6b37e6d9aa..c060059ce4d6b 100644 --- a/run/o2sim_parallel.cxx +++ b/run/o2sim_parallel.cxx @@ -762,9 +762,8 @@ int main(int argc, char* argv[]) // Handle mergerpid status separately if (cpid == mergerpid) { if (WIFEXITED(status)) { - // anything other than 128 is indicative of error - if (WEXITSTATUS(status) != 128) { - LOG(error) << "Merger process exited with abnormal code " << WEXITSTATUS(status); + if (WEXITSTATUS(status) != 0 || WEXITSTATUS(status) != 128) { + LOG(error) << "Merger process exited with abnormal exit status " << WEXITSTATUS(status); errored = true; } } else if (WIFSIGNALED(status)) { From 6f78cf38c2cb16f01d130beb6dfa50008c63ccc0 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Mon, 30 Jun 2025 09:23:27 +0200 Subject: [PATCH 085/315] DPL Analysis: add `PresliceGroup` (#14418) --- Framework/Core/include/Framework/ASoA.h | 18 ++++++++++++++++++ .../Core/include/Framework/AnalysisManagers.h | 18 ++++++++++++++++-- Framework/Core/test/test_AnalysisTask.cxx | 15 +++++++++++++++ Framework/Core/test/test_Concepts.cxx | 9 +++++++++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 0e4c2b82ffa8f..ccf2cab5e6807 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -1468,6 +1468,24 @@ using PresliceOptional = PresliceBase; template concept is_preslice = std::derived_from; +/// Can be user to group together a number of Preslice declaration +/// to avoid the limit of 100 data members per task +/// +/// struct MyTask +/// struct : public PresliceGroup { +/// Preslice perCol = aod::track::collisonId; +/// Preslice perMcCol = aod::mcparticle::mcCollisionId; +/// } preslices; +/// +/// individual components can be access with +/// +/// preslices.perCol; +struct PresliceGroup { +}; + +template +concept is_preslice_group = std::derived_from; + } // namespace o2::framework namespace o2::soa diff --git a/Framework/Core/include/Framework/AnalysisManagers.h b/Framework/Core/include/Framework/AnalysisManagers.h index 7717d5cb3a6a2..02d252970d731 100644 --- a/Framework/Core/include/Framework/AnalysisManagers.h +++ b/Framework/Core/include/Framework/AnalysisManagers.h @@ -580,7 +580,7 @@ static void setGroupedCombination(C& comb, TG& grouping, std::tuple& asso /// Preslice handling template - requires(!is_preslice) + requires(!is_preslice && !is_preslice_group) bool registerCache(T&, Cache&, Cache&) { return false; @@ -622,8 +622,15 @@ bool registerCache(T& preslice, Cache&, Cache& bsksU) return true; } +template +bool registerCache(T& presliceGroup, Cache& bsks, Cache& bsksU) +{ + homogeneous_apply_refs([&bsks, &bsksU](auto& preslice) { return registerCache(preslice, bsks, bsksU); }, presliceGroup); + return true; +} + template - requires(!is_preslice) + requires(!is_preslice && !is_preslice_group) bool updateSliceInfo(T&, ArrowTableSlicingCache&) { return false; @@ -655,6 +662,13 @@ static bool updateSliceInfo(T& preslice, ArrowTableSlicingCache& cache) return true; } +template +static bool updateSliceInfo(T& presliceGroup, ArrowTableSlicingCache& cache) +{ + homogeneous_apply_refs([&cache](auto& preslice) { return updateSliceInfo(preslice, cache); }, presliceGroup); + return true; +} + /// Process switches handling template static bool setProcessSwitch(std::pair, T&) diff --git a/Framework/Core/test/test_AnalysisTask.cxx b/Framework/Core/test/test_AnalysisTask.cxx index ff0f7da1acaab..f5d8c4c43bc38 100644 --- a/Framework/Core/test/test_AnalysisTask.cxx +++ b/Framework/Core/test/test_AnalysisTask.cxx @@ -13,6 +13,7 @@ #include "TestClasses.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include #include @@ -185,6 +186,17 @@ struct LTask { void process(aod::McCollision const&, soa::SmallGroups> const&) {} }; +struct MTask { + SliceCache cache; + struct : public PresliceGroup { + Preslice perCol = aod::track::collisionId; + PresliceOptional perPart = aod::mctracklabel::mcParticleId; + PresliceUnsorted perMcCol = aod::mccollisionlabel::mcCollisionId; + PresliceUnsortedOptional perMcColopt = aod::mccollisionlabel::mcCollisionId; + } foo; + void process(aod::McCollision const&, soa::SmallGroups> const&) {} +}; + TEST_CASE("AdaptorCompilation") { auto cfgc = makeEmptyConfigContext(); @@ -258,6 +270,9 @@ TEST_CASE("AdaptorCompilation") auto task12 = adaptAnalysisTask(*cfgc, TaskName{"test12"}); REQUIRE(task12.inputs.size() == 3); + + auto task13 = adaptAnalysisTask(*cfgc, TaskName{"test13"}); + REQUIRE(task13.inputs.size() == 3); } TEST_CASE("TestPartitionIteration") diff --git a/Framework/Core/test/test_Concepts.cxx b/Framework/Core/test/test_Concepts.cxx index 5e2ad6d96b30f..ea94c4dfffe5a 100644 --- a/Framework/Core/test/test_Concepts.cxx +++ b/Framework/Core/test/test_Concepts.cxx @@ -96,6 +96,14 @@ TEST_CASE("IdentificationConcepts") Preslice ps = o2::aod::track::collisionId; REQUIRE(is_preslice); + struct : PresliceGroup { + Preslice pc = o2::aod::track::collisionId; + Preslice pmcc = o2::aod::mcparticle::mcCollisionId; + } preslices; + REQUIRE(is_preslice_group); + REQUIRE(is_preslice); + REQUIRE(is_preslice); + REQUIRE(has_filtered_policy::iterator>); REQUIRE(is_filtered_iterator::iterator>); @@ -176,6 +184,7 @@ TEST_CASE("IdentificationConcepts") expressions::Filter f = o2::aod::track::pt > 1.0f; REQUIRE(expressions::is_filter); + // Combinations using C = SameKindPair>; REQUIRE(is_combinations_generator); } From 11329f61884cc17f82132960c1a62f8f0244dd1b Mon Sep 17 00:00:00 2001 From: Christian Sonnabend Date: Mon, 30 Jun 2025 22:53:32 +0200 Subject: [PATCH 086/315] Improve filling kernel speed by 20x using for-loop fill on CPU --- .../Definitions/GPUDefParametersDefaults.h | 4 ++-- .../Global/GPUChainTrackingClusterizer.cxx | 16 ++++++++++----- .../GPUTPCNNClusterizerKernels.cxx | 20 +++++++++++++------ .../GPUTPCNNClusterizerKernels.h | 8 ++++---- GPU/GPUTracking/kernels.cmake | 4 ++-- 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h b/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h index 0591ac8c58630..48d00b274dc9c 100644 --- a/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h +++ b/GPU/GPUTracking/Definitions/GPUDefParametersDefaults.h @@ -488,8 +488,8 @@ #define GPUCA_LB_GPUTPCCFNoiseSuppression_updatePeaks GPUCA_LB_GPUTPCCFNoiseSuppression #define GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer GPUCA_LB_GPUTPCNNClusterizerKernels - #define GPUCA_LB_GPUTPCNNClusterizerKernels_fillInputNN GPUCA_LB_GPUTPCNNClusterizerKernels - #define GPUCA_LB_GPUTPCNNClusterizerKernels_fillInputNNSingleElement GPUCA_LB_GPUTPCNNClusterizerKernels + #define GPUCA_LB_GPUTPCNNClusterizerKernels_fillInputNNCPU GPUCA_LB_GPUTPCNNClusterizerKernels + #define GPUCA_LB_GPUTPCNNClusterizerKernels_fillInputNNGPU GPUCA_LB_GPUTPCNNClusterizerKernels #define GPUCA_LB_GPUTPCNNClusterizerKernels_determineClass1Labels GPUCA_LB_GPUTPCNNClusterizerKernels #define GPUCA_LB_GPUTPCNNClusterizerKernels_determineClass2Labels GPUCA_LB_GPUTPCNNClusterizerKernels #define GPUCA_LB_GPUTPCNNClusterizerKernels_publishClass1Regression GPUCA_LB_GPUTPCNNClusterizerKernels diff --git a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx index dd4cd6ef0be96..25bfe37f0db30 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx @@ -990,11 +990,17 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) uint batchStart = batch * clustererNNShadow.mNnClusterizerBatchedMode; size_t iSize = CAMath::Min((uint)clustererNNShadow.mNnClusterizerBatchedMode, (uint)(clusterer.mPmemory->counters.nClusters - batchStart)); - // auto start0 = std::chrono::high_resolution_clock::now(); - runKernel({GetGrid(iSize * clustererNNShadow.mNnClusterizerElementSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, batchStart); // Filling the data + // Filling the data + if (mRec->IsGPU()) { + // Fills element by element of each input matrix -> better parallelizability, but worse on CPU due to unnecessary computations + runKernel({GetGrid(iSize * clustererNNShadow.mNnClusterizerElementSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, batchStart); + } else { + // Fills the whole input matrix at once -> better performance on CPU, but worse parallelizability + runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, batchStart); + } if (clustererNNShadow.mNnClusterizerSetDeconvolutionFlags) { - runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, batchStart); // Filling the regression data + runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, batchStart); // Publishing the deconvolution flags } // NN evaluations @@ -1042,7 +1048,7 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } } - // Publishing kernels + // Publishing kernels for class labels and regression results if (nnApplication.mModelClass.getNumOutputNodes()[0][1] == 1) { runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceOutputDType, propagateMCLabels, batchStart); // Assigning class labels } else { @@ -1057,7 +1063,7 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } if (clustererNNShadow.mNnClusterizerUseCfRegression) { - if(!nn_settings.nnClusterizerApplyCfDeconvolution) { + if(!nn_settings.nnClusterizerApplyCfDeconvolution) { // If it is already applied don't do it twice, otherwise apply now runKernel({GetGrid(clusterer.mPmemory->counters.nPositions, lane), {iSector}}, true); } DoDebugAndDump(RecoStep::TPCClusterFinding, GPUChainTrackingDebugFlags::TPCClustererChargeMap, clusterer, &GPUTPCClusterFinder::DumpChargeMap, *mDebugFile, "Split Charges"); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx index bc8d26954b5dc..8cdc0684ad588 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx @@ -51,7 +51,7 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread -GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint32_t batchStart) +GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint32_t batchStart) { uint32_t glo_idx = get_global_id(0); auto& clusterer = processors.tpcClusterer[sector]; @@ -65,16 +65,14 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread(chargeMap[peak].unpack()); int32_t row_offset = GPUTPCNNClusterizerKernels::rowOffset(row, clustererNN.mNnClusterizerSizeInputRow); -#ifndef GPUCA_GPUCODE - GPUCA_UNROLL(U(), U()); -#endif for (int32_t r = -clustererNN.mNnClusterizerSizeInputRow; r <= clustererNN.mNnClusterizerSizeInputRow; r++) { bool is_row_boundary = ((row + r) > (o2::tpc::constants::MAXGLOBALPADROW - 1)) || ((row + r) < 0); int32_t pad_offset = is_row_boundary ? 0 : GPUTPCNNClusterizerKernels::padOffset(row, row + r); for (int32_t p = -clustererNN.mNnClusterizerSizeInputPad + pad_offset; p <= clustererNN.mNnClusterizerSizeInputPad + pad_offset; p++) { bool is_boundary = is_row_boundary || GPUTPCNNClusterizerKernels::isBoundary(row + r + row_offset, pad + p, clustererNN.mNnClusterizerSizeInputRow); for (int32_t t = -clustererNN.mNnClusterizerSizeInputTime; t <= clustererNN.mNnClusterizerSizeInputTime; t++) { - if (!is_boundary) { + int32_t time_pos = time + t; + if (!is_boundary && (time_pos >= 0) && (time_pos < TPC_MAX_FRAGMENT_LEN_GPU)) { CfChargePos tmp_pos(row + r, pad + p, time + t); if (r == 0 && !clustererNN.mClusterFlags[2 * glo_idx] && CAMath::Abs(p) < 3 && CAMath::Abs(t) < 3 && p != 0 && t != 0) { // ordering is done for short circuit optimization clustererNN.mClusterFlags[2 * glo_idx] += CfUtils::isPeak(isPeakMap[tmp_pos]); @@ -108,10 +106,20 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread(pad) / GPUTPCGeometry::NPads(row); } } + if (!clustererNN.mNnClusterizerSetDeconvolutionFlags) { + clustererNN.mClusterFlags[2 * glo_idx] = 0; + clustererNN.mClusterFlags[2 * glo_idx + 1] = 0; + for (uint16_t i = 0; i < 8; i++) { + Delta2 d = cfconsts::InnerNeighbors[i]; + CfChargePos tmp_pos = peak.delta(d); + clustererNN.mClusterFlags[2 * glo_idx] += CfUtils::isPeak(isPeakMap[tmp_pos]); + } + clustererNN.mClusterFlags[2 * glo_idx + 1] = clustererNN.mClusterFlags[2 * glo_idx]; + } } template <> -GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint32_t batchStart) +GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint32_t batchStart) { uint32_t glo_idx = get_global_id(0); auto& clusterer = processors.tpcClusterer[sector]; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h index 179eb483cdf6b..a3858d47eb99b 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h @@ -38,8 +38,8 @@ class GPUTPCNNClusterizerKernels : public GPUKernelTemplate { public: // Must all have same number of threads, since they use a common SCRATCH_PAD_WORK_GROUP_SIZE below - static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_fillInputNN) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); - static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_fillInputNNSingleElement) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); + static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_fillInputNNCPU) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); + static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_fillInputNNGPU) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_determineClass1Labels) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_determineClass2Labels) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_publishClass1Regression) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); @@ -59,8 +59,8 @@ class GPUTPCNNClusterizerKernels : public GPUKernelTemplate enum K : int32_t { runCfClusterizer = 0, - fillInputNN = 1, - fillInputNNSingleElement = 2, + fillInputNNCPU = 1, + fillInputNNGPU = 2, determineClass1Labels = 3, determineClass2Labels = 4, publishClass1Regression = 5, diff --git a/GPU/GPUTracking/kernels.cmake b/GPU/GPUTracking/kernels.cmake index 52cda3e8ff416..7ebe631d86e92 100644 --- a/GPU/GPUTracking/kernels.cmake +++ b/GPU/GPUTracking/kernels.cmake @@ -127,8 +127,8 @@ o2_gpu_add_kernel("GPUTrackingRefitKernel, mode0asGPU" "= GLO o2_gpu_add_kernel("GPUTrackingRefitKernel, mode1asTrackParCov" "= GLOBALREFIT " LB) if(onnxruntime_FOUND) o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, runCfClusterizer" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) -o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, fillInputNN" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) -o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, fillInputNNSingleElement" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) +o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, fillInputNNCPU" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) +o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, fillInputNNGPU" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, determineClass1Labels" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, determineClass2Labels" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) o2_gpu_add_kernel("GPUTPCNNClusterizerKernels, publishClass1Regression" "= TPCNNCLUSTERFINDER" LB uint8_t sector int8_t dtype int8_t withMC uint32_t batchStart) From fe73d1b146e575fe980b3ba2e1726a8c9297390f Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 26 Jun 2025 13:51:33 +0200 Subject: [PATCH 087/315] TPC reco: Only read CTP digits when tracking should prevent reading CTP digits when merely clusterizing --- Detectors/TPC/workflow/src/RecoWorkflow.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Detectors/TPC/workflow/src/RecoWorkflow.cxx b/Detectors/TPC/workflow/src/RecoWorkflow.cxx index 0edd23de7c57d..0ccc3d73f115c 100644 --- a/Detectors/TPC/workflow/src/RecoWorkflow.cxx +++ b/Detectors/TPC/workflow/src/RecoWorkflow.cxx @@ -159,6 +159,8 @@ framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vecto WorkflowSpec specs; + bool produceTracks = isEnabled(OutputType::Tracks); + // We provide a special publishing method for labels which have been stored in a split format and need // to be transformed into a contiguous shareable container before publishing. For other branches/types this returns // false and the generic RootTreeWriter publishing proceeds @@ -196,7 +198,7 @@ framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vecto if (sclOpts.needTPCScalersWorkflow()) { // for standalone tpc-reco workflow specs.emplace_back(o2::tpc::getTPCScalerSpec(sclOpts.lumiType == 2, sclOpts.enableMShapeCorrection)); } - if (sclOpts.requestCTPLumi) { // need CTP digits (lumi) reader + if (produceTracks && sclOpts.requestCTPLumi) { // need CTP digits (lumi) reader specs.emplace_back(o2::ctp::getDigitsReaderSpec(false)); } } else if (inputType == InputType::ClustersHardware) { @@ -247,7 +249,6 @@ framework::WorkflowSpec getWorkflow(CompletionPolicyData* policyData, std::vecto // Note: the ClusterHardware format is probably a deprecated legacy format and also the // ClusterDecoderRawSpec bool produceCompClusters = isEnabled(OutputType::CompClusters); - bool produceTracks = isEnabled(OutputType::Tracks); bool runGPUReco = (produceTracks || produceCompClusters || (isEnabled(OutputType::Clusters) && caClusterer) || inputType == InputType::CompClustersCTF) && inputType != InputType::CompClustersFlat; bool runHWDecoder = !caClusterer && (runGPUReco || isEnabled(OutputType::Clusters)); bool runClusterer = !caClusterer && (runHWDecoder || isEnabled(OutputType::ClustersHardware)); From bb7db6d0ddeab602325fd0e3b10822433134d0d6 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sat, 17 May 2025 15:47:16 +0200 Subject: [PATCH 088/315] ITS: GPU: print kernel params prints gpu kernel params Signed-off-by: Felix Schlepper --- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 09d9cee06d9f9..5c3a43540f833 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -39,6 +39,9 @@ Tracker::Tracker(TrackerTraits7* traits) : mTraits(traits) { /// Initialise standard configuration with 1 iteration mTrkParams.resize(1); + if (traits->isGPU()) { + ITSGpuTrackingParamConfig::Instance().printKeyValues(true, true); + } } void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) From 2bf4a1549ed9f65e700b5c96f82cc92fd9b5da62 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 30 Jun 2025 14:55:45 +0200 Subject: [PATCH 089/315] ITS: GPU use ms for tracklets uses multiple streams for trackleting Signed-off-by: Felix Schlepper --- .../GPU/ITStrackingGPU/TimeFrameGPU.h | 11 +- .../GPU/ITStrackingGPU/TrackingKernels.h | 6 +- .../ITS/tracking/GPU/ITStrackingGPU/Utils.h | 90 ++++-- .../ITS/tracking/GPU/cuda/TimeFrameGPU.cu | 303 ++++++++---------- .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 8 +- .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 88 ++--- 6 files changed, 269 insertions(+), 237 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h index d41591e6ff25c..8b3e9bddd18d6 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h @@ -23,8 +23,6 @@ namespace o2::its::gpu { -class Stream; - class DefaultGPUAllocator : public ExternalAllocator { void* allocate(size_t size) override; @@ -81,10 +79,11 @@ class TimeFrameGPU : public TimeFrame void downloadCellsLUTDevice(); void unregisterRest(); template - Stream& getStream(const size_t stream) + auto& getStream(const size_t stream) { - return *mGpuStreams[stream]; + return mGpuStreams[stream]; } + auto& getStreams() { return mGpuStreams; } void wipe(const int); /// interface @@ -146,7 +145,7 @@ class TimeFrameGPU : public TimeFrame int getNumberOfNeighbours() const final; private: - void allocMemAsync(void**, size_t, Stream*, bool); // Abstract owned and unowned memory allocations + void allocMemAsync(void**, size_t, Stream&, bool); // Abstract owned and unowned memory allocations bool mHostRegistered = false; TimeFrameGPUParameters mGpuParams; @@ -200,7 +199,7 @@ class TimeFrameGPU : public TimeFrame const TrackingFrameInfo** mTrackingFrameInfoDeviceArray; // State - std::vector mGpuStreams; + Streams mGpuStreams; size_t mAvailMemGB; bool mFirstInit = true; diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h index b847aacd9bba5..a058f7e5fab0c 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h @@ -84,7 +84,8 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, std::vector& radii, bounded_vector& mulScatAng, const int nBlocks, - const int nThreads); + const int nThreads, + gpu::Streams& streams); template void computeTrackletsInROFsHandler(const IndexTableUtils* utils, @@ -117,7 +118,8 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, std::vector& radii, bounded_vector& mulScatAng, const int nBlocks, - const int nThreads); + const int nThreads, + gpu::Streams& streams); void countCellsHandler(const Cluster** sortedClusters, const Cluster** unsortedClusters, diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h index 74c118009d67d..454e39e04a661 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h @@ -16,12 +16,14 @@ #ifndef ITSTRACKINGGPU_UTILS_H_ #define ITSTRACKINGGPU_UTILS_H_ +#include + #include "GPUCommonDef.h" +#include "GPUCommonHelpers.h" -namespace o2 -{ -namespace its +namespace o2::its { + template struct gpuPair { T1 first; @@ -31,11 +33,6 @@ struct gpuPair { namespace gpu { -template -void discardResult(const T&) -{ -} - // Poor man implementation of a span-like struct. It is very limited. template struct gpuSpan { @@ -85,19 +82,74 @@ enum class Task { Vertexer = 1 }; -template -GPUhd() T* getPtrFromRuler(int index, T* src, const int* ruler, const int stride = 1) +// Abstract stream class +class Stream { - return src + ruler[index] * stride; -} + public: +#if defined(__HIPCC__) + using Handle = hipStream_t; + static constexpr Handle Default = 0; +#elif defined(__CUDACC__) + using Handle = cudaStream_t; + static constexpr Handle Default = 0; +#else + using Handle = void*; + static constexpr Handle Default = nullptr; +#endif + + Stream(unsigned int flags = 0) + { +#if defined(__HIPCC__) + GPUChkErrS(hipStreamCreateWithFlags(&mHandle, flags)); +#elif defined(__CUDACC__) + GPUChkErrS(cudaStreamCreateWithFlags(&mHandle, flags)); +#endif + } -template -GPUhd() const T* getPtrFromRuler(int index, const T* src, const int* ruler, const int stride = 1) + Stream(Handle h) : mHandle(h) {} + ~Stream() + { + if (mHandle != Default) { +#if defined(__HIPCC__) + GPUChkErrS(hipStreamDestroy(mHandle)); +#elif defined(__CUDACC__) + GPUChkErrS(cudaStreamDestroy(mHandle)); +#endif + } + } + + operator bool() const { return mHandle != Default; } + const Handle& get() { return mHandle; } + void sync() const + { +#if defined(__HIPCC__) + GPUChkErrS(hipStreamSynchronize(mHandle)); +#elif defined(__CUDACC__) + GPUChkErrS(cudaStreamSynchronize(mHandle)); +#endif + } + + private: + Handle mHandle{Default}; +}; +static_assert(sizeof(Stream) == sizeof(void*), "Stream type must match pointer type!"); + +// Abstract vector for streams. +// Handles specifically wrap around. +class Streams { - return src + ruler[index] * stride; -} + public: + size_t size() const noexcept { return mStreams.size(); } + void resize(size_t n) { mStreams.resize(n); } + void clear() { mStreams.clear(); } + auto& operator[](size_t i) { return mStreams[i % mStreams.size()]; } + void push_back(const Stream& stream) { mStreams.push_back(stream); } + + private: + std::vector mStreams; +}; + } // namespace gpu -} // namespace its -} // namespace o2 +} // namespace o2::its -#endif \ No newline at end of file +#endif diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu index b336073604b62..13851b4cdc1aa 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu @@ -58,38 +58,6 @@ using constants::MB; namespace gpu { -class Stream final -{ - public: - Stream(); - ~Stream(); - - [[nodiscard]] const cudaStream_t& get() const; - - private: - cudaStream_t mStream; -}; - -Stream::Stream() -{ - GPUChkErrS(cudaStreamCreate(&mStream)); -} - -Stream::~Stream() -{ - GPUChkErrS(cudaStreamDestroy(mStream)); -} - -const cudaStream_t& Stream::get() const -{ - return mStream; -} - -void* DefaultGPUAllocator::allocate(size_t size) -{ - LOGP(fatal, "Called DefaultGPUAllocator::allocate with size {}", size); - return nullptr; // to be implemented -} template TimeFrameGPU::TimeFrameGPU() @@ -101,13 +69,13 @@ template TimeFrameGPU::~TimeFrameGPU() = default; template -void TimeFrameGPU::allocMemAsync(void** ptr, size_t size, Stream* strPtr, bool extAllocator) +void TimeFrameGPU::allocMemAsync(void** ptr, size_t size, Stream& stream, bool extAllocator) { if (extAllocator) { *ptr = this->mAllocator->allocate(size); } else { LOGP(debug, "Calling default CUDA allocator"); - GPUChkErrS(cudaMallocAsync(reinterpret_cast(ptr), size, strPtr->get())); + GPUChkErrS(cudaMallocAsync(reinterpret_cast(ptr), size, stream.get())); } } @@ -120,31 +88,31 @@ void TimeFrameGPU::setDevicePropagator(const o2::base::PropagatorImpl void TimeFrameGPU::loadIndexTableUtils(const int iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading indextable utils"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading indextable utils"); if (!iteration) { LOGP(debug, "gpu-allocation: allocating IndexTableUtils buffer, for {} MB.", sizeof(IndexTableUtils) / MB); - allocMemAsync(reinterpret_cast(&mIndexTableUtilsDevice), sizeof(IndexTableUtils), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mIndexTableUtilsDevice), sizeof(IndexTableUtils), mGpuStreams[0], this->getExtAllocator()); } LOGP(debug, "gpu-transfer: loading IndexTableUtils object, for {} MB.", sizeof(IndexTableUtils) / MB); - GPUChkErrS(cudaMemcpyAsync(mIndexTableUtilsDevice, &(this->mIndexTableUtils), sizeof(IndexTableUtils), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + GPUChkErrS(cudaMemcpyAsync(mIndexTableUtilsDevice, &(this->mIndexTableUtils), sizeof(IndexTableUtils), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadUnsortedClustersDevice(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading unsorted clusters"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading unsorted clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} unsorted clusters on layer {}, for {} MB.", this->mUnsortedClusters[iLayer].size(), iLayer, this->mUnsortedClusters[iLayer].size() * sizeof(Cluster) / MB); - allocMemAsync(reinterpret_cast(&mUnsortedClustersDevice[iLayer]), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mUnsortedClustersDevice[iLayer]), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mUnsortedClusters[iLayer].data(), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mUnsortedClustersDevice[iLayer], this->mUnsortedClusters[iLayer].data(), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(mUnsortedClustersDevice[iLayer], this->mUnsortedClusters[iLayer].data(), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - allocMemAsync(reinterpret_cast(&mUnsortedClustersDeviceArray), nLayers * sizeof(Cluster*), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mUnsortedClustersDeviceArray), nLayers * sizeof(Cluster*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mUnsortedClustersDevice.data(), nLayers * sizeof(Cluster*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mUnsortedClustersDeviceArray, mUnsortedClustersDevice.data(), nLayers * sizeof(Cluster*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + GPUChkErrS(cudaMemcpyAsync(mUnsortedClustersDeviceArray, mUnsortedClustersDevice.data(), nLayers * sizeof(Cluster*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } @@ -152,17 +120,17 @@ template void TimeFrameGPU::loadClustersDevice(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading sorted clusters"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading sorted clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} clusters on layer {}, for {} MB.", this->mClusters[iLayer].size(), iLayer, this->mClusters[iLayer].size() * sizeof(Cluster) / MB); - allocMemAsync(reinterpret_cast(&mClustersDevice[iLayer]), this->mClusters[iLayer].size() * sizeof(Cluster), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mClustersDevice[iLayer]), this->mClusters[iLayer].size() * sizeof(Cluster), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mClusters[iLayer].data(), this->mClusters[iLayer].size() * sizeof(Cluster), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mClustersDevice[iLayer], this->mClusters[iLayer].data(), this->mClusters[iLayer].size() * sizeof(Cluster), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(mClustersDevice[iLayer], this->mClusters[iLayer].data(), this->mClusters[iLayer].size() * sizeof(Cluster), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - allocMemAsync(reinterpret_cast(&mClustersDeviceArray), nLayers * sizeof(Cluster*), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mClustersDeviceArray), nLayers * sizeof(Cluster*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mClustersDevice.data(), nLayers * sizeof(Cluster*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mClustersDeviceArray, mClustersDevice.data(), nLayers * sizeof(Cluster*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + GPUChkErrS(cudaMemcpyAsync(mClustersDeviceArray, mClustersDevice.data(), nLayers * sizeof(Cluster*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } @@ -170,15 +138,15 @@ template void TimeFrameGPU::loadClustersIndexTables(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading sorted clusters"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading sorted clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading clusters indextable for layer {} with {} elements, for {} MB.", iLayer, this->mIndexTables[iLayer].size(), this->mIndexTables[iLayer].size() * sizeof(int) / MB); - allocMemAsync(reinterpret_cast(&mClustersIndexTablesDevice[iLayer]), this->mIndexTables[iLayer].size() * sizeof(int), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mClustersIndexTablesDevice[iLayer], this->mIndexTables[iLayer].data(), this->mIndexTables[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + allocMemAsync(reinterpret_cast(&mClustersIndexTablesDevice[iLayer]), this->mIndexTables[iLayer].size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mClustersIndexTablesDevice[iLayer], this->mIndexTables[iLayer].data(), this->mIndexTables[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - allocMemAsync(reinterpret_cast(&mClustersIndexTablesDeviceArray), nLayers * sizeof(int), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mClustersIndexTablesDeviceArray, mClustersIndexTablesDevice.data(), nLayers * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + allocMemAsync(reinterpret_cast(&mClustersIndexTablesDeviceArray), nLayers * sizeof(int), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mClustersIndexTablesDeviceArray, mClustersIndexTablesDevice.data(), nLayers * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } @@ -186,72 +154,72 @@ template void TimeFrameGPU::createUsedClustersDevice(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "creating used clusters flags"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating used clusters flags"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: creating {} used clusters flags on layer {}, for {} MB.", this->mUsedClusters[iLayer].size(), iLayer, this->mUsedClusters[iLayer].size() * sizeof(unsigned char) / MB); - allocMemAsync(reinterpret_cast(&mUsedClustersDevice[iLayer]), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mUsedClustersDevice[iLayer], 0, this->mUsedClusters[iLayer].size() * sizeof(unsigned char), mGpuStreams[0]->get())); + allocMemAsync(reinterpret_cast(&mUsedClustersDevice[iLayer]), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemsetAsync(mUsedClustersDevice[iLayer], 0, this->mUsedClusters[iLayer].size() * sizeof(unsigned char), mGpuStreams[0].get())); } - allocMemAsync(reinterpret_cast(&mUsedClustersDeviceArray), nLayers * sizeof(unsigned char*), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mUsedClustersDeviceArray, mUsedClustersDevice.data(), nLayers * sizeof(unsigned char*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + allocMemAsync(reinterpret_cast(&mUsedClustersDeviceArray), nLayers * sizeof(unsigned char*), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mUsedClustersDeviceArray, mUsedClustersDevice.data(), nLayers * sizeof(unsigned char*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } template void TimeFrameGPU::loadUsedClustersDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading used clusters flags"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading used clusters flags"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} used clusters flags on layer {}, for {} MB.", this->mUsedClusters[iLayer].size(), iLayer, this->mClusters[iLayer].size() * sizeof(unsigned char) / MB); - GPUChkErrS(cudaMemcpyAsync(mUsedClustersDevice[iLayer], this->mUsedClusters[iLayer].data(), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(mUsedClustersDevice[iLayer], this->mUsedClusters[iLayer].data(), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadROframeClustersDevice(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading ROframe clusters"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading ROframe clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} ROframe clusters info on layer {}, for {} MB.", this->mROFramesClusters[iLayer].size(), iLayer, this->mROFramesClusters[iLayer].size() * sizeof(int) / MB); - allocMemAsync(reinterpret_cast(&mROFramesClustersDevice[iLayer]), this->mROFramesClusters[iLayer].size() * sizeof(int), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mROFramesClustersDevice[iLayer], this->mROFramesClusters[iLayer].data(), this->mROFramesClusters[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + allocMemAsync(reinterpret_cast(&mROFramesClustersDevice[iLayer]), this->mROFramesClusters[iLayer].size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mROFramesClustersDevice[iLayer], this->mROFramesClusters[iLayer].data(), this->mROFramesClusters[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - allocMemAsync(reinterpret_cast(&mROFrameClustersDeviceArray), nLayers * sizeof(int*), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mROFrameClustersDeviceArray, mROFramesClustersDevice.data(), nLayers * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + allocMemAsync(reinterpret_cast(&mROFrameClustersDeviceArray), nLayers * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mROFrameClustersDeviceArray, mROFramesClustersDevice.data(), nLayers * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } template void TimeFrameGPU::loadTrackingFrameInfoDevice(const int iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading trackingframeinfo"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading trackingframeinfo"); if (!iteration) { for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} tfinfo on layer {}, for {} MB.", this->mTrackingFrameInfo[iLayer].size(), iLayer, this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo) / MB); - allocMemAsync(reinterpret_cast(&mTrackingFrameInfoDevice[iLayer]), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mTrackingFrameInfoDevice[iLayer]), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mTrackingFrameInfo[iLayer].data(), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mTrackingFrameInfoDevice[iLayer], this->mTrackingFrameInfo[iLayer].data(), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(mTrackingFrameInfoDevice[iLayer], this->mTrackingFrameInfo[iLayer].data(), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - allocMemAsync(reinterpret_cast(&mTrackingFrameInfoDeviceArray), nLayers * sizeof(TrackingFrameInfo*), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mTrackingFrameInfoDeviceArray), nLayers * sizeof(TrackingFrameInfo*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mTrackingFrameInfoDevice.data(), nLayers * sizeof(TrackingFrameInfo*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mTrackingFrameInfoDeviceArray, mTrackingFrameInfoDevice.data(), nLayers * sizeof(TrackingFrameInfo*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(mTrackingFrameInfoDeviceArray, mTrackingFrameInfoDevice.data(), nLayers * sizeof(TrackingFrameInfo*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadMultiplicityCutMask(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading multiplicity cut mask"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading multiplicity cut mask"); LOGP(debug, "gpu-transfer: loading multiplicity cut mask with {} elements, for {} MB.", this->mMultiplicityCutMask.size(), this->mMultiplicityCutMask.size() * sizeof(bool) / MB); - allocMemAsync(reinterpret_cast(&mMultMaskDevice), this->mMultiplicityCutMask.size() * sizeof(uint8_t), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mMultMaskDevice, this->mMultiplicityCutMask.data(), this->mMultiplicityCutMask.size() * sizeof(uint8_t), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + allocMemAsync(reinterpret_cast(&mMultMaskDevice), this->mMultiplicityCutMask.size() * sizeof(uint8_t), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mMultMaskDevice, this->mMultiplicityCutMask.data(), this->mMultiplicityCutMask.size() * sizeof(uint8_t), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } @@ -259,67 +227,67 @@ template void TimeFrameGPU::loadVertices(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading seeding vertices"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading seeding vertices"); LOGP(debug, "gpu-transfer: loading {} ROframes vertices, for {} MB.", this->mROFramesPV.size(), this->mROFramesPV.size() * sizeof(int) / MB); - allocMemAsync(reinterpret_cast(&mROFramesPVDevice), this->mROFramesPV.size() * sizeof(int), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mROFramesPVDevice, this->mROFramesPV.data(), this->mROFramesPV.size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + allocMemAsync(reinterpret_cast(&mROFramesPVDevice), this->mROFramesPV.size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mROFramesPVDevice, this->mROFramesPV.data(), this->mROFramesPV.size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); LOGP(debug, "gpu-transfer: loading {} seeding vertices, for {} MB.", this->mPrimaryVertices.size(), this->mPrimaryVertices.size() * sizeof(Vertex) / MB); - allocMemAsync(reinterpret_cast(&mPrimaryVerticesDevice), this->mPrimaryVertices.size() * sizeof(Vertex), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mPrimaryVerticesDevice, this->mPrimaryVertices.data(), this->mPrimaryVertices.size() * sizeof(Vertex), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + allocMemAsync(reinterpret_cast(&mPrimaryVerticesDevice), this->mPrimaryVertices.size() * sizeof(Vertex), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mPrimaryVerticesDevice, this->mPrimaryVertices.data(), this->mPrimaryVertices.size() * sizeof(Vertex), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } template void TimeFrameGPU::createTrackletsLUTDevice(const int iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "creating tracklets LUTs"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating tracklets LUTs"); for (auto iLayer{0}; iLayer < nLayers - 1; ++iLayer) { if (!iteration) { LOGP(debug, "gpu-transfer: creating tracklets LUT for {} elements on layer {}, for {} MB.", this->mClusters[iLayer].size() + 1, iLayer, (this->mClusters[iLayer].size() + 1) * sizeof(int) / MB); - allocMemAsync(reinterpret_cast(&mTrackletsLUTDevice[iLayer]), (this->mClusters[iLayer].size() + 1) * sizeof(int), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mTrackletsLUTDevice[iLayer]), (this->mClusters[iLayer].size() + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); } - GPUChkErrS(cudaMemsetAsync(mTrackletsLUTDevice[iLayer], 0, (this->mClusters[iLayer].size() + 1) * sizeof(int), mGpuStreams[0]->get())); + GPUChkErrS(cudaMemsetAsync(mTrackletsLUTDevice[iLayer], 0, (this->mClusters[iLayer].size() + 1) * sizeof(int), mGpuStreams[0].get())); } if (!iteration) { - allocMemAsync(reinterpret_cast(&mTrackletsLUTDeviceArray), (nLayers - 1) * sizeof(int*), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDeviceArray, mTrackletsLUTDevice.data(), mTrackletsLUTDevice.size() * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + allocMemAsync(reinterpret_cast(&mTrackletsLUTDeviceArray), (nLayers - 1) * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDeviceArray, mTrackletsLUTDevice.data(), mTrackletsLUTDevice.size() * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createTrackletsBuffers() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "creating cells buffers"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating cells buffers"); for (auto iLayer{0}; iLayer < nLayers - 1; ++iLayer) { mNTracklets[iLayer] = 0; GPUChkErrS(cudaMemcpyAsync(&mNTracklets[iLayer], mTrackletsLUTDevice[iLayer] + this->mClusters[iLayer].size(), sizeof(int), cudaMemcpyDeviceToHost)); LOGP(debug, "gpu-transfer: creating tracklets buffer for {} elements on layer {}, for {} MB.", mNTracklets[iLayer], iLayer, mNTracklets[iLayer] * sizeof(Tracklet) / MB); - allocMemAsync(reinterpret_cast(&mTrackletsDevice[iLayer]), mNTracklets[iLayer] * sizeof(Tracklet), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mTrackletsDevice[iLayer]), mNTracklets[iLayer] * sizeof(Tracklet), mGpuStreams[0], this->getExtAllocator()); } - allocMemAsync(reinterpret_cast(&mTrackletsDeviceArray), (nLayers - 1) * sizeof(Tracklet*), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mTrackletsDeviceArray), (nLayers - 1) * sizeof(Tracklet*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mTrackletsDevice.data(), (nLayers - 1) * sizeof(Tracklet*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mTrackletsDeviceArray, mTrackletsDevice.data(), (nLayers - 1) * sizeof(Tracklet*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + GPUChkErrS(cudaMemcpyAsync(mTrackletsDeviceArray, mTrackletsDevice.data(), (nLayers - 1) * sizeof(Tracklet*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadTrackletsDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading tracklets"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading tracklets"); for (auto iLayer{0}; iLayer < nLayers - 1; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} tracklets on layer {}, for {} MB.", this->mTracklets[iLayer].size(), iLayer, this->mTracklets[iLayer].size() * sizeof(Tracklet) / MB); GPUChkErrS(cudaHostRegister(this->mTracklets[iLayer].data(), this->mTracklets[iLayer].size() * sizeof(Tracklet), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mTrackletsDevice[iLayer], this->mTracklets[iLayer].data(), this->mTracklets[iLayer].size() * sizeof(Tracklet), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(mTrackletsDevice[iLayer], this->mTracklets[iLayer].data(), this->mTracklets[iLayer].size() * sizeof(Tracklet), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadTrackletsLUTDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading tracklets"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading tracklets"); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { LOGP(debug, "gpu-transfer: loading tracklets LUT for {} elements on layer {}, for {} MB", this->mTrackletsLookupTable[iLayer].size(), iLayer + 1, this->mTrackletsLookupTable[iLayer].size() * sizeof(int) / MB); GPUChkErrS(cudaHostRegister(this->mTrackletsLookupTable[iLayer].data(), this->mTrackletsLookupTable[iLayer].size() * sizeof(int), cudaHostRegisterPortable)); @@ -327,90 +295,90 @@ void TimeFrameGPU::loadTrackletsLUTDevice() } GPUChkErrS(cudaHostRegister(mTrackletsLUTDevice.data(), (nLayers - 1) * sizeof(int*), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDeviceArray, mTrackletsLUTDevice.data(), (nLayers - 1) * sizeof(int*), cudaMemcpyHostToDevice)); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createNeighboursIndexTablesDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "creating cells neighbours"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating cells neighbours"); // Here we do also the creation of the CellsDeviceArray, as the cells buffers are populated separately in the previous steps. - allocMemAsync(reinterpret_cast(&mCellsDeviceArray), (nLayers - 2) * sizeof(CellSeed*), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mCellsDeviceArray), (nLayers - 2) * sizeof(CellSeed*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mCellsDeviceArray, mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(mCellsDeviceArray, mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { LOGP(debug, "gpu-transfer: loading neighbours LUT for {} elements on layer {}, for {} MB.", mNCells[iLayer], iLayer, mNCells[iLayer] * sizeof(CellSeed) / MB); - allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (mNCells[iLayer] + 1) * sizeof(int), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (mNCells[iLayer] + 1) * sizeof(int), mGpuStreams[0]->get())); + allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (mNCells[iLayer] + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (mNCells[iLayer] + 1) * sizeof(int), mGpuStreams[0].get())); if (iLayer < nLayers - 3) { mNNeighbours[iLayer] = 0; } } - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createNeighboursLUTDevice(const int layer, const unsigned int nCells) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "reserving neighboursLUT"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "reserving neighboursLUT"); LOGP(debug, "gpu-allocation: reserving neighbours LUT for {} elements on layer {} , for {} MB.", nCells + 1, layer, (nCells + 1) * sizeof(int) / MB); - allocMemAsync(reinterpret_cast(&mNeighboursLUTDevice[layer]), (nCells + 1) * sizeof(int), nullptr, this->getExtAllocator()); // We need one element more to move exc -> inc - GPUChkErrS(cudaMemsetAsync(mNeighboursLUTDevice[layer], 0, (nCells + 1) * sizeof(int), mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + allocMemAsync(reinterpret_cast(&mNeighboursLUTDevice[layer]), (nCells + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); // We need one element more to move exc -> inc + GPUChkErrS(cudaMemsetAsync(mNeighboursLUTDevice[layer], 0, (nCells + 1) * sizeof(int), mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadCellsDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading cell seeds"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading cell seeds"); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} cell seeds on layer {}, for {} MB.", this->mCells[iLayer].size(), iLayer, this->mCells[iLayer].size() * sizeof(CellSeed) / MB); - allocMemAsync(reinterpret_cast(&mCellsDevice[iLayer]), this->mCells[iLayer].size() * sizeof(CellSeed), nullptr, this->getExtAllocator()); - allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (this->mCells[iLayer].size() + 1) * sizeof(int), nullptr, this->getExtAllocator()); // accessory for the neigh. finding. - GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[0]->get())); - GPUChkErrS(cudaMemcpyAsync(mCellsDevice[iLayer], this->mCells[iLayer].data(), this->mCells[iLayer].size() * sizeof(CellSeed), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + allocMemAsync(reinterpret_cast(&mCellsDevice[iLayer]), this->mCells[iLayer].size() * sizeof(CellSeed), mGpuStreams[0], this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); // accessory for the neigh. finding. + GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpyAsync(mCellsDevice[iLayer], this->mCells[iLayer].data(), this->mCells[iLayer].size() * sizeof(CellSeed), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - allocMemAsync(reinterpret_cast(&mCellsDeviceArray), (nLayers - 2) * sizeof(CellSeed*), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mCellsDeviceArray, mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + allocMemAsync(reinterpret_cast(&mCellsDeviceArray), (nLayers - 2) * sizeof(CellSeed*), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mCellsDeviceArray, mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createCellsLUTDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "creating cells LUTs"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating cells LUTs"); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { LOGP(debug, "gpu-transfer: creating cell LUT for {} elements on layer {}, for {} MB.", mNTracklets[iLayer] + 1, iLayer, (mNTracklets[iLayer] + 1) * sizeof(int) / MB); - allocMemAsync(reinterpret_cast(&mCellsLUTDevice[iLayer]), (mNTracklets[iLayer] + 1) * sizeof(int), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mCellsLUTDevice[iLayer], 0, (mNTracklets[iLayer] + 1) * sizeof(int), mGpuStreams[0]->get())); + allocMemAsync(reinterpret_cast(&mCellsLUTDevice[iLayer]), (mNTracklets[iLayer] + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemsetAsync(mCellsLUTDevice[iLayer], 0, (mNTracklets[iLayer] + 1) * sizeof(int), mGpuStreams[0].get())); } - allocMemAsync(reinterpret_cast(&mCellsLUTDeviceArray), (nLayers - 2) * sizeof(int*), nullptr, this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mCellsLUTDeviceArray, mCellsLUTDevice.data(), mCellsLUTDevice.size() * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + allocMemAsync(reinterpret_cast(&mCellsLUTDeviceArray), (nLayers - 2) * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mCellsLUTDeviceArray, mCellsLUTDevice.data(), mCellsLUTDevice.size() * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createCellsBuffers(const int layer) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "creating cells buffers"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating cells buffers"); mNCells[layer] = 0; GPUChkErrS(cudaMemcpyAsync(&mNCells[layer], mCellsLUTDevice[layer] + mNTracklets[layer], sizeof(int), cudaMemcpyDeviceToHost)); LOGP(debug, "gpu-transfer: creating cell buffer for {} elements on layer {}, for {} MB.", mNCells[layer], layer, mNCells[layer] * sizeof(CellSeed) / MB); - allocMemAsync(reinterpret_cast(&mCellsDevice[layer]), mNCells[layer] * sizeof(CellSeed), nullptr, this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mCellsDevice[layer]), mNCells[layer] * sizeof(CellSeed), mGpuStreams[0], this->getExtAllocator()); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadCellsLUTDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading cells LUTs"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading cells LUTs"); for (auto iLayer{0}; iLayer < nLayers - 3; ++iLayer) { LOGP(debug, "gpu-transfer: loading cell LUT for {} elements on layer {}, for {} MB.", this->mCellsLookupTable[iLayer].size(), iLayer, this->mCellsLookupTable[iLayer].size() * sizeof(int) / MB); GPUChkErrS(cudaHostRegister(this->mCellsLookupTable[iLayer].data(), this->mCellsLookupTable[iLayer].size() * sizeof(int), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mCellsLUTDevice[iLayer + 1], this->mCellsLookupTable[iLayer].data(), this->mCellsLookupTable[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(mCellsLUTDevice[iLayer + 1], this->mCellsLookupTable[iLayer].data(), this->mCellsLookupTable[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template @@ -419,128 +387,128 @@ void TimeFrameGPU::loadRoadsDevice() LOGP(debug, "gpu-transfer: loading {} roads, for {} MB.", this->mRoads.size(), this->mRoads.size() * sizeof(Road) / MB); allocMemAsync(reinterpret_cast(&mRoadsDevice), this->mRoads.size() * sizeof(Road), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mRoads.data(), this->mRoads.size() * sizeof(Road), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mRoadsDevice, this->mRoads.data(), this->mRoads.size() * sizeof(Road), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(mRoadsDevice, this->mRoads.data(), this->mRoads.size() * sizeof(Road), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } template void TimeFrameGPU::loadTrackSeedsDevice(bounded_vector& seeds) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "loading track seeds"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading track seeds"); LOGP(debug, "gpu-transfer: loading {} track seeds, for {} MB.", seeds.size(), seeds.size() * sizeof(CellSeed) / MB); allocMemAsync(reinterpret_cast(&mTrackSeedsDevice), seeds.size() * sizeof(CellSeed), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(seeds.data(), seeds.size() * sizeof(CellSeed), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mTrackSeedsDevice, seeds.data(), seeds.size() * sizeof(CellSeed), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + GPUChkErrS(cudaMemcpyAsync(mTrackSeedsDevice, seeds.data(), seeds.size() * sizeof(CellSeed), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createNeighboursDevice(const unsigned int layer, const unsigned int nNeighbours) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "reserving neighbours"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "reserving neighbours"); LOGP(debug, "gpu-allocation: reserving {} neighbours (pairs), for {} MB.", nNeighbours, nNeighbours * sizeof(gpuPair) / MB); allocMemAsync(reinterpret_cast(&mNeighbourPairsDevice[layer]), nNeighbours * sizeof(gpuPair), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, nNeighbours * sizeof(gpuPair), mGpuStreams[0]->get())); + GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, nNeighbours * sizeof(gpuPair), mGpuStreams[0].get())); LOGP(debug, "gpu-allocation: reserving {} neighbours, for {} MB.", nNeighbours, nNeighbours * sizeof(gpuPair) / MB); allocMemAsync(reinterpret_cast(&mNeighboursDevice[layer]), nNeighbours * sizeof(int), mGpuStreams[0], this->getExtAllocator()); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createNeighboursDevice(const unsigned int layer, std::vector>& neighbours) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "reserving neighbours"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "reserving neighbours"); this->mCellsNeighbours[layer].clear(); this->mCellsNeighbours[layer].resize(neighbours.size()); LOGP(debug, "gpu-allocation: reserving {} neighbours (pairs), for {} MB.", neighbours.size(), neighbours.size() * sizeof(gpuPair) / MB); allocMemAsync(reinterpret_cast(&mNeighbourPairsDevice[layer]), neighbours.size() * sizeof(gpuPair), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, neighbours.size() * sizeof(gpuPair), mGpuStreams[0]->get())); + GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, neighbours.size() * sizeof(gpuPair), mGpuStreams[0].get())); LOGP(debug, "gpu-allocation: reserving {} neighbours, for {} MB.", neighbours.size(), neighbours.size() * sizeof(gpuPair) / MB); allocMemAsync(reinterpret_cast(&mNeighboursDevice[layer]), neighbours.size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createNeighboursDeviceArray() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "reserving neighbours"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "reserving neighbours"); allocMemAsync(reinterpret_cast(&mNeighboursDeviceArray), (nLayers - 2) * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mNeighboursDeviceArray, mNeighboursDevice.data(), (nLayers - 2) * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + GPUChkErrS(cudaMemcpyAsync(mNeighboursDeviceArray, mNeighboursDevice.data(), (nLayers - 2) * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createTrackITSExtDevice(bounded_vector& seeds) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "reserving tracks"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "reserving tracks"); mTrackITSExt = bounded_vector(seeds.size(), {}, this->getMemoryPool().get()); LOGP(debug, "gpu-allocation: reserving {} tracks, for {} MB.", seeds.size(), seeds.size() * sizeof(o2::its::TrackITSExt) / MB); allocMemAsync(reinterpret_cast(&mTrackITSExtDevice), seeds.size() * sizeof(o2::its::TrackITSExt), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mTrackITSExtDevice, 0, seeds.size() * sizeof(o2::its::TrackITSExt), mGpuStreams[0]->get())); + GPUChkErrS(cudaMemsetAsync(mTrackITSExtDevice, 0, seeds.size() * sizeof(o2::its::TrackITSExt), mGpuStreams[0].get())); GPUChkErrS(cudaHostRegister(mTrackITSExt.data(), seeds.size() * sizeof(o2::its::TrackITSExt), cudaHostRegisterPortable)); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::downloadCellsDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "downloading cells"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "downloading cells"); for (int iLayer{0}; iLayer < nLayers - 2; ++iLayer) { LOGP(debug, "gpu-transfer: downloading {} cells on layer: {}, for {} MB.", mNCells[iLayer], iLayer, mNCells[iLayer] * sizeof(CellSeed) / MB); this->mCells[iLayer].resize(mNCells[iLayer]); - GPUChkErrS(cudaMemcpyAsync(this->mCells[iLayer].data(), this->mCellsDevice[iLayer], mNCells[iLayer] * sizeof(CellSeed), cudaMemcpyDeviceToHost, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(this->mCells[iLayer].data(), this->mCellsDevice[iLayer], mNCells[iLayer] * sizeof(CellSeed), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::downloadCellsLUTDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "downloading cell luts"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "downloading cell luts"); for (auto iLayer{0}; iLayer < nLayers - 3; ++iLayer) { LOGP(debug, "gpu-transfer: downloading cells lut on layer {} for {} elements", iLayer, (mNTracklets[iLayer + 1] + 1)); this->mCellsLookupTable[iLayer].resize(mNTracklets[iLayer + 1] + 1); - GPUChkErrS(cudaMemcpyAsync(this->mCellsLookupTable[iLayer].data(), mCellsLUTDevice[iLayer + 1], (mNTracklets[iLayer + 1] + 1) * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(this->mCellsLookupTable[iLayer].data(), mCellsLUTDevice[iLayer + 1], (mNTracklets[iLayer + 1] + 1) * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::downloadCellsNeighboursDevice(std::vector>>& neighbours, const int layer) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), fmt::format("downloading neighbours from layer {}", layer)); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), fmt::format("downloading neighbours from layer {}", layer)); LOGP(debug, "gpu-transfer: downloading {} neighbours, for {} MB.", neighbours[layer].size(), neighbours[layer].size() * sizeof(std::pair) / MB); // TODO: something less dangerous than assuming the same memory layout of std::pair and gpuPair... or not? :) - GPUChkErrS(cudaMemcpyAsync(neighbours[layer].data(), mNeighbourPairsDevice[layer], neighbours[layer].size() * sizeof(gpuPair), cudaMemcpyDeviceToHost, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(neighbours[layer].data(), mNeighbourPairsDevice[layer], neighbours[layer].size() * sizeof(gpuPair), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); } template void TimeFrameGPU::downloadNeighboursLUTDevice(bounded_vector& lut, const int layer) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), fmt::format("downloading neighbours LUT from layer {}", layer)); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), fmt::format("downloading neighbours LUT from layer {}", layer)); LOGP(debug, "gpu-transfer: downloading neighbours LUT for {} elements on layer {}, for {} MB.", lut.size(), layer, lut.size() * sizeof(int) / MB); - GPUChkErrS(cudaMemcpyAsync(lut.data(), mNeighboursLUTDevice[layer], lut.size() * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[0]->get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + GPUChkErrS(cudaMemcpyAsync(lut.data(), mNeighboursLUTDevice[layer], lut.size() * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::downloadTrackITSExtDevice(bounded_vector& seeds) { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "downloading tracks"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "downloading tracks"); LOGP(debug, "gpu-transfer: downloading {} tracks, for {} MB.", mTrackITSExt.size(), mTrackITSExt.size() * sizeof(o2::its::TrackITSExt) / MB); - GPUChkErrS(cudaMemcpyAsync(mTrackITSExt.data(), mTrackITSExtDevice, seeds.size() * sizeof(o2::its::TrackITSExt), cudaMemcpyDeviceToHost, mGpuStreams[0]->get())); + GPUChkErrS(cudaMemcpyAsync(mTrackITSExt.data(), mTrackITSExtDevice, seeds.size() * sizeof(o2::its::TrackITSExt), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); GPUChkErrS(cudaHostUnregister(mTrackITSExt.data())); GPUChkErrS(cudaHostUnregister(seeds.data())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::unregisterRest() { - START_GPU_STREAM_TIMER(mGpuStreams[0]->get(), "unregistering rest of the host memory"); + START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "unregistering rest of the host memory"); LOGP(debug, "unregistering rest of the host memory..."); GPUChkErrS(cudaHostUnregister(mCellsDevice.data())); GPUChkErrS(cudaHostUnregister(mTrackletsDevice.data())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0]->get()); + STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template @@ -563,10 +531,7 @@ void TimeFrameGPU::initialise(const int iteration, IndexTableUtils* utils, const TimeFrameGPUParameters* gpuParam) { - mGpuStreams.resize(mGpuParams.nTimeFrameChunks); - for (auto& str : mGpuStreams) { - str = new Stream(); - } + mGpuStreams.resize(nLayers); o2::its::TimeFrame::initialise(iteration, trkParam, maxLayers); } diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index b32189f3fabe3..d804d0062764f 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -49,13 +49,13 @@ template void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int iROFslice, int iVertex) { auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); - mTimeFrameGPU->createTrackletsLUTDevice(iteration); const Vertex diamondVert({this->mTrkParams[iteration].Diamond[0], this->mTrkParams[iteration].Diamond[1], this->mTrkParams[iteration].Diamond[2]}, {25.e-6f, 0.f, 0.f, 25.e-6f, 0.f, 36.f}, 1, 1.f); gsl::span diamondSpan(&diamondVert, 1); int startROF{this->mTrkParams[iteration].nROFsPerIterations > 0 ? iROFslice * this->mTrkParams[iteration].nROFsPerIterations : 0}; int endROF{o2::gpu::CAMath::Min(this->mTrkParams[iteration].nROFsPerIterations > 0 ? (iROFslice + 1) * this->mTrkParams[iteration].nROFsPerIterations + this->mTrkParams[iteration].DeltaROF : mTimeFrameGPU->getNrof(), mTimeFrameGPU->getNrof())}; + mTimeFrameGPU->createTrackletsLUTDevice(iteration); countTrackletsInROFsHandler(mTimeFrameGPU->getDeviceIndexTableUtils(), mTimeFrameGPU->getDeviceMultCutMask(), startROF, @@ -83,7 +83,8 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i this->mTrkParams[iteration].LayerRadii, mTimeFrameGPU->getMSangles(), conf.nBlocks, - conf.nThreads); + conf.nThreads, + mTimeFrameGPU->getStreams()); mTimeFrameGPU->createTrackletsBuffers(); computeTrackletsInROFsHandler(mTimeFrameGPU->getDeviceIndexTableUtils(), mTimeFrameGPU->getDeviceMultCutMask(), @@ -115,7 +116,8 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i this->mTrkParams[iteration].LayerRadii, mTimeFrameGPU->getMSangles(), conf.nBlocks, - conf.nThreads); + conf.nThreads, + mTimeFrameGPU->getStreams()); } template diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 8c6367c221583..8245aee33718c 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -890,11 +890,14 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, std::vector& radii, bounded_vector& mulScatAng, const int nBlocks, - const int nThreads) + const int nThreads, + gpu::Streams& streams) { for (int iLayer = 0; iLayer < nLayers - 1; ++iLayer) { gpu::computeLayerTrackletsMultiROFKernel<<>>( + o2::gpu::CAMath::Min(nThreads, GPU_THREADS), + 0, + streams[iLayer].get()>>>( utils, multMask, iLayer, @@ -921,7 +924,7 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, resolutions[iLayer], radii[iLayer + 1] - radii[iLayer], mulScatAng[iLayer]); - gpu::cubExclusiveScanInPlace(trackletsLUTsHost[iLayer], nClusters[iLayer] + 1); + gpu::cubExclusiveScanInPlace(trackletsLUTsHost[iLayer], nClusters[iLayer] + 1, streams[iLayer].get()); } } @@ -956,45 +959,52 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, std::vector& radii, bounded_vector& mulScatAng, const int nBlocks, - const int nThreads) + const int nThreads, + gpu::Streams& streams) { for (int iLayer = 0; iLayer < nLayers - 1; ++iLayer) { - gpu::computeLayerTrackletsMultiROFKernel<<>>(utils, - multMask, - iLayer, - startROF, - endROF, - maxROF, - deltaROF, - vertices, - rofPV, - nVertices, - vertexId, - clusters, - ROFClusters, - usedClusters, - clustersIndexTables, - tracklets, - trackletsLUTs, - iteration, - NSigmaCut, - phiCuts[iLayer], - resolutionPV, - minRs[iLayer + 1], - maxRs[iLayer + 1], - resolutions[iLayer], - radii[iLayer + 1] - radii[iLayer], - mulScatAng[iLayer]); + gpu::computeLayerTrackletsMultiROFKernel<<>>( + utils, + multMask, + iLayer, + startROF, + endROF, + maxROF, + deltaROF, + vertices, + rofPV, + nVertices, + vertexId, + clusters, + ROFClusters, + usedClusters, + clustersIndexTables, + tracklets, + trackletsLUTs, + iteration, + NSigmaCut, + phiCuts[iLayer], + resolutionPV, + minRs[iLayer + 1], + maxRs[iLayer + 1], + resolutions[iLayer], + radii[iLayer + 1] - radii[iLayer], + mulScatAng[iLayer]); thrust::device_ptr tracklets_ptr(spanTracklets[iLayer]); - thrust::sort(thrust::device, tracklets_ptr, tracklets_ptr + nTracklets[iLayer], gpu::sort_tracklets()); - auto unique_end = thrust::unique(thrust::device, tracklets_ptr, tracklets_ptr + nTracklets[iLayer], gpu::equal_tracklets()); + auto nosync_policy = THRUST_NAMESPACE::par_nosync.on(streams[iLayer].get()); + thrust::sort(nosync_policy, tracklets_ptr, tracklets_ptr + nTracklets[iLayer], gpu::sort_tracklets()); + auto unique_end = thrust::unique(nosync_policy, tracklets_ptr, tracklets_ptr + nTracklets[iLayer], gpu::equal_tracklets()); nTracklets[iLayer] = unique_end - tracklets_ptr; if (iLayer > 0) { - GPUChkErrS(cudaMemset(trackletsLUTsHost[iLayer], 0, nClusters[iLayer] * sizeof(int))); + GPUChkErrS(cudaMemsetAsync(trackletsLUTsHost[iLayer], 0, nClusters[iLayer] * sizeof(int), streams[iLayer].get())); gpu::compileTrackletsLookupTableKernel<<>>( - spanTracklets[iLayer], trackletsLUTsHost[iLayer], nTracklets[iLayer]); - gpu::cubExclusiveScanInPlace(trackletsLUTsHost[iLayer], nClusters[iLayer] + 1); + o2::gpu::CAMath::Min(nThreads, GPU_THREADS), + 0, + streams[iLayer].get()>>>(spanTracklets[iLayer], trackletsLUTsHost[iLayer], nTracklets[iLayer]); + gpu::cubExclusiveScanInPlace(trackletsLUTsHost[iLayer], nClusters[iLayer] + 1, streams[iLayer].get()); } } } @@ -1350,7 +1360,8 @@ template void countTrackletsInROFsHandler<7>(const IndexTableUtils* utils, std::vector& radii, bounded_vector& mulScatAng, const int nBlocks, - const int nThreads); + const int nThreads, + gpu::Streams& streams); template void computeTrackletsInROFsHandler<7>(const IndexTableUtils* utils, const uint8_t* multMask, @@ -1382,7 +1393,8 @@ template void computeTrackletsInROFsHandler<7>(const IndexTableUtils* utils, std::vector& radii, bounded_vector& mulScatAng, const int nBlocks, - const int nThreads); + const int nThreads, + gpu::Streams& streams); template void processNeighboursHandler<7>(const int startLayer, const int startLevel, From fdc30b14b75630ec1f6769a152852f3a9e3c8089 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 9 Jun 2025 11:35:44 +0200 Subject: [PATCH 090/315] ITS: add GPUTimer and use streams Signed-off-by: Felix Schlepper --- .../ITS/tracking/GPU/cuda/TimeFrameGPU.cu | 211 ++++++++++-------- 1 file changed, 114 insertions(+), 97 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu index 13851b4cdc1aa..d5ea573a2f0e8 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu @@ -14,6 +14,7 @@ #include #include "ITStracking/Constants.h" +#include "ITStracking/BoundedAllocator.h" #include "ITStrackingGPU/Utils.h" #include "ITStrackingGPU/TimeFrameGPU.h" @@ -21,6 +22,8 @@ #include #include +#include +#include #include #include "GPUCommonDef.h" @@ -28,27 +31,6 @@ #include "GPUCommonLogger.h" #include "GPUCommonHelpers.h" -#ifdef ITS_MEASURE_GPU_TIME -#define START_GPU_STREAM_TIMER(stream, name) \ - cudaEvent_t event_start, event_stop; \ - GPUChkErrS(cudaEventCreate(&event_start)); \ - GPUChkErrS(cudaEventCreate(&event_stop)); \ - GPUChkErrS(cudaEventRecord(event_start, stream)); \ - const std::string task_name = name; - -#define STOP_GPU_STREAM_TIMER(stream) \ - GPUChkErrS(cudaEventRecord(event_stop, stream)); \ - GPUChkErrS(cudaEventSynchronize(event_stop)); \ - float ms; \ - GPUChkErrS(cudaEventElapsedTime(&ms, event_start, event_stop)); \ - std::cout << "Elapsed time for " << task_name << ": " << ms << " ms" << std::endl; \ - GPUChkErrS(cudaEventDestroy(event_start)); \ - GPUChkErrS(cudaEventDestroy(event_stop)); -#else -#define START_GPU_STREAM_TIMER(stream, name) -#define STOP_GPU_STREAM_TIMER(stream) -#endif - namespace o2 { namespace its @@ -59,6 +41,71 @@ using constants::MB; namespace gpu { +#ifdef ITS_MEASURE_GPU_TIME +class GPUTimer +{ + public: + GPUTimer(Streams& streams, const std::string& name) + : mName(name) + { + for (size_t i{0}; i < streams.size(); ++i) { + mStreams.push_back(streams[i].get()); + } + startTimers(); + } + GPUTimer(Streams& streams, const std::string& name, size_t end, size_t start = 0) + : mName(name) + { + for (size_t sta{start}; sta < end; ++sta) { + mStreams.push_back(streams[sta].get()); + } + startTimers(); + } + GPUTimer(Stream& stream, const std::string& name) + : mName(name) + { + mStreams.push_back(stream.get()); + startTimers(); + } + ~GPUTimer() + { + for (size_t i{0}; i < mStreams.size(); ++i) { + GPUChkErrS(cudaEventRecord(mStops[i], mStreams[i])); + GPUChkErrS(cudaEventSynchronize(mStops[i])); + float ms = 0.0f; + GPUChkErrS(cudaEventElapsedTime(&ms, mStarts[i], mStops[i])); + LOGP(info, "Elapsed time for {}:{} {} ms", mName, i, ms); + GPUChkErrS(cudaEventDestroy(mStarts[i])); + GPUChkErrS(cudaEventDestroy(mStops[i])); + } + } + + void startTimers() + { + mStarts.resize(mStreams.size()); + mStops.resize(mStreams.size()); + for (size_t i{0}; i < mStreams.size(); ++i) { + GPUChkErrS(cudaEventCreate(&mStarts[i])); + GPUChkErrS(cudaEventCreate(&mStops[i])); + GPUChkErrS(cudaEventRecord(mStarts[i], mStreams[i])); + } + } + + private: + std::string mName; + std::vector mStarts, mStops; + std::vector mStreams; +}; +#else // ITS_MEASURE_GPU_TIME not defined +class GPUTimer +{ + public: + GPUTimer(Stream&, const std::string&) {} + GPUTimer(Streams&, const std::string&) {} + GPUTimer(Streams&, const std::string&, int, int = 0) {} +}; +#endif + template TimeFrameGPU::TimeFrameGPU() { @@ -88,21 +135,20 @@ void TimeFrameGPU::setDevicePropagator(const o2::base::PropagatorImpl void TimeFrameGPU::loadIndexTableUtils(const int iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading indextable utils"); + GPUTimer timer(mGpuStreams[0], "loading indextable utils"); if (!iteration) { LOGP(debug, "gpu-allocation: allocating IndexTableUtils buffer, for {} MB.", sizeof(IndexTableUtils) / MB); allocMemAsync(reinterpret_cast(&mIndexTableUtilsDevice), sizeof(IndexTableUtils), mGpuStreams[0], this->getExtAllocator()); } LOGP(debug, "gpu-transfer: loading IndexTableUtils object, for {} MB.", sizeof(IndexTableUtils) / MB); GPUChkErrS(cudaMemcpyAsync(mIndexTableUtilsDevice, &(this->mIndexTableUtils), sizeof(IndexTableUtils), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadUnsortedClustersDevice(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading unsorted clusters"); + GPUTimer timer(mGpuStreams[0], "loading unsorted clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} unsorted clusters on layer {}, for {} MB.", this->mUnsortedClusters[iLayer].size(), iLayer, this->mUnsortedClusters[iLayer].size() * sizeof(Cluster) / MB); allocMemAsync(reinterpret_cast(&mUnsortedClustersDevice[iLayer]), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), mGpuStreams[0], this->getExtAllocator()); @@ -112,7 +158,6 @@ void TimeFrameGPU::loadUnsortedClustersDevice(const int iteration) allocMemAsync(reinterpret_cast(&mUnsortedClustersDeviceArray), nLayers * sizeof(Cluster*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mUnsortedClustersDevice.data(), nLayers * sizeof(Cluster*), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mUnsortedClustersDeviceArray, mUnsortedClustersDevice.data(), nLayers * sizeof(Cluster*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } @@ -120,7 +165,7 @@ template void TimeFrameGPU::loadClustersDevice(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading sorted clusters"); + GPUTimer timer(mGpuStreams[0], "loading sorted clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} clusters on layer {}, for {} MB.", this->mClusters[iLayer].size(), iLayer, this->mClusters[iLayer].size() * sizeof(Cluster) / MB); allocMemAsync(reinterpret_cast(&mClustersDevice[iLayer]), this->mClusters[iLayer].size() * sizeof(Cluster), mGpuStreams[0], this->getExtAllocator()); @@ -130,7 +175,6 @@ void TimeFrameGPU::loadClustersDevice(const int iteration) allocMemAsync(reinterpret_cast(&mClustersDeviceArray), nLayers * sizeof(Cluster*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mClustersDevice.data(), nLayers * sizeof(Cluster*), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mClustersDeviceArray, mClustersDevice.data(), nLayers * sizeof(Cluster*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } @@ -138,7 +182,7 @@ template void TimeFrameGPU::loadClustersIndexTables(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading sorted clusters"); + GPUTimer timer(mGpuStreams[0], "loading sorted clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading clusters indextable for layer {} with {} elements, for {} MB.", iLayer, this->mIndexTables[iLayer].size(), this->mIndexTables[iLayer].size() * sizeof(int) / MB); allocMemAsync(reinterpret_cast(&mClustersIndexTablesDevice[iLayer]), this->mIndexTables[iLayer].size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); @@ -146,7 +190,6 @@ void TimeFrameGPU::loadClustersIndexTables(const int iteration) } allocMemAsync(reinterpret_cast(&mClustersIndexTablesDeviceArray), nLayers * sizeof(int), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mClustersIndexTablesDeviceArray, mClustersIndexTablesDevice.data(), nLayers * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } @@ -154,7 +197,7 @@ template void TimeFrameGPU::createUsedClustersDevice(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating used clusters flags"); + GPUTimer timer(mGpuStreams[0], "creating used clusters flags"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: creating {} used clusters flags on layer {}, for {} MB.", this->mUsedClusters[iLayer].size(), iLayer, this->mUsedClusters[iLayer].size() * sizeof(unsigned char) / MB); allocMemAsync(reinterpret_cast(&mUsedClustersDevice[iLayer]), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), mGpuStreams[0], this->getExtAllocator()); @@ -162,26 +205,24 @@ void TimeFrameGPU::createUsedClustersDevice(const int iteration) } allocMemAsync(reinterpret_cast(&mUsedClustersDeviceArray), nLayers * sizeof(unsigned char*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mUsedClustersDeviceArray, mUsedClustersDevice.data(), nLayers * sizeof(unsigned char*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } template void TimeFrameGPU::loadUsedClustersDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading used clusters flags"); + GPUTimer timer(mGpuStreams[0], "loading used clusters flags"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} used clusters flags on layer {}, for {} MB.", this->mUsedClusters[iLayer].size(), iLayer, this->mClusters[iLayer].size() * sizeof(unsigned char) / MB); GPUChkErrS(cudaMemcpyAsync(mUsedClustersDevice[iLayer], this->mUsedClusters[iLayer].data(), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadROframeClustersDevice(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading ROframe clusters"); + GPUTimer timer(mGpuStreams[0], "loading ROframe clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} ROframe clusters info on layer {}, for {} MB.", this->mROFramesClusters[iLayer].size(), iLayer, this->mROFramesClusters[iLayer].size() * sizeof(int) / MB); allocMemAsync(reinterpret_cast(&mROFramesClustersDevice[iLayer]), this->mROFramesClusters[iLayer].size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); @@ -189,14 +230,13 @@ void TimeFrameGPU::loadROframeClustersDevice(const int iteration) } allocMemAsync(reinterpret_cast(&mROFrameClustersDeviceArray), nLayers * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mROFrameClustersDeviceArray, mROFramesClustersDevice.data(), nLayers * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } template void TimeFrameGPU::loadTrackingFrameInfoDevice(const int iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading trackingframeinfo"); + GPUTimer timer(mGpuStreams[0], "loading trackingframeinfo"); if (!iteration) { for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} tfinfo on layer {}, for {} MB.", this->mTrackingFrameInfo[iLayer].size(), iLayer, this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo) / MB); @@ -208,18 +248,16 @@ void TimeFrameGPU::loadTrackingFrameInfoDevice(const int iteration) GPUChkErrS(cudaHostRegister(mTrackingFrameInfoDevice.data(), nLayers * sizeof(TrackingFrameInfo*), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackingFrameInfoDeviceArray, mTrackingFrameInfoDevice.data(), nLayers * sizeof(TrackingFrameInfo*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadMultiplicityCutMask(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading multiplicity cut mask"); + GPUTimer timer(mGpuStreams[0], "loading multiplicity cut mask"); LOGP(debug, "gpu-transfer: loading multiplicity cut mask with {} elements, for {} MB.", this->mMultiplicityCutMask.size(), this->mMultiplicityCutMask.size() * sizeof(bool) / MB); allocMemAsync(reinterpret_cast(&mMultMaskDevice), this->mMultiplicityCutMask.size() * sizeof(uint8_t), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mMultMaskDevice, this->mMultiplicityCutMask.data(), this->mMultiplicityCutMask.size() * sizeof(uint8_t), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } @@ -227,81 +265,76 @@ template void TimeFrameGPU::loadVertices(const int iteration) { if (!iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading seeding vertices"); + GPUTimer timer(mGpuStreams[0], "loading seeding vertices"); LOGP(debug, "gpu-transfer: loading {} ROframes vertices, for {} MB.", this->mROFramesPV.size(), this->mROFramesPV.size() * sizeof(int) / MB); allocMemAsync(reinterpret_cast(&mROFramesPVDevice), this->mROFramesPV.size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mROFramesPVDevice, this->mROFramesPV.data(), this->mROFramesPV.size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); LOGP(debug, "gpu-transfer: loading {} seeding vertices, for {} MB.", this->mPrimaryVertices.size(), this->mPrimaryVertices.size() * sizeof(Vertex) / MB); allocMemAsync(reinterpret_cast(&mPrimaryVerticesDevice), this->mPrimaryVertices.size() * sizeof(Vertex), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mPrimaryVerticesDevice, this->mPrimaryVertices.data(), this->mPrimaryVertices.size() * sizeof(Vertex), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } } template void TimeFrameGPU::createTrackletsLUTDevice(const int iteration) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating tracklets LUTs"); + GPUTimer timer(mGpuStreams, "creating tracklets LUTs", nLayers - 1); for (auto iLayer{0}; iLayer < nLayers - 1; ++iLayer) { if (!iteration) { LOGP(debug, "gpu-transfer: creating tracklets LUT for {} elements on layer {}, for {} MB.", this->mClusters[iLayer].size() + 1, iLayer, (this->mClusters[iLayer].size() + 1) * sizeof(int) / MB); - allocMemAsync(reinterpret_cast(&mTrackletsLUTDevice[iLayer]), (this->mClusters[iLayer].size() + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mTrackletsLUTDevice[iLayer]), (this->mClusters[iLayer].size() + 1) * sizeof(int), mGpuStreams[iLayer], this->getExtAllocator()); } - GPUChkErrS(cudaMemsetAsync(mTrackletsLUTDevice[iLayer], 0, (this->mClusters[iLayer].size() + 1) * sizeof(int), mGpuStreams[0].get())); + GPUChkErrS(cudaMemsetAsync(mTrackletsLUTDevice[iLayer], 0, (this->mClusters[iLayer].size() + 1) * sizeof(int), mGpuStreams[iLayer].get())); } if (!iteration) { allocMemAsync(reinterpret_cast(&mTrackletsLUTDeviceArray), (nLayers - 1) * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDeviceArray, mTrackletsLUTDevice.data(), mTrackletsLUTDevice.size() * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createTrackletsBuffers() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating cells buffers"); + GPUTimer timer(mGpuStreams, "creating cells buffers", nLayers - 1); for (auto iLayer{0}; iLayer < nLayers - 1; ++iLayer) { mNTracklets[iLayer] = 0; GPUChkErrS(cudaMemcpyAsync(&mNTracklets[iLayer], mTrackletsLUTDevice[iLayer] + this->mClusters[iLayer].size(), sizeof(int), cudaMemcpyDeviceToHost)); LOGP(debug, "gpu-transfer: creating tracklets buffer for {} elements on layer {}, for {} MB.", mNTracklets[iLayer], iLayer, mNTracklets[iLayer] * sizeof(Tracklet) / MB); - allocMemAsync(reinterpret_cast(&mTrackletsDevice[iLayer]), mNTracklets[iLayer] * sizeof(Tracklet), mGpuStreams[0], this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mTrackletsDevice[iLayer]), mNTracklets[iLayer] * sizeof(Tracklet), mGpuStreams[iLayer], this->getExtAllocator()); } allocMemAsync(reinterpret_cast(&mTrackletsDeviceArray), (nLayers - 1) * sizeof(Tracklet*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mTrackletsDevice.data(), (nLayers - 1) * sizeof(Tracklet*), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackletsDeviceArray, mTrackletsDevice.data(), (nLayers - 1) * sizeof(Tracklet*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadTrackletsDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading tracklets"); + GPUTimer timer(mGpuStreams, "loading tracklets", nLayers - 1); for (auto iLayer{0}; iLayer < nLayers - 1; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} tracklets on layer {}, for {} MB.", this->mTracklets[iLayer].size(), iLayer, this->mTracklets[iLayer].size() * sizeof(Tracklet) / MB); GPUChkErrS(cudaHostRegister(this->mTracklets[iLayer].data(), this->mTracklets[iLayer].size() * sizeof(Tracklet), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mTrackletsDevice[iLayer], this->mTracklets[iLayer].data(), this->mTracklets[iLayer].size() * sizeof(Tracklet), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpyAsync(mTrackletsDevice[iLayer], this->mTracklets[iLayer].data(), this->mTracklets[iLayer].size() * sizeof(Tracklet), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadTrackletsLUTDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading tracklets"); + GPUTimer timer(mGpuStreams, "loading tracklets", nLayers - 2); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { LOGP(debug, "gpu-transfer: loading tracklets LUT for {} elements on layer {}, for {} MB", this->mTrackletsLookupTable[iLayer].size(), iLayer + 1, this->mTrackletsLookupTable[iLayer].size() * sizeof(int) / MB); GPUChkErrS(cudaHostRegister(this->mTrackletsLookupTable[iLayer].data(), this->mTrackletsLookupTable[iLayer].size() * sizeof(int), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDevice[iLayer + 1], this->mTrackletsLookupTable[iLayer].data(), this->mTrackletsLookupTable[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice)); + GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDevice[iLayer + 1], this->mTrackletsLookupTable[iLayer].data(), this->mTrackletsLookupTable[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } GPUChkErrS(cudaHostRegister(mTrackletsLUTDevice.data(), (nLayers - 1) * sizeof(int*), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDeviceArray, mTrackletsLUTDevice.data(), (nLayers - 1) * sizeof(int*), cudaMemcpyHostToDevice)); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createNeighboursIndexTablesDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating cells neighbours"); + GPUTimer timer(mGpuStreams[0], "creating cells neighbours"); // Here we do also the creation of the CellsDeviceArray, as the cells buffers are populated separately in the previous steps. allocMemAsync(reinterpret_cast(&mCellsDeviceArray), (nLayers - 2) * sizeof(CellSeed*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaHostRegisterPortable)); @@ -314,76 +347,70 @@ void TimeFrameGPU::createNeighboursIndexTablesDevice() mNNeighbours[iLayer] = 0; } } - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createNeighboursLUTDevice(const int layer, const unsigned int nCells) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "reserving neighboursLUT"); + GPUTimer timer(mGpuStreams[0], "reserving neighboursLUT"); LOGP(debug, "gpu-allocation: reserving neighbours LUT for {} elements on layer {} , for {} MB.", nCells + 1, layer, (nCells + 1) * sizeof(int) / MB); allocMemAsync(reinterpret_cast(&mNeighboursLUTDevice[layer]), (nCells + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); // We need one element more to move exc -> inc GPUChkErrS(cudaMemsetAsync(mNeighboursLUTDevice[layer], 0, (nCells + 1) * sizeof(int), mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadCellsDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading cell seeds"); + GPUTimer timer(mGpuStreams, "loading cell seeds", nLayers - 2); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { LOGP(debug, "gpu-transfer: loading {} cell seeds on layer {}, for {} MB.", this->mCells[iLayer].size(), iLayer, this->mCells[iLayer].size() * sizeof(CellSeed) / MB); - allocMemAsync(reinterpret_cast(&mCellsDevice[iLayer]), this->mCells[iLayer].size() * sizeof(CellSeed), mGpuStreams[0], this->getExtAllocator()); - allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); // accessory for the neigh. finding. - GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[0].get())); - GPUChkErrS(cudaMemcpyAsync(mCellsDevice[iLayer], this->mCells[iLayer].data(), this->mCells[iLayer].size() * sizeof(CellSeed), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + allocMemAsync(reinterpret_cast(&mCellsDevice[iLayer]), this->mCells[iLayer].size() * sizeof(CellSeed), mGpuStreams[iLayer], this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[iLayer], this->getExtAllocator()); // accessory for the neigh. finding. + GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[iLayer].get())); + GPUChkErrS(cudaMemcpyAsync(mCellsDevice[iLayer], this->mCells[iLayer].data(), this->mCells[iLayer].size() * sizeof(CellSeed), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } allocMemAsync(reinterpret_cast(&mCellsDeviceArray), (nLayers - 2) * sizeof(CellSeed*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mCellsDeviceArray, mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createCellsLUTDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating cells LUTs"); + GPUTimer timer(mGpuStreams, "creating cells LUTs", nLayers - 2); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { LOGP(debug, "gpu-transfer: creating cell LUT for {} elements on layer {}, for {} MB.", mNTracklets[iLayer] + 1, iLayer, (mNTracklets[iLayer] + 1) * sizeof(int) / MB); - allocMemAsync(reinterpret_cast(&mCellsLUTDevice[iLayer]), (mNTracklets[iLayer] + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mCellsLUTDevice[iLayer], 0, (mNTracklets[iLayer] + 1) * sizeof(int), mGpuStreams[0].get())); + allocMemAsync(reinterpret_cast(&mCellsLUTDevice[iLayer]), (mNTracklets[iLayer] + 1) * sizeof(int), mGpuStreams[iLayer], this->getExtAllocator()); + GPUChkErrS(cudaMemsetAsync(mCellsLUTDevice[iLayer], 0, (mNTracklets[iLayer] + 1) * sizeof(int), mGpuStreams[iLayer].get())); } allocMemAsync(reinterpret_cast(&mCellsLUTDeviceArray), (nLayers - 2) * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mCellsLUTDeviceArray, mCellsLUTDevice.data(), mCellsLUTDevice.size() * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createCellsBuffers(const int layer) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "creating cells buffers"); + GPUTimer timer(mGpuStreams[0], "creating cells buffers"); mNCells[layer] = 0; GPUChkErrS(cudaMemcpyAsync(&mNCells[layer], mCellsLUTDevice[layer] + mNTracklets[layer], sizeof(int), cudaMemcpyDeviceToHost)); LOGP(debug, "gpu-transfer: creating cell buffer for {} elements on layer {}, for {} MB.", mNCells[layer], layer, mNCells[layer] * sizeof(CellSeed) / MB); allocMemAsync(reinterpret_cast(&mCellsDevice[layer]), mNCells[layer] * sizeof(CellSeed), mGpuStreams[0], this->getExtAllocator()); - - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadCellsLUTDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading cells LUTs"); + GPUTimer timer(mGpuStreams, "loading cells LUTs", nLayers - 3); for (auto iLayer{0}; iLayer < nLayers - 3; ++iLayer) { LOGP(debug, "gpu-transfer: loading cell LUT for {} elements on layer {}, for {} MB.", this->mCellsLookupTable[iLayer].size(), iLayer, this->mCellsLookupTable[iLayer].size() * sizeof(int) / MB); GPUChkErrS(cudaHostRegister(this->mCellsLookupTable[iLayer].data(), this->mCellsLookupTable[iLayer].size() * sizeof(int), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mCellsLUTDevice[iLayer + 1], this->mCellsLookupTable[iLayer].data(), this->mCellsLookupTable[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpyAsync(mCellsLUTDevice[iLayer + 1], this->mCellsLookupTable[iLayer].data(), this->mCellsLookupTable[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::loadRoadsDevice() { + GPUTimer timer(mGpuStreams[0], "loading roads device"); LOGP(debug, "gpu-transfer: loading {} roads, for {} MB.", this->mRoads.size(), this->mRoads.size() * sizeof(Road) / MB); allocMemAsync(reinterpret_cast(&mRoadsDevice), this->mRoads.size() * sizeof(Road), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mRoads.data(), this->mRoads.size() * sizeof(Road), cudaHostRegisterPortable)); @@ -393,30 +420,28 @@ void TimeFrameGPU::loadRoadsDevice() template void TimeFrameGPU::loadTrackSeedsDevice(bounded_vector& seeds) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "loading track seeds"); + GPUTimer timer(mGpuStreams[0], "loading track seeds"); LOGP(debug, "gpu-transfer: loading {} track seeds, for {} MB.", seeds.size(), seeds.size() * sizeof(CellSeed) / MB); allocMemAsync(reinterpret_cast(&mTrackSeedsDevice), seeds.size() * sizeof(CellSeed), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(seeds.data(), seeds.size() * sizeof(CellSeed), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackSeedsDevice, seeds.data(), seeds.size() * sizeof(CellSeed), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createNeighboursDevice(const unsigned int layer, const unsigned int nNeighbours) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "reserving neighbours"); + GPUTimer timer(mGpuStreams[0], "reserving neighbours"); LOGP(debug, "gpu-allocation: reserving {} neighbours (pairs), for {} MB.", nNeighbours, nNeighbours * sizeof(gpuPair) / MB); allocMemAsync(reinterpret_cast(&mNeighbourPairsDevice[layer]), nNeighbours * sizeof(gpuPair), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, nNeighbours * sizeof(gpuPair), mGpuStreams[0].get())); LOGP(debug, "gpu-allocation: reserving {} neighbours, for {} MB.", nNeighbours, nNeighbours * sizeof(gpuPair) / MB); allocMemAsync(reinterpret_cast(&mNeighboursDevice[layer]), nNeighbours * sizeof(int), mGpuStreams[0], this->getExtAllocator()); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createNeighboursDevice(const unsigned int layer, std::vector>& neighbours) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "reserving neighbours"); + GPUTimer timer(mGpuStreams[0], "reserving neighbours"); this->mCellsNeighbours[layer].clear(); this->mCellsNeighbours[layer].resize(neighbours.size()); LOGP(debug, "gpu-allocation: reserving {} neighbours (pairs), for {} MB.", neighbours.size(), neighbours.size() * sizeof(gpuPair) / MB); @@ -424,58 +449,53 @@ void TimeFrameGPU::createNeighboursDevice(const unsigned int layer, std GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, neighbours.size() * sizeof(gpuPair), mGpuStreams[0].get())); LOGP(debug, "gpu-allocation: reserving {} neighbours, for {} MB.", neighbours.size(), neighbours.size() * sizeof(gpuPair) / MB); allocMemAsync(reinterpret_cast(&mNeighboursDevice[layer]), neighbours.size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createNeighboursDeviceArray() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "reserving neighbours"); + GPUTimer timer(mGpuStreams[0], "reserving neighbours"); allocMemAsync(reinterpret_cast(&mNeighboursDeviceArray), (nLayers - 2) * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mNeighboursDeviceArray, mNeighboursDevice.data(), (nLayers - 2) * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::createTrackITSExtDevice(bounded_vector& seeds) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "reserving tracks"); + GPUTimer timer(mGpuStreams[0], "reserving tracks"); mTrackITSExt = bounded_vector(seeds.size(), {}, this->getMemoryPool().get()); LOGP(debug, "gpu-allocation: reserving {} tracks, for {} MB.", seeds.size(), seeds.size() * sizeof(o2::its::TrackITSExt) / MB); allocMemAsync(reinterpret_cast(&mTrackITSExtDevice), seeds.size() * sizeof(o2::its::TrackITSExt), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemsetAsync(mTrackITSExtDevice, 0, seeds.size() * sizeof(o2::its::TrackITSExt), mGpuStreams[0].get())); GPUChkErrS(cudaHostRegister(mTrackITSExt.data(), seeds.size() * sizeof(o2::its::TrackITSExt), cudaHostRegisterPortable)); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::downloadCellsDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "downloading cells"); + GPUTimer timer(mGpuStreams, "downloading cells", nLayers - 2); for (int iLayer{0}; iLayer < nLayers - 2; ++iLayer) { LOGP(debug, "gpu-transfer: downloading {} cells on layer: {}, for {} MB.", mNCells[iLayer], iLayer, mNCells[iLayer] * sizeof(CellSeed) / MB); this->mCells[iLayer].resize(mNCells[iLayer]); - GPUChkErrS(cudaMemcpyAsync(this->mCells[iLayer].data(), this->mCellsDevice[iLayer], mNCells[iLayer] * sizeof(CellSeed), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpyAsync(this->mCells[iLayer].data(), this->mCellsDevice[iLayer], mNCells[iLayer] * sizeof(CellSeed), cudaMemcpyDeviceToHost, mGpuStreams[iLayer].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::downloadCellsLUTDevice() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "downloading cell luts"); + GPUTimer timer(mGpuStreams, "downloading cell luts", nLayers - 3); for (auto iLayer{0}; iLayer < nLayers - 3; ++iLayer) { LOGP(debug, "gpu-transfer: downloading cells lut on layer {} for {} elements", iLayer, (mNTracklets[iLayer + 1] + 1)); this->mCellsLookupTable[iLayer].resize(mNTracklets[iLayer + 1] + 1); - GPUChkErrS(cudaMemcpyAsync(this->mCellsLookupTable[iLayer].data(), mCellsLUTDevice[iLayer + 1], (mNTracklets[iLayer + 1] + 1) * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpyAsync(this->mCellsLookupTable[iLayer].data(), mCellsLUTDevice[iLayer + 1], (mNTracklets[iLayer + 1] + 1) * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[iLayer].get())); } - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::downloadCellsNeighboursDevice(std::vector>>& neighbours, const int layer) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), fmt::format("downloading neighbours from layer {}", layer)); + GPUTimer timer(mGpuStreams[0], fmt::format("downloading neighbours from layer {}", layer)); LOGP(debug, "gpu-transfer: downloading {} neighbours, for {} MB.", neighbours[layer].size(), neighbours[layer].size() * sizeof(std::pair) / MB); // TODO: something less dangerous than assuming the same memory layout of std::pair and gpuPair... or not? :) GPUChkErrS(cudaMemcpyAsync(neighbours[layer].data(), mNeighbourPairsDevice[layer], neighbours[layer].size() * sizeof(gpuPair), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); @@ -484,31 +504,28 @@ void TimeFrameGPU::downloadCellsNeighboursDevice(std::vector void TimeFrameGPU::downloadNeighboursLUTDevice(bounded_vector& lut, const int layer) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), fmt::format("downloading neighbours LUT from layer {}", layer)); + GPUTimer timer(mGpuStreams[0], fmt::format("downloading neighbours LUT from layer {}", layer)); LOGP(debug, "gpu-transfer: downloading neighbours LUT for {} elements on layer {}, for {} MB.", lut.size(), layer, lut.size() * sizeof(int) / MB); GPUChkErrS(cudaMemcpyAsync(lut.data(), mNeighboursLUTDevice[layer], lut.size() * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::downloadTrackITSExtDevice(bounded_vector& seeds) { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "downloading tracks"); + GPUTimer timer(mGpuStreams[0], "downloading tracks"); LOGP(debug, "gpu-transfer: downloading {} tracks, for {} MB.", mTrackITSExt.size(), mTrackITSExt.size() * sizeof(o2::its::TrackITSExt) / MB); GPUChkErrS(cudaMemcpyAsync(mTrackITSExt.data(), mTrackITSExtDevice, seeds.size() * sizeof(o2::its::TrackITSExt), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); GPUChkErrS(cudaHostUnregister(mTrackITSExt.data())); GPUChkErrS(cudaHostUnregister(seeds.data())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template void TimeFrameGPU::unregisterRest() { - START_GPU_STREAM_TIMER(mGpuStreams[0].get(), "unregistering rest of the host memory"); + GPUTimer timer(mGpuStreams[0], "unregistering rest of the host memory"); LOGP(debug, "unregistering rest of the host memory..."); GPUChkErrS(cudaHostUnregister(mCellsDevice.data())); GPUChkErrS(cudaHostUnregister(mTrackletsDevice.data())); - STOP_GPU_STREAM_TIMER(mGpuStreams[0].get()); } template From 4cfc7e41b257c04ab83ecc641296f4d92bd0f622 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 1 Jul 2025 21:51:22 +0200 Subject: [PATCH 091/315] DPL: make sure devices with Sporadic inputs get sorted last, if possible (#14459) --- Framework/Core/src/TopologyPolicy.cxx | 81 +++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/Framework/Core/src/TopologyPolicy.cxx b/Framework/Core/src/TopologyPolicy.cxx index e209c2702031e..5458d9d65da4a 100644 --- a/Framework/Core/src/TopologyPolicy.cxx +++ b/Framework/Core/src/TopologyPolicy.cxx @@ -69,6 +69,40 @@ bool dataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) return false; } +// This is to make sure that if a device has sporadic / timer inputs +// it gets sorted after one which does not, in case there is no other +// dependencies between the two. +bool sporadicDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) +{ + auto checkSporadic = [](InputSpec const& input) { + return input.lifetime == Lifetime::Sporadic; + }; + bool isBWithSporadicInput = std::find_if(b.inputs.begin(), b.inputs.end(), checkSporadic) != b.inputs.end(); + bool isAWithSporadicInput = std::find_if(a.inputs.begin(), a.inputs.end(), checkSporadic) != a.inputs.end(); + // If neither has sporadic inputs, we return false and sort as usual + if (!isAWithSporadicInput && !isBWithSporadicInput) { + return false; + } + // If both have sporadic inputs, we return false and sort as usual. + if (isAWithSporadicInput && isBWithSporadicInput) { + return false; + } + // If a has sporadic inputs + if (isAWithSporadicInput && isBWithSporadicInput) { + return false; + } + + // We have a with sporadic inputs. We sort it later, unless there was already some actual + // dependency between A and B. + if (isAWithSporadicInput) { + bool hasDependency = dataDeps(b, a); + return !hasDependency; + } + + // b is has sporadic inputs and a does not. We are fine as it is. + return false; +} + bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) { O2_SIGNPOST_ID_GENERATE(sid, topology); @@ -93,7 +127,7 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) return true; } // If we are here we do not have any data dependency, - // however we strill consider a dependent on b if + // however we still consider a dependent on b if // a has the "expendable" label and b does not. auto checkExpendable = [](DataProcessorLabel const& label) { if (label.value == "expendable") { @@ -108,26 +142,45 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) } return false; }; + bool isBExpendable = std::find_if(b.labels.begin(), b.labels.end(), checkExpendable) != b.labels.end(); bool isAExpendable = std::find_if(a.labels.begin(), a.labels.end(), checkExpendable) != a.labels.end(); bool bResilient = std::find_if(b.labels.begin(), b.labels.end(), checkResilient) != b.labels.end(); // If none is expendable. We simply return false and sort as usual. if (!isAExpendable && !isBExpendable) { + bool sporadic = sporadicDataDeps(a, b); + if (sporadic) { + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. Neither %s nor %s are expendable. However the former has sporadic inputs so we sort it after.", + a.name.c_str(), b.name.c_str()); + return true; + } O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. Neither %s nor %s are expendable. No dependency beyond data deps.", a.name.c_str(), b.name.c_str()); return false; } // If both are expendable. We return false and sort as usual. if (isAExpendable && isBExpendable) { + bool sporadic = sporadicDataDeps(a, b); + if (sporadic) { + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. Both %s and %s are expendable. However the former has sporadic inputs, so we sort it after.", + a.name.c_str(), b.name.c_str()); + return true; + } O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. Both %s and %s are expendable. No dependency.", a.name.c_str(), b.name.c_str()); return false; } - // If b is expendable but b is resilient, we can keep the same order. + // If a is expendable but b is resilient, we can keep the same order. if (isAExpendable && bResilient) { - O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. %s is expendable but %s is resilient, no need to add an unneeded dependency", + bool sporadic = sporadicDataDeps(a, b); + if (sporadic) { + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. %s is expendable but %s is resilient, however the former also has sporadic inputs, so we sort it after.", + a.name.c_str(), b.name.c_str()); + return true; + } + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. %s is expendable but %s is resilient. No need to do do anything.", a.name.c_str(), b.name.c_str()); return false; } @@ -138,11 +191,31 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "%s is expendable. %s from %s to %s => %s.", a.name.c_str(), hasDependency ? "There is however an inverse dependency" : "No inverse dependency", b.name.c_str(), a.name.c_str(), !hasDependency ? "true" : "false"); - return !hasDependency; + if (!hasDependency) { + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "%s is expendable. There is however an inverse dependecy from %s to %s => true.", + a.name.c_str(), b.name.c_str(), a.name.c_str()); + return true; + } + bool sporadic = sporadicDataDeps(a, b); + if (sporadic) { + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "%s is expendable. No inverse dependency from %s to %s. However the former has an occasioanl input => true.", + a.name.c_str(), b.name.c_str(), a.name.c_str()); + } + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "%s is expendable. No inverse dependency from %s to %s => false.", + a.name.c_str(), b.name.c_str(), a.name.c_str()); + return false; + } + // b is expendable and a is not. We are fine with no dependency. + bool sporadic = sporadicDataDeps(a, b); + if (sporadic) { + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. %s is expendable but %s is not. However the former has an sporadic input => true.", + b.name.c_str(), a.name.c_str()); + return true; } // b is expendable and a is not. We are fine with no dependency. O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. %s is expendable but %s is not. No need to add an unneeded dependency.", b.name.c_str(), a.name.c_str()); + return false; }; From bf8eb6f134eea9d19ac81a2832d6bb1e95cdcb8d Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer Date: Tue, 1 Jul 2025 16:55:10 +0200 Subject: [PATCH 092/315] OpenCL: Propagate number of host threads to PoCL runtime. --- GPU/GPUTracking/Base/opencl/GPUReconstructionOCL.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL.cxx b/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL.cxx index ce05e159461e5..49533216869d2 100644 --- a/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL.cxx +++ b/GPU/GPUTracking/Base/opencl/GPUReconstructionOCL.cxx @@ -63,6 +63,13 @@ int32_t GPUReconstructionOCL::GPUChkErrInternal(const int64_t error, const char* int32_t GPUReconstructionOCL::InitDevice_Runtime() { + // Propagate processing settings to PoCL runtime. + // Won't affect other OpenCL runtimes. + if (int nThreads = mProcessingSettings->nHostThreads; nThreads > 0) { + auto nThreadsStr = std::to_string(nThreads); + setenv("POCL_CPU_MAX_CU_COUNT", nThreadsStr.c_str(), 1); + } + if (mMaster == nullptr) { cl_int ocl_error; cl_uint num_platforms; From 678b1ae8cb1592f5511357a928a212c99479a5c2 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 2 Jul 2025 18:25:54 +0200 Subject: [PATCH 093/315] GPU Display: Fix typo in Vulkan version check --- GPU/GPUTracking/display/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/display/CMakeLists.txt b/GPU/GPUTracking/display/CMakeLists.txt index 3280a0655ce9f..25b028d573bcf 100644 --- a/GPU/GPUTracking/display/CMakeLists.txt +++ b/GPU/GPUTracking/display/CMakeLists.txt @@ -32,7 +32,7 @@ endif() if(Vulkan_FOUND) string(FIND "${Vulkan_VERSION}" "." vulkan_dot_index) - if(NOT ${Vulkan_VERSION} VERSION_GREATER_EQUAL "1.3.0" OR dot_index EQUAL -1 OR Vulkan_GLSLC_EXECUTABLE STREQUAL "Vulkan_GLSLC_EXECUTABLE-NOTFOUND") + if(NOT ${Vulkan_VERSION} VERSION_GREATER_EQUAL "1.3.0" OR vulkan_dot_index EQUAL -1 OR Vulkan_GLSLC_EXECUTABLE STREQUAL "Vulkan_GLSLC_EXECUTABLE-NOTFOUND") set(Vulkan_FOUND 0) endif() endif() From af304dee4ac1ca8b5d7e32cf7a7bdd5b7b752b54 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 2 Jul 2025 21:58:07 +0200 Subject: [PATCH 094/315] DPL: add signposts replacement for LOG(alarm) / LOG(important) (#14468) --- .../Foundation/include/Framework/Signpost.h | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Framework/Foundation/include/Framework/Signpost.h b/Framework/Foundation/include/Framework/Signpost.h index 53cc4d914a73b..781a2242375c8 100644 --- a/Framework/Foundation/include/Framework/Signpost.h +++ b/Framework/Foundation/include/Framework/Signpost.h @@ -562,6 +562,26 @@ void o2_debug_log_set_stacktrace(_o2_log_t* log, int stacktrace) O2_LOG_MACRO_RAW(critical, remove_engineering_type(format).data(), ##__VA_ARGS__); \ }) +// Similar to the above, however it will also print a normal alarm message regardless of the signpost being enabled or not. +#define O2_SIGNPOST_EVENT_EMIT_ALARM(log, id, name, format, ...) __extension__({ \ + if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \ + O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \ + } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \ + _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \ + } \ + O2_LOG_MACRO_RAW(alarm, remove_engineering_type(format).data(), ##__VA_ARGS__); \ +}) + +// Similar to the above, however it will also print a normal alarm message regardless of the signpost being enabled or not. +#define O2_SIGNPOST_EVENT_EMIT_IMPORTANT(log, id, name, format, ...) __extension__({ \ + if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \ + O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \ + } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \ + _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \ + } \ + O2_LOG_MACRO_RAW(important, remove_engineering_type(format).data(), ##__VA_ARGS__); \ +}) + #define O2_SIGNPOST_START(log, id, name, format, ...) \ if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \ O2_SIGNPOST_START_MAC(log, id, name, format, ##__VA_ARGS__); \ From 76543b9985775e548a9bcc0c2b7de0858ac1c41a Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 2 Jul 2025 12:26:29 +0200 Subject: [PATCH 095/315] Reset ITS tracks ROF counters if not tracks found --- Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index 15348bca9fde7..4f4941aca9f4d 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -377,6 +377,11 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) allTracks.emplace_back(trc); } } + } else { + for (auto& r : trackROFvec) { // reset data copied from the clusters + r.setFirstEntry(0); + r.setNEntries(0); + } } LOGP(info, "ITSTracker pushed {} tracks and {} vertices", allTracks.size(), vertices.size()); if (mIsMC) { From 5b28f57c3d9bf060c980374ec3203f185dc414c4 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 1 Jul 2025 09:56:35 +0200 Subject: [PATCH 096/315] CommonUtils: Don't use ROOT TGrid if we build standalone benchmark --- Common/Utils/CMakeLists.txt | 2 +- Common/Utils/include/CommonUtils/StringUtils.h | 3 +-- Common/Utils/src/StringUtils.cxx | 5 +++++ GPU/GPUTracking/DataTypes/CalibdEdxTrackTopologyPol.cxx | 6 ++---- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Common/Utils/CMakeLists.txt b/Common/Utils/CMakeLists.txt index 18f2aa7c1b6ed..def743d11791c 100644 --- a/Common/Utils/CMakeLists.txt +++ b/Common/Utils/CMakeLists.txt @@ -26,7 +26,7 @@ o2_add_library(CommonUtils src/DebugStreamer.cxx src/DLLoaderBase.cxx PUBLIC_LINK_LIBRARIES ROOT::Hist ROOT::Tree Boost::iostreams O2::CommonDataFormat O2::Headers - FairLogger::FairLogger O2::MathUtils TBB::tbb) + FairLogger::FairLogger O2::MathUtils TBB::tbb O2::GPUCommon) o2_target_root_dictionary(CommonUtils HEADERS include/CommonUtils/TreeStream.h diff --git a/Common/Utils/include/CommonUtils/StringUtils.h b/Common/Utils/include/CommonUtils/StringUtils.h index c68e441d5b1c4..710632fc7dbfe 100644 --- a/Common/Utils/include/CommonUtils/StringUtils.h +++ b/Common/Utils/include/CommonUtils/StringUtils.h @@ -20,8 +20,7 @@ #include #include #include -#include -#include +#include "GPUCommonRtypes.h" namespace o2 { diff --git a/Common/Utils/src/StringUtils.cxx b/Common/Utils/src/StringUtils.cxx index 4c0dd30ae6211..687225d069ed2 100644 --- a/Common/Utils/src/StringUtils.cxx +++ b/Common/Utils/src/StringUtils.cxx @@ -12,7 +12,10 @@ #include "CommonUtils/StringUtils.h" #include #include +#ifndef GPUCA_STANDALONE #include +#include +#endif #include using namespace o2::utils; @@ -77,6 +80,7 @@ std::string Str::getFullPath(const std::string_view p) return std::filesystem::canonical(std::string{p}).string(); } +#ifndef GPUCA_STANDALONE std::string Str::rectifyDirectory(const std::string_view p) { std::string dir(p); @@ -104,6 +108,7 @@ std::string Str::rectifyDirectory(const std::string_view p) } return dir; } +#endif // Create unique non-existing path name starting with prefix. Loose equivalent of boost::filesystem::unique_path() // The prefix can be either existing directory or just a string to add in front of the random part diff --git a/GPU/GPUTracking/DataTypes/CalibdEdxTrackTopologyPol.cxx b/GPU/GPUTracking/DataTypes/CalibdEdxTrackTopologyPol.cxx index 4e093da5d2cf6..1f6d6709e0ab0 100644 --- a/GPU/GPUTracking/DataTypes/CalibdEdxTrackTopologyPol.cxx +++ b/GPU/GPUTracking/DataTypes/CalibdEdxTrackTopologyPol.cxx @@ -9,16 +9,14 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef GPUCA_NO_VC +#ifndef GPUCA_STANDALONE #include "Rtypes.h" +#include "TFile.h" #endif #include "CalibdEdxTrackTopologyPol.h" #include #include -#if !defined(GPUCA_STANDALONE) -#include "TFile.h" -#endif using namespace o2::tpc; From 925c580e1275856021d24b9f6ffed0c982d7384b Mon Sep 17 00:00:00 2001 From: Jan Fiete Date: Thu, 3 Jul 2025 09:15:01 +0200 Subject: [PATCH 097/315] Fix bug in weight filling (#14461) --- Framework/Core/src/StepTHn.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Core/src/StepTHn.cxx b/Framework/Core/src/StepTHn.cxx index a091c304f425a..ac5da966f6ad4 100644 --- a/Framework/Core/src/StepTHn.cxx +++ b/Framework/Core/src/StepTHn.cxx @@ -441,7 +441,7 @@ void StepTHn::Fill(int iStep, int nParams, double positionAndWeight[]) if (weight != 1.) { // initialize with already filled entries (which have been filled with weight == 1), in this case mSumw2 := mValues if (!mSumw2[iStep]) { - mSumw2[iStep] = createArray(); + mSumw2[iStep] = createArray(mValues[iStep]); LOGF(info, "Created sumw2 container for step %d", iStep); } } @@ -449,7 +449,7 @@ void StepTHn::Fill(int iStep, int nParams, double positionAndWeight[]) // TODO probably slow; add StepTHnT::add ? mValues[iStep]->SetAt(mValues[iStep]->GetAt(bin) + weight, bin); if (mSumw2[iStep]) { - mSumw2[iStep]->SetAt(mSumw2[iStep]->GetAt(bin) + weight, bin); + mSumw2[iStep]->SetAt(mSumw2[iStep]->GetAt(bin) + weight * weight, bin); } } From 9fa8cf58b183291ca50ac46f19c23105a4787879 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 2 Jul 2025 23:05:54 +0200 Subject: [PATCH 098/315] =?UTF-8?q?GPU=20QA:=20Add=20Correctly=20Attached?= =?UTF-8?q?=20non-fake=20normalized=20cluster=20count=C2=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GPU/GPUTracking/qa/GPUQA.cxx | 58 ++++++++++++++++++++++++++++-------- GPU/GPUTracking/qa/GPUQA.h | 2 +- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/GPU/GPUTracking/qa/GPUQA.cxx b/GPU/GPUTracking/qa/GPUQA.cxx index e65246968cefa..b32ef80c7c87a 100644 --- a/GPU/GPUTracking/qa/GPUQA.cxx +++ b/GPU/GPUTracking/qa/GPUQA.cxx @@ -1660,6 +1660,10 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx if (mQATasks & taskTrackStatistics) { // Fill track statistic histograms + std::vector> clusterAttachCounts; + if (mcAvail) { + clusterAttachCounts.resize(GetNMCLabels(), {0.f, 0.f}); + } for (uint32_t i = 0; i < nReconstructedTracks; i++) { const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; if (!track.OK()) { @@ -1668,21 +1672,38 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx mTracks->Fill(1.f / fabsf(track.GetParam().GetQPt())); mNCl[0]->Fill(track.NClustersFitted()); uint32_t nClCorrected = 0; - int32_t lastSector = -1, lastRow = -1; const auto& trackClusters = mTracking->mIOPtrs.mergedTrackHits; - for (uint32_t j = 0; j < track.NClusters(); j++) { - if (trackClusters[track.FirstClusterRef() + j].state & GPUTPCGMMergedTrackHit::flagReject) { - continue; + uint32_t jNext = 0; + for (uint32_t j = 0; j < track.NClusters(); j = jNext) { + uint32_t rowClCount = !(trackClusters[track.FirstClusterRef() + j].state & GPUTPCGMMergedTrackHit::flagReject); + for (jNext = j + 1; j < track.NClusters(); jNext++) { + if (trackClusters[track.FirstClusterRef() + j].sector != trackClusters[track.FirstClusterRef() + jNext].sector || trackClusters[track.FirstClusterRef() + j].row != trackClusters[track.FirstClusterRef() + jNext].row) { + break; + } + rowClCount += !(trackClusters[track.FirstClusterRef() + jNext].state & GPUTPCGMMergedTrackHit::flagReject); } - if (trackClusters[track.FirstClusterRef() + j].sector == lastSector && trackClusters[track.FirstClusterRef() + j].row == lastRow) { - continue; + if (trackClusters[track.FirstClusterRef() + j].leg == trackClusters[track.FirstClusterRef() + track.NClusters() - 1].leg && rowClCount) { + nClCorrected++; } - if (trackClusters[track.FirstClusterRef() + j].leg != trackClusters[track.FirstClusterRef() + track.NClusters() - 1].leg) { - continue; + if (mcAvail && rowClCount) { + for (uint32_t k = j; k < jNext; k++) { + const auto& cl = trackClusters[track.FirstClusterRef() + k]; + if (cl.state & GPUTPCGMMergedTrackHit::flagReject) { + continue; + } + bool labelOk = false; + if (mTrackMCLabels[i].isValid() && !mTrackMCLabels[i].isFake()) { + for (int32_t l = 0; l < GetMCLabelNID(cl.num); l++) { + if (GetMCLabel(cl.num, l) == mTrackMCLabels[i]) { + labelOk = true; + break; + } + } + } + clusterAttachCounts[cl.num][0] += (float)labelOk / rowClCount; + clusterAttachCounts[cl.num][1] += 1.0f; + } } - nClCorrected++; - lastSector = trackClusters[track.FirstClusterRef() + j].sector; - lastRow = trackClusters[track.FirstClusterRef() + j].sector; } mNCl[1]->Fill(nClCorrected); } @@ -1699,6 +1720,16 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx } } } + if (mcAvail) { + double clusterAttachNormalizedCount = 0; + for (uint32_t i = 0; i < clusterAttachCounts.size(); i++) { + if (clusterAttachCounts[i][1]) { + clusterAttachNormalizedCount += clusterAttachCounts[i][0] / clusterAttachCounts[i][1]; + } + } + mClusterCounts.nCorrectlyAttachedNormalized = clusterAttachNormalizedCount; + clusterAttachCounts.clear(); + } if (QA_TIMING || (mTracking && mTracking->GetProcessingSettings().debugLevel >= 3)) { GPUInfo("QA Time: Fill track statistics:\t%6.0f us", timer.GetCurrentElapsedTime(true) * 1e6); @@ -2824,7 +2855,7 @@ void GPUQA::PrintClusterCount(int32_t mode, int32_t& num, const char* name, uint createHist(mHistClusterCount[num], name2, name, 1000, 0, mConfig.histMaxNClusters, 1000, 0, 100); } else if (mode == 0) { if (normalization && mConfig.enableLocalOutput) { - printf("\t%35s: %'12" PRIu64 " (%6.2f%%)\n", name, n, 100.f * n / normalization); + printf("\t%40s: %'12" PRIu64 " (%6.2f%%)\n", name, n, 100.f * n / normalization); } if (mConfig.clusterRejectionHistograms) { float ratio = 100.f * n / std::max(normalization, 1); @@ -2869,6 +2900,9 @@ int32_t GPUQA::DoClusterCounts(uint64_t* attachClusterCounts, int32_t mode) PrintClusterCount(mode, num, "Tracks < 40 MeV", mClusterCounts.nBelow40, mClusterCounts.nTotal); PrintClusterCount(mode, num, "Fake Protect (< 40 MeV)", mClusterCounts.nFakeProtect40, mClusterCounts.nBelow40); } + if (mcPresent() && (mQATasks & taskTrackStatistics)) { + PrintClusterCount(mode, num, "Correctly Attached non-fake normalized", mClusterCounts.nCorrectlyAttachedNormalized, mClusterCounts.nTotal); + } return num; } diff --git a/GPU/GPUTracking/qa/GPUQA.h b/GPU/GPUTracking/qa/GPUQA.h index 3d5030e20dba5..9e137f6a6b34c 100644 --- a/GPU/GPUTracking/qa/GPUQA.h +++ b/GPU/GPUTracking/qa/GPUQA.h @@ -290,7 +290,7 @@ class GPUQA TLegend* mLClust[N_CLS_TYPE]; struct counts_t { - int64_t nRejected = 0, nTube = 0, nTube200 = 0, nLoopers = 0, nLowPt = 0, n200MeV = 0, nPhysics = 0, nProt = 0, nUnattached = 0, nTotal = 0, nHighIncl = 0, nAbove400 = 0, nFakeRemove400 = 0, nFullFakeRemove400 = 0, nBelow40 = 0, nFakeProtect40 = 0, nMergedLooper = 0; + int64_t nRejected = 0, nTube = 0, nTube200 = 0, nLoopers = 0, nLowPt = 0, n200MeV = 0, nPhysics = 0, nProt = 0, nUnattached = 0, nTotal = 0, nHighIncl = 0, nAbove400 = 0, nFakeRemove400 = 0, nFullFakeRemove400 = 0, nBelow40 = 0, nFakeProtect40 = 0, nMergedLooper = 0, nCorrectlyAttachedNormalized = 0; double nUnaccessible = 0; } mClusterCounts; From e629c0a34361a178a722b1ed56a15f2aaf10a2a2 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 2 Jul 2025 18:40:57 +0200 Subject: [PATCH 099/315] GPU Standalone CI: Test also build without ROOT/VC/FMT/ONNX --- GPU/GPUTracking/Standalone/cmake/build.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/GPU/GPUTracking/Standalone/cmake/build.sh b/GPU/GPUTracking/Standalone/cmake/build.sh index 2698a5bad3950..cf03539d5c3f4 100755 --- a/GPU/GPUTracking/Standalone/cmake/build.sh +++ b/GPU/GPUTracking/Standalone/cmake/build.sh @@ -19,4 +19,16 @@ EOF fi cmake -DCMAKE_INSTALL_PREFIX=../ $1/GPU/GPUTracking/Standalone make ${JOBS+-j $JOBS} install +if [[ $GPUCA_STANDALONE_CI == 1 ]]; then + cat >> config.cmake << "EOF" + set(ENABLE_CUDA 0) + set(ENABLE_HIP 0) + set(ENABLE_OPENCL 0) + set(GPUCA_CONFIG_ONNX 0) + set(GPUCA_CONFIG_VC 0) + set(GPUCA_CONFIG_FMT 0) + set(GPUCA_CONFIG_ROOT 0) +EOF + make ${JOBS+-j $JOBS} install +fi popd From e68f2070d344622d1d97e9af28339c4c90ec4d78 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 2 Jul 2025 14:54:42 +0200 Subject: [PATCH 100/315] DPL: improve debugging for rate limiting --- Framework/Core/src/ArrowSupport.cxx | 44 ++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/Framework/Core/src/ArrowSupport.cxx b/Framework/Core/src/ArrowSupport.cxx index 3b13e30581f70..3a7699fb6876d 100644 --- a/Framework/Core/src/ArrowSupport.cxx +++ b/Framework/Core/src/ArrowSupport.cxx @@ -33,6 +33,7 @@ #include "Framework/AnalysisSupportHelpers.h" #include "Framework/ServiceRegistryRef.h" #include "Framework/ServiceRegistryHelpers.h" +#include "Framework/Signpost.h" #include "CommonMessageBackendsHelpers.h" #include @@ -46,6 +47,8 @@ #include #include +O2_DECLARE_DYNAMIC_LOG(rate_limiting); + namespace o2::framework { @@ -132,6 +135,7 @@ o2::framework::ServiceSpec ArrowSupport::arrowBackendSpec() auto &allDeviceMetrics = sm.deviceMetricsInfos; auto &specs = sm.deviceSpecs; auto &infos = sm.deviceInfos; + O2_SIGNPOST_ID_FROM_POINTER(sid, rate_limiting, &sm); static auto stateMetric = DeviceMetricsHelper::createNumericMetric(driverMetrics, "rate-limit-state"); static auto totalBytesCreatedMetric = DeviceMetricsHelper::createNumericMetric(driverMetrics, "total-arrow-bytes-created"); @@ -298,14 +302,17 @@ o2::framework::ServiceSpec ArrowSupport::arrowBackendSpec() for (size_t di = 0; di < specs.size(); di++) { if (availableSharedMemory < possibleOffer) { if (lowSharedMemoryCount == 0) { - LOGP(detail, "We do not have enough shared memory ({}MB) to offer {}MB. Total offerings {}", availableSharedMemory, possibleOffer, offeredSharedMemory); + O2_SIGNPOST_EVENT_EMIT(rate_limiting, sid, "not enough", + "We do not have enough shared memory (%{bytes}llu MB) to offer %{bytes}llu MB. Total offerings %{bytes}llu", + availableSharedMemory, possibleOffer, offeredSharedMemory); } lowSharedMemoryCount++; enoughSharedMemoryCount = 0; break; } else { if (enoughSharedMemoryCount == 0) { - LOGP(detail, "We are back in a state where we enough shared memory: {}MB", availableSharedMemory); + O2_SIGNPOST_EVENT_EMIT(rate_limiting, sid, "enough", + "We are back in a state where we enough shared memory: %{bytes}llu MB", availableSharedMemory); } enoughSharedMemoryCount++; lowSharedMemoryCount = 0; @@ -323,7 +330,9 @@ o2::framework::ServiceSpec ArrowSupport::arrowBackendSpec() continue; } possibleOffer = std::min(MAX_QUANTUM_SHARED_MEMORY, availableSharedMemory); - LOGP(detail, "Offering {}MB out of {} to {}", possibleOffer, availableSharedMemory, specs[candidate].id); + O2_SIGNPOST_EVENT_EMIT(rate_limiting, sid, "offer", + "Offering %{bytes}llu MB out of %{bytes}llu to %{public}s", + possibleOffer, availableSharedMemory, specs[candidate].id.c_str()); manager.queueMessage(specs[candidate].id.c_str(), fmt::format("/shm-offer {}", possibleOffer).data()); availableSharedMemory -= possibleOffer; offeredSharedMemory += possibleOffer; @@ -341,12 +350,15 @@ o2::framework::ServiceSpec ArrowSupport::arrowBackendSpec() static int64_t lastShmOfferConsumed = 0; static int64_t lastUnusedOfferedMemory = 0; if (shmOfferBytesConsumed != lastShmOfferConsumed) { - LOGP(detail, "Offer consumed so far {}", shmOfferBytesConsumed); + O2_SIGNPOST_EVENT_EMIT(rate_limiting, sid, "offer", + "Offer consumed so far %{bytes}llu", shmOfferBytesConsumed); lastShmOfferConsumed = shmOfferBytesConsumed; } int unusedOfferedMemory = (offeredSharedMemory - (totalBytesExpired + shmOfferBytesConsumed) / 1000000); if (lastUnusedOfferedMemory != unusedOfferedMemory) { - LOGP(detail, "unusedOfferedMemory:{} = offered:{} - (expired:{} + consumed:{}) / 1000000", unusedOfferedMemory, offeredSharedMemory, totalBytesExpired / 1000000, shmOfferBytesConsumed / 1000000); + O2_SIGNPOST_EVENT_EMIT(rate_limiting, sid, "offer", + "unusedOfferedMemory:%{bytes}d = offered:%{bytes}llu - (expired:%{bytes}llu + consumed:%{bytes}llu) / 1000000", + unusedOfferedMemory, offeredSharedMemory, totalBytesExpired / 1000000, shmOfferBytesConsumed / 1000000); lastUnusedOfferedMemory = unusedOfferedMemory; } // availableSharedMemory is the amount of memory which we know is available to be offered. @@ -362,6 +374,7 @@ o2::framework::ServiceSpec ArrowSupport::arrowBackendSpec() auto* arrow = reinterpret_cast(service); auto totalBytes = 0; auto totalMessages = 0; + O2_SIGNPOST_ID_FROM_POINTER(sid, rate_limiting, &arrow); for (auto& input : ctx.inputs()) { if (input.header == nullptr) { continue; @@ -369,7 +382,9 @@ o2::framework::ServiceSpec ArrowSupport::arrowBackendSpec() auto const* dh = DataRefUtils::getHeader(input); auto payloadSize = DataRefUtils::getPayloadSize(input); if (dh->serialization != o2::header::gSerializationMethodArrow) { - LOGP(debug, "Message {}/{} is not of kind arrow, therefore we are not accounting its shared memory", dh->dataOrigin, dh->dataDescription); + O2_SIGNPOST_EVENT_EMIT(rate_limiting, sid, "offer", + "Message %{public}.4s/%{public}.16s is not of kind arrow, therefore we are not accounting its shared memory.", + dh->dataOrigin.str, dh->dataDescription.str); continue; } bool forwarded = false; @@ -380,15 +395,21 @@ o2::framework::ServiceSpec ArrowSupport::arrowBackendSpec() } } if (forwarded) { - LOGP(debug, "Message {}/{} is forwarded so we are not returning its memory.", dh->dataOrigin, dh->dataDescription); + O2_SIGNPOST_EVENT_EMIT(rate_limiting, sid, "offer", + "Message %{public}.4s/%{public}16.s is forwarded so we are not returning its memory.", + dh->dataOrigin.str, dh->dataDescription.str); continue; } - LOGP(debug, "Message {}/{} is being deleted. We will return {}MB.", dh->dataOrigin, dh->dataDescription, payloadSize / 1000000.); + O2_SIGNPOST_EVENT_EMIT(rate_limiting, sid, "offer", + "Message %{public}.4s/%{public}.16s is being deleted. We will return %{bytes}f MB.", + dh->dataOrigin.str, dh->dataDescription.str, payloadSize / 1000000.); totalBytes += payloadSize; totalMessages += 1; } arrow->updateBytesDestroyed(totalBytes); - LOGP(debug, "{}MB bytes being given back to reader, totaling {}MB", totalBytes / 1000000., arrow->bytesDestroyed() / 1000000.); + O2_SIGNPOST_EVENT_EMIT(rate_limiting, sid, "give back", + "%{bytes}f MB bytes being given back to reader, totaling %{bytes}f MB", + totalBytes / 1000000., arrow->bytesDestroyed() / 1000000.); arrow->updateMessagesDestroyed(totalMessages); auto& stats = ctx.services().get(); stats.updateStats({static_cast(ProcessingStatsId::ARROW_BYTES_DESTROYED), DataProcessingStats::Op::Set, static_cast(arrow->bytesDestroyed())}); @@ -410,7 +431,10 @@ o2::framework::ServiceSpec ArrowSupport::arrowBackendSpec() static bool once = false; // Until we guarantee this is called only once... if (!once) { - LOGP(info, "Rate limiting set up at {}MB distributed over {} readers", config->maxMemory, readers); + O2_SIGNPOST_ID_GENERATE(sid, rate_limiting); + O2_SIGNPOST_EVENT_EMIT_INFO(rate_limiting, sid, "setup", + "Rate limiting set up at %{bytes}llu MB distributed over %d readers", + config->maxMemory, readers); registry.registerService(ServiceRegistryHelpers::handleForService(config)); once = true; } }, From eb67b94958158840fe04b4fe9a944af560c93d98 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 2 Jul 2025 16:54:59 +0200 Subject: [PATCH 101/315] DPL: move rate limiter to use signposts rather than log messages. --- Framework/Core/src/RateLimiter.cxx | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/Framework/Core/src/RateLimiter.cxx b/Framework/Core/src/RateLimiter.cxx index f381148223280..e0a320c8b9c9c 100644 --- a/Framework/Core/src/RateLimiter.cxx +++ b/Framework/Core/src/RateLimiter.cxx @@ -16,6 +16,8 @@ #include "Framework/DataTakingContext.h" #include "Framework/DeviceState.h" #include "Framework/DeviceContext.h" +#include "Framework/Signpost.h" + #include #include #include @@ -23,10 +25,13 @@ #include #include +O2_DECLARE_DYNAMIC_LOG(rate_limiting); + using namespace o2::framework; int RateLimiter::check(ProcessingContext& ctx, int maxInFlight, size_t minSHM) { + O2_SIGNPOST_ID_GENERATE(sid, rate_limiting); if (!maxInFlight && !minSHM) { return 0; } @@ -45,9 +50,13 @@ int RateLimiter::check(ProcessingContext& ctx, int maxInFlight, size_t minSHM) while ((mSentTimeframes - mConsumedTimeframes) >= maxInFlight) { if (recvTimeout != 0 && !waitMessage && (timeoutForMessage == false || std::chrono::duration_cast>(std::chrono::system_clock::now() - startTime).count() > MESSAGE_DELAY_TIME)) { if (dtc.deploymentMode == DeploymentMode::OnlineDDS || dtc.deploymentMode == DeploymentMode::OnlineECS || dtc.deploymentMode == DeploymentMode::FST) { - LOG(alarm) << "Maximum number of TF in flight reached (" << maxInFlight << ": published " << mSentTimeframes << " - finished " << mConsumedTimeframes << "), waiting"; + O2_SIGNPOST_EVENT_EMIT_ALARM(rate_limiting, sid, "timeframe_ratelimit", + "Maximum number of TF in flight reached (%d: published %llu - finished %llu), waiting", + maxInFlight, mSentTimeframes, mConsumedTimeframes); } else { - LOG(info) << "Maximum number of TF in flight reached (" << maxInFlight << ": published " << mSentTimeframes << " - finished " << mConsumedTimeframes << "), waiting"; + O2_SIGNPOST_EVENT_EMIT_INFO(rate_limiting, sid, "timeframe_ratelimit", + "Maximum number of TF in flight reached (%d: published %llu - finished %llu), waiting", + maxInFlight, mSentTimeframes, mConsumedTimeframes); } waitMessage = true; timeoutForMessage = false; @@ -67,12 +76,19 @@ int RateLimiter::check(ProcessingContext& ctx, int maxInFlight, size_t minSHM) } assert(msg->GetSize() == 8); mConsumedTimeframes = *(int64_t*)msg->GetData(); + O2_SIGNPOST_EVENT_EMIT(rate_limiting, sid, "timeframe_ratelimit", + "Received %llu as consumed timeframes", + mConsumedTimeframes); } if (waitMessage) { if (dtc.deploymentMode == DeploymentMode::OnlineDDS || dtc.deploymentMode == DeploymentMode::OnlineECS || dtc.deploymentMode == DeploymentMode::FST) { - LOG(important) << (mSentTimeframes - mConsumedTimeframes) << " / " << maxInFlight << " TF in flight, continuing to publish"; + O2_SIGNPOST_EVENT_EMIT_IMPORTANT(rate_limiting, sid, "timeframe_ratelimit", + "%lli / %d TF in flight, continue to publish", + (mSentTimeframes - mConsumedTimeframes), maxInFlight); } else { - LOG(info) << (mSentTimeframes - mConsumedTimeframes) << " / " << maxInFlight << " TF in flight, continuing to publish"; + O2_SIGNPOST_EVENT_EMIT_INFO(rate_limiting, sid, "timeframe_ratelimit", + "%lli / %d TF in flight, continue to publish", + (mSentTimeframes - mConsumedTimeframes), maxInFlight); } } From ad445652650c15dc876c23b8bd0cc387ee2ffc7d Mon Sep 17 00:00:00 2001 From: jokonig Date: Tue, 1 Jul 2025 20:18:49 +0200 Subject: [PATCH 102/315] [EMCAL-567] Add class to handle EMCal temperature calibration - Gain of EMCal cell is temperature dependent. - The temperature is stored in the ccdb about every 3min for 8 sensors per SM - New class downloads temperature values from ccdb and averages them per SM - Per cell, the energy dependence was determined in run2. These values are stored in the ccdb and also read in at initializeFromCCDB - As the temperature values are accumulated per run, the end of run timestamp is taken - 60s of safety margin --- Detectors/EMCAL/calibration/CMakeLists.txt | 2 + .../EMCALTempCalibExtractor.h | 93 +++++++++++++ .../src/EMCALTempCalibExtractor.cxx | 127 ++++++++++++++++++ 3 files changed, 222 insertions(+) create mode 100644 Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALTempCalibExtractor.h create mode 100644 Detectors/EMCAL/calibration/src/EMCALTempCalibExtractor.cxx diff --git a/Detectors/EMCAL/calibration/CMakeLists.txt b/Detectors/EMCAL/calibration/CMakeLists.txt index 68c8fd1eb69c7..7fec9fcef0f93 100644 --- a/Detectors/EMCAL/calibration/CMakeLists.txt +++ b/Detectors/EMCAL/calibration/CMakeLists.txt @@ -20,6 +20,7 @@ o2_add_library(EMCALCalibration src/PedestalCalibDevice.cxx src/PedestalProcessorDevice.cxx src/PedestalProcessorData.cxx + src/EMCALTempCalibExtractor.cxx PUBLIC_LINK_LIBRARIES O2::CCDB O2::EMCALBase O2::EMCALCalib O2::EMCALReconstruction @@ -46,6 +47,7 @@ o2_target_root_dictionary(EMCALCalibration include/EMCALCalibration/EMCDCSProcessor.h include/EMCALCalibration/EMCALPedestalHelper.h include/EMCALCalibration/PedestalProcessorData.h + include/EMCALCalibration/EMCALTempCalibExtractor.h LINKDEF src/EMCALCalibrationLinkDef.h) o2_add_executable(emcal-channel-calib-workflow diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALTempCalibExtractor.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALTempCalibExtractor.h new file mode 100644 index 0000000000000..5dbaec4c933f8 --- /dev/null +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALTempCalibExtractor.h @@ -0,0 +1,93 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \class EMCALTempCalibExtractor +/// \brief Calculate gain correction factors based on the temperature and the cell-by-cell temperature dependent correction factors (slope and intercept) +/// \author Joshua König +/// \ingroup EMCALCalib +/// \since June 30, 2025 + +#ifndef EMCALTEMPCALIBEXTRACTOR_H_ +#define EMCALTEMPCALIBEXTRACTOR_H_ + +#include +#include +#include +#include "CCDB/BasicCCDBManager.h" +#include "EMCALCalib/ElmbData.h" +#include "EMCALCalib/TempCalibrationParams.h" +#include "EMCALBase/Geometry.h" + +namespace o2 +{ +namespace emcal +{ + +class EMCALTempCalibExtractor +{ + + public: + /// \brief Constructor + EMCALTempCalibExtractor() + { + LOG(info) << "initialized EMCALTempCalibExtractor"; + try { + // Try to access geometry initialized ountside + mGeometry = o2::emcal::Geometry::GetInstance(); + } catch (o2::emcal::GeometryNotInitializedException& e) { + mGeometry = o2::emcal::Geometry::GetInstanceFromRunNumber(300000); // fallback option + } + }; + /// \brief Destructor + ~EMCALTempCalibExtractor() = default; + + /// \brief Initialize temperature data and slope for each cell from the ccdb + /// \param path path to the slope data + /// \param timestamp timestamp for the ccdb objects or runnumber (will detect automatically if its a runnumber and convert it) + void InitializeFromCCDB(std::string path, uint64_t timestamp); + + /// \brief get average temperature in a supermodule + /// \param iSM SM number + /// \param ElmbData object where temperature sensor values are stored + /// \return average temperature in a supermodule + float getTemperatureForSM(const unsigned short iSM, o2::emcal::ElmbData* ElmbData) const; + + /// \brief get gain calibration factor depending on the temperature and the slope of the cell + /// \param cellID cell ID + /// \return gain calibration factor + float getGainCalibFactor(const unsigned short cellID) const; + + /// \brief set temperature range in which sensor ddata is assumed to be good + /// \param low lower temperature + /// \param high upper temperature + void setAcceptedEnergyRange(float low, float high); + + /// \brief set if median (true) or mean (false) should be used for averaging of the temperature in a SM + void setUseMedian(const bool tmp) { mUseMedian = tmp; } + + /// \brief get sensor IDs for a specific supermodule + /// \param iSM SM number + /// \return vector of sensor IDs + std::vector getSensorsForSM(const unsigned short iSM) const; + + private: + static constexpr unsigned short mNCells = 17664; ///< Number of EMCal cells + std::array mGainCalibFactors; ///< gain calibration factors that are calculated based on the temperature and the slopes for each cell + o2::emcal::Geometry* mGeometry; ///< pointer to the EMCal geometry + std::array mAcceptedTempRange = {15., 30.}; ///< Temperature range where sensors are believed to send good data. Temperatures outside this range will be rejected + bool mUseMedian = true; /// switch to decide if temperature within a SM should be calculated as the mean or the median of the individual sensor data +}; + +} // namespace emcal + +} // namespace o2 + +#endif \ No newline at end of file diff --git a/Detectors/EMCAL/calibration/src/EMCALTempCalibExtractor.cxx b/Detectors/EMCAL/calibration/src/EMCALTempCalibExtractor.cxx new file mode 100644 index 0000000000000..b6dc2b0a7c0a7 --- /dev/null +++ b/Detectors/EMCAL/calibration/src/EMCALTempCalibExtractor.cxx @@ -0,0 +1,127 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "EMCALCalibration/EMCALTempCalibExtractor.h" +#include "EMCALCalib/CalibDB.h" +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include + +namespace o2 +{ +namespace emcal +{ + +void EMCALTempCalibExtractor::InitializeFromCCDB(std::string path, uint64_t timestamp) +{ + + auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); + uint64_t maxRunNr = 1000000; + if (timestamp < maxRunNr) { + LOG(info) << "assuming input is run " << timestamp << " will convert it to timstamp"; + auto [sor, eor] = ccdbMgr.getRunDuration(timestamp); + uint64_t sixtySec = 60000; + timestamp = eor - sixtySec; // safety margin of 1min at EOR + LOG(info) << "set timestamp to " << timestamp; + } + + o2::emcal::CalibDB calibdb("http://alice-ccdb.cern.ch"); + std::map metadata; + auto tempSensorData = calibdb.readTemperatureSensorData(timestamp, metadata); + + // also obtain cell dependent correction factors + TempCalibrationParams* params = ccdbMgr.getForTimeStamp(path, timestamp); + + std::map mapSMTemperature; + for (unsigned short i = 0; i < mNCells; ++i) { + const unsigned short iSM = mGeometry->GetSuperModuleNumber(i); + if (mapSMTemperature.count(iSM) == 0) { + mapSMTemperature[iSM] = getTemperatureForSM(iSM, tempSensorData); + } + float corrFac = params->getTempCalibParamA0(i) + params->getTempCalibParamSlope(i) * mapSMTemperature[iSM]; + mGainCalibFactors[i] = corrFac; + } +} + +float EMCALTempCalibExtractor::getTemperatureForSM(const unsigned short iSM, o2::emcal::ElmbData* ElmbData) const +{ + if (iSM < 0 || iSM > 20) { + LOG(error) << "SM " << iSM << "does not exist!"; // could be replaced with a proper exception + return 0.; + } + std::vector vecSensorID = getSensorsForSM(iSM); + + // Obtain temperature for these sensors + std::vector vecTemperature; + for (const auto& iSensor : vecSensorID) { + float temp = ElmbData->getMean(iSensor); + if (temp < mAcceptedTempRange[0] || temp > mAcceptedTempRange[1]) { + continue; + } + vecTemperature.push_back(temp); + } + + const unsigned int nEntries = vecTemperature.size(); + if (nEntries == 0) { + LOG(warning) << "No sensor data between " << mAcceptedTempRange[0] << " and " << mAcceptedTempRange[1] << "degree found... for SM " << iSM << " Setting to default 20 degree"; + return 20.; // + } + + // get median energy + float tempSM = 0.; + if (mUseMedian) { + std::sort(vecTemperature.begin(), vecTemperature.end()); + if (nEntries % 2 == 0) { + // even number of elements: average the two middle ones + tempSM = (vecTemperature[nEntries / 2 - 1] + vecTemperature[nEntries / 2]) / 2.0; + } else { + // odd number of elements: return the middle one + tempSM = vecTemperature[nEntries / 2]; + } + } else { // use Mean temperature + float sum = std::accumulate(vecTemperature.begin(), vecTemperature.end(), 0.0); + tempSM = sum / vecTemperature.size(); + } + return tempSM; +} + +float EMCALTempCalibExtractor::getGainCalibFactor(const unsigned short cellID) const +{ + if (cellID >= mNCells) { + LOG(error) << "cell ID" << cellID << " does not exist"; + return 1.; + } + return mGainCalibFactors[cellID]; +} + +std::vector EMCALTempCalibExtractor::getSensorsForSM(const unsigned short iSM) const +{ + unsigned short nSensors = 8; + if (iSM == 10 || iSM == 11 || iSM == 19 || iSM == 20) { + nSensors = 4; + } + + std::vector vecSensorID; + for (unsigned short iELMBSensor = iSM * 8; iELMBSensor < iSM * 8 + nSensors; iELMBSensor++) { + vecSensorID.push_back(iELMBSensor); + } + return vecSensorID; +} + +void EMCALTempCalibExtractor::setAcceptedEnergyRange(float low, float high) +{ + mAcceptedTempRange[0] = low; + mAcceptedTempRange[1] = high; +} + +} // namespace emcal + +} // namespace o2 \ No newline at end of file From 8c105b5a103f32ee86ea8f79f09325f732137fc0 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Wed, 2 Jul 2025 10:29:41 +0200 Subject: [PATCH 103/315] Update CODEOWNERS updates for EMCAL --- CODEOWNERS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 5337622522bbb..117ff0d92b272 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -28,9 +28,9 @@ /DataFormats/Detectors/Common @shahor02 /DataFormats/Detectors/CPV @peressounko @kharlov /DataFormats/Detectors/CTP @lietava -/DataFormats/Detectors/EMCAL @mfasDa @jokonig +/DataFormats/Detectors/EMCAL @nstrangm @jokonig /DataFormats/Detectors/FIT @jotwinow @afurs @andreasmolander @sahilupadhyaya92 -/DataFormats/Detectors/FOCAL @maxrauch @mfasDa @iarsene @matthiasrichter +/DataFormats/Detectors/FOCAL @maxrauch @iarsene @matthiasrichter /DataFormats/Detectors/GlobalTracking @shahor02 /DataFormats/Detectors/GlobalTrackingWorkflow @shahor02 /DataFormats/Detectors/HMPID @gvolpe79 @@ -58,9 +58,9 @@ /Detectors/Base @sawenzel @shahor02 /Detectors/Calibration @chiarazampolli @shahor02 /Detectors/CPV @peressounko @kharlov -/Detectors/EMCAL @mfasDa @jokonig +/Detectors/EMCAL @nstrangm @jokonig /Detectors/FIT @jotwinow @afurs @andreasmolander @sahilupadhyaya92 -/Detectors/FOCAL @maxrauch @mfasDa @iarsene @matthiasrichter +/Detectors/FOCAL @maxrauch @iarsene @matthiasrichter /Detectors/Geometry @sawenzel @shahor02 /Detectors/GlobalTracking @shahor02 /Detectors/GlobalTrackingWorkflow @shahor02 From 434fb2768278842a8c626d44a880fb2ba6c20cba Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Thu, 3 Jul 2025 19:05:23 +0200 Subject: [PATCH 104/315] [EMCAL-567] Fix 1/3 SM numbers (#14477) - SM20 -> SM19. SM20 does not exist Co-authored-by: jokonig --- Detectors/EMCAL/calibration/src/EMCALTempCalibExtractor.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/EMCAL/calibration/src/EMCALTempCalibExtractor.cxx b/Detectors/EMCAL/calibration/src/EMCALTempCalibExtractor.cxx index b6dc2b0a7c0a7..02e25696f161d 100644 --- a/Detectors/EMCAL/calibration/src/EMCALTempCalibExtractor.cxx +++ b/Detectors/EMCAL/calibration/src/EMCALTempCalibExtractor.cxx @@ -105,7 +105,7 @@ float EMCALTempCalibExtractor::getGainCalibFactor(const unsigned short cellID) c std::vector EMCALTempCalibExtractor::getSensorsForSM(const unsigned short iSM) const { unsigned short nSensors = 8; - if (iSM == 10 || iSM == 11 || iSM == 19 || iSM == 20) { + if (iSM == 10 || iSM == 11 || iSM == 18 || iSM == 19) { // 1/3 SM of EMCal only have 4 sensors nSensors = 4; } From ab99262d3197ddf2d66fd1a7e68f022683e56d27 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 3 Jul 2025 10:59:06 +0200 Subject: [PATCH 105/315] GPU Standalone CI: Build also event display --- GPU/GPUTracking/Definitions/GPUSettingsList.h | 2 +- GPU/GPUTracking/Standalone/cmake/build.sh | 5 ++++- GPU/GPUTracking/Standalone/cmake/prepare.sh | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index e75d5a5890e4b..0ff8adb1cb957 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -73,7 +73,7 @@ AddOptionRTC(tubeMaxSize2, float, 2.5f * 2.5f, "", 0, "Square of max tube size ( AddOptionRTC(clustersShiftTimebins, float, 0, "", 0, "Shift of TPC clusters (applied during CTF cluster decoding)") AddOptionRTC(clustersShiftTimebinsClusterizer, float, 0, "", 0, "Shift of TPC clusters (applied during CTF clusterization)") AddOptionRTC(clustersEdgeFixDistance, float, 0.f, "", 0, "If >0, revert cluster.flag edge bit distance to edge exceeds this parameter (fixed during CTF decoding)") -AddOptionRTC(defaultZOffsetOverR, float, 0.5210953f, "", 0, "Shift of TPC clusters (applied during CTF cluster decoding)") +AddOptionRTC(defaultZOffsetOverR, float, 0.5210953f, "", 0, "ZOffset for secondary tracks, multiple of radius") AddOptionRTC(PID_EKrangeMin, float, 0.47f, "", 0, "min P of electron/K BB bands crossing") AddOptionRTC(PID_EKrangeMax, float, 0.57f, "", 0, "max P of electron/K BB bands crossing") AddOptionRTC(PID_EPrangeMin, float, 0.93f, "", 0, "min P of electron/p BB bands crossing") diff --git a/GPU/GPUTracking/Standalone/cmake/build.sh b/GPU/GPUTracking/Standalone/cmake/build.sh index cf03539d5c3f4..1f7f446a336ac 100755 --- a/GPU/GPUTracking/Standalone/cmake/build.sh +++ b/GPU/GPUTracking/Standalone/cmake/build.sh @@ -13,7 +13,9 @@ if [[ $GPUCA_STANDALONE_CI == 1 ]]; then set(ENABLE_HIP 1) set(ENABLE_OPENCL 1) set(GPUCA_CONFIG_ONNX 1) - set(GPUCA_BUILD_EVENT_DISPLAY 0) + set(GPUCA_BUILD_EVENT_DISPLAY_VULKAN 0) + set(GPUCA_BUILD_EVENT_DISPLAY_WAYLAND 0) + set(GPUCA_BUILD_EVENT_DISPLAY_QT 0) set(GPUCA_CONFIG_WERROR 1) EOF fi @@ -24,6 +26,7 @@ if [[ $GPUCA_STANDALONE_CI == 1 ]]; then set(ENABLE_CUDA 0) set(ENABLE_HIP 0) set(ENABLE_OPENCL 0) + set(GPUCA_BUILD_EVENT_DISPLAY 0) set(GPUCA_CONFIG_ONNX 0) set(GPUCA_CONFIG_VC 0) set(GPUCA_CONFIG_FMT 0) diff --git a/GPU/GPUTracking/Standalone/cmake/prepare.sh b/GPU/GPUTracking/Standalone/cmake/prepare.sh index 121245e23dc65..a7b2ff1f7db35 100755 --- a/GPU/GPUTracking/Standalone/cmake/prepare.sh +++ b/GPU/GPUTracking/Standalone/cmake/prepare.sh @@ -11,6 +11,6 @@ else fi eval "`alienv shell-helper`" # alienv load O2/latest -for i in Vc boost fmt CMake ms_gsl Clang ninja TBB ROOT ONNXRuntime; do +for i in Vc boost fmt CMake ms_gsl Clang ninja TBB ROOT ONNXRuntime GLFW; do source sw/$ALIARCH/$i/latest/etc/profile.d/init.sh done From 0c3f2b5b0b72a7ef653c54787192851f1b8bfaa1 Mon Sep 17 00:00:00 2001 From: Anton Riedel Date: Fri, 14 Feb 2025 14:02:39 +0100 Subject: [PATCH 106/315] Feat: add skeleton for GPUErrorQA task --- Detectors/TPC/qc/CMakeLists.txt | 4 +- Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h | 69 +++++++++++++++++++++ Detectors/TPC/qc/src/GPUErrorQA.cxx | 55 ++++++++++++++++ Detectors/TPC/qc/src/TPCQCLinkDef.h | 1 + 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h create mode 100644 Detectors/TPC/qc/src/GPUErrorQA.cxx diff --git a/Detectors/TPC/qc/CMakeLists.txt b/Detectors/TPC/qc/CMakeLists.txt index 6bb4c726a90fa..60195ed6d451a 100644 --- a/Detectors/TPC/qc/CMakeLists.txt +++ b/Detectors/TPC/qc/CMakeLists.txt @@ -19,6 +19,7 @@ o2_add_library(TPCQC src/SACs.cxx src/IDCsVsSACs.cxx src/TrackClusters.cxx + src/GPUErrorQA.cxx PUBLIC_LINK_LIBRARIES O2::TPCBase O2::DataFormatsTPC O2::GPUO2Interface @@ -36,7 +37,8 @@ o2_target_root_dictionary(TPCQC include/TPCQC/DCSPTemperature.h include/TPCQC/SACs.h include/TPCQC/IDCsVsSACs.h - include/TPCQC/TrackClusters.h) + include/TPCQC/TrackClusters.h + include/TPCQC/GPUErrorQA.h) o2_add_test(PID COMPONENT_NAME tpc diff --git a/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h b/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h new file mode 100644 index 0000000000000..e9ddcfb66d594 --- /dev/null +++ b/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h @@ -0,0 +1,69 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// @file GPUErrorQA.h +/// @author Anton Riedel, anton.riedel@cern.ch +/// + +#ifndef AliceO2_TPC_QC_GPUERRORQA_H +#define AliceO2_TPC_QC_GPUERRORQA_H + +#include +#include + +// root includes +#include "TH1.h" + +// o2 includes +// #include "DataFormatsTPC/Defs.h" + +namespace o2 +{ +namespace tpc +{ +namespace qc +{ + +/// @brief TPC QC task for errors from GPU reconstruction +/// +/// This class is used to retrieve and visualize GPU errors +/// according to corresponding error code and location. +/// +/// origin: TPC +/// @author Anton Riedel, anton.riedel@cern.ch +class GPUErrorQA +{ + public: + /// \brief Constructor. + GPUErrorQA() = default; + + /// process gpu error reported by the reconstruction workflow + void processErrors(gsl::span> errors); + + /// Initialize all histograms + void initializeHistograms(); + + /// Reset all histograms + void resetHistograms(); + + /// Dump results to a file + void dumpToFile(std::string filename); + + private: + std::unique_ptr mHist; + ClassDefNV(GPUErrorQA, 1) +}; +} // namespace qc +} // namespace tpc +} // namespace o2 + +#endif // AliceO2_TPC_QC_GPUERRORQA_H diff --git a/Detectors/TPC/qc/src/GPUErrorQA.cxx b/Detectors/TPC/qc/src/GPUErrorQA.cxx new file mode 100644 index 0000000000000..876c63d6e89f5 --- /dev/null +++ b/Detectors/TPC/qc/src/GPUErrorQA.cxx @@ -0,0 +1,55 @@ +// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#define _USE_MATH_DEFINES + +#include +#include + +// root includes +#include "TFile.h" +#include + +// o2 includes +#include "TPCQC/GPUErrorQA.h" +#include "GPUErrors.h" + +ClassImp(o2::tpc::qc::GPUErrorQA); + +using namespace o2::tpc::qc; + +//______________________________________________________________________________ +void GPUErrorQA::initializeHistograms() +{ + TH1::AddDirectory(false); + mHist = std::make_unique("ErrorCounter", "ErrorCounter", o2::gpu::GPUErrors::getMaxErrors(), 0, o2::gpu::GPUErrors::getMaxErrors()); +} +//______________________________________________________________________________ +void GPUErrorQA::resetHistograms() +{ + mHist->Reset(); +} +//______________________________________________________________________________ +void GPUErrorQA::processErrors(gsl::span> errors) +{ + for (const auto& error : errors) { + uint32_t errorCode = error[0]; + mHist->Fill(static_cast(errorCode)); + } +} + +//______________________________________________________________________________ +void GPUErrorQA::dumpToFile(const std::string filename) +{ + auto f = std::unique_ptr(TFile::Open(filename.c_str(), "recreate")); + mHist->Write(); + f->Close(); +} diff --git a/Detectors/TPC/qc/src/TPCQCLinkDef.h b/Detectors/TPC/qc/src/TPCQCLinkDef.h index c227ebcad8c09..3921d7dfe5649 100644 --- a/Detectors/TPC/qc/src/TPCQCLinkDef.h +++ b/Detectors/TPC/qc/src/TPCQCLinkDef.h @@ -24,6 +24,7 @@ #pragma link C++ class o2::tpc::qc::SACs + ; #pragma link C++ class o2::tpc::qc::IDCsVsSACs + ; #pragma link C++ class o2::tpc::qc::TrackClusters + ; +#pragma link C++ class o2::tpc::qc::GPUErrorQA + ; #pragma link C++ function o2::tpc::qc::helpers::makeLogBinning + ; #pragma link C++ function o2::tpc::qc::helpers::setStyleHistogram1D + ; #pragma link C++ function o2::tpc::qc::helpers::setStyleHistogram2D + ; From b83d67398f86951e3b58799e7aa663d9d27eda70 Mon Sep 17 00:00:00 2001 From: Anton Riedel Date: Thu, 6 Mar 2025 10:26:24 +0100 Subject: [PATCH 107/315] Feat: add GPUErrorQA class --- Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h | 28 ++++++------- Detectors/TPC/qc/src/GPUErrorQA.cxx | 44 +++++++++++++++------ 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h b/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h index e9ddcfb66d594..797e5da0223b7 100644 --- a/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h +++ b/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h @@ -18,22 +18,20 @@ #define AliceO2_TPC_QC_GPUERRORQA_H #include -#include +#include +#include +#include // root includes -#include "TH1.h" // o2 includes // #include "DataFormatsTPC/Defs.h" -namespace o2 -{ -namespace tpc -{ -namespace qc +class TH1; +namespace o2::tpc::qc { -/// @brief TPC QC task for errors from GPU reconstruction +/// @brief TPC QC task for errors from GPU reconstruction /// /// This class is used to retrieve and visualize GPU errors /// according to corresponding error code and location. @@ -47,7 +45,7 @@ class GPUErrorQA GPUErrorQA() = default; /// process gpu error reported by the reconstruction workflow - void processErrors(gsl::span> errors); + void processErrors(std::vector> errors); /// Initialize all histograms void initializeHistograms(); @@ -55,15 +53,17 @@ class GPUErrorQA /// Reset all histograms void resetHistograms(); + /// return histograms + const std::unordered_map>& getMapHist() const { return mMapHist; }; + /// Dump results to a file void dumpToFile(std::string filename); private: - std::unique_ptr mHist; - ClassDefNV(GPUErrorQA, 1) + std::unordered_map> mMapHist; + + ClassDefNV(GPUErrorQA, 1); }; -} // namespace qc -} // namespace tpc -} // namespace o2 +} // namespace o2::tpc::qc #endif // AliceO2_TPC_QC_GPUERRORQA_H diff --git a/Detectors/TPC/qc/src/GPUErrorQA.cxx b/Detectors/TPC/qc/src/GPUErrorQA.cxx index 876c63d6e89f5..f59332b658466 100644 --- a/Detectors/TPC/qc/src/GPUErrorQA.cxx +++ b/Detectors/TPC/qc/src/GPUErrorQA.cxx @@ -11,16 +11,13 @@ #define _USE_MATH_DEFINES -#include -#include - // root includes #include "TFile.h" -#include +#include "TH1I.h" // o2 includes #include "TPCQC/GPUErrorQA.h" -#include "GPUErrors.h" +#include "GPUDefMacros.h" ClassImp(o2::tpc::qc::GPUErrorQA); @@ -30,26 +27,49 @@ using namespace o2::tpc::qc; void GPUErrorQA::initializeHistograms() { TH1::AddDirectory(false); - mHist = std::make_unique("ErrorCounter", "ErrorCounter", o2::gpu::GPUErrors::getMaxErrors(), 0, o2::gpu::GPUErrors::getMaxErrors()); + + // get gpu error names + // copied from GPUErrors.h + static std::unordered_map errorNames = { +#define GPUCA_ERROR_CODE(num, name, ...) {num, GPUCA_M_STR(name)}, +#include "GPUErrorCodes.h" +#undef GPUCA_ERROR_CODE + }; + + // 1D histogram counting all reported errors + mMapHist["ErrorCounter"] = std::make_unique("ErrorCounter", "ErrorCounter", errorNames.size(), -0.5, errorNames.size() - 0.5); + mMapHist["ErrorCounter"]->GetXaxis()->SetTitle("Error Codes"); + mMapHist["ErrorCounter"]->GetYaxis()->SetTitle("Entries"); + // for convienence, label each bin with the error name + for (size_t bin = 1; bin < mMapHist["ErrorCounter"]->GetNbinsX(); bin++) { + auto const& it = errorNames.find(bin); + mMapHist["ErrorCounter"]->GetXaxis()->SetBinLabel(bin, it->second); + } } //______________________________________________________________________________ void GPUErrorQA::resetHistograms() { - mHist->Reset(); + for (const auto& pair : mMapHist) { + pair.second->Reset(); + } } //______________________________________________________________________________ -void GPUErrorQA::processErrors(gsl::span> errors) +void GPUErrorQA::processErrors(std::vector> errors) { for (const auto& error : errors) { uint32_t errorCode = error[0]; - mHist->Fill(static_cast(errorCode)); + mMapHist["ErrorCounter"]->AddBinContent(errorCode); } } //______________________________________________________________________________ void GPUErrorQA::dumpToFile(const std::string filename) { - auto f = std::unique_ptr(TFile::Open(filename.c_str(), "recreate")); - mHist->Write(); - f->Close(); + auto f = std::unique_ptr(TFile::Open(filename.data(), "recreate")); + TObjArray arr; + arr.SetName("GPUErrorQA_Hists"); + for (const auto& [name, hist] : mMapHist) { + arr.Add(hist.get()); + } + arr.Write(arr.GetName(), TObject::kSingleKey); } From 7b8b2e7cd1742d6a2ea9ca536cfceda95fbc77ff Mon Sep 17 00:00:00 2001 From: Anton Riedel Date: Thu, 12 Jun 2025 15:14:07 +0200 Subject: [PATCH 108/315] Feat: movde error names to GPUErrors.h --- Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h | 4 ++-- Detectors/TPC/qc/src/GPUErrorQA.cxx | 16 ++++------------ GPU/GPUTracking/Global/GPUErrors.cxx | 7 ------- GPU/GPUTracking/Global/GPUErrors.h | 8 ++++++++ 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h b/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h index 797e5da0223b7..ec171a6925a98 100644 --- a/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h +++ b/Detectors/TPC/qc/include/TPCQC/GPUErrorQA.h @@ -54,7 +54,7 @@ class GPUErrorQA void resetHistograms(); /// return histograms - const std::unordered_map>& getMapHist() const { return mMapHist; }; + const std::unordered_map>& getMapHist() const { return mMapHist; } /// Dump results to a file void dumpToFile(std::string filename); @@ -62,7 +62,7 @@ class GPUErrorQA private: std::unordered_map> mMapHist; - ClassDefNV(GPUErrorQA, 1); + ClassDefNV(GPUErrorQA, 2); }; } // namespace o2::tpc::qc diff --git a/Detectors/TPC/qc/src/GPUErrorQA.cxx b/Detectors/TPC/qc/src/GPUErrorQA.cxx index f59332b658466..912b036a6cccf 100644 --- a/Detectors/TPC/qc/src/GPUErrorQA.cxx +++ b/Detectors/TPC/qc/src/GPUErrorQA.cxx @@ -17,7 +17,7 @@ // o2 includes #include "TPCQC/GPUErrorQA.h" -#include "GPUDefMacros.h" +#include "GPUErrors.h" ClassImp(o2::tpc::qc::GPUErrorQA); @@ -28,21 +28,13 @@ void GPUErrorQA::initializeHistograms() { TH1::AddDirectory(false); - // get gpu error names - // copied from GPUErrors.h - static std::unordered_map errorNames = { -#define GPUCA_ERROR_CODE(num, name, ...) {num, GPUCA_M_STR(name)}, -#include "GPUErrorCodes.h" -#undef GPUCA_ERROR_CODE - }; - // 1D histogram counting all reported errors - mMapHist["ErrorCounter"] = std::make_unique("ErrorCounter", "ErrorCounter", errorNames.size(), -0.5, errorNames.size() - 0.5); + mMapHist["ErrorCounter"] = std::make_unique("ErrorCounter", "ErrorCounter", o2::gpu::errorNames.size(), -0.5, o2::gpu::errorNames.size() - 0.5); mMapHist["ErrorCounter"]->GetXaxis()->SetTitle("Error Codes"); mMapHist["ErrorCounter"]->GetYaxis()->SetTitle("Entries"); // for convienence, label each bin with the error name for (size_t bin = 1; bin < mMapHist["ErrorCounter"]->GetNbinsX(); bin++) { - auto const& it = errorNames.find(bin); + auto const& it = o2::gpu::errorNames.find(bin); mMapHist["ErrorCounter"]->GetXaxis()->SetBinLabel(bin, it->second); } } @@ -68,7 +60,7 @@ void GPUErrorQA::dumpToFile(const std::string filename) auto f = std::unique_ptr(TFile::Open(filename.data(), "recreate")); TObjArray arr; arr.SetName("GPUErrorQA_Hists"); - for (const auto& [name, hist] : mMapHist) { + for ([[maybe_unused]] const auto& [name, hist] : mMapHist) { arr.Add(hist.get()); } arr.Write(arr.GetName(), TObject::kSingleKey); diff --git a/GPU/GPUTracking/Global/GPUErrors.cxx b/GPU/GPUTracking/Global/GPUErrors.cxx index e9d5a74c6567a..ed4ca892cc331 100644 --- a/GPU/GPUTracking/Global/GPUErrors.cxx +++ b/GPU/GPUTracking/Global/GPUErrors.cxx @@ -36,7 +36,6 @@ GPUd() void GPUErrors::raiseError(uint32_t code, uint32_t param1, uint32_t param #ifndef GPUCA_GPUCODE #include -#include uint32_t GPUErrors::getMaxErrors() { @@ -48,12 +47,6 @@ void GPUErrors::clear() memset(mErrors, 0, GPUCA_MAX_ERRORS * sizeof(*mErrors)); } -static std::unordered_map errorNames = { -#define GPUCA_ERROR_CODE(num, name, ...) {num, GPUCA_M_STR(name)}, -#include "GPUErrorCodes.h" -#undef GPUCA_ERROR_CODE -}; - bool GPUErrors::printErrors(bool silent, uint64_t mask) { bool retVal = 0; diff --git a/GPU/GPUTracking/Global/GPUErrors.h b/GPU/GPUTracking/Global/GPUErrors.h index 1cbc4a019601d..698c0ef0c026c 100644 --- a/GPU/GPUTracking/Global/GPUErrors.h +++ b/GPU/GPUTracking/Global/GPUErrors.h @@ -16,10 +16,18 @@ #define GPUERRORS_H #include "GPUCommonDef.h" +#include "GPUDefMacros.h" +#include namespace o2::gpu { +static std::unordered_map errorNames = { +#define GPUCA_ERROR_CODE(num, name, ...) {num, GPUCA_M_STR(name)}, +#include "GPUErrorCodes.h" +#undef GPUCA_ERROR_CODE +}; + class GPUErrors { public: From 8aec6f6b787090654e13adc5474fa5ea4f4a5fd0 Mon Sep 17 00:00:00 2001 From: Anton Riedel Date: Tue, 17 Jun 2025 16:49:10 +0200 Subject: [PATCH 109/315] Fix: expose gpu error names with static function --- GPU/GPUTracking/Global/GPUErrors.cxx | 12 ++++++++++++ GPU/GPUTracking/Global/GPUErrors.h | 11 ++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUErrors.cxx b/GPU/GPUTracking/Global/GPUErrors.cxx index ed4ca892cc331..4baa299c6b976 100644 --- a/GPU/GPUTracking/Global/GPUErrors.cxx +++ b/GPU/GPUTracking/Global/GPUErrors.cxx @@ -36,6 +36,7 @@ GPUd() void GPUErrors::raiseError(uint32_t code, uint32_t param1, uint32_t param #ifndef GPUCA_GPUCODE #include +#include uint32_t GPUErrors::getMaxErrors() { @@ -47,9 +48,20 @@ void GPUErrors::clear() memset(mErrors, 0, GPUCA_MAX_ERRORS * sizeof(*mErrors)); } +const std::unordered_map& GPUErrors::getErrorNames() +{ + static std::unordered_map errorNames = { +#define GPUCA_ERROR_CODE(num, name, ...) {num, GPUCA_M_STR(name)}, +#include "GPUErrorCodes.h" +#undef GPUCA_ERROR_CODE + }; + return errorNames; +} + bool GPUErrors::printErrors(bool silent, uint64_t mask) { bool retVal = 0; + const auto& errorNames = getErrorNames(); for (uint32_t i = 0; i < std::min(*mErrors, GPUCA_MAX_ERRORS); i++) { uint32_t errorCode = mErrors[4 * i + 1]; const auto& it = errorNames.find(errorCode); diff --git a/GPU/GPUTracking/Global/GPUErrors.h b/GPU/GPUTracking/Global/GPUErrors.h index 698c0ef0c026c..d14c9ffaeda96 100644 --- a/GPU/GPUTracking/Global/GPUErrors.h +++ b/GPU/GPUTracking/Global/GPUErrors.h @@ -16,18 +16,14 @@ #define GPUERRORS_H #include "GPUCommonDef.h" -#include "GPUDefMacros.h" + +#ifndef GPUCA_GPUCODE #include +#endif namespace o2::gpu { -static std::unordered_map errorNames = { -#define GPUCA_ERROR_CODE(num, name, ...) {num, GPUCA_M_STR(name)}, -#include "GPUErrorCodes.h" -#undef GPUCA_ERROR_CODE -}; - class GPUErrors { public: @@ -42,6 +38,7 @@ class GPUErrors void setMemory(GPUglobalref() uint32_t* m) { mErrors = m; } void clear(); bool printErrors(bool silent = false, uint64_t mask = 0); + static const std::unordered_map& getErrorNames(); uint32_t getNErrors() const; const uint32_t* getErrorPtr() const; static uint32_t getMaxErrors(); From 7b5af49b2a59c92f29463e6c9d36bc57d2785edc Mon Sep 17 00:00:00 2001 From: Anton Riedel Date: Tue, 17 Jun 2025 17:12:50 +0200 Subject: [PATCH 110/315] Feat: account for missing error codes --- Detectors/TPC/qc/src/GPUErrorQA.cxx | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Detectors/TPC/qc/src/GPUErrorQA.cxx b/Detectors/TPC/qc/src/GPUErrorQA.cxx index 912b036a6cccf..d4848aaefecb7 100644 --- a/Detectors/TPC/qc/src/GPUErrorQA.cxx +++ b/Detectors/TPC/qc/src/GPUErrorQA.cxx @@ -28,14 +28,27 @@ void GPUErrorQA::initializeHistograms() { TH1::AddDirectory(false); + auto const& errorNames = o2::gpu::GPUErrors::getErrorNames(); + + int maxErrorCode = 1; + for (const auto& [key, _] : errorNames) { + if (static_cast(key) > maxErrorCode) { + maxErrorCode = key; + } + } + // 1D histogram counting all reported errors - mMapHist["ErrorCounter"] = std::make_unique("ErrorCounter", "ErrorCounter", o2::gpu::errorNames.size(), -0.5, o2::gpu::errorNames.size() - 0.5); + mMapHist["ErrorCounter"] = std::make_unique("ErrorCounter", "ErrorCounter", maxErrorCode, -0.5, maxErrorCode - 0.5); mMapHist["ErrorCounter"]->GetXaxis()->SetTitle("Error Codes"); mMapHist["ErrorCounter"]->GetYaxis()->SetTitle("Entries"); // for convienence, label each bin with the error name - for (size_t bin = 1; bin < mMapHist["ErrorCounter"]->GetNbinsX(); bin++) { - auto const& it = o2::gpu::errorNames.find(bin); - mMapHist["ErrorCounter"]->GetXaxis()->SetBinLabel(bin, it->second); + for (size_t bin = 1; bin <= maxErrorCode; bin++) { + auto const& it = errorNames.find(bin); + if (it != errorNames.end()) { + mMapHist["ErrorCounter"]->GetXaxis()->SetBinLabel(bin, it->second); + } else { + mMapHist["ErrorCounter"]->GetXaxis()->SetBinLabel(bin, "NO_DEF"); + } } } //______________________________________________________________________________ From c2f066ac14c1e7d40c322a46f2c9ceed67dc2d11 Mon Sep 17 00:00:00 2001 From: Anton Riedel Date: Thu, 3 Jul 2025 16:32:01 +0200 Subject: [PATCH 111/315] Fix: add header guard --- GPU/GPUTracking/Global/GPUErrors.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Global/GPUErrors.h b/GPU/GPUTracking/Global/GPUErrors.h index d14c9ffaeda96..535364bf08ce1 100644 --- a/GPU/GPUTracking/Global/GPUErrors.h +++ b/GPU/GPUTracking/Global/GPUErrors.h @@ -16,7 +16,6 @@ #define GPUERRORS_H #include "GPUCommonDef.h" - #ifndef GPUCA_GPUCODE #include #endif @@ -38,7 +37,9 @@ class GPUErrors void setMemory(GPUglobalref() uint32_t* m) { mErrors = m; } void clear(); bool printErrors(bool silent = false, uint64_t mask = 0); +#ifndef GPUCA_GPUCODE static const std::unordered_map& getErrorNames(); +#endif uint32_t getNErrors() const; const uint32_t* getErrorPtr() const; static uint32_t getMaxErrors(); From bc3e04cb1ce8030d05de09271fafdb0557241d69 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 4 Jul 2025 10:47:37 +0200 Subject: [PATCH 112/315] GPU: Update build documentation for new gpu-system.sh package --- GPU/documentation/build-O2.md | 56 ++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/GPU/documentation/build-O2.md b/GPU/documentation/build-O2.md index 098629f45a832..dd21f7e154a63 100644 --- a/GPU/documentation/build-O2.md +++ b/GPU/documentation/build-O2.md @@ -11,6 +11,36 @@ GPU support should be detected and enabled automatically. If you just want to reproduce the GPU build locally without running it, it might be easiest to use the GPU CI container (see below). The provisioning script of the container also demonstrates which patches need to be applied such that everything works correctly. +In a nutshell, all is steered via CMake variables, and the `ALIBUILD_O2_FORCE_GPU...` environment variables exist to steer what [alidist/o2.sh](https://github.com/alisw/alidist/blob/master/o2.sh) puts as CMake defaults. +We try to run the same CMake GPU detection as in O2 ([FindO2GPU.cmake](https://github.com/AliceO2Group/AliceO2/blob/dev/dependencies/FindO2GPU.cmake)) during the aliBuild `prefer_system_check` ([gpu-system.sh](https://github.com/alisw/alidist/blob/master/gpu-system.sh)), such that all GPU features / versions / architectures can become part of the `gpu-system` version, which avoid inconsistencies between different packages we build. + +All is steered via environment variables, which will go into the version and thus the hash: +- `ALIBUILD_O2_FORCE_GPU=...` sets the mode +- `ALIBUILD_O2_FORCE_GPU_CUDA=1` can force-enable (`=1`) or disable (`=0`) backends, even if they were not detected. Same for `..._HIP` and `..._OPENCL`. +- `ALIBUILD_O2_FORCE_GPU_CUDA_ARCH=...` can override the architecture to cross-compile, e.g. `ALIBUILD_O2_FORCE_GPU_CUDA_ARCH="86;89"`. Same for `..._HIP_ARCH`. + +Modes for `ALIBUILD_O2_FORCE_GPU` +- `force` / `1` / `ci`: Force that all backends / features are detected, fail if not. GPU architectures are set to the default ones if not specified by environment variables. +CI is currently identical to force, but should allow special behavior when running in the CI. +- `auto`: check for supported system-cmake version, fail if not found. Auto-detect GPU backends / features and architectures. Selected features can be force-enabled on top via env variable. But not selectively disabled. (But one can use the manual mode below.) +- `onthefly`: Don't detect GPUs at alidist levels. gPUs disabled in ONNX. GPUs auto-detcted in O2 CMake during build as before, but this means the O2 build hash does not depend on GPU features, so we also have the same problems as before. This is just a fallback, to allow users to build with GPUs if they don't have a compatible system CMake. +- `fullauto`: Detect supported system-cmake. If found, behave as Auto. If not found behave as OnTheFly. +- `disabled`: Disable all GPU builds. No extra time during aliBuild command. +- `manual`: all GPU builds disabled by default, to be enabled manually via env variable. No extra time during aliBuild command. + +*Additional reasoning for this approach* +Advantages: +- O2 hash and ONNX hash depend on available GPU backends, detected features (like tensorrt for ML) and on the detected GPU architectures and librar versions. I.e. when you plug in a new GPU or update the CUDA version, the O2 hash will change and this will trigger a rebuild. Otherwise, the build could just fail due to stale settings in CMakeCache. +- We can have binary tarballs depending on the enabled backends. +- O2 and ONNX are always in sync. +- Same detection during aliBuild as in O2 CMake. +- One can see enabled GPU features / versions / architectures in the version string of `gpu-system`. + +Disadvantages: +- Need system `CMake` >= `3.26` for the detsction at aliBuild level. +- `FindO2GPU.cmake` is duplicated in O2 and alidist and must be kept in sync. But at least this is checked and gives an error otherwise. +- Running cmake during the system check takes around 5 sec for every aliBuild command involving O2 or ONNX. + *GPU Tracking with CUDA* * The CMake option `-DENABLE_CUDA=ON/OFF/AUTO` steers whether CUDA is forced enabled / unconditionally disabled / auto-detected. * The CMake option `-DCUDA_COMPUTETARGET=...` fixes a GPU target, e.g. 61 for PASCAL or 75 for Turing (if unset, it compiles for the lowest supported architecture) @@ -19,10 +49,9 @@ The provisioning script of the container also demonstrates which patches need to * CMake will report "Building GPUTracking with CUDA support" when enabled. *GPU Tracking with HIP* - * HIP and HCC must be installed, and CMake must be able to detect HIP via find_package(hip). - * If HIP and HCC are not installed to /opt/rocm, the environment variables `$HIP_PATH` and `$HCC_HOME` must point to the installation directories. - * HIP from ROCm >= 4.0 is required. - * The CMake option `-DHIP_AMDGPUTARGET=...` forces a GPU target, e.g. gfx906 for Radeon VII (if unset, it auto-detects the GPU). + * HIP must be installed, and CMake must be able to detect HIP via find_package(hip) and enable language(hip). + * For the minimum ROCm / HIP version, please check [FindO2GPU.cmake](https://github.com/AliceO2Group/AliceO2/blob/dev/dependencies/FindO2GPU.cmake#L287). + * The CMake option `-DHIP_AMDGPUTARGET=...` / env variable `ALIBUILD_O2_FORCE_GPU_HIP_ARCH=...` forces a GPU target, e.g. gfx906 for MI50 (if unset, it auto-detects the GPU). * CMake will report "Building GPUTracking with HIP support" when enabled. * It may be that some patches must be applied to ROCm after the installation. You find the details in the provisioning script of the GPU CI container below. @@ -31,7 +60,7 @@ The provisioning script of the container also demonstrates which patches need to * Needs the SPIR-V LLVM translator together with LLVM to create the SPIR-V binaries, also detectable via CMake. *OpenGL visualization of TPC tracking* - * Needs the following libraries (all detectable via CMake find_package): libOpenGL, libGLEW, libGLFW, libGLU. + * Needs the following libraries (all detectable via CMake find_package): libOpenGL, libGLEW or libGLFW (default), libGLU. * OpenGL must be at least version 4.5, but this is not detectable at CMake time. If the supported OpenGL version is below, the display is not/partially built, and not available at runtime. (Whether it is not or partially built depends on whether the maximum OpenGL version supported by GLEW or that of the system runtime in insufficient.) * Note: If ROOT does not detect the system GLEW library, ROOT will install its own very outdated GLEW library, which will be insufficient for the display. Since the ROOT include path will come first in the order, this will prevent the display from being built. * CMake will report "Building GPU Event Display" when enabled. @@ -46,17 +75,16 @@ The provisioning script of the container also demonstrates which patches need to *Using the GPU CI container* * Setting up everything locally might be somewhat time-consuming, instead you can use the GPU CI cdocker container. - * The docker images is `alisw/slc8-gpu-builder`. - * The container exports the `ALIBUILD_O2_FORCE_GPU` env variable, which force-enables all GPU builds. + * The docker images is `alisw/slc9-gpu-builder`. + * The container exports the `ALIBUILD_O2_FORCE_GPU=1` env variable, which force-enables all GPU builds. * Note that it might not be possible out-of-the-box to run the GPU version from within the container. In case of HIP it should work when you forwards the necessary GPU devices in the container. For CUDA however, you would either need to (in addition to device forwarding) match the system CUDA driver and toolkit installation to the files present in the container, or you need to use the CUDA docker runtime, which is currently not installed in the container. * There are currently some patches needed to install all the GPU backends in a proper way and together. Please refer to the container provisioning script [provision.sh](https://github.com/alisw/docks/blob/master/slc9-gpu-builder/provision.sh). If you want to reproduce the installation locally, it is recommended to follow the steps from the script. *Summary* -If you want to enforce the GPU builds on a system without GPU, please set the following CMake settings: - * `ENABLE_CUDA=ON` - * `ENABLE_HIP=ON` - * `ENABLE_OPENCL=ON - * `HIP_AMDGPUTARGET=default` - * `CUDA_COMPUTETARGET=default` -Alternatively you can set the environment variables `ALIBUILD_ENABLE_CUDA=1` and `ALIBUILD_ENABLE_HIP=1` to enforce building CUDA or HIP without modifying the alidist scripts. +If you want to enforce the GPU builds on a system without GPU, please export the following environment variables: + * `ALIBUILD_O2_FORCE_GPU_CUDA=ON` + * `ALIBUILD_O2_FORCE_GPU_HIP=ON` + * `ALIBUILD_O2_FORCE_GPU_OPENCL=ON` + * `ALIBUILD_O2_FORCE_GPU_CUDA_ARCH=default` + * `ALIBUILD_O2_FORCE_GPU_HIP_ARCH=default` From e2894300f0fd042c199037143254353be46b726e Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 1 Jul 2025 16:53:39 +0200 Subject: [PATCH 113/315] Add/use in TPCFastTransform mean IDC data member on top of Lumi Nominally both IDC (setIDC(val)) and Lumi (setLumi(val)) info of the map should be filled at the creation time. Depending what is used for the corrections (accoding to --lumi-type value: 1 for CTP lumi or 2 for IDC scaler) the getLumi or getIDC will be used. For the old maps, where the mIDC is absent (i.e. default value -1 returned by getIDC()) but the Lumi was used to stored the IDC mean value, we check if getLumi() is below the threshold TPCCorrMap.CTP2IDCFallBackThreshold (by default set to 30). If this is a case, the getLumi() value will be used as IDC scale, otherwise a Fatal will be thrown. Note that the inverse check is not done: if CTP Lumi scaling is requested for the old map where getLumi returns IDC, a wrong scale will be accepted. --- .../include/TPCCalibration/CorrMapParam.h | 1 + .../TPCCalibration/CorrectionMapsLoader.h | 1 + .../src/CorrectdEdxDistortions.cxx | 4 +- .../calibration/src/CorrectionMapsLoader.cxx | 44 ++++++++++++++++--- .../TPCFastTransform.cxx | 35 ++++++++++++++- GPU/TPCFastTransformation/TPCFastTransform.h | 25 ++++++++++- 6 files changed, 98 insertions(+), 12 deletions(-) diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CorrMapParam.h b/Detectors/TPC/calibration/include/TPCCalibration/CorrMapParam.h index 147e5587accbb..4ce0e642f4ea3 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CorrMapParam.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CorrMapParam.h @@ -29,6 +29,7 @@ struct CorrMapParam : public o2::conf::ConfigurableParamHelper { float lumiMean = 0.; // override TPC corr.map mean lumi (if > 0), disable corrections if < 0 float lumiMeanRef = 0.; // override TPC corr.mapRef mean lumi (if > 0)" float lumiInstFactor = 1.; // scaling to apply to instantaneous lumi from CTP (but not to IDC scaler) + float CTP2IDCFallBackThreshold = 30.; // if needed, interpret map->getLumi() as map->getIDC(), provided map->getLumi() is below this threshold int ctpLumiSource = 0; // CTP lumi source: 0 = LumiInfo.getLumi(), 1 = LumiInfo.getLumiAlt() O2ParamDef(CorrMapParam, "TPCCorrMap"); diff --git a/Detectors/TPC/calibration/include/TPCCalibration/CorrectionMapsLoader.h b/Detectors/TPC/calibration/include/TPCCalibration/CorrectionMapsLoader.h index 90dc84e618cec..41e3ed6d3dcd5 100644 --- a/Detectors/TPC/calibration/include/TPCCalibration/CorrectionMapsLoader.h +++ b/Detectors/TPC/calibration/include/TPCCalibration/CorrectionMapsLoader.h @@ -63,6 +63,7 @@ class CorrectionMapsLoader : public o2::gpu::CorrectionMapsHelper void init(o2::framework::InitContext& ic); void copySettings(const CorrectionMapsLoader& src); void updateInverse(); /// recalculate inverse correction + float getMapMeanRate(const o2::gpu::TPCFastTransform* mp, bool lumiOverridden) const; static void requestCCDBInputs(std::vector& inputs, std::vector& options, const CorrectionMapsLoaderGloOpts& gloOpts); static void addGlobalOptions(std::vector& options); diff --git a/Detectors/TPC/calibration/src/CorrectdEdxDistortions.cxx b/Detectors/TPC/calibration/src/CorrectdEdxDistortions.cxx index e5d1f32ad5661..73599e744483c 100644 --- a/Detectors/TPC/calibration/src/CorrectdEdxDistortions.cxx +++ b/Detectors/TPC/calibration/src/CorrectdEdxDistortions.cxx @@ -70,8 +70,8 @@ void o2::tpc::CorrectdEdxDistortions::setLumi(float lumi) LOGP(warn, "Nullptr detected in accessing the correction maps"); return; } - const float lumiAvg = mCorrAvg->getLumi(); - const float lumiDer = mCorrDer->getLumi(); + const float lumiAvg = mCorrAvg->getIDC(); + const float lumiDer = mCorrDer->getIDC(); mScaleDer = (lumi - lumiAvg) / lumiDer; LOGP(info, "Setting mScaleDer: {} for inst lumi: {} avg lumi: {} deriv. lumi: {}", mScaleDer, lumi, lumiAvg, lumiDer); } diff --git a/Detectors/TPC/calibration/src/CorrectionMapsLoader.cxx b/Detectors/TPC/calibration/src/CorrectionMapsLoader.cxx index e13f887cbdc21..d1e1f60d4b801 100644 --- a/Detectors/TPC/calibration/src/CorrectionMapsLoader.cxx +++ b/Detectors/TPC/calibration/src/CorrectionMapsLoader.cxx @@ -176,20 +176,52 @@ bool CorrectionMapsLoader::accountCCDBInputs(const ConcreteDataMatcher& matcher, if (matcher == ConcreteDataMatcher("TPC", "CorrMap", 0)) { setCorrMap((o2::gpu::TPCFastTransform*)obj); mCorrMap->rectifyAfterReadingFromFile(); - if (getMeanLumiOverride() == 0 && mCorrMap->getLumi() > 0.) { - setMeanLumi(mCorrMap->getLumi(), false); + mCorrMap->setCTP2IDCFallBackThreshold(o2::tpc::CorrMapParam::Instance().CTP2IDCFallBackThreshold); + if (getMeanLumiOverride() != 0) { + if (getLumiScaleType() == 1) { + mCorrMap->setLumi(getMeanLumiOverride()); + LOGP(info, "CorrMap mean lumi rate is overridden to {}", mCorrMap->getLumi()); + } else if (getLumiScaleType() == 2) { + mCorrMap->setIDC(getMeanLumiOverride()); + LOGP(info, "CorrMap mean IDC rate is overridden to {}", mCorrMap->getIDC()); + } + } + float mapMeanRate = 0; + if (getLumiScaleType() == 1) { + mapMeanRate = mCorrMap->getLumi(); + } else if (getLumiScaleType() == 2) { + mapMeanRate = mCorrMap->getIDC(); + } + if (getMeanLumiOverride() == 0 && mapMeanRate > 0.) { + setMeanLumi(mapMeanRate, false); } - LOGP(debug, "MeanLumiOverride={} MeanLumiMap={} -> meanLumi = {}", getMeanLumiOverride(), mCorrMap->getLumi(), getMeanLumi()); + LOGP(debug, "MeanLumiOverride={} MeanLumiMap={} -> meanLumi = {}", getMeanLumiOverride(), mapMeanRate, getMeanLumi()); setUpdatedMap(); return true; } if (matcher == ConcreteDataMatcher("TPC", "CorrMapRef", 0)) { setCorrMapRef((o2::gpu::TPCFastTransform*)obj); mCorrMapRef->rectifyAfterReadingFromFile(); + mCorrMapRef->setCTP2IDCFallBackThreshold(o2::tpc::CorrMapParam::Instance().CTP2IDCFallBackThreshold); + if (getMeanLumiRefOverride() != 0) { + if (getLumiScaleType() == 1) { + mCorrMapRef->setLumi(getMeanLumiRefOverride()); + LOGP(info, "CorrMapRef mean lumi rate is overridden to {}", mCorrMapRef->getLumi()); + } else if (getLumiScaleType() == 2) { + mCorrMapRef->setIDC(getMeanLumiRefOverride()); + LOGP(info, "CorrMapRef mean IDC rate is overridden to {}", mCorrMapRef->getIDC()); + } + } + float mapRefMeanRate = 0; + if (getLumiScaleType() == 1) { + mapRefMeanRate = mCorrMapRef->getLumi(); + } else if (getLumiScaleType() == 2) { + mapRefMeanRate = mCorrMapRef->getIDC(); + } if (getMeanLumiRefOverride() == 0) { - setMeanLumiRef(mCorrMapRef->getLumi()); + setMeanLumiRef(mapRefMeanRate); } - LOGP(debug, "MeanLumiRefOverride={} MeanLumiMap={} -> meanLumi = {}", getMeanLumiRefOverride(), mCorrMapRef->getLumi(), getMeanLumiRef()); + LOGP(debug, "MeanLumiRefOverride={} MeanLumiMap={} -> meanLumi = {}", getMeanLumiRefOverride(), mapRefMeanRate, getMeanLumiRef()); setUpdatedMapRef(); return true; } @@ -217,7 +249,7 @@ bool CorrectionMapsLoader::accountCCDBInputs(const ConcreteDataMatcher& matcher, int scaleType = getLumiScaleType(); const std::array lumiS{"OFF", "CTP", "TPC scaler"}; if (scaleType >= lumiS.size()) { - LOGP(fatal, "Wrong lumi-scale-type provided!"); + LOGP(fatal, "Wrong corrmap-lumi-mode provided!"); } LOGP(info, "TPC correction map params updated: SP corrections: {} (corr.map scaling type={}, override values: lumiMean={} lumiRefMean={} lumiScaleMode={}), CTP Lumi: source={} lumiInstOverride={} , LumiInst scale={} ", diff --git a/GPU/TPCFastTransformation/TPCFastTransform.cxx b/GPU/TPCFastTransformation/TPCFastTransform.cxx index aea6589761403..bd29a760615ad 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.cxx +++ b/GPU/TPCFastTransformation/TPCFastTransform.cxx @@ -37,7 +37,7 @@ using namespace o2::gpu; TPCFastTransform::TPCFastTransform() - : FlatObject(), mTimeStamp(0), mCorrection(), mApplyCorrection(1), mT0(0.f), mVdrift(0.f), mVdriftCorrY(0.f), mLdriftCorr(0.f), mTOFcorr(0.f), mPrimVtxZ(0.f), mLumi(0.f), mLumiError(0.f), mLumiScaleFactor(1.0f) + : FlatObject(), mTimeStamp(0), mCorrection(), mApplyCorrection(1), mT0(0.f), mVdrift(0.f), mVdriftCorrY(0.f), mLdriftCorr(0.f), mTOFcorr(0.f), mPrimVtxZ(0.f), mLumi(TPCFastTransform::DEFLUMI), mLumiError(0.f), mLumiScaleFactor(1.0f), mIDC(TPCFastTransform::DEFIDC), mIDCError(0.f), mCTP2IDCFallBackThreshold(30.f) { // Default Constructor: creates an empty uninitialized object } @@ -60,6 +60,9 @@ void TPCFastTransform::cloneFromObject(const TPCFastTransform& obj, char* newFla mPrimVtxZ = obj.mPrimVtxZ; mLumi = obj.mLumi; mLumiError = obj.mLumiError; + mIDC = obj.mIDC; + mIDCError = obj.mIDCError; + mCTP2IDCFallBackThreshold = obj.mCTP2IDCFallBackThreshold; mLumiScaleFactor = obj.mLumiScaleFactor; // variable-size data @@ -108,8 +111,11 @@ void TPCFastTransform::startConstruction(const TPCFastSpaceChargeCorrection& cor mLdriftCorr = 0.f; mTOFcorr = 0.f; mPrimVtxZ = 0.f; - mLumi = 0.f; + mLumi = DEFLUMI; mLumiError = 0.f; + mIDC = DEFIDC; + mIDCError = 0.f; + mCTP2IDCFallBackThreshold = 30.f; mLumiScaleFactor = 1.f; // variable-size data @@ -160,6 +166,9 @@ void TPCFastTransform::print() const LOG(info) << "mPrimVtxZ = " << mPrimVtxZ; LOG(info) << "mLumi = " << mLumi; LOG(info) << "mLumiError = " << mLumiError; + LOG(info) << "mIDC = " << mIDC; + LOG(info) << "mIDCError = " << mIDCError; + LOG(info) << "mCTP2IDCFallBackThreshold = " << mCTP2IDCFallBackThreshold; LOG(info) << "mLumiScaleFactor = " << mLumiScaleFactor; mCorrection.print(); #endif @@ -251,3 +260,25 @@ void TPCFastTransform::setSlowTPCSCCorrection(TFile& inpf) mCorrectionSlow->mCorr->setGlobalCorrectionsFromFile(inpf, o2::tpc::Side::C); } #endif + +float TPCFastTransform::getIDC() const +{ + auto val = mIDC; + if (!isIDCSet()) { + if (mLumi < mCTP2IDCFallBackThreshold) { +#if !defined(GPUCA_GPUCODE) + bool static report = true; + if (report) { + report = false; + LOG(warn) << "IDC scaling is requested but map IDC record is empty. Since map Lumi " << mLumi << " is less than fall-back threshold " << mCTP2IDCFallBackThreshold << ", interpret Lumi record as IDC"; + } +#endif + val = mLumi; + } else { +#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) + LOG(fatal) << "IDC scaling is requested but map IDC record is empty. The map Lumi " << mLumi << " exceeds Lumi->IDC fall-back threshold " << mCTP2IDCFallBackThreshold; +#endif + } + } + return val; +} diff --git a/GPU/TPCFastTransformation/TPCFastTransform.h b/GPU/TPCFastTransformation/TPCFastTransform.h index 4e0403422ee06..14cd892b2554a 100644 --- a/GPU/TPCFastTransformation/TPCFastTransform.h +++ b/GPU/TPCFastTransformation/TPCFastTransform.h @@ -96,6 +96,9 @@ struct TPCSlowSpaceChargeCorrection { class TPCFastTransform : public FlatObject { public: + static constexpr float DEFLUMI = -1e6f; // default value to check if member was set + static constexpr float DEFIDC = -1e6f; // default value to check if member was set + /// _____________ Constructors / destructors __________________________ /// Default constructor: creates an empty uninitialized object @@ -162,7 +165,9 @@ class TPCFastTransform : public FlatObject void setLumi(float l) { mLumi = l; } void setLumiError(float e) { mLumiError = e; } void setLumiScaleFactor(float s) { mLumiScaleFactor = s; } - + void setIDC(float l) { mIDC = l; } + void setIDCError(float e) { mIDCError = e; } + void setCTP2IDCFallBackThreshold(float v) { mCTP2IDCFallBackThreshold = v; } /// Sets the time stamp of the current calibaration void setTimeStamp(int64_t v) { mTimeStamp = v; } @@ -251,9 +256,21 @@ class TPCFastTransform : public FlatObject /// Return map lumi GPUd() float getLumi() const { return mLumi; } + GPUd() float isLumiSet() const { return mLumi != DEFLUMI; } + /// Return map lumi error GPUd() float getLumiError() const { return mLumiError; } + /// Return map lumi + GPUd() float getIDC() const; + + GPUd() bool isIDCSet() const { return mIDC != DEFIDC; } + + /// Return map lumi error + GPUd() float getIDCError() const { return mIDCError; } + + GPUd() float getCTP2IDCFallBackThreshold() const { return mCTP2IDCFallBackThreshold; } + /// Return map user defined lumi scale factor GPUd() float getLumiScaleFactor() const { return mLumiScaleFactor; } @@ -334,12 +351,16 @@ class TPCFastTransform : public FlatObject float mLumiError; ///< error on luminosity float mLumiScaleFactor; ///< user correction factor for lumi (e.g. normalization, efficiency correction etc.) + float mIDC; ///< IDC estimator + float mIDCError; ///< error on IDC + float mCTP2IDCFallBackThreshold; ///< if IDC is not set but requested, use Lumi if it does not exceed this threshold + /// Correction of (x,u,v) with tricubic interpolator on a regular grid TPCSlowSpaceChargeCorrection* mCorrectionSlow{nullptr}; ///< reference space charge corrections GPUd() void TransformInternal(int32_t slice, int32_t row, float& u, float& v, float& x, const TPCFastTransform* ref, const TPCFastTransform* ref2, float scale, float scale2, int32_t scaleMode) const; - ClassDefNV(TPCFastTransform, 3); + ClassDefNV(TPCFastTransform, 4); }; // ======================================================================= From b562533593101251481e099e9ddf554c80433b2a Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Fri, 4 Jul 2025 08:51:12 +0200 Subject: [PATCH 114/315] TRD: decrease default --max-delay for gain, t0, vdexb calibrations --- Detectors/TRD/workflow/include/TRDWorkflow/GainCalibSpec.h | 4 ++-- Detectors/TRD/workflow/include/TRDWorkflow/T0FitSpec.h | 4 ++-- .../TRD/workflow/include/TRDWorkflow/VdAndExBCalibSpec.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/GainCalibSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/GainCalibSpec.h index 295ce0bf1d0ac..1c60a05462508 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/GainCalibSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/GainCalibSpec.h @@ -45,7 +45,7 @@ class GainCalibDevice : public o2::framework::Task { o2::base::GRPGeomHelper::instance().setRequest(mCCDBRequest); auto slotL = ic.options().get("sec-per-slot"); - auto delay = ic.options().get("max-delay"); + auto delay = ic.options().get("max-delay"); mCalibrator = std::make_unique(); mCalibrator->setSlotLengthInSeconds(slotL); mCalibrator->setMaxSlotsDelay(delay); @@ -155,7 +155,7 @@ DataProcessorSpec getTRDGainCalibSpec() AlgorithmSpec{adaptFromTask(ccdbRequest)}, Options{ {"sec-per-slot", VariantType::UInt32, 900u, {"number of seconds per calibration time slot"}}, - {"max-delay", VariantType::UInt32, 2u, {"number of slots in past to consider"}}, + {"max-delay", VariantType::Float, 0.05f, {"number of slots in past to consider"}}, {"enable-root-output", VariantType::Bool, false, {"output tprofiles and fits to root file"}}, }}; } diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/T0FitSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/T0FitSpec.h index 3f4fc7a1e69fd..f39174b95ba64 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/T0FitSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/T0FitSpec.h @@ -46,7 +46,7 @@ class T0FitDevice : public o2::framework::Task { o2::base::GRPGeomHelper::instance().setRequest(mCCDBRequest); auto slotL = ic.options().get("sec-per-slot"); - auto delay = ic.options().get("max-delay"); + auto delay = ic.options().get("max-delay"); mFitInstance = std::make_unique(); mFitInstance->setSlotLengthInSeconds(slotL); @@ -159,7 +159,7 @@ DataProcessorSpec getTRDT0FitSpec() AlgorithmSpec{adaptFromTask(ccdbRequest)}, Options{ {"sec-per-slot", VariantType::UInt32, 900u, {"number of seconds per calibration time slot"}}, - {"max-delay", VariantType::UInt32, 2u, {"number of slots in past to consider"}}, + {"max-delay", VariantType::Float, 0.05f, {"number of slots in past to consider"}}, {"enable-root-output", VariantType::Bool, false, {"output t0 values to root file"}}, }}; } diff --git a/Detectors/TRD/workflow/include/TRDWorkflow/VdAndExBCalibSpec.h b/Detectors/TRD/workflow/include/TRDWorkflow/VdAndExBCalibSpec.h index cddbb45e169da..f45b7a1808287 100644 --- a/Detectors/TRD/workflow/include/TRDWorkflow/VdAndExBCalibSpec.h +++ b/Detectors/TRD/workflow/include/TRDWorkflow/VdAndExBCalibSpec.h @@ -45,7 +45,7 @@ class VdAndExBCalibDevice : public o2::framework::Task { o2::base::GRPGeomHelper::instance().setRequest(mCCDBRequest); auto slotL = ic.options().get("sec-per-slot"); - auto delay = ic.options().get("max-delay"); + auto delay = ic.options().get("max-delay"); mCalibrator = std::make_unique(); mCalibrator->setSlotLengthInSeconds(slotL); mCalibrator->setMaxSlotsDelay(delay); @@ -158,7 +158,7 @@ DataProcessorSpec getTRDVdAndExBCalibSpec() AlgorithmSpec{adaptFromTask(ccdbRequest)}, Options{ {"sec-per-slot", VariantType::UInt32, 900u, {"number of seconds per calibration time slot"}}, - {"max-delay", VariantType::UInt32, 2u, {"number of slots in past to consider"}}, + {"max-delay", VariantType::Float, 0.05f, {"number of slots in past to consider"}}, {"enable-root-output", VariantType::Bool, false, {"output tprofiles and fits to root file"}}, }}; } From 8b07c99a8252c952c9a104d34bd461797f77138f Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 24 Jun 2025 21:09:16 +0200 Subject: [PATCH 115/315] Vtx: make class printable Signed-off-by: Felix Schlepper --- .../ReconstructionDataFormats/Vertex.h | 55 ++++++++++++++++++- DataFormats/Reconstruction/src/Vertex.cxx | 4 +- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h index fc89f162a0727..2d13e029f8c00 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/Vertex.h @@ -18,10 +18,13 @@ #include "CommonDataFormat/TimeStamp.h" #ifndef GPUCA_GPUCODE_DEVICE -#include -#include #include #include +#ifndef GPUCA_NO_FMT +#include +#include +#include +#endif #endif namespace o2 @@ -135,6 +138,11 @@ class Vertex : public VertexBase { } +#if !defined(GPUCA_NO_FMT) && !defined(GPUCA_GPUCODE_DEVICE) + void print() const; + std::string asString() const; +#endif + GPUd() ushort getNContributors() const { return mNContributors; } GPUd() void setNContributors(ushort v) { mNContributors = v; } GPUd() void addContributor() { mNContributors++; } @@ -162,6 +170,49 @@ class Vertex : public VertexBase #if !defined(GPUCA_GPUCODE_DEVICE) && !defined(GPUCA_NO_FMT) std::ostream& operator<<(std::ostream& os, const o2::dataformats::VertexBase& v); + +namespace detail +{ +template +concept Streamable = requires(std::ostream& os, const T& a) { + { os << a } -> std::same_as; +}; + +template +concept HasFormattableTimeStamp = requires(const T& t) { + { fmt::format("{}", t.getTimeStamp()) } -> std::convertible_to; +}; +} // namespace detail + +template +inline std::string Vertex::asString() const +{ + const std::string stamp = [&]() -> std::string { + if constexpr (detail::Streamable) { + std::ostringstream oss; + oss << mTimeStamp; + return oss.str(); + } else if constexpr (detail::HasFormattableTimeStamp) { + return fmt::format("{}", mTimeStamp.getTimeStamp()); + } else { + return "X"; + } + }(); + return fmt::format("{} NContrib:{} Chi2:{:.2f} Flags:{:b} Stamp:{}", VertexBase::asString(), mNContributors, mChi2, mBits, stamp); +} + +template +inline std::ostream& operator<<(std::ostream& os, const o2::dataformats::Vertex& v) +{ + os << v.asString(); + return os; +} + +template +inline void Vertex::print() const +{ + std::cout << *this << '\n'; +} #endif } // namespace dataformats diff --git a/DataFormats/Reconstruction/src/Vertex.cxx b/DataFormats/Reconstruction/src/Vertex.cxx index b902e9972a13d..85145683ddd97 100644 --- a/DataFormats/Reconstruction/src/Vertex.cxx +++ b/DataFormats/Reconstruction/src/Vertex.cxx @@ -10,9 +10,9 @@ // or submit itself to any jurisdiction. #include "ReconstructionDataFormats/Vertex.h" -#include #ifndef GPUCA_NO_FMT -#include +#include +#include #endif namespace o2 From 9cef6de4f9d3e8cc1957836c43eb82ebe93a837e Mon Sep 17 00:00:00 2001 From: mcoquet642 <74600025+mcoquet642@users.noreply.github.com> Date: Fri, 4 Jul 2025 13:03:01 +0200 Subject: [PATCH 116/315] Computation of DCAxyz for forward tracks (#14460) * Computation of 3D DCA for forward tracks * clang format --------- Co-authored-by: Maurice Coquet --- .../ReconstructionDataFormats/TrackFwd.h | 1 + DataFormats/Reconstruction/src/TrackFwd.cxx | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h index 76ca8473553cd..50ed36d466d25 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackFwd.h @@ -161,6 +161,7 @@ class TrackParCovFwd : public TrackParFwd void propagateToZquadratic(double zEnd, double zField); void propagateToZhelix(double zEnd, double zField); void propagateToZ(double zEnd, double zField); // Parameters: helix; errors: quadratic + void propagateToDCAhelix(double zField, const std::array& p, std::array& dca); // Add Multiple Coulomb Scattering effects void addMCSEffect(double x2X0); diff --git a/DataFormats/Reconstruction/src/TrackFwd.cxx b/DataFormats/Reconstruction/src/TrackFwd.cxx index 3c45a8ecb6ec2..dfe72c5b2ccc4 100644 --- a/DataFormats/Reconstruction/src/TrackFwd.cxx +++ b/DataFormats/Reconstruction/src/TrackFwd.cxx @@ -11,6 +11,7 @@ #include "ReconstructionDataFormats/TrackFwd.h" #include "Math/MatrixFunctions.h" +#include namespace o2 { @@ -503,5 +504,73 @@ bool TrackParCovFwd::getCovXYZPxPyPzGlo(std::array& cv) const return true; } +//________________________________________________________________ + +void TrackParCovFwd::propagateToDCAhelix(double zField, const std::array& p, std::array& dca) +{ + // Computing DCA of fwd track w.r.t vertex in helix track model, using Newton-Raphson minimization + + auto x0 = mParameters(0); + auto y0 = mParameters(1); + auto z0 = mZ; + auto phi0 = mParameters(2); + auto tanl = mParameters(3); + auto qOverPt = mParameters(4); + auto k = TMath::Abs(o2::constants::math::B2C * zField); + auto qpt = 1.0 / qOverPt; + auto qR = qpt / std::fabs(k); + auto invtanl = 1.0 / tanl; + auto Hz = std::copysign(1, zField); + + auto xPV = p[0]; + auto yPV = p[1]; + auto zPV = p[2]; + + auto qRtanl = qR * tanl; + auto invqRtanl = 1.0 / qRtanl; + auto [sinp, cosp] = o2::math_utils::sincosd(phi0); + + auto z = zPV; + double tol = 1e-4; + int max_iter = 10; + int iter = 0; + + while (iter++ < max_iter) { + double theta = (z0 - z) * invqRtanl; + double phi_theta = phi0 + Hz * theta; + double sin_phi_theta = sin(phi_theta); + double cos_phi_theta = cos(phi_theta); + + double DX = x0 - Hz * qR * (sin_phi_theta - sinp) - xPV; + double DY = y0 + Hz * qR * (cos_phi_theta - cosp) - yPV; + double DZ = z - zPV; + + double dD2_dZ = + 2 * DX * cos_phi_theta * invtanl + + 2 * DY * sin_phi_theta * invtanl + + 2 * DZ; + + double d2D2_dZ2 = + 2 * invtanl * invtanl + + 2 * invtanl * (DX * Hz * sin_phi_theta - DY * Hz * cos_phi_theta) * invqRtanl + + 2; + + double z_new = z - dD2_dZ / d2D2_dZ2; + + if (std::abs(z_new - z) < tol) { + z = z_new; + this->propagateToZhelix(z, zField); + dca[0] = this->getX() - xPV; + dca[1] = this->getY() - yPV; + dca[2] = this->getZ() - zPV; + LOG(debug) << "Converged after " << iter << " iterations for vertex X=" << p[0] << ", Y=" << p[1] << ", Z = " << p[2]; + return; + } + z = z_new; + } + LOG(debug) << "Failed to converge after " << iter << " iterations for vertex X=" << p[0] << ", Y=" << p[1] << ", Z = " << p[2]; + return; +} + } // namespace track } // namespace o2 From 9ce304b4e99f5f721c1eac92194f282cb732d0bd Mon Sep 17 00:00:00 2001 From: Andrea Sofia Triolo Date: Fri, 4 Jul 2025 20:30:24 +0200 Subject: [PATCH 117/315] ALICE3-TRK: detector ID used to fill Hit information correctly retrieved according to the chosen geometry (#14480) * ALICE3-TRK: Detector.cxx modified to retrieve the correct Detector ID following the chosen indexing scheme * ALICE3-TRK: considering half staves for the staggered geometry for ML/OT * ALICE3-TRK: indexing scheme now working independently from the chosen geometry layout * minor fixes --- .../TRK/base/include/TRKBase/GeometryTGeo.h | 23 +++- .../ALICE3/TRK/base/src/GeometryTGeo.cxx | 117 ++++++++++++++---- .../include/TRKSimulation/Detector.h | 15 +++ .../ALICE3/TRK/simulation/src/Detector.cxx | 90 ++++++++++++-- 4 files changed, 203 insertions(+), 42 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h index 852cb138e2be7..cfd991728d09b 100644 --- a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h @@ -60,33 +60,44 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache int extractNumberOfDisksVD() const; int extractNumberOfChipsPerPetalVD() const; int extractNumberOfStavesMLOT(int lay) const; + int extractNumberOfHalfStavesMLOT(int lay) const; /// Extract number following the prefix in the name string int extractVolumeCopy(const char* name, const char* prefix) const; int getNumberOfLayersMLOT() const { return mNumberOfLayersMLOT; } - int getNumberOffActivePartsVD() const { return mNumberOfActivePartsVD; } + int getNumberOfActivePartsVD() const { return mNumberOfActivePartsVD; } + int getNumberOfHalfStaves(int lay) const { return mNumberOfHalfStaves[lay]; } bool isOwner() const { return mOwner; } void setOwner(bool v) { mOwner = v; } void Print(Option_t* opt = "") const; - void PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int indexRetrieved) const; + void PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int indexRetrieved) const; int getLayer(int index) const; int getStave(int index) const; + int getHalfStave(int index) const; int getSubDetID(int index) const; int getPetalCase(int index) const; int getDisk(int index) const; /// This routine computes the chip index number from the subDetID, petal, disk, layer, stave /// TODO: retrieve also from chip when chips will be available - /// in substave /// \param int subDetID The subdetector ID, 0 for VD, 1 for MLOT /// \param int petalcase The petal case number for VD, from 0 to 3 /// \param int disk The disk number for VD, from 0 to 5 /// \param int lay The layer number. Starting from 0 both for VD and MLOT /// \param int stave The stave number for MLOT. Starting from 0 - int getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave) const; + /// \param int halfstave The half stave number for MLOT. Can be 0 or 1 + int getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave, int halfstave) const; + + /// This routine computes the chip index number from the subDetID, volume, layer, stave /// TODO: retrieve also from chip when chips will be available + /// \param int subDetID The subdetector ID, 0 for VD, 1 for MLOT + /// \param int volume is needed only with the current configuration for VD where each single element is a volume. // TODO: when the geometry naming scheme will be changed, change this method + /// \param int lay The layer number for the MLOT. In the current configuration for VD this is not needed. // TODO: when the geometry naming scheme will be changed, change this method + /// \param int stave The stave number in each layer for MLOT. Starting from 0. + /// \param int halfstave The half stave number for MLOT. Can be 0 or 1 + int getChipIndex(int subDetID, int volume, int lay, int stave, int halfstave) const; /// This routine computes subDetID, petal, disk, layer, stave given the chip index number /// TODO: copute also from chip when chips will be available /// \param int index The chip index number, starting from 0 @@ -95,7 +106,8 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache /// \param int disk The disk number for VD, from 0 to 5 /// \param int lay The layer number. Starting from 0 both for VD and MLOT /// \param int stave The stave number for MLOT. Starting from 0 - bool getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave) const; + /// \param int halfstave The half stave number for MLOT. Can be 0 or 1 + bool getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave, int& halfstave) const; int getLastChipIndex(int lay) const { return mLastChipIndex[lay]; } int getFirstChipIndex(int lay, int petalcase, int subDetID) const @@ -150,6 +162,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache std::vector mNumbersOfChipPerDiskVD; ///< numbersOfChipPerDiskVD std::vector mNumberOfChipsPerPetalVD; ///< numbersOfChipPerPetalVD std::vector mNumberOfStaves; ///< Number Of Staves per layer in ML/OT + std::vector mNumberOfHalfStaves; ///< Number Of Staves in each stave of the layer in ML/OT std::array mLayerToWrapper; ///< Layer to wrapper correspondence bool mOwner = true; //! is it owned by the singleton? diff --git a/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx index 4547225033498..69bae0fad9cee 100644 --- a/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx @@ -54,9 +54,9 @@ GeometryTGeo::GeometryTGeo(bool build, int loadTrans) : DetMatrixCache(detectors void GeometryTGeo::Build(int loadTrans) { ///// current geometry organization: - ///// total elements = 258 = x staves * 8 layers ML+OT + 4 petal cases * (3 layers + 6 disks) + ///// total elements = x staves (*2 half staves if staggered geometry) * 8 layers ML+OT + 4 petal cases * (3 layers + 6 disks) ///// indexing from 0 to 35: VD petals -> layers -> disks - ///// indexing from 36 to 257: MLOT staves + ///// indexing from 36 to y: MLOT staves if (isBuilt()) { LOGP(warning, "Already built"); @@ -74,6 +74,7 @@ void GeometryTGeo::Build(int loadTrans) mNumberOfDisksVD = extractNumberOfDisksVD(); mNumberOfStaves.resize(mNumberOfLayersMLOT); + mNumberOfHalfStaves.resize(mNumberOfLayersMLOT); mLastChipIndex.resize(mNumberOfPetalsVD + mNumberOfLayersMLOT); mLastChipIndexVD.resize(mNumberOfPetalsVD); mLastChipIndexMLOT.resize(mNumberOfLayersMLOT); /// ML and OT are part of TRK as the same detector, without disks @@ -85,6 +86,7 @@ void GeometryTGeo::Build(int loadTrans) for (int i = 0; i < mNumberOfLayersMLOT; i++) { std::cout << "Layer MLOT: " << i << std::endl; mNumberOfStaves[i] = extractNumberOfStavesMLOT(i); + mNumberOfHalfStaves[i] = extractNumberOfHalfStavesMLOT(i); } int numberOfChipsTotal = 0; @@ -99,13 +101,12 @@ void GeometryTGeo::Build(int loadTrans) /// filling the information for the MLOT for (int i = 0; i < mNumberOfLayersMLOT; i++) { - mNumberOfChipsPerLayerMLOT[i] = extractNumberOfStavesMLOT(i); // for the moment, considering 1 stave = 1 chip. TODO: add the final segmentation in chips + mNumberOfChipsPerLayerMLOT[i] = extractNumberOfStavesMLOT(i) * extractNumberOfHalfStavesMLOT(i); // for the moment, considering 1 half stave = 1 chip. TODO: add the final segmentation in chips numberOfChipsTotal += mNumberOfChipsPerLayerMLOT[i]; mLastChipIndex[i + mNumberOfPetalsVD] = numberOfChipsTotal - 1; mLastChipIndexMLOT[i] = numberOfChipsTotal - 1; } - // setSize(mNumberOfLayersMLOT + mNumberOfActivePartsVD); /// temporary, number of chips = number of layers and active parts setSize(numberOfChipsTotal); /// temporary, number of chips = number of staves and active parts fillMatrixCache(loadTrans); } @@ -155,7 +156,7 @@ int GeometryTGeo::getLayer(int index) const while (index > mLastChipIndex[lay]) { lay++; } - return lay - mNumberOfPetalsVD; /// numeration of MLOT layesrs starting from 1 + return lay - mNumberOfPetalsVD; /// numeration of MLOT layesrs starting from 0 } return -1; /// -1 if not found } @@ -170,8 +171,26 @@ int GeometryTGeo::getStave(int index) const return -1; } else if (subDetID == 1) { /// MLOT int lay = getLayer(index); - index -= getFirstChipIndex(lay, petalcase, subDetID); - return index; /// |||| + index -= getFirstChipIndex(lay, petalcase, subDetID); // get the index of the sensing element in the layer + return index / mNumberOfHalfStaves[lay]; + } + return -1; /// not found +} + +//__________________________________________________________________________ +int GeometryTGeo::getHalfStave(int index) const +{ + int subDetID = getSubDetID(index); + int lay = getLayer(index); + int petalcase = getPetalCase(index); + int stave = getStave(index); + + if (subDetID == 0) { /// VD + return -1; + } else if (subDetID == 1) { /// MLOT + int lay = getLayer(index); + index -= getFirstChipIndex(lay, petalcase, subDetID); // get the index of the sensing element in the layer + return index % 2; /// 0 = half stave left, 1 = half stave right, as geometry is filled /// TODO: generalize once chips will be in place. Can it be working also with chips? } return -1; /// not found } @@ -193,7 +212,7 @@ int GeometryTGeo::getDisk(int index) const } //__________________________________________________________________________ -int GeometryTGeo::getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave) const +int GeometryTGeo::getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave, int halfstave) const { if (subDetID == 0) { // VD if (lay == -1) { // disk @@ -201,20 +220,41 @@ int GeometryTGeo::getChipIndex(int subDetID, int petalcase, int disk, int lay, i } else { // layer return getFirstChipIndex(lay, petalcase, subDetID) + lay; } - } else if (subDetID == 1) { // MLOT - return getFirstChipIndex(lay, petalcase, subDetID) + stave; + } else if (subDetID == 1) { // MLOT + if (mNumberOfHalfStaves[lay] == 2) { // staggered geometry + return getFirstChipIndex(lay, petalcase, subDetID) + stave * mNumberOfHalfStaves[lay] + halfstave; + } else if (mNumberOfHalfStaves[lay] == 1) { // turbo geometry + return getFirstChipIndex(lay, petalcase, subDetID) + stave; + } + } + return -1; // not found +} + +//__________________________________________________________________________ +int GeometryTGeo::getChipIndex(int subDetID, int volume, int lay, int stave, int halfstave) const +{ + if (subDetID == 0) { // VD + return volume; /// In the current configuration for VD, each volume is the sensor element = chip. // TODO: when the geometry naming scheme will be changed, change this method + + } else if (subDetID == 1) { // MLOT + if (mNumberOfHalfStaves[lay] == 2) { // staggered geometry + return getFirstChipIndex(lay, -1, subDetID) + stave * mNumberOfHalfStaves[lay] + halfstave; + } else if (mNumberOfHalfStaves[lay] == 1) { // turbo geometry + return getFirstChipIndex(lay, -1, subDetID) + stave; + } } return -1; // not found } //__________________________________________________________________________ -bool GeometryTGeo::getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave) const +bool GeometryTGeo::getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave, int& halfstave) const { subDetID = getSubDetID(index); petalcase = getPetalCase(index); disk = getDisk(index); lay = getLayer(index); stave = getStave(index); + halfstave = getHalfStave(index); return kTRUE; } @@ -223,13 +263,12 @@ bool GeometryTGeo::getChipID(int index, int& subDetID, int& petalcase, int& disk TString GeometryTGeo::getMatrixPath(int index) const { - // int lay, hba, stav, sstav, mod, chipInMod; - int subDetID, petalcase, disk, lay, stave; //// TODO: add chips in a second step - getChipID(index, subDetID, petalcase, disk, lay, stave); + int subDetID, petalcase, disk, lay, stave, halfstave; //// TODO: add chips in a second step + getChipID(index, subDetID, petalcase, disk, lay, stave, halfstave); - int indexRetrieved = getChipIndex(subDetID, petalcase, disk, lay, stave); + int indexRetrieved = getChipIndex(subDetID, petalcase, disk, lay, stave, halfstave); - PrintChipID(index, subDetID, petalcase, disk, lay, stave, indexRetrieved); + PrintChipID(index, subDetID, petalcase, disk, lay, stave, halfstave, indexRetrieved); // TString path = Form("/cave_1/barrel_1/%s_2/", GeometryTGeo::getTRKVolPattern()); TString path = "/cave_1/barrel_1/TRKV_2/TRKLayer0_1/TRKStave0_1/TRKChip0_1/TRKSensor0_1/"; /// dummy path, to be replaced @@ -291,7 +330,7 @@ TGeoHMatrix* GeometryTGeo::extractMatrixSensor(int index) const auto path = getMatrixPath(index); static TGeoHMatrix matTmp; - gGeoManager->PushPath(); + // gGeoManager->PushPath(); // Preserve the modeler state. // if (!gGeoManager->cd(path.Data())) { // gGeoManager->PopPath(); @@ -440,7 +479,6 @@ int GeometryTGeo::extractNumberOfActivePartsVD() const if (vdV == nullptr) { LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry"; } - LOG(info) << "Volume name: " << getTRKVolPattern(); // Loop on all TRKV nodes, count Layer volumes by checking names TObjArray* nodes = vdV->GetNodes(); @@ -470,7 +508,6 @@ int GeometryTGeo::extractNumberOfDisksVD() const if (vdV == nullptr) { LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry"; } - LOG(info) << "Volume name: " << getTRKVolPattern(); // Loop on all TRKV nodes, count Layer volumes by checking names TObjArray* nodes = vdV->GetNodes(); @@ -500,7 +537,6 @@ int GeometryTGeo::extractNumberOfPetalsVD() const if (vdV == nullptr) { LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry"; } - LOG(info) << "Volume name: " << getTRKVolPattern(); // Loop on all TRKV nodes, count Layer volumes by checking names TObjArray* nodes = vdV->GetNodes(); @@ -530,7 +566,6 @@ int GeometryTGeo::extractNumberOfLayersVD() const if (vdV == nullptr) { LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry"; } - LOG(info) << "Volume name: " << getTRKVolPattern(); // Loop on all TRKV nodes, count Layer volumes by checking names TObjArray* nodes = vdV->GetNodes(); @@ -560,7 +595,6 @@ int GeometryTGeo::extractNumberOfChipsPerPetalVD() const if (vdV == nullptr) { LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry"; } - LOG(info) << "Volume name: " << getTRKVolPattern(); // Loop on all TRKV nodes, count Layer volumes by checking names TObjArray* nodes = vdV->GetNodes(); @@ -610,7 +644,35 @@ int GeometryTGeo::extractNumberOfStavesMLOT(int lay) const } //__________________________________________________________________________ -void GeometryTGeo::PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int indexRetrieved) const +int GeometryTGeo::extractNumberOfHalfStavesMLOT(int lay) const +{ + int numberOfHalfStaves = 0; + + std::string staveName = Form("%s%d", getTRKStavePattern(), lay); + TGeoVolume* staveV = gGeoManager->GetVolume(staveName.c_str()); + + if (staveV == nullptr) { + LOG(fatal) << getName() << " volume " << getTRKStavePattern() << " is not in the geometry"; + } + + // Loop on all layV nodes, count Layer volumes by checking names + TObjArray* nodes = staveV->GetNodes(); + // std::cout << "Printing nodes for layer " << lay << std::endl; + // nodes->Print(); + int nNodes = nodes->GetEntriesFast(); + + for (int j = 0; j < nNodes; j++) { + auto nd = dynamic_cast(nodes->At(j)); /// layer node + const char* name = nd->GetName(); + if (strstr(name, getTRKChipPattern()) != nullptr) { + numberOfHalfStaves++; + } + } + return numberOfHalfStaves; +} + +//__________________________________________________________________________ +void GeometryTGeo::PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int indexRetrieved) const { std::cout << "\nindex = " << index << std::endl; std::cout << "subDetID = " << subDetID << std::endl; @@ -619,7 +681,8 @@ void GeometryTGeo::PrintChipID(int index, int subDetID, int petalcase, int disk, std::cout << "disk = " << disk << std::endl; std::cout << "first chip index = " << getFirstChipIndex(lay, petalcase, subDetID) << std::endl; std::cout << "stave = " << stave << std::endl; - std::cout << "chck index Retrieved = " << indexRetrieved << std::endl; + std::cout << "halfstave = " << halfstave << std::endl; + std::cout << "check index Retrieved = " << indexRetrieved << std::endl; } //__________________________________________________________________________ @@ -641,11 +704,11 @@ void GeometryTGeo::Print(Option_t*) const for (int i = 0; i < mNumberOfPetalsVD; i++) { LOGF(info, "%d", mNumberOfChipsPerPetalVD[i]); } - LOGF(info, "Number of staves per layer MLOT: "); + LOGF(info, "Number of staves and half staves per layer MLOT: "); for (int i = 0; i < mNumberOfLayersMLOT; i++) { std::string mlot = ""; - mlot = (i < 5) ? "ML" : "OT"; - LOGF(info, "Layer: %d, %s, %d staves", i, mlot.c_str(), mNumberOfStaves[i]); + mlot = (i < 4) ? "ML" : "OT"; + LOGF(info, "Layer: %d, %s, %d staves, %d half staves per stave", i, mlot.c_str(), mNumberOfStaves[i], mNumberOfHalfStaves[i]); } LOGF(info, "Total number of chips: %d", getNumberOfChips()); diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h index 31f3da7a00bb4..8ed5737abcb35 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h @@ -31,6 +31,9 @@ namespace trk class Detector : public o2::base::DetImpl { public: + static constexpr Int_t mNumberOfVolumes = 44; /// hardcoded for the current geometry = 8 MLOT layers + 36 volumes in the VD. TODO: automatize or change according to the current geometry + static constexpr Int_t mNumberOfVolumesVD = 36; /// hardcoded for the current geometry = 36 volumes in the VD. TODO: automatize or change according to the current geometry + Detector(bool active); Detector(); ~Detector(); @@ -96,6 +99,18 @@ class Detector : public o2::base::DetImpl void defineSensitiveVolumes(); + protected: + std::vector mSensorID; //! layer identifiers + std::vector mSensorName; //! layer names + + public: + static constexpr Int_t sNumberVDPetalCases = 4; //! Number of VD petals + int getNumberOfLayers() const { return mLayers.size(); } //! Number of TRK layers + int getNumberOfLayersVD() const { return mPetalCases[0].mPetalLayers.size(); } + int getNumberOfDisksVD() const { return mPetalCases[0].mPetalDisks.size(); } + + void Print(FairVolume* vol, int volume, int subDetID, int layer, int stave, int halfstave, int chipID) const; + template friend class o2::base::DetImpl; ClassDefOverride(Detector, 1); diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index 9b8ffc07b2d0e..f5027310fa66d 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -53,6 +53,28 @@ Detector::Detector(bool active) configServices(); } + mSensorName.resize(mNumberOfVolumes); // hardcoded. TODO: change size when a different naming scheme for VD is in place. Ideally could be 4 petals + 8 layers = 12 + int VDvolume = 0; + for (int i = 0; i < 4; i++) { /// VD + for (int j = 0; j < 3; j++) { + mSensorName[VDvolume].Form("%s%d_%s%d_%s%d", GeometryTGeo::getTRKPetalPattern(), i, GeometryTGeo::getTRKPetalLayerPattern(), j, GeometryTGeo::getTRKSensorPattern(), j); + VDvolume++; + } + for (int j = 0; j < 6; j++) { + mSensorName[VDvolume].Form("%s%d_%s%d_%s%d", GeometryTGeo::getTRKPetalPattern(), i, GeometryTGeo::getTRKPetalDiskPattern(), j, GeometryTGeo::getTRKSensorPattern(), j); + VDvolume++; + } + } + + for (int i = 0; i < 8; i++) { /// MLOT + mSensorName[VDvolume].Form("%s%d", GeometryTGeo::getTRKSensorPattern(), i); + VDvolume++; + } + + for (auto vd : mSensorName) { + std::cout << "Volume name: " << vd << std::endl; + } + LOGP(info, "Summary of TRK configuration:"); for (auto& layer : mLayers) { LOGP(info, "Layer: {} name: {} r: {} cm | z: {} cm | thickness: {} cm", layer.getNumber(), layer.getName(), layer.getInnerRadius(), layer.getZ(), layer.getChipThickness()); @@ -241,7 +263,7 @@ void Detector::createGeometry() mPetalCases.clear(); // Add petal cases (the sensitive layers inside the petal cases get constructed here too) auto& trkPars = TRKBaseParam::Instance(); - for (Int_t petalCaseNumber = 0; petalCaseNumber < 4; ++petalCaseNumber) { + for (Int_t petalCaseNumber = 0; petalCaseNumber < sNumberVDPetalCases; ++petalCaseNumber) { mPetalCases.emplace_back(petalCaseNumber, vTRK, trkPars.irisOpen); mServices.excavateFromVacuum(mPetalCases[petalCaseNumber].getFullName()); } @@ -253,6 +275,12 @@ void Detector::InitializeO2Detector() LOG(info) << "Initialize TRK O2Detector"; mGeometryTGeo = GeometryTGeo::Instance(); defineSensitiveVolumes(); + + mSensorID.resize(mNumberOfVolumes); // hardcoded. TODO: change size when a different namingh scheme for VD is in place. Ideally could be 4 petals + 8 layers = 12 + for (int i = 0; i < mNumberOfVolumes; i++) { + mSensorID[i] = gMC ? TVirtualMC::GetMC()->VolId(mSensorName[i]) : 0; // Volume ID from the Geant geometry + LOGP(info, "{}: mSensorID={}", i, mSensorID[i]); + } } void Detector::defineSensitiveVolumes() @@ -264,7 +292,7 @@ void Detector::defineSensitiveVolumes() LOGP(info, "Adding TRK Sensitive Volumes"); // Add petal case sensitive volumes - for (int petalCase = 0; petalCase < 4; ++petalCase) { + for (int petalCase = 0; petalCase < sNumberVDPetalCases; ++petalCase) { // Petal layers for (int petalLayer = 0; petalLayer < mPetalCases[petalCase].mPetalLayers.size(); ++petalLayer) { volumeName = mPetalCases[petalCase].mPetalLayers[petalLayer].getSensorName(); @@ -338,9 +366,28 @@ bool Detector::ProcessHits(FairVolume* vol) return false; } - int lay = vol->getVolumeId(); + int subDetID = -1; + int layer = -1; + int volume = 0; + int stave = -1; int volID = vol->getMCid(); + bool notSens = false; + while ((volume < mNumberOfVolumes) && (notSens = (volID != mSensorID[volume]))) { + ++volume; /// there are 44 volumes, 36 for the VD (1 for each sensing element) and 8 for the MLOT (1 for each layer) + } + + if (notSens) { + return kFALSE; // RS: can this happen? This method must be called for sensors only? + } + + if (volume < mNumberOfVolumesVD) { + subDetID = 0; // VD. For the moment each "chip" is a volume./// TODO: change this logic once the naming scheme is changed + } else { + subDetID = 1; // MLOT + layer = volume - mNumberOfVolumesVD; + } + // Is it needed to keep a track reference when the outer ITS volume is encountered? auto stack = (o2::data::Stack*)fMC->GetStack(); // if (fMC->IsTrackExiting() && (lay == 0 || lay == mLayers.size() - 1)) { @@ -348,7 +395,7 @@ bool Detector::ProcessHits(FairVolume* vol) // Keep the track refs for the innermost and outermost layers only o2::TrackReference tr(*fMC, GetDetId()); tr.setTrackID(stack->GetCurrentTrackNumber()); - tr.setUserId(lay); + tr.setUserId(volume); stack->addTrackReference(tr); } bool startHit = false, stopHit = false; @@ -398,13 +445,17 @@ bool Detector::ProcessHits(FairVolume* vol) TLorentzVector positionStop; fMC->TrackPosition(positionStop); // Retrieve the indices with the volume path - int stave(0), halfstave(0), chipinmodule(0), module; - fMC->CurrentVolOffID(1, chipinmodule); - fMC->CurrentVolOffID(2, module); - fMC->CurrentVolOffID(3, halfstave); - fMC->CurrentVolOffID(4, stave); + int stave(0), halfstave(0); + if (subDetID == 1) { + fMC->CurrentVolOffID(1, halfstave); + fMC->CurrentVolOffID(2, stave); + } /// if VD, for the moment the volume is the "chipID" so no need to retrieve other elments + + int chipID = mGeometryTGeo->getChipIndex(subDetID, volume, layer, stave, halfstave); + + Print(vol, volume, subDetID, layer, stave, halfstave, chipID); - Hit* p = addHit(stack->GetCurrentTrackNumber(), lay, mTrackData.mPositionStart.Vect(), positionStop.Vect(), + Hit* p = addHit(stack->GetCurrentTrackNumber(), chipID, mTrackData.mPositionStart.Vect(), positionStop.Vect(), mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(), mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status); // p->SetTotalEnergy(vmc->Etot()); @@ -424,6 +475,25 @@ o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startP mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus); return &(mHits->back()); } + +void Detector::Print(FairVolume* vol, int volume, int subDetID, int layer, int stave, int halfstave, int chipID) const +{ + int currentVol(0); + LOG(info) << "Current volume name: " << fMC->CurrentVolName() << " and ID " << fMC->CurrentVolID(currentVol); + LOG(info) << "volume: " << volume << "/" << mNumberOfVolumes - 1; + if (subDetID == 1 && mGeometryTGeo->getNumberOfHalfStaves(layer) == 2) { // staggered geometry + LOG(info) << "off volume name 1 " << fMC->CurrentVolOffName(1) << " halfstave: " << halfstave; + LOG(info) << "off volume name 2 " << fMC->CurrentVolOffName(2) << " stave: " << stave; + LOG(info) << "SubDetector ID: " << subDetID << " Layer: " << layer << " staveinLayer: " << stave << " Chip ID: " << chipID; + } else if (subDetID == 1 && mGeometryTGeo->getNumberOfHalfStaves(layer) == 1) { // turbo geometry + LOG(info) << "off volume name 2 " << fMC->CurrentVolOffName(2) << " stave: " << stave; + LOG(info) << "SubDetector ID: " << subDetID << " Layer: " << layer << " staveinLayer: " << stave << " Chip ID: " << chipID; + } else { + LOG(info) << "SubDetector ID: " << subDetID << " Chip ID: " << chipID; + } + LOG(info); +} + } // namespace trk } // namespace o2 From 7bbe96466276bf222374d5067be35d5080ee69b5 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 4 Jul 2025 22:07:03 +0200 Subject: [PATCH 118/315] DPL: rename log stream to check sockets activity --- Framework/Core/src/DataProcessingDevice.cxx | 30 +++++++++++---------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index ba3fc2cd1bedd..a902ed9326e07 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -86,6 +86,8 @@ struct formatter : ostream_format // A log to use for general device logging O2_DECLARE_DYNAMIC_LOG(device); +// A log to use for general device logging +O2_DECLARE_DYNAMIC_LOG(sockets); // Special log to keep track of the lifetime of the parts O2_DECLARE_DYNAMIC_LOG(parts); // Stream which keeps track of the calibration lifetime logic @@ -339,21 +341,21 @@ void on_socket_polled(uv_poll_t* poller, int status, int events) { auto* context = (PollerContext*)poller->data; assert(context); - O2_SIGNPOST_ID_FROM_POINTER(sid, device, poller); + O2_SIGNPOST_ID_FROM_POINTER(sid, sockets, poller); context->state->loopReason |= DeviceState::DATA_SOCKET_POLLED; switch (events) { case UV_READABLE: { - O2_SIGNPOST_EVENT_EMIT(device, sid, "socket_state", "Data pending on socket for channel %{public}s", context->name); + O2_SIGNPOST_EVENT_EMIT(sockets, sid, "socket_state", "Data pending on socket for channel %{public}s", context->name); context->state->loopReason |= DeviceState::DATA_INCOMING; } break; case UV_WRITABLE: { - O2_SIGNPOST_END(device, sid, "socket_state", "Socket connected for channel %{public}s", context->name); + O2_SIGNPOST_END(sockets, sid, "socket_state", "Socket connected for channel %{public}s", context->name); if (context->read) { - O2_SIGNPOST_START(device, sid, "socket_state", "Socket connected for read in context %{public}s", context->name); + O2_SIGNPOST_START(sockets, sid, "socket_state", "Socket connected for read in context %{public}s", context->name); uv_poll_start(poller, UV_READABLE | UV_DISCONNECT | UV_PRIORITIZED, &on_socket_polled); context->state->loopReason |= DeviceState::DATA_CONNECTED; } else { - O2_SIGNPOST_START(device, sid, "socket_state", "Socket connected for write for channel %{public}s", context->name); + O2_SIGNPOST_START(sockets, sid, "socket_state", "Socket connected for write for channel %{public}s", context->name); context->state->loopReason |= DeviceState::DATA_OUTGOING; // If the socket is writable, fairmq will handle the rest, so we can stop polling and // just wait for the disconnect. @@ -362,10 +364,10 @@ void on_socket_polled(uv_poll_t* poller, int status, int events) context->pollerState = PollerContext::PollerState::Connected; } break; case UV_DISCONNECT: { - O2_SIGNPOST_END(device, sid, "socket_state", "Socket disconnected in context %{public}s", context->name); + O2_SIGNPOST_END(sockets, sid, "socket_state", "Socket disconnected in context %{public}s", context->name); } break; case UV_PRIORITIZED: { - O2_SIGNPOST_EVENT_EMIT(device, sid, "socket_state", "Socket prioritized for context %{public}s", context->name); + O2_SIGNPOST_EVENT_EMIT(sockets, sid, "socket_state", "Socket prioritized for context %{public}s", context->name); } break; } // We do nothing, all the logic for now stays in DataProcessingDevice::doRun() @@ -373,7 +375,7 @@ void on_socket_polled(uv_poll_t* poller, int status, int events) void on_out_of_band_polled(uv_poll_t* poller, int status, int events) { - O2_SIGNPOST_ID_FROM_POINTER(sid, device, poller); + O2_SIGNPOST_ID_FROM_POINTER(sid, sockets, poller); auto* context = (PollerContext*)poller->data; context->state->loopReason |= DeviceState::OOB_ACTIVITY; if (status < 0) { @@ -382,27 +384,27 @@ void on_out_of_band_polled(uv_poll_t* poller, int status, int events) } switch (events) { case UV_READABLE: { - O2_SIGNPOST_EVENT_EMIT(device, sid, "socket_state", "Data pending on socket for channel %{public}s", context->name); + O2_SIGNPOST_EVENT_EMIT(sockets, sid, "socket_state", "Data pending on socket for channel %{public}s", context->name); context->state->loopReason |= DeviceState::DATA_INCOMING; assert(context->channelInfo); context->channelInfo->readPolled = true; } break; case UV_WRITABLE: { - O2_SIGNPOST_END(device, sid, "socket_state", "OOB socket connected for channel %{public}s", context->name); + O2_SIGNPOST_END(sockets, sid, "socket_state", "OOB socket connected for channel %{public}s", context->name); if (context->read) { - O2_SIGNPOST_START(device, sid, "socket_state", "OOB socket connected for read in context %{public}s", context->name); + O2_SIGNPOST_START(sockets, sid, "socket_state", "OOB socket connected for read in context %{public}s", context->name); uv_poll_start(poller, UV_READABLE | UV_DISCONNECT | UV_PRIORITIZED, &on_out_of_band_polled); } else { - O2_SIGNPOST_START(device, sid, "socket_state", "OOB socket connected for write for channel %{public}s", context->name); + O2_SIGNPOST_START(sockets, sid, "socket_state", "OOB socket connected for write for channel %{public}s", context->name); context->state->loopReason |= DeviceState::DATA_OUTGOING; } } break; case UV_DISCONNECT: { - O2_SIGNPOST_END(device, sid, "socket_state", "OOB socket disconnected in context %{public}s", context->name); + O2_SIGNPOST_END(sockets, sid, "socket_state", "OOB socket disconnected in context %{public}s", context->name); uv_poll_start(poller, UV_WRITABLE, &on_out_of_band_polled); } break; case UV_PRIORITIZED: { - O2_SIGNPOST_EVENT_EMIT(device, sid, "socket_state", "OOB socket prioritized for context %{public}s", context->name); + O2_SIGNPOST_EVENT_EMIT(sockets, sid, "socket_state", "OOB socket prioritized for context %{public}s", context->name); } break; } // We do nothing, all the logic for now stays in DataProcessingDevice::doRun() From d807214812da4d6d571b34ebcbc5d5fae2dfb1ff Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sat, 5 Jul 2025 11:22:58 +0200 Subject: [PATCH 119/315] DPL: add signposts with log-level detail. --- Framework/Foundation/include/Framework/Signpost.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Framework/Foundation/include/Framework/Signpost.h b/Framework/Foundation/include/Framework/Signpost.h index 781a2242375c8..0ea0a1f5ec75b 100644 --- a/Framework/Foundation/include/Framework/Signpost.h +++ b/Framework/Foundation/include/Framework/Signpost.h @@ -532,6 +532,17 @@ void o2_debug_log_set_stacktrace(_o2_log_t* log, int stacktrace) } \ }) +// Similar to the above, however it will print a normal info message if the signpost is not enabled. +#define O2_SIGNPOST_EVENT_EMIT_DETAIL(log, id, name, format, ...) __extension__({ \ + if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \ + O2_SIGNPOST_EVENT_EMIT_MAC(log, id, name, format, ##__VA_ARGS__); \ + } else if (O2_BUILTIN_UNLIKELY(private_o2_log_##log->stacktrace)) { \ + _o2_signpost_event_emit(private_o2_log_##log, id, name, remove_engineering_type(format).data(), ##__VA_ARGS__); \ + } else { \ + O2_LOG_MACRO_RAW(detail, remove_engineering_type(format).data(), ##__VA_ARGS__); \ + } \ +}) + // Similar to the above, however it will always print a normal error message regardless of the signpost being enabled or not. #define O2_SIGNPOST_EVENT_EMIT_ERROR(log, id, name, format, ...) __extension__({ \ if (O2_BUILTIN_UNLIKELY(O2_SIGNPOST_ENABLED_MAC(log))) { \ From 2a7442d525a673398d5f972b9ca3267f90101c40 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 4 Jul 2025 09:37:31 +0200 Subject: [PATCH 120/315] GPU Standalone CI: With the new build container, we can also build Vulkan and Wayland front/backends --- GPU/GPUTracking/Standalone/cmake/build.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/GPU/GPUTracking/Standalone/cmake/build.sh b/GPU/GPUTracking/Standalone/cmake/build.sh index 1f7f446a336ac..8128603b6e923 100755 --- a/GPU/GPUTracking/Standalone/cmake/build.sh +++ b/GPU/GPUTracking/Standalone/cmake/build.sh @@ -13,8 +13,6 @@ if [[ $GPUCA_STANDALONE_CI == 1 ]]; then set(ENABLE_HIP 1) set(ENABLE_OPENCL 1) set(GPUCA_CONFIG_ONNX 1) - set(GPUCA_BUILD_EVENT_DISPLAY_VULKAN 0) - set(GPUCA_BUILD_EVENT_DISPLAY_WAYLAND 0) set(GPUCA_BUILD_EVENT_DISPLAY_QT 0) set(GPUCA_CONFIG_WERROR 1) EOF From d9d6894dc2b8990a93444ec7a1dbcc9307502f6e Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 6 Jul 2025 19:49:52 +0200 Subject: [PATCH 121/315] TPC QA: Separate normalized attached counts for non-fake and all tracks --- GPU/GPUTracking/qa/GPUQA.cxx | 31 +++++++++++++++++++++---------- GPU/GPUTracking/qa/GPUQA.h | 3 ++- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/GPU/GPUTracking/qa/GPUQA.cxx b/GPU/GPUTracking/qa/GPUQA.cxx index b32ef80c7c87a..6f640578a8804 100644 --- a/GPU/GPUTracking/qa/GPUQA.cxx +++ b/GPU/GPUTracking/qa/GPUQA.cxx @@ -234,6 +234,7 @@ inline float GPUQA::GetMCLabelWeight(const mcLabel_t& label) { return 1; } inline bool GPUQA::mcPresent() { return !mConfig.noMC && mTracking && mClNative && mClNative->clustersMCTruth && mMCInfos.size(); } uint32_t GPUQA::GetMCLabelCol(const mcLabel_t& label) const { return !label.isValid() ? 0 : (mMCEventOffset[label.getSourceID()] + label.getEventID()); } GPUQA::mcLabelI_t GPUQA::GetMCTrackLabel(uint32_t trackId) const { return trackId >= mTrackMCLabels.size() ? MCCompLabel() : mTrackMCLabels[trackId]; } +bool GPUQA::CompareIgnoreFake(const mcLabelI_t& l1, const mcLabelI_t& l2) { return l1.compare(l2) >= 0; } #define TRACK_EXPECTED_REFERENCE_X 78 #else inline GPUQA::mcLabelI_t::mcLabelI_t(const GPUQA::mcLabel_t& l) : track(l.fMCID) {} @@ -263,6 +264,7 @@ inline int32_t GPUQA::AbsLabelID(int32_t id) { return id >= 0 ? id : (-id - 2); inline bool GPUQA::mcPresent() { return !mConfig.noMC && mTracking && GetNMCLabels() && GetNMCTracks(0); } uint32_t GPUQA::GetMCLabelCol(const mcLabel_t& label) const { return 0; } GPUQA::mcLabelI_t GPUQA::GetMCTrackLabel(uint32_t trackId) const { return trackId >= mTrackMCLabels.size() ? mcLabelI_t() : mTrackMCLabels[trackId]; } +bool GPUQA::CompareIgnoreFake(const mcLabelI_t& l1, const mcLabelI_t& l2) { return AbsLabelID(l1) == AbsLabelID(l2); } #define TRACK_EXPECTED_REFERENCE_X TRACK_EXPECTED_REFERENCE_X_DEFAULT #endif template @@ -1660,7 +1662,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx if (mQATasks & taskTrackStatistics) { // Fill track statistic histograms - std::vector> clusterAttachCounts; + std::vector> clusterAttachCounts; if (mcAvail) { clusterAttachCounts.resize(GetNMCLabels(), {0.f, 0.f}); } @@ -1691,17 +1693,23 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx if (cl.state & GPUTPCGMMergedTrackHit::flagReject) { continue; } - bool labelOk = false; - if (mTrackMCLabels[i].isValid() && !mTrackMCLabels[i].isFake()) { + bool labelOk = false, labelOkNonFake = false; + const mcLabelI_t& trkLabel = mTrackMCLabels[i]; + if (trkLabel.isValid() && !trkLabel.isNoise()) { for (int32_t l = 0; l < GetMCLabelNID(cl.num); l++) { - if (GetMCLabel(cl.num, l) == mTrackMCLabels[i]) { + const mcLabelI_t& clLabel = GetMCLabel(cl.num, l); + if (clLabel.isValid() && !clLabel.isNoise() && CompareIgnoreFake(trkLabel, clLabel)) { labelOk = true; + if (!trkLabel.isFake()) { + labelOkNonFake = true; + } break; } } } - clusterAttachCounts[cl.num][0] += (float)labelOk / rowClCount; - clusterAttachCounts[cl.num][1] += 1.0f; + clusterAttachCounts[cl.num][0] += 1.0f; + clusterAttachCounts[cl.num][1] += (float)labelOk / rowClCount; + clusterAttachCounts[cl.num][2] += (float)labelOkNonFake / rowClCount; } } } @@ -1721,13 +1729,15 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx } } if (mcAvail) { - double clusterAttachNormalizedCount = 0; + double clusterAttachNormalizedCount = 0, clusterAttachNormalizedCountNonFake = 0; for (uint32_t i = 0; i < clusterAttachCounts.size(); i++) { - if (clusterAttachCounts[i][1]) { - clusterAttachNormalizedCount += clusterAttachCounts[i][0] / clusterAttachCounts[i][1]; + if (clusterAttachCounts[i][0]) { + clusterAttachNormalizedCount += clusterAttachCounts[i][1] / clusterAttachCounts[i][0]; + clusterAttachNormalizedCountNonFake += clusterAttachCounts[i][2] / clusterAttachCounts[i][0]; } } mClusterCounts.nCorrectlyAttachedNormalized = clusterAttachNormalizedCount; + mClusterCounts.nCorrectlyAttachedNormalizedNonFake = clusterAttachNormalizedCountNonFake; clusterAttachCounts.clear(); } @@ -2901,7 +2911,8 @@ int32_t GPUQA::DoClusterCounts(uint64_t* attachClusterCounts, int32_t mode) PrintClusterCount(mode, num, "Fake Protect (< 40 MeV)", mClusterCounts.nFakeProtect40, mClusterCounts.nBelow40); } if (mcPresent() && (mQATasks & taskTrackStatistics)) { - PrintClusterCount(mode, num, "Correctly Attached non-fake normalized", mClusterCounts.nCorrectlyAttachedNormalized, mClusterCounts.nTotal); + PrintClusterCount(mode, num, "Correctly Attached all-trk normalized", mClusterCounts.nCorrectlyAttachedNormalized, mClusterCounts.nTotal); + PrintClusterCount(mode, num, "Correctly Attached non-fake normalized", mClusterCounts.nCorrectlyAttachedNormalizedNonFake, mClusterCounts.nTotal); } return num; } diff --git a/GPU/GPUTracking/qa/GPUQA.h b/GPU/GPUTracking/qa/GPUQA.h index 9e137f6a6b34c..e587b15f68d80 100644 --- a/GPU/GPUTracking/qa/GPUQA.h +++ b/GPU/GPUTracking/qa/GPUQA.h @@ -226,6 +226,7 @@ class GPUQA float GetMCLabelWeight(uint32_t i, uint32_t j); float GetMCLabelWeight(const mcLabels_t& label, uint32_t j); float GetMCLabelWeight(const mcLabel_t& label); + static bool CompareIgnoreFake(const mcLabelI_t& l1, const mcLabelI_t& l2); const auto& GetClusterLabels(); bool mcPresent(); @@ -290,7 +291,7 @@ class GPUQA TLegend* mLClust[N_CLS_TYPE]; struct counts_t { - int64_t nRejected = 0, nTube = 0, nTube200 = 0, nLoopers = 0, nLowPt = 0, n200MeV = 0, nPhysics = 0, nProt = 0, nUnattached = 0, nTotal = 0, nHighIncl = 0, nAbove400 = 0, nFakeRemove400 = 0, nFullFakeRemove400 = 0, nBelow40 = 0, nFakeProtect40 = 0, nMergedLooper = 0, nCorrectlyAttachedNormalized = 0; + int64_t nRejected = 0, nTube = 0, nTube200 = 0, nLoopers = 0, nLowPt = 0, n200MeV = 0, nPhysics = 0, nProt = 0, nUnattached = 0, nTotal = 0, nHighIncl = 0, nAbove400 = 0, nFakeRemove400 = 0, nFullFakeRemove400 = 0, nBelow40 = 0, nFakeProtect40 = 0, nMergedLooper = 0, nCorrectlyAttachedNormalized = 0, nCorrectlyAttachedNormalizedNonFake = 0; double nUnaccessible = 0; } mClusterCounts; From b05744ad5c006ba9aad2827b6f1ca7115574f3ae Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:53:02 +0200 Subject: [PATCH 122/315] DPL: improve debug information in case of circular dependencies. --- Framework/Core/src/runDataProcessing.cxx | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index f1111da79edd5..d691041a366cf 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -2835,6 +2835,20 @@ std::unique_ptr createRegistry() return std::make_unique(); } +void describeDataProcessorSpec(std::ostream& stream, DataProcessorSpec const& spec) +{ + stream << spec.name; + if (!spec.labels.empty()) { + stream << "("; + bool first = false; + for (auto& label : spec.labels) { + stream << (first ? "" : ",") << label.value; + first = true; + } + stream << ")"; + } +} + // This is a toy executor for the workflow spec // What it needs to do is: // @@ -3059,18 +3073,22 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, edges.emplace_back(i, j); if (both) { std::ostringstream str; + describeDataProcessorSpec(str, physicalWorkflow[i]); + str << " has circular dependency with "; + describeDataProcessorSpec(str, physicalWorkflow[j]); + str << ":\n"; for (auto x : {i, j}) { str << physicalWorkflow[x].name << ":\n"; str << "inputs:\n"; for (auto& input : physicalWorkflow[x].inputs) { - str << "- " << input << "\n"; + str << "- " << input << " " << (int)input.lifetime << "\n"; } str << "outputs:\n"; for (auto& output : physicalWorkflow[x].outputs) { - str << "- " << output << "\n"; + str << "- " << output << " " << (int)output.lifetime << "\n"; } } - throw std::runtime_error(physicalWorkflow[i].name + " has circular dependency with " + physicalWorkflow[j].name + ":\n" + str.str()); + throw std::runtime_error(str.str()); } } } From dd12eda43a3bd84124d7957b0af06a8a26de993c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 8 Jul 2025 12:16:05 +0200 Subject: [PATCH 123/315] DPL: remove duplicate branch. --- Framework/Core/src/TopologyPolicy.cxx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Framework/Core/src/TopologyPolicy.cxx b/Framework/Core/src/TopologyPolicy.cxx index 5458d9d65da4a..5cdef818f3aaf 100644 --- a/Framework/Core/src/TopologyPolicy.cxx +++ b/Framework/Core/src/TopologyPolicy.cxx @@ -87,10 +87,6 @@ bool sporadicDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) if (isAWithSporadicInput && isBWithSporadicInput) { return false; } - // If a has sporadic inputs - if (isAWithSporadicInput && isBWithSporadicInput) { - return false; - } // We have a with sporadic inputs. We sort it later, unless there was already some actual // dependency between A and B. From 1071e77be9a714d13b026278aadcc53c694b25c7 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 8 Jul 2025 12:20:21 +0200 Subject: [PATCH 124/315] DPL: fix missing return true in ToologyPolicy --- Framework/Core/src/TopologyPolicy.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/src/TopologyPolicy.cxx b/Framework/Core/src/TopologyPolicy.cxx index 5cdef818f3aaf..a36f478909d6b 100644 --- a/Framework/Core/src/TopologyPolicy.cxx +++ b/Framework/Core/src/TopologyPolicy.cxx @@ -196,6 +196,7 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) if (sporadic) { O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "%s is expendable. No inverse dependency from %s to %s. However the former has an occasioanl input => true.", a.name.c_str(), b.name.c_str(), a.name.c_str()); + return true; } O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "%s is expendable. No inverse dependency from %s to %s => false.", a.name.c_str(), b.name.c_str(), a.name.c_str()); From 1f08dbe505b1a01fe5d6c290c6f82d5995695fe1 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 8 Jul 2025 17:11:56 +0200 Subject: [PATCH 125/315] [ITS3] Fix Y position of ITS3 clusters and hits (#14483) * Fix Y position of ITS3 clusters and hits * Please consider the following formatting changes * Fix namespace --------- Co-authored-by: ALICE Action Bot --- .../ITS3/base/include/ITS3Base/SpecsV2.h | 3 +- .../ITS3/macros/test/CheckClustersITS3.C | 45 ++++++++++--------- .../ITS3/macros/test/CreateDictionariesITS3.C | 35 ++++++++++++--- .../reconstruction/src/TopologyDictionary.cxx | 2 + 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/Detectors/Upgrades/ITS3/base/include/ITS3Base/SpecsV2.h b/Detectors/Upgrades/ITS3/base/include/ITS3Base/SpecsV2.h index 83db7632e72f4..cb6af1dcfc5b7 100644 --- a/Detectors/Upgrades/ITS3/base/include/ITS3Base/SpecsV2.h +++ b/Detectors/Upgrades/ITS3/base/include/ITS3Base/SpecsV2.h @@ -147,8 +147,7 @@ namespace apts { constexpr double pitchX{15.0 * mu}; constexpr double pitchZ{15.0 * mu}; -constexpr double responseUpperLimit{10 * mu}; -constexpr double responseYShift{responseUpperLimit - silicon::thicknessOut}; +constexpr double responseYShift{15.5 * mu}; } // namespace apts namespace moss { diff --git a/Detectors/Upgrades/ITS3/macros/test/CheckClustersITS3.C b/Detectors/Upgrades/ITS3/macros/test/CheckClustersITS3.C index 006271a1ea7bd..f245a047377ae 100644 --- a/Detectors/Upgrades/ITS3/macros/test/CheckClustersITS3.C +++ b/Detectors/Upgrades/ITS3/macros/test/CheckClustersITS3.C @@ -225,28 +225,33 @@ void CheckClustersITS3(const std::string& clusfile = "o2clus_its.root", locH = gman->getMatrixL2G(chipID) ^ (hit.GetPos()); // inverse conversion from global to local locHsta = gman->getMatrixL2G(chipID) ^ (hit.GetPosStart()); - float x0 = locHsta.X(), dltx = locH.X() - x0; - float y0 = locHsta.Y(), dlty = locH.Y() - y0; - float z0 = locHsta.Z(), dltz = locH.Z() - z0; - auto r = (0.5 * (Segmentation::SensorLayerThickness - Segmentation::SensorLayerThicknessEff) - y0) / dlty; - - if (!isIB) { - locH.SetXYZ(x0 + r * dltx, y0 + r * dlty, z0 + r * dltz); + float x0, y0, z0, dltx, dlty, dltz, r; + if (isIB) { + float xFlat{0.}, yFlat{0.}; + mMosaixSegmentations[layer].curvedToFlat(locC.X(), locC.Y(), xFlat, yFlat); + locC.SetCoordinates(xFlat, yFlat, locC.Z()); + mMosaixSegmentations[layer].curvedToFlat(locH.X(), locH.Y(), xFlat, yFlat); + locH.SetCoordinates(xFlat, yFlat, locH.Z()); + mMosaixSegmentations[layer].curvedToFlat(locHsta.X(), locHsta.Y(), xFlat, yFlat); + locHsta.SetCoordinates(xFlat, yFlat, locHsta.Z()); + x0 = locHsta.X(); + dltx = locH.X() - x0; + y0 = locHsta.Y(); + dlty = locH.Y() - y0; + z0 = locHsta.Z(); + dltz = locH.Z() - z0; + r = (o2::its3::constants::pixelarray::pixels::apts::responseYShift - y0) / dlty; } else { - // compare in local flat coordinates - float xFlatEnd{0.}, yFlatEnd{0.}; - mMosaixSegmentations[layer].curvedToFlat(locH.X(), locH.Y(), xFlatEnd, yFlatEnd); - locH.SetXYZ(xFlatEnd, yFlatEnd, locH.Z()); - float xFlatSta{0.}, yFlatSta{0.}; - mMosaixSegmentations[layer].curvedToFlat(locHsta.X(), locHsta.Y(), xFlatSta, yFlatSta); - locHsta.SetXYZ(xFlatSta, yFlatSta, locHsta.Z()); - - // not really precise, but okish - locH.SetXYZ(0.5f * (locH.X() + locHsta.X()), 0.5f * (locH.Y() + locHsta.Y()), 0.5f * (locH.Z() + locHsta.Z())); - - mMosaixSegmentations[layer].curvedToFlat(locC.X(), locC.Y(), xFlatSta, yFlatSta); - locC.SetXYZ(xFlatSta, yFlatSta, locC.Z()); + x0 = locHsta.X(); + dltx = locH.X() - x0; + y0 = locHsta.Y(); + dlty = locH.Y() - y0; + z0 = locHsta.Z(); + dltz = locH.Z() - z0; + r = (0.5 * (Segmentation::SensorLayerThickness - Segmentation::SensorLayerThicknessEff) - y0) / dlty; } + locH.SetXYZ(x0 + r * dltx, y0 + r * dlty, z0 + r * dltz); + float theta = std::acos(gloC.Z() / gloC.Rho()); float eta = -std::log(std::tan(theta / 2)); diff --git a/Detectors/Upgrades/ITS3/macros/test/CreateDictionariesITS3.C b/Detectors/Upgrades/ITS3/macros/test/CreateDictionariesITS3.C index 459e3c59d1e82..c02b4bc238955 100644 --- a/Detectors/Upgrades/ITS3/macros/test/CreateDictionariesITS3.C +++ b/Detectors/Upgrades/ITS3/macros/test/CreateDictionariesITS3.C @@ -33,6 +33,7 @@ #define ENABLE_UPGRADES #include "DetectorsCommonDataFormats/DetID.h" #include "ITSBase/GeometryTGeo.h" +#include "ITS3Base/SpecsV2.h" #include "ITSMFTBase/SegmentationAlpide.h" #include "ITS3Base/SegmentationMosaix.h" #include "DataFormatsITSMFT/CompCluster.h" @@ -94,7 +95,7 @@ void CreateDictionariesITS3(bool saveDeltas = true, TNtuple* nt = nullptr; if (saveDeltas) { fout = TFile::Open("CreateDictionaries.root", "recreate"); - nt = new TNtuple("nt", "hashes ntuple", "hash:layer:chipID:xhf:zhf:xcf:zcf:dx:dz:outlimDx:outlimDz"); + nt = new TNtuple("nt", "hashes ntuple", "hash:layer:chipID:xhf:zhf:xcf:zcf:dx:dz:outlimDx:outlimDz:clusterSize:eta"); } const o2::steer::DigitizationContext* digContext = nullptr; @@ -270,16 +271,34 @@ void CreateDictionariesITS3(bool saveDeltas = true, auto xyzLocE = gman->getMatrixL2G(chipID) ^ (hit.GetPos()); // inverse conversion from global to local auto xyzLocS = gman->getMatrixL2G(chipID) ^ (hit.GetPosStart()); o2::math_utils::Vector3D xyzLocM; - xyzLocM.SetCoordinates(0.5f * (xyzLocE.X() + xyzLocS.X()), 0.5f * (xyzLocE.Y() + xyzLocS.Y()), 0.5f * (xyzLocE.Z() + xyzLocS.Z())); auto locC = o2::its3::TopologyDictionary::getClusterCoordinates(cluster, pattern, false); int layer = gman->getLayer(chipID); + float x0, y0, z0, dltx, dlty, dltz, r; if (ib) { float xFlat{0.}, yFlat{0.}; - mMosaixSegmentations[layer].curvedToFlat(xyzLocM.X(), xyzLocM.Y(), xFlat, yFlat); - xyzLocM.SetCoordinates(xFlat, yFlat, xyzLocM.Z()); mMosaixSegmentations[layer].curvedToFlat(locC.X(), locC.Y(), xFlat, yFlat); locC.SetCoordinates(xFlat, yFlat, locC.Z()); + mMosaixSegmentations[layer].curvedToFlat(xyzLocE.X(), xyzLocE.Y(), xFlat, yFlat); + xyzLocE.SetCoordinates(xFlat, yFlat, xyzLocE.Z()); + mMosaixSegmentations[layer].curvedToFlat(xyzLocS.X(), xyzLocS.Y(), xFlat, yFlat); + xyzLocS.SetCoordinates(xFlat, yFlat, xyzLocS.Z()); + x0 = xyzLocS.X(); + dltx = xyzLocE.X() - x0; + y0 = xyzLocS.Y(); + dlty = xyzLocE.Y() - y0; + z0 = xyzLocS.Z(); + dltz = xyzLocE.Z() - z0; + r = (o2::its3::constants::pixelarray::pixels::apts::responseYShift - y0) / dlty; + } else { + x0 = xyzLocS.X(); + dltx = xyzLocE.X() - x0; + y0 = xyzLocS.Y(); + dlty = xyzLocE.Y() - y0; + z0 = xyzLocS.Z(); + dltz = xyzLocE.Z() - z0; + r = (0.5 * (Segmentation::SensorLayerThickness - Segmentation::SensorLayerThicknessEff) - y0) / dlty; } + xyzLocM.SetXYZ(x0 + r * dltx, y0 + r * dlty, z0 + r * dltz); auto pitchX = (ib) ? o2::its3::SegmentationMosaix::PitchRow : o2::itsmft::SegmentationAlpide::PitchRow; auto pitchZ = (ib) ? o2::its3::SegmentationMosaix::PitchCol : o2::itsmft::SegmentationAlpide::PitchCol; @@ -302,7 +321,13 @@ void CreateDictionariesITS3(bool saveDeltas = true, } } if (saveDeltas) { - nt->Fill(topology.getHash(), layer, chipID, xyzLocM.X(), xyzLocM.Z(), locC.X(), locC.Z(), dX, dZ, outLimitDx, outLimitDz); + auto vectDiff = xyzLocE - xyzLocS; + auto theta = std::acos(vectDiff.Z() / std::hypot(vectDiff.X(), vectDiff.Y(), vectDiff.Z())); + auto eta = -std::log(std::tan(theta / 2)); + if (ib) { + LOGP(info, "Yhit flat start: {}, end: {}, middle: {}", xyzLocS.Y(), xyzLocE.Y(), xyzLocM.Y()); + } + nt->Fill(topology.getHash(), layer, chipID, xyzLocM.X(), xyzLocM.Z(), locC.X(), locC.Z(), dX, dZ, outLimitDx, outLimitDz, pattern.getNPixels(), eta); } } } else { diff --git a/Detectors/Upgrades/ITS3/reconstruction/src/TopologyDictionary.cxx b/Detectors/Upgrades/ITS3/reconstruction/src/TopologyDictionary.cxx index 61ab051ffb565..0d1deb77b7c2e 100644 --- a/Detectors/Upgrades/ITS3/reconstruction/src/TopologyDictionary.cxx +++ b/Detectors/Upgrades/ITS3/reconstruction/src/TopologyDictionary.cxx @@ -13,6 +13,7 @@ #include "ITS3Reconstruction/TopologyDictionary.h" #include "ITS3Base/SegmentationMosaix.h" +#include "ITS3Base/SpecsV2.h" #include "ITSMFTBase/SegmentationAlpide.h" #include "CommonUtils/StringUtils.h" #include @@ -202,6 +203,7 @@ math_utils::Point3D TopologyDictionary::getClusterCoordinates(const itsmft::C auto layer = its3::constants::detID::getDetID2Layer(cl.getSensorID()); mIBSegmentations[layer].detectorToLocalUnchecked(cl.getRow(), cl.getCol(), locCl); locCl.SetX(locCl.X() + this->getXCOG(cl.getPatternID(), true) * its3::SegmentationMosaix::PitchRow); + locCl.SetY(its3::constants::pixelarray::pixels::apts::responseYShift); locCl.SetZ(locCl.Z() + this->getZCOG(cl.getPatternID(), true) * its3::SegmentationMosaix::PitchCol); float xCurved{0.f}, yCurved{0.f}; mIBSegmentations[layer].flatToCurved(locCl.X(), locCl.Y(), xCurved, yCurved); From 5a776fffb8429a9dcdc86873a70f34171f41ee67 Mon Sep 17 00:00:00 2001 From: Anton Riedel Date: Fri, 4 Jul 2025 14:03:01 +0200 Subject: [PATCH 126/315] Feat: add ratio plots to TrackClusters QA task --- Detectors/TPC/qc/src/TrackClusters.cxx | 12 ++++++++++-- Detectors/TPC/qc/src/Tracks.cxx | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Detectors/TPC/qc/src/TrackClusters.cxx b/Detectors/TPC/qc/src/TrackClusters.cxx index bcc071920e2e9..f57a35c395d58 100644 --- a/Detectors/TPC/qc/src/TrackClusters.cxx +++ b/Detectors/TPC/qc/src/TrackClusters.cxx @@ -35,16 +35,21 @@ struct binning { double max; }; +const binning binsClusters{160, 0., 160.}; const binning binsSharedClusters{160, 0., 160.}; const binning binsFoundClusters{160, 0., 160.}; const binning binsCrossedRows{160, 0., 160.}; +const binning binsRatio{150, 0., 1.5}; //______________________________________________________________________________ void TrackClusters::initializeHistograms() { TH1::AddDirectory(false); + mMapHist["clusters"].emplace_back(std::make_unique("clusters", "Clusters;NClusters;Entries", binsClusters.bins, binsClusters.min, binsClusters.max)); mMapHist["sharedClusters"].emplace_back(std::make_unique("sharedClusters", "sharedClusters;NSharedClusters;Entries", binsSharedClusters.bins, binsSharedClusters.min, binsSharedClusters.max)); - mMapHist["crossedRows"].emplace_back(std::make_unique("crossedRows", "crossedRows;crossedRows;Entries", binsCrossedRows.bins, binsCrossedRows.min, binsCrossedRows.max)); + mMapHist["crossedRows"].emplace_back(std::make_unique("crossedRows", "crossedRows;NCrossedRows;Entries", binsCrossedRows.bins, binsCrossedRows.min, binsCrossedRows.max)); + mMapHist["sharedClustersOverClusters"].emplace_back(std::make_unique("sharedClustersOverClusters", "sharedClustersOverClusters;NSharedClusters/NClusters;Entries", binsRatio.bins, binsRatio.min, binsRatio.max)); + mMapHist["clustersOverCrossedRow"].emplace_back(std::make_unique("clustersOverCrossedRow", "clustersOverCrossedRow;NClusters/NCrossedRows;Entries", binsRatio.bins, binsRatio.min, binsRatio.max)); } //______________________________________________________________________________ @@ -71,7 +76,7 @@ bool TrackClusters::processTrackAndClusters(const std::vector const auto nCls = uint8_t(track.getNClusters()); const auto eta = track.getEta(); - if (nCls < mCutMinNCls || dEdxTot < mCutMindEdxTot || abs(eta) > mCutAbsEta) { + if (nCls < mCutMinNCls || dEdxTot < mCutMindEdxTot || std::fabs(eta) > mCutAbsEta) { continue; } @@ -79,8 +84,11 @@ bool TrackClusters::processTrackAndClusters(const std::vector o2::TrackMethods::countTPCClusters(track, *clusRefs, mBufVec, *clusterIndex, shared, found, crossed); + mMapHist["clusters"][0]->Fill(found); mMapHist["sharedClusters"][0]->Fill(shared); mMapHist["crossedRows"][0]->Fill(crossed); + mMapHist["sharedClustersOverClusters"][0]->Fill(static_cast(shared) / static_cast(found)); + mMapHist["clustersOverCrossedRow"][0]->Fill(static_cast(found) / static_cast(crossed)); } return true; diff --git a/Detectors/TPC/qc/src/Tracks.cxx b/Detectors/TPC/qc/src/Tracks.cxx index 5f29e80c89d2e..dd74502540fb9 100644 --- a/Detectors/TPC/qc/src/Tracks.cxx +++ b/Detectors/TPC/qc/src/Tracks.cxx @@ -38,7 +38,7 @@ struct binning { const std::vector types{"A_Pos", "A_Neg", "C_Pos", "C_Neg"}; const binning binsDCAr{200, -5., 5.}; const binning binsDCArLargerRange{400, -10., 10.}; -const binning binsEta{200, -1., 1.}; +const binning binsEta{300, -1.5, 1.5}; const binning binsClus{120, 60., 180.}; const binning binsClusLargerRange{140, 60., 200.}; //______________________________________________________________________________ From 00b201b7926db4e5f4c22fb4763502170926b105 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 3 Jun 2025 16:22:59 +0200 Subject: [PATCH 127/315] New methods to query AggregatedRunInfo for MC This commit is * slightly changing BasicCCDBManager to be able to - retrieve meta information headers - retrieve the underlying CCDB api for reuse * offering an API to build AggregatedRunInfo with values overwritten from specific MC production settings - This could be used from the analysis side. Analysis needs to identify if AOD is from MC, and use the MC production tag (lpm_prod_tag) in the query. This needs separate upload of MCProdInfo meta-information to CCDB. Relates to https://its.cern.ch/jira/browse/O2-6027 --- CCDB/include/CCDB/BasicCCDBManager.h | 19 ++++-- .../DataFormatsParameters/AggregatedRunInfo.h | 24 ++++++- .../Parameters/src/AggregatedRunInfo.cxx | 66 ++++++++++++++++++- 3 files changed, 99 insertions(+), 10 deletions(-) diff --git a/CCDB/include/CCDB/BasicCCDBManager.h b/CCDB/include/CCDB/BasicCCDBManager.h index b7bf6920a5c7c..9668097c39473 100644 --- a/CCDB/include/CCDB/BasicCCDBManager.h +++ b/CCDB/include/CCDB/BasicCCDBManager.h @@ -108,16 +108,20 @@ class CCDBManagerInstance /// retrieve an object of type T from CCDB as stored under path, timestamp and metaData template - T* getSpecific(std::string const& path, long timestamp = -1, MD metaData = MD()) + T* getSpecific(std::string const& path, long timestamp = -1, MD metaData = MD(), std::map* headers = nullptr) { // TODO: add some error info/handling when failing mMetaData = metaData; - return getForTimeStamp(path, timestamp); + auto obj = getForTimeStamp(path, timestamp); + if (headers) { + *headers = mHeaders; + } + return obj; } /// retrieve an object of type T from CCDB as stored under path and using the timestamp in the middle of the run + metadata. The run number is provided separately to conform to typical analysis use (in which case metadata does not include runNumber) template - T* getSpecificForRun(std::string const& path, int runNumber, MD metaData = MD()); + T* getSpecificForRun(std::string const& path, int runNumber, MD const& metaData = MD()); /// detect online processing modes (i.e. CCDB objects may be updated in the lifetime of the manager) bool isOnline() const { return mDeplMode == o2::framework::DeploymentMode::OnlineAUX || mDeplMode == o2::framework::DeploymentMode::OnlineDDS || mDeplMode == o2::framework::DeploymentMode::OnlineECS; } @@ -129,6 +133,9 @@ class CCDBManagerInstance return getForTimeStamp(path, mTimestamp); } + // gain access to underlaying CCDB layer (to allow for more complex queries without need to reinit another API) + CcdbApi& getCCDBAccessor() { return mCCDBAccessor; } + bool isHostReachable() const { return mCCDBAccessor.isHostReachable(); } /// clear all entries in the cache @@ -230,11 +237,12 @@ class CCDBManagerInstance template T* CCDBManagerInstance::getForTimeStamp(std::string const& path, long timestamp) { + mHeaders.clear(); // we clear at the beginning; to allow to retrieve the header information in a subsequent call T* ptr = nullptr; mQueries++; auto start = std::chrono::system_clock::now(); if (!isCachingEnabled()) { - ptr = mCCDBAccessor.retrieveFromTFileAny(path, mMetaData, timestamp, nullptr, "", + ptr = mCCDBAccessor.retrieveFromTFileAny(path, mMetaData, timestamp, &mHeaders, "", mCreatedNotAfter ? std::to_string(mCreatedNotAfter) : "", mCreatedNotBefore ? std::to_string(mCreatedNotBefore) : ""); if (!ptr) { @@ -305,7 +313,6 @@ T* CCDBManagerInstance::getForTimeStamp(std::string const& path, long timestamp) } else { cached.cacheValidUntil = -1; } - mHeaders.clear(); mMetaData.clear(); if (!ptr) { if (mFatalWhenNull) { @@ -328,7 +335,7 @@ T* CCDBManagerInstance::getForRun(std::string const& path, int runNumber, bool s } template -T* CCDBManagerInstance::getSpecificForRun(std::string const& path, int runNumber, MD metaData) +T* CCDBManagerInstance::getSpecificForRun(std::string const& path, int runNumber, MD const& metaData) { auto [start, stop] = getRunDuration(runNumber, mFatalWhenNull); if (start < 0 || stop < 0) { diff --git a/DataFormats/Parameters/include/DataFormatsParameters/AggregatedRunInfo.h b/DataFormats/Parameters/include/DataFormatsParameters/AggregatedRunInfo.h index e509be97a14fa..bd2cb0c5cbb27 100644 --- a/DataFormats/Parameters/include/DataFormatsParameters/AggregatedRunInfo.h +++ b/DataFormats/Parameters/include/DataFormatsParameters/AggregatedRunInfo.h @@ -32,7 +32,7 @@ struct AggregatedRunInfo { int runNumber = 0; // run number int64_t sor = 0; // best known timestamp for the start of run int64_t eor = 0; // best known timestamp for end of run - int64_t orbitsPerTF = 0; // number of orbits per TF + int64_t orbitsPerTF = 0; // number of orbits per TF (takes precedence over that in GRPECS) int64_t orbitReset = 0; // timestamp of orbit reset before run int64_t orbitSOR = 0; // orbit when run starts after orbit reset int64_t orbitEOR = 0; // orbit when run ends after orbit reset @@ -40,9 +40,27 @@ struct AggregatedRunInfo { // we may have pointers to actual data source objects GRPECS, ... const o2::parameters::GRPECSObject* grpECS = nullptr; // pointer to GRPECSobject (fetched during struct building) - // fills and returns AggregatedRunInfo for a given run number. - static AggregatedRunInfo buildAggregatedRunInfo(o2::ccdb::CCDBManagerInstance& ccdb, int runnumber); static AggregatedRunInfo buildAggregatedRunInfo(int runnumber, long sorMS, long eorMS, long orbitResetMUS, const o2::parameters::GRPECSObject* grpecs, const std::vector* ctfFirstRunOrbitVec); + + // fills and returns AggregatedRunInfo for a given data run number. + static AggregatedRunInfo buildAggregatedRunInfo_DATA(o2::ccdb::CCDBManagerInstance& ccdb, int runnumber); + + // Returns the meta-data (MCProdInfo) associated to production lpm_prod_tag (performed by username) + static std::map getMCProdInfo(o2::ccdb::CCDBManagerInstance& ccdb, int runnumber, + std::string const& lpm_prod_tag, std::string const& username = "aliprod"); + + // function that adjusts with values from MC + void adjust_from_MC(o2::ccdb::CCDBManagerInstance& ccdb, int run_number, std::string const& lpm_prod_tag, std::string const& username = "aliprod"); + + // Fills and returns AggregatedRunInfo for a given run number. + // If a non-empty lpm_prod_tag is given, it will potentially override values with specifics from a + // MC production identified by that tag and username. + static AggregatedRunInfo buildAggregatedRunInfo(o2::ccdb::CCDBManagerInstance& ccdb, + int runnumber, + std::string const& lpm_prod_tag = "", + std::string const& username = "aliprod"); + + ClassDefNV(AggregatedRunInfo, 1); }; } // namespace o2::parameters diff --git a/DataFormats/Parameters/src/AggregatedRunInfo.cxx b/DataFormats/Parameters/src/AggregatedRunInfo.cxx index 22ce362b5d85a..f8f6439eded83 100644 --- a/DataFormats/Parameters/src/AggregatedRunInfo.cxx +++ b/DataFormats/Parameters/src/AggregatedRunInfo.cxx @@ -21,7 +21,7 @@ using namespace o2::parameters; -o2::parameters::AggregatedRunInfo AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::CCDBManagerInstance& ccdb, int runnumber) +o2::parameters::AggregatedRunInfo AggregatedRunInfo::buildAggregatedRunInfo_DATA(o2::ccdb::CCDBManagerInstance& ccdb, int runnumber) { // TODO: could think about caching results per runnumber to // avoid going to CCDB multiple times ---> but should be done inside the CCDBManagerInstance @@ -83,3 +83,67 @@ o2::parameters::AggregatedRunInfo AggregatedRunInfo::buildAggregatedRunInfo(int } return AggregatedRunInfo{runnumber, sorMS, eorMS, nOrbitsPerTF, orbitResetMUS, orbitSOR, orbitEOR, grpecs}; } + +namespace +{ + +// get path where to find MC production info +std::string getFullPath_MC(std::string const& username, std::string const& lpm_prod_tag) +{ + // construct the path where to lookup + std::string path = "/Users/" + std::string(1, username[0]) + "/" + username; + std::string fullpath = path + "/" + "MCProdInfo/" + lpm_prod_tag; + return fullpath; +} + +} // namespace + +std::map AggregatedRunInfo::getMCProdInfo(o2::ccdb::CCDBManagerInstance& ccdb, + int run_number, + std::string const& lpm_prod_tag, + std::string const& username) +{ + std::map metaDataFilter; + metaDataFilter["lpm_prod_tag"] = lpm_prod_tag; + + // fetch the meta information for MC productions + auto header_data = ccdb.getCCDBAccessor().retrieveHeaders(getFullPath_MC(username, lpm_prod_tag), metaDataFilter, run_number); + return header_data; +} + +void AggregatedRunInfo::adjust_from_MC(o2::ccdb::CCDBManagerInstance& ccdb, + int run_number, + std::string const& lpm_prod_tag, + std::string const& username) +{ + auto header_data = AggregatedRunInfo::getMCProdInfo(ccdb, run_number, lpm_prod_tag, username); + + // adjust timeframe length if we find entry for MC production + auto iter = header_data.find("OrbitsPerTF"); + if (iter != header_data.end()) { + auto mc_orbitsPerTF = std::stoi(iter->second); + if (mc_orbitsPerTF != orbitsPerTF) { + LOG(info) << "Adjusting OrbitsPerTF from " << orbitsPerTF << " to " << mc_orbitsPerTF << " based on differing MC info"; + orbitsPerTF = mc_orbitsPerTF; + } + } else { + LOG(warn) << "No OrbitsPerTF information found for MC production " << lpm_prod_tag << " and run number " << run_number; + } +} + +AggregatedRunInfo AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::CCDBManagerInstance& ccdb, int run_number, std::string const& lpm_prod_tag, std::string const& username) +{ + // (a) lookup the AggregatedRunInfo for the data run + // (b) modify/overwrite the info object with MC specific settings if lpm_prod_tag is given + + auto original_info = buildAggregatedRunInfo_DATA(ccdb, run_number); + + if (lpm_prod_tag.size() == 0) { + return original_info; + } + + // in this case we adjust the info from MC + original_info.adjust_from_MC(ccdb, run_number, lpm_prod_tag, username); + + return original_info; +} From 2dbe3ffc0a5b5a0ed954d12ed7c830c9eff7f963 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 8 Jul 2025 14:46:29 +0200 Subject: [PATCH 128/315] Update AggregatedRunInfo.cxx --- DataFormats/Parameters/src/AggregatedRunInfo.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/Parameters/src/AggregatedRunInfo.cxx b/DataFormats/Parameters/src/AggregatedRunInfo.cxx index f8f6439eded83..5495ae73bd6ca 100644 --- a/DataFormats/Parameters/src/AggregatedRunInfo.cxx +++ b/DataFormats/Parameters/src/AggregatedRunInfo.cxx @@ -104,7 +104,7 @@ std::map AggregatedRunInfo::getMCProdInfo(o2::ccdb::CC std::string const& username) { std::map metaDataFilter; - metaDataFilter["lpm_prod_tag"] = lpm_prod_tag; + metaDataFilter["LPMProductionTag"] = lpm_prod_tag; // fetch the meta information for MC productions auto header_data = ccdb.getCCDBAccessor().retrieveHeaders(getFullPath_MC(username, lpm_prod_tag), metaDataFilter, run_number); From 1013f6968d56097dcffb42fd5b2fa8881a48b119 Mon Sep 17 00:00:00 2001 From: shahor02 Date: Wed, 9 Jul 2025 18:15:37 +0200 Subject: [PATCH 129/315] Make O and Ne nuclei known to LHCIF processor (#14494) --- DataFormats/Parameters/src/GRPLHCIFData.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DataFormats/Parameters/src/GRPLHCIFData.cxx b/DataFormats/Parameters/src/GRPLHCIFData.cxx index 8e779ef452191..d39569f79376b 100644 --- a/DataFormats/Parameters/src/GRPLHCIFData.cxx +++ b/DataFormats/Parameters/src/GRPLHCIFData.cxx @@ -28,6 +28,8 @@ using namespace o2::constants::lhc; const std::unordered_map GRPLHCIFData::mZtoA = { {1, 1}, + {8, 16}, + {10, 20}, {82, 208}}; //_______________________________________________ From 9d56f5d35568383e11776f8b532cd36c4c2ac1ea Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Wed, 9 Jul 2025 09:24:46 +0200 Subject: [PATCH 130/315] DPL: fixes for dependency checks of devices with sporadic inputs in TopologyPolicy --- Framework/Core/src/TopologyPolicy.cxx | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Framework/Core/src/TopologyPolicy.cxx b/Framework/Core/src/TopologyPolicy.cxx index a36f478909d6b..23e2a2eac0c5c 100644 --- a/Framework/Core/src/TopologyPolicy.cxx +++ b/Framework/Core/src/TopologyPolicy.cxx @@ -147,7 +147,7 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) if (!isAExpendable && !isBExpendable) { bool sporadic = sporadicDataDeps(a, b); if (sporadic) { - O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. Neither %s nor %s are expendable. However the former has sporadic inputs so we sort it after.", + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "true. Neither %s nor %s are expendable. However the former has sporadic inputs so we sort it after.", a.name.c_str(), b.name.c_str()); return true; } @@ -159,7 +159,7 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) if (isAExpendable && isBExpendable) { bool sporadic = sporadicDataDeps(a, b); if (sporadic) { - O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. Both %s and %s are expendable. However the former has sporadic inputs, so we sort it after.", + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "true. Both %s and %s are expendable. However the former has sporadic inputs, so we sort it after.", a.name.c_str(), b.name.c_str()); return true; } @@ -172,7 +172,7 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) if (isAExpendable && bResilient) { bool sporadic = sporadicDataDeps(a, b); if (sporadic) { - O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. %s is expendable but %s is resilient, however the former also has sporadic inputs, so we sort it after.", + O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "true. %s is expendable but %s is resilient, however the former also has sporadic inputs, so we sort it after.", a.name.c_str(), b.name.c_str()); return true; } @@ -188,8 +188,6 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) a.name.c_str(), hasDependency ? "There is however an inverse dependency" : "No inverse dependency", b.name.c_str(), a.name.c_str(), !hasDependency ? "true" : "false"); if (!hasDependency) { - O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "%s is expendable. There is however an inverse dependecy from %s to %s => true.", - a.name.c_str(), b.name.c_str(), a.name.c_str()); return true; } bool sporadic = sporadicDataDeps(a, b); @@ -203,13 +201,6 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) return false; } // b is expendable and a is not. We are fine with no dependency. - bool sporadic = sporadicDataDeps(a, b); - if (sporadic) { - O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. %s is expendable but %s is not. However the former has an sporadic input => true.", - b.name.c_str(), a.name.c_str()); - return true; - } - // b is expendable and a is not. We are fine with no dependency. O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "false. %s is expendable but %s is not. No need to add an unneeded dependency.", b.name.c_str(), a.name.c_str()); @@ -270,6 +261,12 @@ TopologyPolicy::DependencyChecker TopologyPolicyHelpers::alwaysDependent() hasDependency ? "true" : "false", dependent.name.c_str(), hasDependency ? "has" : "has not", ancestor.name.c_str()); return hasDependency; } + + if (sporadicDataDeps(ancestor, dependent)) { + O2_SIGNPOST_END(topology, sid, "alwaysDependent", "false. Dependent %s is an output proxy and ancestor %s has sporadic inputs", dependent.name.c_str(), ancestor.name.c_str()); + return false; + } + O2_SIGNPOST_END(topology, sid, "alwaysDependent", "true by default. Ancestor %s is not an output proxy.", ancestor.name.c_str()); return true; }; From fe1d400db39904b1ff0d290a50de9d6902409e4d Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Wed, 9 Jul 2025 10:52:29 +0200 Subject: [PATCH 131/315] keeping the previous logic that output-proxies should be last --- Framework/Core/src/TopologyPolicy.cxx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Framework/Core/src/TopologyPolicy.cxx b/Framework/Core/src/TopologyPolicy.cxx index 23e2a2eac0c5c..f5a378e983b08 100644 --- a/Framework/Core/src/TopologyPolicy.cxx +++ b/Framework/Core/src/TopologyPolicy.cxx @@ -142,11 +142,14 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) bool isBExpendable = std::find_if(b.labels.begin(), b.labels.end(), checkExpendable) != b.labels.end(); bool isAExpendable = std::find_if(a.labels.begin(), a.labels.end(), checkExpendable) != a.labels.end(); bool bResilient = std::find_if(b.labels.begin(), b.labels.end(), checkResilient) != b.labels.end(); + const std::regex matcher(".*output-proxy.*"); + std::cmatch m; + bool isBOutputProxy = std::regex_match(b.name.data(), m, matcher); // If none is expendable. We simply return false and sort as usual. if (!isAExpendable && !isBExpendable) { bool sporadic = sporadicDataDeps(a, b); - if (sporadic) { + if (sporadic && !isBOutputProxy) { O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "true. Neither %s nor %s are expendable. However the former has sporadic inputs so we sort it after.", a.name.c_str(), b.name.c_str()); return true; @@ -158,7 +161,7 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) // If both are expendable. We return false and sort as usual. if (isAExpendable && isBExpendable) { bool sporadic = sporadicDataDeps(a, b); - if (sporadic) { + if (sporadic && !isBOutputProxy) { O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "true. Both %s and %s are expendable. However the former has sporadic inputs, so we sort it after.", a.name.c_str(), b.name.c_str()); return true; @@ -171,7 +174,7 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) // If a is expendable but b is resilient, we can keep the same order. if (isAExpendable && bResilient) { bool sporadic = sporadicDataDeps(a, b); - if (sporadic) { + if (sporadic && !isBOutputProxy) { O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "true. %s is expendable but %s is resilient, however the former also has sporadic inputs, so we sort it after.", a.name.c_str(), b.name.c_str()); return true; @@ -191,7 +194,7 @@ bool expendableDataDeps(DataProcessorSpec const& a, DataProcessorSpec const& b) return true; } bool sporadic = sporadicDataDeps(a, b); - if (sporadic) { + if (sporadic && !isBOutputProxy) { O2_SIGNPOST_END(topology, sid, "expendableDataDeps", "%s is expendable. No inverse dependency from %s to %s. However the former has an occasioanl input => true.", a.name.c_str(), b.name.c_str(), a.name.c_str()); return true; @@ -262,11 +265,6 @@ TopologyPolicy::DependencyChecker TopologyPolicyHelpers::alwaysDependent() return hasDependency; } - if (sporadicDataDeps(ancestor, dependent)) { - O2_SIGNPOST_END(topology, sid, "alwaysDependent", "false. Dependent %s is an output proxy and ancestor %s has sporadic inputs", dependent.name.c_str(), ancestor.name.c_str()); - return false; - } - O2_SIGNPOST_END(topology, sid, "alwaysDependent", "true by default. Ancestor %s is not an output proxy.", ancestor.name.c_str()); return true; }; From aee683345c296c798a4d7f6b299d405dd0c78140 Mon Sep 17 00:00:00 2001 From: Jan Fiete Date: Thu, 10 Jul 2025 15:33:37 +0200 Subject: [PATCH 132/315] explicit call to Sumw2 (cosmetic only) --- Framework/Core/src/StepTHn.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Framework/Core/src/StepTHn.cxx b/Framework/Core/src/StepTHn.cxx index ac5da966f6ad4..4b2e81f02e1a2 100644 --- a/Framework/Core/src/StepTHn.cxx +++ b/Framework/Core/src/StepTHn.cxx @@ -327,6 +327,8 @@ void StepTHn::createTarget(Int_t step, Bool_t sparse) } THnBase* target = mTarget[step]; + if (mSumw2[step]) + target->Sumw2(); Int_t* binIdx = new Int_t[mNVars]; Int_t* nBins = new Int_t[mNVars]; From 2f7ce66c03f7ca552f96e6c6605b4afe540d158c Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer Date: Mon, 23 Jun 2025 10:10:26 +0200 Subject: [PATCH 133/315] GPU: Use warp barriers in ZS decoder. --- GPU/Common/GPUCommonAlgorithm.h | 12 ++++++------ GPU/Common/GPUCommonDefAPI.h | 6 +++--- GPU/GPUTracking/TPCClusterFinder/CfUtils.h | 10 ++++------ .../TPCClusterFinder/GPUTPCCFDecodeZS.cxx | 14 ++++++++------ 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/GPU/Common/GPUCommonAlgorithm.h b/GPU/Common/GPUCommonAlgorithm.h index 8cd53ec5e0609..db57e7ec06d4b 100644 --- a/GPU/Common/GPUCommonAlgorithm.h +++ b/GPU/Common/GPUCommonAlgorithm.h @@ -331,28 +331,28 @@ GPUdi() void GPUCommonAlgorithm::swap(T& a, T& b) #pragma OPENCL EXTENSION cl_khr_subgroups : enable template -GPUdi() T work_group_scan_inclusive_add_FUNC(T v) +GPUdi() T warp_scan_inclusive_add_FUNC(T v) { return sub_group_scan_inclusive_add(v); } template <> // FIXME: It seems OpenCL does not support 8 and 16 bit subgroup operations -GPUdi() uint8_t work_group_scan_inclusive_add_FUNC(uint8_t v) +GPUdi() uint8_t warp_scan_inclusive_add_FUNC(uint8_t v) { return sub_group_scan_inclusive_add((uint32_t)v); } template -GPUdi() T work_group_broadcast_FUNC(T v, int32_t i) +GPUdi() T warp_broadcast_FUNC(T v, int32_t i) { return sub_group_broadcast(v, i); } template <> -GPUdi() uint8_t work_group_broadcast_FUNC(uint8_t v, int32_t i) +GPUdi() uint8_t warp_broadcast_FUNC(uint8_t v, int32_t i) { return sub_group_broadcast((uint32_t)v, i); } -#define warp_scan_inclusive_add(v) work_group_scan_inclusive_add_FUNC(v) -#define warp_broadcast(v, i) work_group_broadcast_FUNC(v, i) +#define warp_scan_inclusive_add(v) warp_scan_inclusive_add_FUNC(v) +#define warp_broadcast(v, i) warp_broadcast_FUNC(v, i) #elif (defined(__CUDACC__) || defined(__HIPCC__)) // CUDA and HIP work the same way using cub, need just different header diff --git a/GPU/Common/GPUCommonDefAPI.h b/GPU/Common/GPUCommonDefAPI.h index b029038a3b521..2494cd8dd6fe5 100644 --- a/GPU/Common/GPUCommonDefAPI.h +++ b/GPU/Common/GPUCommonDefAPI.h @@ -96,13 +96,13 @@ #define GPUgeneric() __generic #define GPUconstexprref() GPUconstexpr() #if defined(__OPENCL__) && !defined(__clang__) - #define GPUbarrier() work_group_barrier(mem_fence::global | mem_fence::local); - #define GPUbarrierWarp() + #define GPUbarrier() work_group_barrier(mem_fence::global | mem_fence::local) + #define GPUbarrierWarp() sub_group_barrier(mem_fence::global | mem_fence::local) #define GPUAtomic(type) atomic static_assert(sizeof(atomic) == sizeof(uint32_t), "Invalid size of atomic type"); #else #define GPUbarrier() barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE) - #define GPUbarrierWarp() + #define GPUbarrierWarp() sub_group_barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE) #if defined(__OPENCL__) && defined(GPUCA_OPENCL_CLANG_C11_ATOMICS) namespace o2 { namespace gpu { template struct oclAtomic; diff --git a/GPU/GPUTracking/TPCClusterFinder/CfUtils.h b/GPU/GPUTracking/TPCClusterFinder/CfUtils.h index 96f4893c74af3..f9e3f7a304d84 100644 --- a/GPU/GPUTracking/TPCClusterFinder/CfUtils.h +++ b/GPU/GPUTracking/TPCClusterFinder/CfUtils.h @@ -58,10 +58,9 @@ class CfUtils *sum = __popc(waveMask); return myOffset; #else // CPU / OpenCL fallback - int32_t myOffset = warp_scan_inclusive_add(pred ? 1 : 0); + int32_t myOffset = warp_scan_inclusive_add(!!pred); *sum = warp_broadcast(myOffset, GPUCA_WARP_SIZE - 1); - myOffset--; - return myOffset; + return myOffset - !!pred; #endif } @@ -111,8 +110,7 @@ class CfUtils if (sum != nullptr) { *sum = work_group_broadcast(lpos, BlockSize - 1); } - lpos--; - return lpos; + return lpos - !!pred; #endif } @@ -149,7 +147,7 @@ class CfUtils return sum; #else // CPU / OpenCL fallback - return work_group_reduce_add(pred ? 1 : 0); + return work_group_reduce_add(!!pred); #endif } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx index 312085d2947ab..f7bb64106fe4f 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx @@ -224,7 +224,7 @@ GPUd() size_t GPUTPCCFDecodeZSLink::DecodePage(GPUSharedMemory& smem, processorT return pageDigitOffset; } - int32_t nDecoded = 0; + [[maybe_unused]] int32_t nDecoded = 0; const auto* decHdr = ConsumeHeader(page); ConsumeBytes(page, decHdr->firstZSDataOffset * 16); @@ -275,7 +275,7 @@ GPUd() size_t GPUTPCCFDecodeZSLink::DecodePage(GPUSharedMemory& smem, processorT #endif pageDigitOffset += nAdc; } // for (uint32_t t = 0; t < decHdr->nTimebinHeaders; t++) - (void)nDecoded; + #ifdef GPUCA_CHECK_TPCZS_CORRUPTION if (iThread == 0 && nDecoded != decHdr->nADCsamples) { clusterer.raiseError(GPUErrors::ERROR_TPCZS_INVALID_NADC, clusterer.mISector * 1000 + decHdr->cruID, decHdr->nADCsamples, nDecoded); @@ -566,6 +566,7 @@ GPUd() void GPUTPCCFDecodeZSLinkBase::WriteCharge(processorType& clusterer, floa positions[positionOffset] = pos; charge *= clusterer.GetConstantMem()->calibObjects.tpcPadGain->getGainCorrection(sector, padAndRow.getRow(), padAndRow.getPad()); + chargeMap[pos] = PackedCharge(charge); } @@ -615,6 +616,7 @@ GPUd() uint32_t GPUTPCCFDecodeZSDenseLink::DecodePage(GPUSharedMemory& smem, pro ConsumeBytes(page, decHeader->firstZSDataOffset - sizeof(o2::header::RAWDataHeader)); for (uint16_t i = 0; i < decHeader->nTimebinHeaders; i++) { + [[maybe_unused]] ptrdiff_t sizeLeftInPage = payloadEnd - page; assert(sizeLeftInPage > 0); @@ -728,8 +730,6 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread( uint16_t nSamplesInTB = 0; - GPUbarrier(); - // Read timebin link headers for (uint8_t iLink = 0; iLink < nLinksInTimebin; iLink++) { uint8_t timebinLinkHeaderStart = ConsumeByte(page); @@ -777,6 +777,8 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread( } // for (uint8_t iLink = 0; iLink < nLinksInTimebin; iLink++) + GPUbarrierWarp(); // Ensure all writes to shared memory are finished, before reading it + const uint8_t* adcData = ConsumeBytes(page, (nSamplesInTB * DECODE_BITS + 7) / 8); MAYBE_PAGE_OVERFLOW(page); // TODO: We don't need this check? @@ -784,8 +786,6 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread( return FillWithInvalid(clusterer, iThread, NTHREADS, pageDigitOffset, nSamplesInTB); } - GPUbarrier(); - // Unpack ADC int32_t iLink = 0; for (uint16_t sample = iThread; sample < nSamplesInTB; sample += NTHREADS) { @@ -819,6 +819,8 @@ GPUd() uint16_t GPUTPCCFDecodeZSDenseLink::DecodeTBMultiThread( } // for (uint16_t sample = iThread; sample < nSamplesInTB; sample += NTHREADS) + GPUbarrierWarp(); // Ensure all reads to shared memory are finished, before decoding next header into shmem + assert(PayloadExtendsToNextPage || adcData <= page); assert(PayloadExtendsToNextPage || page <= payloadEnd); From 7d9bcd8d3571395cfaa89f1d867cf488d53aa8b6 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 26 Jun 2025 10:20:36 +0200 Subject: [PATCH 134/315] ITS: fix seeding vertex labels Signed-off-by: Felix Schlepper --- Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index 11304e17d234a..e6c7884588f18 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -482,7 +482,6 @@ void VertexerTraits::computeVertices(const int iteration) } } for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - vertices.clear(); std::sort(mTimeFrame->getTrackletClusters(rofId).begin(), mTimeFrame->getTrackletClusters(rofId).end(), [](ClusterLines& cluster1, ClusterLines& cluster2) { return cluster1.getSize() > cluster2.getSize(); }); // ensure clusters are ordered by contributors, so that we can cat after the first. #ifdef VTX_DEBUG @@ -541,6 +540,8 @@ void VertexerTraits::computeVertices(const int iteration) if (vertices.empty() && !(iteration && (int)mTimeFrame->getPrimaryVertices(rofId).size() > mVrtParams[iteration].vertPerRofThreshold)) { mTimeFrame->getNoVertexROF()++; } + vertices.clear(); + polls.clear(); } #ifdef VTX_DEBUG TFile* dbg_file = TFile::Open("artefacts_tf.root", "update"); From 1232a9503c49119d61b6501df888311c127932ad Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 18 Jun 2025 13:41:06 +0200 Subject: [PATCH 135/315] ITS: Vertexer return early and only one arena Signed-off-by: Felix Schlepper --- .../ITS/tracking/src/VertexerTraits.cxx | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index e6c7884588f18..a7487200886e6 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -214,13 +214,16 @@ void VertexerTraits::computeTracklets(const int iteration) mTimeFrame->getNTrackletsROF(pivotRofId, 1) = std::accumulate(mTimeFrame->getNTrackletsCluster(pivotRofId, 1).begin(), mTimeFrame->getNTrackletsCluster(pivotRofId, 1).end(), 0); } }); - }); - mTimeFrame->computeTrackletsPerROFScans(); - mTimeFrame->getTracklets()[0].resize(mTimeFrame->getTotalTrackletsTF(0)); - mTimeFrame->getTracklets()[1].resize(mTimeFrame->getTotalTrackletsTF(1)); + mTimeFrame->computeTrackletsPerROFScans(); + if (auto tot0 = mTimeFrame->getTotalTrackletsTF(0), tot1 = mTimeFrame->getTotalTrackletsTF(1); + tot0 == 0 || tot1 == 0) { + return; + } else { + mTimeFrame->getTracklets()[0].resize(tot0); + mTimeFrame->getTracklets()[1].resize(tot1); + } - mTaskArena->execute([&] { tbb::parallel_for( tbb::blocked_range(0, (short)mTimeFrame->getNrof()), [&](const tbb::blocked_range& Rofs) { @@ -266,18 +269,20 @@ void VertexerTraits::computeTracklets(const int iteration) if (mTimeFrame->hasMCinformation()) { for (const auto& trk : mTimeFrame->getTracklets()[0]) { o2::MCCompLabel label; - int sortedId0{mTimeFrame->getSortedIndex(trk.rof[0], 0, trk.firstClusterIndex)}; - int sortedId1{mTimeFrame->getSortedIndex(trk.rof[1], 1, trk.secondClusterIndex)}; - for (const auto& lab0 : mTimeFrame->getClusterLabels(0, mTimeFrame->getClusters()[0][sortedId0].clusterId)) { - for (const auto& lab1 : mTimeFrame->getClusterLabels(1, mTimeFrame->getClusters()[1][sortedId1].clusterId)) { - if (lab0 == lab1 && lab0.isValid()) { - label = lab0; + if (!trk.isEmpty()) { + int sortedId0{mTimeFrame->getSortedIndex(trk.rof[0], 0, trk.firstClusterIndex)}; + int sortedId1{mTimeFrame->getSortedIndex(trk.rof[1], 1, trk.secondClusterIndex)}; + for (const auto& lab0 : mTimeFrame->getClusterLabels(0, mTimeFrame->getClusters()[0][sortedId0].clusterId)) { + for (const auto& lab1 : mTimeFrame->getClusterLabels(1, mTimeFrame->getClusters()[1][sortedId1].clusterId)) { + if (lab0 == lab1 && lab0.isValid()) { + label = lab0; + break; + } + } + if (label.isValid()) { break; } } - if (label.isValid()) { - break; - } } mTimeFrame->getTrackletsLabel(0).emplace_back(label); } From 6522275f8f8bf10c189194f76059890f1db246b1 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sun, 8 Jun 2025 13:38:08 +0200 Subject: [PATCH 136/315] ITS: unify configuration of algorithms Signed-off-by: Felix Schlepper --- .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 4 +- .../include/ITStracking/Configuration.h | 51 ++-- .../tracking/include/ITStracking/Tracker.h | 2 - .../include/ITStracking/TrackerTraits.h | 2 - .../include/ITStracking/TrackingInterface.h | 11 +- .../tracking/include/ITStracking/Vertexer.h | 1 - .../ITSMFT/ITS/tracking/src/Configuration.cxx | 274 ++++++++++++++++-- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 66 ----- .../ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 10 +- .../ITS/tracking/src/TrackingInterface.cxx | 131 +-------- .../ITSMFT/ITS/tracking/src/Vertexer.cxx | 30 -- .../include/ITSWorkflow/CookedTrackerSpec.h | 6 +- .../include/ITSWorkflow/RecoWorkflow.h | 4 +- .../include/ITSWorkflow/TrackerSpec.h | 5 +- .../ITS/workflow/src/CookedTrackerSpec.cxx | 11 +- .../ITSMFT/ITS/workflow/src/RecoWorkflow.cxx | 4 +- .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 7 +- .../ITS/workflow/src/its-reco-workflow.cxx | 8 +- .../reconstruction/src/TrackingInterface.cxx | 1 - .../include/ITS3Workflow/RecoWorkflow.h | 4 +- .../include/ITS3Workflow/TrackerSpec.h | 4 +- .../ITS3/workflow/src/RecoWorkflow.cxx | 4 +- .../ITS3/workflow/src/TrackerSpec.cxx | 9 +- .../ITS3/workflow/src/its3-reco-workflow.cxx | 3 +- 24 files changed, 322 insertions(+), 330 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index d804d0062764f..1b1c4af682dc5 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -246,7 +246,7 @@ void TrackerTraitsGPU::findRoads(const int iteration) this->mTrkParams[0].MaxChi2ClusterAttachment, this->mTrkParams[0].MaxChi2NDF, mTimeFrameGPU->getDevicePropagator(), - this->mCorrType, + this->mTrkParams[0].CorrType, conf.nBlocks, conf.nThreads); } @@ -268,7 +268,7 @@ void TrackerTraitsGPU::findRoads(const int iteration) this->mTrkParams[0].MaxChi2ClusterAttachment, // float maxChi2ClusterAttachment this->mTrkParams[0].MaxChi2NDF, // float maxChi2NDF mTimeFrameGPU->getDevicePropagator(), // const o2::base::Propagator* propagator - this->mCorrType, // o2::base::PropagatorImpl::MatCorrType + this->mTrkParams[0].CorrType, // o2::base::PropagatorImpl::MatCorrType conf.nBlocks, conf.nThreads); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 2a40b817a7005..34b2d11fc16e6 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -26,36 +26,8 @@ #include "DetectorsBase/Propagator.h" #include "ITStracking/Constants.h" -namespace o2 +namespace o2::its { -namespace its -{ - -enum class TrackingMode { - Sync, - Async, - Cosmics, - Unset, // Special value to leave a default in case we want to override via Configurable Params -}; - -std::string asString(TrackingMode mode); -std::ostream& operator<<(std::ostream& os, TrackingMode v); - -template -class Configuration : public Param -{ - public: - static Configuration& getInstance() - { - static Configuration instance; - return instance; - } - Configuration(const Configuration&) = delete; - const Configuration& operator=(const Configuration&) = delete; - - private: - Configuration() = default; -}; struct TrackingParameters { int CellMinimumLevel() const noexcept { return MinTrackLength - constants::ClustersPerCell + 1; } @@ -166,7 +138,24 @@ struct TimeFrameGPUParameters { int maxGPUMemoryGB = -1; }; -} // namespace its -} // namespace o2 +namespace TrackingMode +{ +enum Type : int8_t { + Unset = -1, // Special value to leave a default in case we want to override via Configurable Params + Sync = 0, + Async = 1, + Cosmics = 2, + Off = 3, +}; + +Type fromString(std::string_view str); +std::string toString(Type mode); + +std::vector getTrackingParameters(Type mode); +std::vector getVertexingParameters(Type mode); + +}; // namespace TrackingMode + +} // namespace o2::its #endif /* TRACKINGITSU_INCLUDE_CONFIGURATION_H_ */ diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index 5ba9b5039f808..78c290374a67d 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -71,9 +71,7 @@ class Tracker void setParameters(const std::vector& p) { mTrkParams = p; } void setMemoryPool(std::shared_ptr& pool) { mMemoryPool = pool; } std::vector& getParameters() { return mTrkParams; } - void getGlobalConfiguration(); void setBz(float bz) { mTraits->setBz(bz); } - void setCorrType(const o2::base::PropagatorImpl::MatCorrType type) { mTraits->setCorrType(type); } bool isMatLUT() const { return mTraits->isMatLUT(); } void setNThreads(int n, std::shared_ptr& arena) { mTraits->setNThreads(n, arena); } void printSummary() const; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h index 7ba67a01fce13..cba536324edeb 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h @@ -65,7 +65,6 @@ class TrackerTraits virtual void setBz(float bz); float getBz() const { return mBz; } - void setCorrType(const o2::base::PropagatorImpl::MatCorrType type) { mCorrType = type; } bool isMatLUT() const; virtual const char* getName() const noexcept { return "CPU"; } virtual bool isGPU() const noexcept { return false; } @@ -99,7 +98,6 @@ class TrackerTraits std::shared_ptr mTaskArena; protected: - o2::base::PropagatorImpl::MatCorrType mCorrType = o2::base::PropagatorImpl::MatCorrType::USEMatCorrNONE; o2::gpu::GPUChainITS* mChain = nullptr; TimeFrame* mTimeFrame; std::vector mTrkParams; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h index 64fd4f8156cca..bf9cb79169566 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h @@ -68,13 +68,7 @@ class ITSTrackingInterface // Custom void setTraitsFromProvider(VertexerTraits*, TrackerTraits7*, TimeFrame7*); - void setTrackingMode(TrackingMode mode = TrackingMode::Unset) - { - if (mode == TrackingMode::Unset) { - LOGP(fatal, "ITS Tracking mode Unset is meant to be a default. Specify the mode"); - } - mMode = mode; - } + void setTrackingMode(TrackingMode::Type mode = TrackingMode::Unset) { mMode = mode; } auto getTracker() const { return mTracker.get(); } auto getVertexer() const { return mVertexer.get(); } @@ -86,14 +80,13 @@ class ITSTrackingInterface gsl::span clusters, gsl::span::iterator& pattIt, const dataformats::MCTruthContainer* mcLabels); - void getConfiguration(framework::ProcessingContext& pc); private: bool mIsMC = false; bool mRunVertexer = true; bool mCosmicsProcessing = false; int mUseTriggers = 0; - TrackingMode mMode = TrackingMode::Unset; + TrackingMode::Type mMode = TrackingMode::Unset; bool mOverrideBeamEstimation = false; const o2::itsmft::TopologyDictionary* mDict = nullptr; std::unique_ptr mTracker = nullptr; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h index 98bcb95ef65df..285e4d7e9547d 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h @@ -60,7 +60,6 @@ class Vertexer auto& getVertParameters() const { return mTraits->getVertexingParameters(); } void setParameters(const std::vector& vertParams) { mVertParams = vertParams; } const auto& getParameters() const noexcept { return mVertParams; } - void getGlobalConfiguration(); void setMemoryPool(std::shared_ptr& pool) { mMemoryPool = pool; } std::vector exportVertices(); diff --git a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx index 9e631ad6afb7f..56aa52b25940e 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx @@ -9,34 +9,18 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include #include -#include "ITStracking/Constants.h" +#include +#include +#include +#include "Framework/Logger.h" +#include "ITStracking/Constants.h" #include "ITStracking/Configuration.h" +#include "ITStracking/TrackingConfigParam.h" -namespace o2::its -{ - -std::string asString(TrackingMode mode) -{ - switch (mode) { - case TrackingMode::Sync: - return "sync"; - case TrackingMode::Async: - return "async"; - case TrackingMode::Cosmics: - return "cosmics"; - case TrackingMode::Unset: - return "unset"; - } - return "unknown"; -} - -std::ostream& operator<<(std::ostream& os, TrackingMode v) -{ - os << asString(v); - return os; -} +using namespace o2::its; std::string TrackingParameters::asString() const { @@ -72,4 +56,244 @@ std::string VertexingParameters::asString() const return str; } -} // namespace o2::its +namespace +{ +constexpr bool iequals(std::string_view a, std::string_view b) +{ + return std::equal(a.begin(), a.end(), b.begin(), b.end(), + [](char x, char y) { return std::tolower(x) == std::tolower(y); }); +} +} // namespace + +TrackingMode::Type TrackingMode::fromString(std::string_view str) +{ + constexpr std::array smodes = { + std::pair{"sync", Sync}, + std::pair{"async", Async}, + std::pair{"cosmics", Cosmics}, + std::pair{"unset", Unset}, + std::pair{"off", Off}}; + + auto it = std::find_if(smodes.begin(), smodes.end(), [&str](const auto& pair) { + return iequals(str, pair.first); + }); + if (it == smodes.end()) { + LOGP(fatal, "Unrecognized tracking mode '{}'", str); + } + return it->second; +} + +std::string TrackingMode::toString(TrackingMode::Type mode) +{ + if (mode == TrackingMode::Sync) { + return "sync"; + } else if (mode == TrackingMode::Async) { + return "async"; + } else if (mode == TrackingMode::Cosmics) { + return "cosmics"; + } else if (mode == TrackingMode::Unset) { + return "unset"; + } else if (mode == TrackingMode::Off) { + return "off"; + } + LOGP(fatal, "Unrecognized tracking mode '{}'", (int)mode); + return ""; // not reachable +} + +std::vector TrackingMode::getTrackingParameters(TrackingMode::Type mode) +{ + const auto& tc = o2::its::TrackerParamConfig::Instance(); + std::vector trackParams; + + if (mode == TrackingMode::Async) { + trackParams.resize(tc.doUPCIteration ? 4 : 3); + trackParams[1].TrackletMinPt = 0.2f; + trackParams[1].CellDeltaTanLambdaSigma *= 2.; + trackParams[2].TrackletMinPt = 0.1f; + trackParams[2].CellDeltaTanLambdaSigma *= 4.; + + trackParams[0].MinPt[0] = 1.f / 12; // 7cl + trackParams[1].MinPt[0] = 1.f / 12; // 7cl + + trackParams[2].MinTrackLength = 4; + trackParams[2].MinPt[0] = 1.f / 12; // 7cl + trackParams[2].MinPt[1] = 1.f / 5; // 6cl + trackParams[2].MinPt[2] = 1.f / 1; // 5cl + trackParams[2].MinPt[3] = 1.f / 6; // 4cl + + trackParams[2].StartLayerMask = (1 << 6) + (1 << 3); + if (tc.doUPCIteration) { + trackParams[3].MinTrackLength = 4; + trackParams[3].TrackletMinPt = 0.1f; + trackParams[3].CellDeltaTanLambdaSigma *= 4.; + trackParams[3].DeltaROF = 0; // UPC specific setting + } + for (size_t ip = 0; ip < trackParams.size(); ip++) { + auto& param = trackParams[ip]; + param.ZBins = 64; + param.PhiBins = 32; + param.CellsPerClusterLimit = 1.e3f; + param.TrackletsPerClusterLimit = 1.e3f; + // check if something was overridden via configurable params + if (ip < tc.MaxIter) { + if (tc.startLayerMask[ip] > 0) { + trackParams[2].StartLayerMask = tc.startLayerMask[ip]; + } + if (tc.minTrackLgtIter[ip] > 0) { + param.MinTrackLength = tc.minTrackLgtIter[ip]; + } + for (int ilg = tc.MaxTrackLength; ilg >= tc.MinTrackLength; ilg--) { + int lslot0 = (tc.MaxTrackLength - ilg), lslot = lslot0 + ip * (tc.MaxTrackLength - tc.MinTrackLength + 1); + if (tc.minPtIterLgt[lslot] > 0.) { + param.MinPt[lslot0] = tc.minPtIterLgt[lslot]; + } + } + } + } + } else if (mode == TrackingMode::Sync) { + trackParams.resize(1); + trackParams[0].ZBins = 64; + trackParams[0].PhiBins = 32; + trackParams[0].MinTrackLength = 4; + } else if (mode == TrackingMode::Cosmics) { + trackParams.resize(1); + trackParams[0].MinTrackLength = 4; + trackParams[0].CellDeltaTanLambdaSigma *= 10; + trackParams[0].PhiBins = 4; + trackParams[0].ZBins = 16; + trackParams[0].PVres = 1.e5f; + trackParams[0].MaxChi2ClusterAttachment = 60.; + trackParams[0].MaxChi2NDF = 40.; + trackParams[0].TrackletsPerClusterLimit = 100.; + trackParams[0].CellsPerClusterLimit = 100.; + } else { + LOGP(fatal, "Unsupported ITS tracking mode {} ", toString(mode)); + } + + float bFactor = std::abs(o2::base::Propagator::Instance()->getNominalBz()) / 5.0066791; + float bFactorTracklets = bFactor < 0.01 ? 1. : bFactor; // for tracklets only + int nROFsPerIterations = tc.nROFsPerIterations > 0 ? tc.nROFsPerIterations : -1; + + if (tc.nOrbitsPerIterations > 0) { + /// code to be used when the number of ROFs per orbit is known, this gets priority over the number of ROFs per iteration + } + + // global parameters set for every iteration + for (auto& p : trackParams) { + // adjust pT settings to actual mag. field + p.TrackletMinPt *= bFactorTracklets; + for (int ilg = tc.MaxTrackLength; ilg >= tc.MinTrackLength; ilg--) { + int lslot = tc.MaxTrackLength - ilg; + p.MinPt[lslot] *= bFactor; + } + + p.PrintMemory = tc.printMemory; + p.MaxMemory = tc.maxMemory; + p.DropTFUponFailure = tc.dropTFUponFailure; + p.SaveTimeBenchmarks = tc.saveTimeBenchmarks; + p.FataliseUponFailure = tc.fataliseUponFailure; + + if (tc.useMatCorrTGeo) { + p.CorrType = o2::base::PropagatorImpl::MatCorrType::USEMatCorrTGeo; + } else if (tc.useFastMaterial) { + p.CorrType = o2::base::PropagatorImpl::MatCorrType::USEMatCorrNONE; + } else { + p.CorrType = o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT; + } + + if (p.NLayers == 7) { + for (int i{0}; i < 7; ++i) { + p.SystErrorY2[i] = tc.sysErrY2[i] > 0 ? tc.sysErrY2[i] : p.SystErrorY2[i]; + p.SystErrorZ2[i] = tc.sysErrZ2[i] > 0 ? tc.sysErrZ2[i] : p.SystErrorZ2[i]; + } + } + p.DeltaROF = tc.deltaRof; + p.DoUPCIteration = tc.doUPCIteration; + p.MaxChi2ClusterAttachment = tc.maxChi2ClusterAttachment > 0 ? tc.maxChi2ClusterAttachment : p.MaxChi2ClusterAttachment; + p.MaxChi2NDF = tc.maxChi2NDF > 0 ? tc.maxChi2NDF : p.MaxChi2NDF; + p.PhiBins = tc.LUTbinsPhi > 0 ? tc.LUTbinsPhi : p.PhiBins; + p.ZBins = tc.LUTbinsZ > 0 ? tc.LUTbinsZ : p.ZBins; + p.PVres = tc.pvRes > 0 ? tc.pvRes : p.PVres; + p.NSigmaCut *= tc.nSigmaCut > 0 ? tc.nSigmaCut : 1.f; + p.CellDeltaTanLambdaSigma *= tc.deltaTanLres > 0 ? tc.deltaTanLres : 1.f; + p.TrackletMinPt *= tc.minPt > 0 ? tc.minPt : 1.f; + p.nROFsPerIterations = nROFsPerIterations; + p.PerPrimaryVertexProcessing = tc.perPrimaryVertexProcessing; + for (int iD{0}; iD < 3; ++iD) { + p.Diamond[iD] = tc.diamondPos[iD]; + } + p.UseDiamond = tc.useDiamond; + if (tc.useTrackFollower > 0) { + p.UseTrackFollower = true; + // Bit 0: Allow for mixing of top&bot extension --> implies Bits 1&2 set + // Bit 1: Allow for top extension + // Bit 2: Allow for bot extension + p.UseTrackFollowerMix = ((tc.useTrackFollower & (1 << 0)) != 0); + p.UseTrackFollowerTop = ((tc.useTrackFollower & (1 << 1)) != 0); + p.UseTrackFollowerBot = ((tc.useTrackFollower & (1 << 2)) != 0); + p.TrackFollowerNSigmaCutZ = tc.trackFollowerNSigmaZ; + p.TrackFollowerNSigmaCutPhi = tc.trackFollowerNSigmaPhi; + } + if (tc.cellsPerClusterLimit >= 0) { + p.CellsPerClusterLimit = tc.cellsPerClusterLimit; + } + if (tc.trackletsPerClusterLimit >= 0) { + p.TrackletsPerClusterLimit = tc.trackletsPerClusterLimit; + } + if (tc.findShortTracks >= 0) { + p.FindShortTracks = tc.findShortTracks; + } + } + + return trackParams; +} + +std::vector TrackingMode::getVertexingParameters(TrackingMode::Type mode) +{ + const auto& vc = o2::its::VertexerParamConfig::Instance(); + std::vector vertParams; + if (mode == TrackingMode::Async) { + vertParams.resize(2); // The number of actual iterations will be set as a configKeyVal to allow for pp/PbPb choice + vertParams[1].phiCut = 0.015f; + vertParams[1].tanLambdaCut = 0.015f; + vertParams[1].vertPerRofThreshold = 0; + vertParams[1].deltaRof = 0; + } else if (mode == TrackingMode::Sync) { + vertParams.resize(1); + } else if (mode == TrackingMode::Cosmics) { + vertParams.resize(1); + } else { + LOGP(fatal, "Unsupported ITS vertexing mode {} ", toString(mode)); + } + + // global parameters set for every iteration + for (auto& p : vertParams) { + p.SaveTimeBenchmarks = vc.saveTimeBenchmarks; + p.PrintMemory = vc.printMemory; + p.MaxMemory = vc.maxMemory; + p.DropTFUponFailure = vc.dropTFUponFailure; + p.nIterations = vc.nIterations; + p.deltaRof = vc.deltaRof; + p.allowSingleContribClusters = vc.allowSingleContribClusters; + p.trackletSigma = vc.trackletSigma; + p.maxZPositionAllowed = vc.maxZPositionAllowed; + p.clusterContributorsCut = vc.clusterContributorsCut; + p.phiSpan = vc.phiSpan; + p.nThreads = vc.nThreads; + p.ZBins = vc.ZBins; + p.PhiBins = vc.PhiBins; + } + // set for now outside to not disturb status quo + vertParams[0].vertNsigmaCut = vc.vertNsigmaCut; + vertParams[0].vertRadiusSigma = vc.vertRadiusSigma; + vertParams[0].maxTrackletsPerCluster = vc.maxTrackletsPerCluster; + vertParams[0].lowMultBeamDistCut = vc.lowMultBeamDistCut; + vertParams[0].zCut = vc.zCut; + vertParams[0].phiCut = vc.phiCut; + vertParams[0].pairCut = vc.pairCut; + vertParams[0].clusterCut = vc.clusterCut; + vertParams[0].histPairCut = vc.histPairCut; + vertParams[0].tanLambdaCut = vc.tanLambdaCut; + + return vertParams; +} diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 5c3a43540f833..e0bd94ed223c0 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -335,72 +335,6 @@ void Tracker::rectifyClusterIndices() } } -void Tracker::getGlobalConfiguration() -{ - const auto& tc = o2::its::TrackerParamConfig::Instance(); - if (tc.useMatCorrTGeo) { - mTraits->setCorrType(o2::base::PropagatorImpl::MatCorrType::USEMatCorrTGeo); - } else if (tc.useFastMaterial) { - mTraits->setCorrType(o2::base::PropagatorImpl::MatCorrType::USEMatCorrNONE); - } else { - mTraits->setCorrType(o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT); - } - int nROFsPerIterations = tc.nROFsPerIterations > 0 ? tc.nROFsPerIterations : -1; - if (tc.nOrbitsPerIterations > 0) { - /// code to be used when the number of ROFs per orbit is known, this gets priority over the number of ROFs per iteration - } - for (auto& params : mTrkParams) { - if (params.NLayers == 7) { - for (int i{0}; i < 7; ++i) { - params.SystErrorY2[i] = tc.sysErrY2[i] > 0 ? tc.sysErrY2[i] : params.SystErrorY2[i]; - params.SystErrorZ2[i] = tc.sysErrZ2[i] > 0 ? tc.sysErrZ2[i] : params.SystErrorZ2[i]; - } - } - params.DeltaROF = tc.deltaRof; - params.DoUPCIteration = tc.doUPCIteration; - params.MaxChi2ClusterAttachment = tc.maxChi2ClusterAttachment > 0 ? tc.maxChi2ClusterAttachment : params.MaxChi2ClusterAttachment; - params.MaxChi2NDF = tc.maxChi2NDF > 0 ? tc.maxChi2NDF : params.MaxChi2NDF; - params.PhiBins = tc.LUTbinsPhi > 0 ? tc.LUTbinsPhi : params.PhiBins; - params.ZBins = tc.LUTbinsZ > 0 ? tc.LUTbinsZ : params.ZBins; - params.PVres = tc.pvRes > 0 ? tc.pvRes : params.PVres; - params.NSigmaCut *= tc.nSigmaCut > 0 ? tc.nSigmaCut : 1.f; - params.CellDeltaTanLambdaSigma *= tc.deltaTanLres > 0 ? tc.deltaTanLres : 1.f; - params.TrackletMinPt *= tc.minPt > 0 ? tc.minPt : 1.f; - params.nROFsPerIterations = nROFsPerIterations; - params.PerPrimaryVertexProcessing = tc.perPrimaryVertexProcessing; - params.SaveTimeBenchmarks = tc.saveTimeBenchmarks; - params.FataliseUponFailure = tc.fataliseUponFailure; - params.DropTFUponFailure = tc.dropTFUponFailure; - for (int iD{0}; iD < 3; ++iD) { - params.Diamond[iD] = tc.diamondPos[iD]; - } - params.UseDiamond = tc.useDiamond; - if (tc.maxMemory) { - params.MaxMemory = tc.maxMemory; - } - if (tc.useTrackFollower > 0) { - params.UseTrackFollower = true; - // Bit 0: Allow for mixing of top&bot extension --> implies Bits 1&2 set - // Bit 1: Allow for top extension - // Bit 2: Allow for bot extension - params.UseTrackFollowerMix = ((tc.useTrackFollower & (1 << 0)) != 0); - params.UseTrackFollowerTop = ((tc.useTrackFollower & (1 << 1)) != 0); - params.UseTrackFollowerBot = ((tc.useTrackFollower & (1 << 2)) != 0); - params.TrackFollowerNSigmaCutZ = tc.trackFollowerNSigmaZ; - params.TrackFollowerNSigmaCutPhi = tc.trackFollowerNSigmaPhi; - } - if (tc.cellsPerClusterLimit >= 0) { - params.CellsPerClusterLimit = tc.cellsPerClusterLimit; - } - if (tc.trackletsPerClusterLimit >= 0) { - params.TrackletsPerClusterLimit = tc.trackletsPerClusterLimit; - } - if (tc.findShortTracks >= 0) { - params.FindShortTracks = tc.findShortTracks; - } - } -} - void Tracker::adoptTimeFrame(TimeFrame7& tf) { mTimeFrame = &tf; diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index 8dd6b9870115c..da7f31bd678b5 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -616,12 +616,12 @@ void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bou continue; } - if (!propagator->propagateToX(seed, trHit.xTrackingFrame, getBz(), o2::base::PropagatorImpl::MAX_SIN_PHI, o2::base::PropagatorImpl::MAX_STEP, mCorrType)) { + if (!propagator->propagateToX(seed, trHit.xTrackingFrame, getBz(), o2::base::PropagatorImpl::MAX_SIN_PHI, o2::base::PropagatorImpl::MAX_STEP, mTrkParams[0].CorrType)) { CA_DEBUGGER(failed[2]++); continue; } - if (mCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { + if (mTrkParams[0].CorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { if (!seed.correctForMaterial(mTrkParams[0].LayerxX0[iLayer - 1], mTrkParams[0].LayerxX0[iLayer - 1] * constants::Radl * constants::Rho, true)) { continue; } @@ -1023,11 +1023,11 @@ bool TrackerTraits::fitTrack(TrackITSExt& track, int start, int end, in return false; } - if (!propInstance->propagateToX(track, trackingHit.xTrackingFrame, getBz(), o2::base::PropagatorImpl::MAX_SIN_PHI, o2::base::PropagatorImpl::MAX_STEP, mCorrType)) { + if (!propInstance->propagateToX(track, trackingHit.xTrackingFrame, getBz(), o2::base::PropagatorImpl::MAX_SIN_PHI, o2::base::PropagatorImpl::MAX_STEP, mTrkParams[0].CorrType)) { return false; } - if (mCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { + if (mTrkParams[0].CorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { if (!track.correctForMaterial(mTrkParams[0].LayerxX0[iLayer], mTrkParams[0].LayerxX0[iLayer] * constants::Radl * constants::Rho, true)) { continue; } @@ -1201,7 +1201,7 @@ void TrackerTraits::setBz(float bz) template bool TrackerTraits::isMatLUT() const { - return o2::base::Propagator::Instance()->getMatLUT() && (mCorrType == o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT); + return o2::base::Propagator::Instance()->getMatLUT() && (mTrkParams[0].CorrType == o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT); } template diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index 4f4941aca9f4d..4bdd2060d2110 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -33,122 +33,26 @@ using namespace o2::its; void ITSTrackingInterface::initialise() { - mRunVertexer = true; - mCosmicsProcessing = false; - std::vector vertParams; - std::vector trackParams; - const auto& vertConf = o2::its::VertexerParamConfig::Instance(); + // get parameters const auto& trackConf = o2::its::TrackerParamConfig::Instance(); - float bFactor = std::abs(o2::base::Propagator::Instance()->getNominalBz()) / 5.0066791; - float bFactorTracklets = bFactor < 0.01 ? 1. : bFactor; // for tracklets only + const auto& vertConf = o2::its::VertexerParamConfig::Instance(); if (mMode == TrackingMode::Unset) { - mMode = (TrackingMode)(trackConf.trackingMode); - LOGP(info, "Tracking mode not set, trying to fetch it from configurable params to: {}", asString(mMode)); - } - if (mMode == TrackingMode::Async) { - trackParams.resize(trackConf.doUPCIteration ? 4 : 3); - vertParams.resize(2); // The number of actual iterations will be set as a configKeyVal to allow for pp/PbPb choice - trackParams[1].TrackletMinPt = 0.2f; - trackParams[1].CellDeltaTanLambdaSigma *= 2.; - trackParams[2].TrackletMinPt = 0.1f; - trackParams[2].CellDeltaTanLambdaSigma *= 4.; - - trackParams[0].MinPt[0] = 1.f / 12; // 7cl - - trackParams[1].MinPt[0] = 1.f / 12; // 7cl - - trackParams[2].MinTrackLength = 4; - trackParams[2].MinPt[0] = 1.f / 12; // 7cl - trackParams[2].MinPt[1] = 1.f / 5; // 6cl - trackParams[2].MinPt[2] = 1.f / 1; // 5cl - trackParams[2].MinPt[3] = 1.f / 6; // 4cl - - trackParams[2].StartLayerMask = (1 << 6) + (1 << 3); - if (o2::its::TrackerParamConfig::Instance().doUPCIteration) { - trackParams[3].MinTrackLength = 4; - trackParams[3].TrackletMinPt = 0.1f; - trackParams[3].CellDeltaTanLambdaSigma *= 4.; - trackParams[3].DeltaROF = 0; // UPC specific setting - } - for (size_t ip = 0; ip < trackParams.size(); ip++) { - auto& param = trackParams[ip]; - param.ZBins = 64; - param.PhiBins = 32; - param.CellsPerClusterLimit = 1.e3f; - param.TrackletsPerClusterLimit = 1.e3f; - // check if something was overridden via configurable params - if (ip < trackConf.MaxIter) { - if (trackConf.startLayerMask[ip] > 0) { - trackParams[2].StartLayerMask = trackConf.startLayerMask[ip]; - } - if (trackConf.minTrackLgtIter[ip] > 0) { - param.MinTrackLength = trackConf.minTrackLgtIter[ip]; - } - for (int ilg = trackConf.MaxTrackLength; ilg >= trackConf.MinTrackLength; ilg--) { - int lslot0 = (trackConf.MaxTrackLength - ilg), lslot = lslot0 + ip * (trackConf.MaxTrackLength - trackConf.MinTrackLength + 1); - if (trackConf.minPtIterLgt[lslot] > 0.) { - param.MinPt[lslot0] = trackConf.minPtIterLgt[lslot]; - } - } - } - } - LOGP(info, "Initializing tracker in async. phase reconstruction with {} passes for tracking and {}/{} for vertexing", trackParams.size(), o2::its::VertexerParamConfig::Instance().nIterations, vertParams.size()); - vertParams[1].phiCut = 0.015f; - vertParams[1].tanLambdaCut = 0.015f; - vertParams[1].vertPerRofThreshold = 0; - vertParams[1].deltaRof = 0; - } else if (mMode == TrackingMode::Sync) { - trackParams.resize(1); - trackParams[0].ZBins = 64; - trackParams[0].PhiBins = 32; - trackParams[0].MinTrackLength = 4; - LOGP(info, "Initializing tracker in sync. phase reconstruction with {} passes", trackParams.size()); - vertParams.resize(1); - } else if (mMode == TrackingMode::Cosmics) { - mCosmicsProcessing = true; - mRunVertexer = false; - trackParams.resize(1); - trackParams[0].MinTrackLength = 4; - trackParams[0].CellDeltaTanLambdaSigma *= 10; - trackParams[0].PhiBins = 4; - trackParams[0].ZBins = 16; - trackParams[0].PVres = 1.e5f; - trackParams[0].MaxChi2ClusterAttachment = 60.; - trackParams[0].MaxChi2NDF = 40.; - trackParams[0].TrackletsPerClusterLimit = 100.; - trackParams[0].CellsPerClusterLimit = 100.; - LOGP(info, "Initializing tracker in reconstruction for cosmics with {} passes", trackParams.size()); - - } else { - throw std::runtime_error(fmt::format("Unsupported ITS tracking mode {:s} ", asString(mMode))); + mMode = (TrackingMode::Type)trackConf.trackingMode; + LOGP(info, "Tracking mode not set, trying to fetch it from configurable params to: {}", TrackingMode::toString(mMode)); } + auto trackParams = TrackingMode::getTrackingParameters(mMode); + auto vertParams = TrackingMode::getVertexingParameters(mMode); + LOGP(info, "Initializing tracker in {} phase reconstruction with {} passes for tracking and {}/{} for vertexing", TrackingMode::toString(mMode), trackParams.size(), o2::its::VertexerParamConfig::Instance().nIterations, vertParams.size()); + mTracker->setParameters(trackParams); + mVertexer->setParameters(vertParams); - // TODO this imposes the same memory limits on each iteration - for (auto& p : vertParams) { - p.PrintMemory = vertConf.printMemory; - p.MaxMemory = vertConf.maxMemory; - p.DropTFUponFailure = vertConf.dropTFUponFailure; - } - for (auto& p : trackParams) { - p.PrintMemory = trackConf.printMemory; - p.MaxMemory = trackConf.maxMemory; - p.DropTFUponFailure = trackConf.dropTFUponFailure; + if (mMode == TrackingMode::Cosmics) { + mRunVertexer = false; + mCosmicsProcessing = true; + LOGP(info, "Cosmic mode enabled, will skip vertexing"); } - for (auto& params : trackParams) { - params.CorrType = o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT; - } - // adjust pT settings to actual mag. field - for (size_t ip = 0; ip < trackParams.size(); ip++) { - auto& param = trackParams[ip]; - param.TrackletMinPt *= bFactorTracklets; - for (int ilg = trackConf.MaxTrackLength; ilg >= trackConf.MinTrackLength; ilg--) { - int lslot = trackConf.MaxTrackLength - ilg; - param.MinPt[lslot] *= bFactor; - } - } - mTracker->setParameters(trackParams); - mVertexer->setParameters(vertParams); + // threading if (trackConf.nThreads == vertConf.nThreads) { bool clamped{false}; int nThreads = trackConf.nThreads; @@ -409,7 +313,6 @@ void ITSTrackingInterface::updateTimeDependentParams(framework::ProcessingContex GeometryTGeo* geom = GeometryTGeo::Instance(); geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::T2G)); initialise(); - getConfiguration(pc); if (pc.services().get().inputTimesliceId == 0) { // print settings only for the 1st pipeling o2::its::VertexerParamConfig::Instance().printKeyValues(); @@ -428,12 +331,6 @@ void ITSTrackingInterface::updateTimeDependentParams(framework::ProcessingContex } } -void ITSTrackingInterface::getConfiguration(framework::ProcessingContext& pc) -{ - mVertexer->getGlobalConfiguration(); - mTracker->getGlobalConfiguration(); -} - void ITSTrackingInterface::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) { if (o2::base::GRPGeomHelper::instance().finaliseCCDB(matcher, obj)) { diff --git a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx index a1a1a90da8963..bd9d1402a1ebf 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx @@ -84,36 +84,6 @@ float Vertexer::clustersToVertices(LogFunc logger) return timeInit + timeTracklet + timeSelection + timeVertexing; } -void Vertexer::getGlobalConfiguration() -{ - auto& vc = o2::its::VertexerParamConfig::Instance(); - auto& grc = o2::its::ITSGpuTrackingParamConfig::Instance(); - - // This is odd: we override only the parameters for the first iteration. - // Variations for the next iterations are set in the trackingInterfrace. - mVertParams[0].nIterations = vc.nIterations; - mVertParams[0].deltaRof = vc.deltaRof; - mVertParams[0].allowSingleContribClusters = vc.allowSingleContribClusters; - mVertParams[0].zCut = vc.zCut; - mVertParams[0].phiCut = vc.phiCut; - mVertParams[0].pairCut = vc.pairCut; - mVertParams[0].clusterCut = vc.clusterCut; - mVertParams[0].histPairCut = vc.histPairCut; - mVertParams[0].tanLambdaCut = vc.tanLambdaCut; - mVertParams[0].lowMultBeamDistCut = vc.lowMultBeamDistCut; - mVertParams[0].vertNsigmaCut = vc.vertNsigmaCut; - mVertParams[0].vertRadiusSigma = vc.vertRadiusSigma; - mVertParams[0].trackletSigma = vc.trackletSigma; - mVertParams[0].maxZPositionAllowed = vc.maxZPositionAllowed; - mVertParams[0].clusterContributorsCut = vc.clusterContributorsCut; - mVertParams[0].maxTrackletsPerCluster = vc.maxTrackletsPerCluster; - mVertParams[0].phiSpan = vc.phiSpan; - mVertParams[0].nThreads = vc.nThreads; - mVertParams[0].ZBins = vc.ZBins; - mVertParams[0].PhiBins = vc.PhiBins; - mVertParams[0].SaveTimeBenchmarks = vc.saveTimeBenchmarks; -} - void Vertexer::adoptTimeFrame(TimeFrame7& tf) { mTimeFrame = &tf; diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h index 02e278eeedda9..88e4b06a5c8ce 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h @@ -35,7 +35,7 @@ namespace its class CookedTrackerDPL : public Task { public: - CookedTrackerDPL(std::shared_ptr gr, bool useMC, int trgType, const TrackingMode& trMode); + CookedTrackerDPL(std::shared_ptr gr, bool useMC, int trgType, TrackingMode::Type trMode); ~CookedTrackerDPL() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -51,7 +51,7 @@ class CookedTrackerDPL : public Task bool mUseMC = true; bool mRunVertexer = true; int mUseTriggers = 0; - TrackingMode mMode = TrackingMode::Sync; + TrackingMode::Type mMode = TrackingMode::Sync; const o2::itsmft::TopologyDictionary* mDict = nullptr; std::unique_ptr mGRP = nullptr; o2::its::CookedTracker mTracker; @@ -62,7 +62,7 @@ class CookedTrackerDPL : public Task /// create a processor spec /// run ITS CookedMatrix tracker -framework::DataProcessorSpec getCookedTrackerSpec(bool useMC, bool useGeom, int useTrig, const std::string& trMode); +framework::DataProcessorSpec getCookedTrackerSpec(bool useMC, bool useGeom, int useTrig, TrackingMode::Type trMode); } // namespace its } // namespace o2 diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h index 7f9efa2098893..0ab48d713f7c7 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/RecoWorkflow.h @@ -15,7 +15,7 @@ /// @file RecoWorkflow.h #include "Framework/WorkflowSpec.h" - +#include "ITStracking/Configuration.h" #include "GPUDataTypes.h" namespace o2 @@ -26,7 +26,7 @@ namespace its namespace reco_workflow { -framework::WorkflowSpec getWorkflow(bool useMC, bool useCAtracker, const std::string& trmode, const bool overrideBeamPosition = false, +framework::WorkflowSpec getWorkflow(bool useMC, bool useCAtracker, TrackingMode::Type trmode, const bool overrideBeamPosition = false, bool upstreamDigits = false, bool upstreamClusters = false, bool disableRootOutput = false, bool useGeom = false, int useTrig = 0, bool useGPUWF = false, o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU); } diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h index 27c4174fab244..ee5ba4d5cc61c 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/TrackerSpec.h @@ -37,7 +37,7 @@ class TrackerDPL : public framework::Task TrackerDPL(std::shared_ptr gr, bool isMC, int trgType, - const TrackingMode& trMode = TrackingMode::Unset, + const TrackingMode::Type trMode = TrackingMode::Unset, const bool overrBeamEst = false, o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU); ~TrackerDPL() override = default; @@ -57,8 +57,7 @@ class TrackerDPL : public framework::Task TStopwatch mTimer; }; -using o2::its::TrackingMode; -framework::DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int useTrig, const std::string& trMode, const bool overrBeamEst = false, o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU); +framework::DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int useTrig, TrackingMode::Type trMode, const bool overrBeamEst = false, o2::gpu::GPUDataTypes::DeviceType dType = o2::gpu::GPUDataTypes::DeviceType::CPU); } // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx index 4a0470adcf07a..640265f881749 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx @@ -52,7 +52,7 @@ namespace its using Vertex = o2::dataformats::Vertex>; -CookedTrackerDPL::CookedTrackerDPL(std::shared_ptr gr, bool useMC, int trgType, const TrackingMode& trMode) : mGGCCDBRequest(gr), mUseMC(useMC), mUseTriggers{trgType}, mMode(trMode) +CookedTrackerDPL::CookedTrackerDPL(std::shared_ptr gr, bool useMC, int trgType, TrackingMode::Type trMode) : mGGCCDBRequest(gr), mUseMC(useMC), mUseTriggers{trgType}, mMode(trMode) { mVertexerTraitsPtr = std::make_unique(); mVertexerPtr = std::make_unique(mVertexerTraitsPtr.get()); @@ -225,13 +225,13 @@ void CookedTrackerDPL::updateTimeDependentParams(ProcessingContext& pc) if (pc.inputs().getPos("itsTGeo") >= 0) { pc.inputs().get("itsTGeo"); } - mVertexerPtr->getGlobalConfiguration(); + mVertexerPtr->setParameters(TrackingMode::getVertexingParameters(mMode)); o2::its::GeometryTGeo* geom = o2::its::GeometryTGeo::Instance(); geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::T2G)); mTracker.setGeometry(geom); mTracker.setConfigParams(); - LOG(info) << "Tracking mode " << mMode; + LOG(info) << "Tracking mode " << TrackingMode::toString(mMode); if (mMode == TrackingMode::Cosmics) { LOG(info) << "Setting cosmics parameters..."; mTracker.setParametersCosmics(); @@ -269,7 +269,7 @@ void CookedTrackerDPL::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) } } -DataProcessorSpec getCookedTrackerSpec(bool useMC, bool useGeom, int trgType, const std::string& trModeS) +DataProcessorSpec getCookedTrackerSpec(bool useMC, bool useGeom, int trgType, TrackingMode::Type trmode) { std::vector inputs; inputs.emplace_back("compClusters", "ITS", "COMPCLUSTERS", 0, Lifetime::Timeframe); @@ -315,8 +315,7 @@ DataProcessorSpec getCookedTrackerSpec(bool useMC, bool useGeom, int trgType, co AlgorithmSpec{adaptFromTask(ggRequest, useMC, trgType, - trModeS == "sync" ? o2::its::TrackingMode::Sync : trModeS == "async" ? o2::its::TrackingMode::Async - : o2::its::TrackingMode::Cosmics)}, + trmode)}, Options{{"nthreads", VariantType::Int, 1, {"Number of threads"}}}}; } diff --git a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx index 05e873c18b898..a72c26a3681e1 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx @@ -36,7 +36,7 @@ namespace reco_workflow framework::WorkflowSpec getWorkflow(bool useMC, bool useCAtracker, - const std::string& trmode, + TrackingMode::Type trmode, const bool overrideBeamPosition, bool upstreamDigits, bool upstreamClusters, @@ -56,7 +56,7 @@ framework::WorkflowSpec getWorkflow(bool useMC, if (!disableRootOutput) { specs.emplace_back(o2::its::getClusterWriterSpec(useMC)); } - if (!trmode.empty()) { + if (trmode != TrackingMode::Off) { if (useCAtracker) { if (useGPUWF) { o2::gpu::GPURecoWorkflowSpec::Config cfg; diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index 9f84ee6522567..fedc42c017f7e 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -26,7 +26,7 @@ using Vertex = o2::dataformats::Vertex>; TrackerDPL::TrackerDPL(std::shared_ptr gr, bool isMC, int trgType, - const TrackingMode& trMode, + const TrackingMode::Type trMode, const bool overrBeamEst, o2::gpu::GPUDataTypes::DeviceType dType) : mGGCCDBRequest(gr), mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)}, @@ -79,7 +79,7 @@ void TrackerDPL::end() LOGF(info, "ITS CA-Tracker total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, const std::string& trModeS, const bool overrBeamEst, o2::gpu::GPUDataTypes::DeviceType dType) +DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, TrackingMode::Type trMode, const bool overrBeamEst, o2::gpu::GPUDataTypes::DeviceType dType) { std::vector inputs; @@ -132,8 +132,7 @@ DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, const st AlgorithmSpec{adaptFromTask(ggRequest, useMC, trgType, - trModeS == "sync" ? o2::its::TrackingMode::Sync : trModeS == "async" ? o2::its::TrackingMode::Async - : o2::its::TrackingMode::Cosmics, + trMode, overrBeamEst, dType)}, Options{}}; diff --git a/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx index 168e1363d6fb5..b7d72eb3618db 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/its-reco-workflow.cxx @@ -11,7 +11,6 @@ #include "ITSWorkflow/RecoWorkflow.h" #include "CommonUtils/ConfigurableParam.h" -#include "ITStracking/TrackingConfigParam.h" #include "ITStracking/Configuration.h" #include "DetectorsRaw/HBFUtilsInitializer.h" #include "Framework/CallbacksPolicy.h" @@ -45,7 +44,7 @@ void customize(std::vector& workflowOptions) {"trackerCA", o2::framework::VariantType::Bool, false, {"use trackerCA (default: trackerCM)"}}, {"ccdb-meanvertex-seed", o2::framework::VariantType::Bool, false, {"use MeanVertex from CCDB if available to provide beam position seed (default: false)"}}, {"select-with-triggers", o2::framework::VariantType::String, "none", {"use triggers to prescale processed ROFs: phys, trd, none"}}, - {"tracking-mode", o2::framework::VariantType::String, "sync", {"sync,async,cosmics"}}, + {"tracking-mode", o2::framework::VariantType::String, "sync", {"sync,async,cosmics,unset,off"}}, {"disable-tracking", o2::framework::VariantType::Bool, false, {"disable tracking step"}}, {"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings"}}, {"use-full-geometry", o2::framework::VariantType::Bool, false, {"use full geometry instead of the light-weight ITS part"}}, @@ -75,9 +74,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto disableRootOutput = configcontext.options().get("disable-root-output"); auto useGeom = configcontext.options().get("use-full-geometry"); if (configcontext.options().get("disable-tracking")) { - trmode = ""; + trmode = "off"; } - std::transform(trmode.begin(), trmode.end(), trmode.begin(), [](unsigned char c) { return std::tolower(c); }); o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); int trType = 0; @@ -92,7 +90,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) } auto wf = o2::its::reco_workflow::getWorkflow(useMC, useCAtracker, - trmode, + o2::its::TrackingMode::fromString(trmode), beamPosOVerride, extDigits, extClusters, diff --git a/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx b/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx index afb276e956e76..99ac05e61baf8 100644 --- a/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx +++ b/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx @@ -33,7 +33,6 @@ void ITS3TrackingInterface::updateTimeDependentParams(framework::ProcessingConte auto geom = its::GeometryTGeo::Instance(); geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::T2G)); initialise(); - getConfiguration(pc); if (pc.services().get().inputTimesliceId == 0) { // print settings only for the 1st pipeling o2::its::VertexerParamConfig::Instance().printKeyValues(); o2::its::TrackerParamConfig::Instance().printKeyValues(); diff --git a/Detectors/Upgrades/ITS3/workflow/include/ITS3Workflow/RecoWorkflow.h b/Detectors/Upgrades/ITS3/workflow/include/ITS3Workflow/RecoWorkflow.h index 1760aa1d850eb..592a34d94a3ca 100644 --- a/Detectors/Upgrades/ITS3/workflow/include/ITS3Workflow/RecoWorkflow.h +++ b/Detectors/Upgrades/ITS3/workflow/include/ITS3Workflow/RecoWorkflow.h @@ -15,7 +15,7 @@ /// @file RecoWorkflow.h #include "Framework/WorkflowSpec.h" - +#include "ITStracking/Configuration.h" #include "GPUO2Interface.h" #include "GPUReconstruction.h" #include "GPUChainITS.h" @@ -24,7 +24,7 @@ namespace o2::its3::reco_workflow { framework::WorkflowSpec getWorkflow(bool useMC, - const std::string& trmode, + its::TrackingMode::Type trmode, o2::gpu::GPUDataTypes::DeviceType dtype, bool useGPUWorkflow, bool upstreamDigits, diff --git a/Detectors/Upgrades/ITS3/workflow/include/ITS3Workflow/TrackerSpec.h b/Detectors/Upgrades/ITS3/workflow/include/ITS3Workflow/TrackerSpec.h index f5c1d7bf0e947..42f71b6ccebe0 100644 --- a/Detectors/Upgrades/ITS3/workflow/include/ITS3Workflow/TrackerSpec.h +++ b/Detectors/Upgrades/ITS3/workflow/include/ITS3Workflow/TrackerSpec.h @@ -37,7 +37,7 @@ class TrackerDPL : public framework::Task TrackerDPL(std::shared_ptr gr, bool isMC, int trgType, - const its::TrackingMode& trMode = its::TrackingMode::Unset, + its::TrackingMode::Type trmode = its::TrackingMode::Unset, const bool overrBeamEst = false, gpu::GPUDataTypes::DeviceType dType = gpu::GPUDataTypes::DeviceType::CPU); ~TrackerDPL() override = default; @@ -63,7 +63,7 @@ class TrackerDPL : public framework::Task /// create a processor spec /// run ITS CA tracker -framework::DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int useTrig, const std::string& trMode, const bool overrBeamEst = false, gpu::GPUDataTypes::DeviceType dType = gpu::GPUDataTypes::DeviceType::CPU); +framework::DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int useTrig, its::TrackingMode::Type trMode, const bool overrBeamEst = false, gpu::GPUDataTypes::DeviceType dType = gpu::GPUDataTypes::DeviceType::CPU); } // namespace o2::its3 diff --git a/Detectors/Upgrades/ITS3/workflow/src/RecoWorkflow.cxx b/Detectors/Upgrades/ITS3/workflow/src/RecoWorkflow.cxx index 947e53f80ddf1..8a1c1ef73cf2b 100644 --- a/Detectors/Upgrades/ITS3/workflow/src/RecoWorkflow.cxx +++ b/Detectors/Upgrades/ITS3/workflow/src/RecoWorkflow.cxx @@ -26,7 +26,7 @@ static std::shared_ptr gTask; namespace o2::its3::reco_workflow { -framework::WorkflowSpec getWorkflow(bool useMC, const std::string& trmode, o2::gpu::GPUDataTypes::DeviceType dtype, bool useGPUWorkflow, +framework::WorkflowSpec getWorkflow(bool useMC, its::TrackingMode::Type trmode, o2::gpu::GPUDataTypes::DeviceType dtype, bool useGPUWorkflow, bool upstreamDigits, bool upstreamClusters, bool disableRootOutput, bool useGeom, int useTrig, bool overrideBeamPosition) { framework::WorkflowSpec specs; @@ -43,7 +43,7 @@ framework::WorkflowSpec getWorkflow(bool useMC, const std::string& trmode, o2::g specs.emplace_back(o2::its::getClusterWriterSpec(useMC)); } - if (trmode != "off") { + if (trmode != its::TrackingMode::Off) { if (useGPUWorkflow) { o2::gpu::GPURecoWorkflowSpec::Config cfg; cfg.runITSTracking = true; diff --git a/Detectors/Upgrades/ITS3/workflow/src/TrackerSpec.cxx b/Detectors/Upgrades/ITS3/workflow/src/TrackerSpec.cxx index 5b710a3d11fef..7945f8e0af1df 100644 --- a/Detectors/Upgrades/ITS3/workflow/src/TrackerSpec.cxx +++ b/Detectors/Upgrades/ITS3/workflow/src/TrackerSpec.cxx @@ -49,7 +49,7 @@ using Vertex = o2::dataformats::Vertex>; TrackerDPL::TrackerDPL(std::shared_ptr gr, bool isMC, int trgType, - const its::TrackingMode& trMode, + its::TrackingMode::Type trMode, const bool overrBeamEst, o2::gpu::GPUDataTypes::DeviceType dType) : mGGCCDBRequest(gr), mRecChain{o2::gpu::GPUReconstruction::CreateInstance(dType, true)}, @@ -95,7 +95,7 @@ void TrackerDPL::endOfStream(EndOfStreamContext& ec) LOGF(info, "ITS3 CA-Tracker total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, const std::string& trModeS, const bool overrBeamEst, o2::gpu::GPUDataTypes::DeviceType dType) +DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, its::TrackingMode::Type trMode, const bool overrBeamEst, o2::gpu::GPUDataTypes::DeviceType dType) { std::vector inputs; inputs.emplace_back("compClusters", "ITS", "COMPCLUSTERS", 0, Lifetime::Timeframe); @@ -145,10 +145,7 @@ DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, const st "its3-tracker", inputs, outputs, - AlgorithmSpec{adaptFromTask(ggRequest, useMC, trgType, - trModeS == "sync" ? o2::its::TrackingMode::Sync : trModeS == "async" ? o2::its::TrackingMode::Async - : o2::its::TrackingMode::Cosmics, - overrBeamEst, dType)}, + AlgorithmSpec{adaptFromTask(ggRequest, useMC, trgType, trMode, overrBeamEst, dType)}, Options{}}; } diff --git a/Detectors/Upgrades/ITS3/workflow/src/its3-reco-workflow.cxx b/Detectors/Upgrades/ITS3/workflow/src/its3-reco-workflow.cxx index 2f0eda73742cb..e4c78b3323a5e 100644 --- a/Detectors/Upgrades/ITS3/workflow/src/its3-reco-workflow.cxx +++ b/Detectors/Upgrades/ITS3/workflow/src/its3-reco-workflow.cxx @@ -69,7 +69,6 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) auto disableRootOutput = configcontext.options().get("disable-root-output"); auto useGeom = configcontext.options().get("use-full-geometry"); auto useGPUWfx = configcontext.options().get("use-gpu-workflow"); - std::transform(trmode.begin(), trmode.end(), trmode.begin(), [](unsigned char c) { return std::tolower(c); }); o2::conf::ConfigurableParam::updateFromString(configcontext.options().get("configKeyValues")); int trType = 0; @@ -82,7 +81,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) LOG(fatal) << "Unknown trigger type requested for events prescaling: " << selTrig; } } - auto wf = o2::its3::reco_workflow::getWorkflow(useMC, trmode, gpuDevice, useGPUWfx, extDigits, extClusters, disableRootOutput, useGeom, trType, beamPosOVerride); + auto wf = o2::its3::reco_workflow::getWorkflow(useMC, o2::its::TrackingMode::fromString(trmode), gpuDevice, useGPUWfx, extDigits, extClusters, disableRootOutput, useGeom, trType, beamPosOVerride); // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit o2::raw::HBFUtilsInitializer hbfIni(configcontext, wf); From 82d072d317b0342bda21e92e35e89ef16f3176e1 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sun, 8 Jun 2025 14:13:03 +0200 Subject: [PATCH 137/315] ITS: prefer config params over cli Signed-off-by: Felix Schlepper --- Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index 4bdd2060d2110..604c6ad88080f 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -36,9 +36,9 @@ void ITSTrackingInterface::initialise() // get parameters const auto& trackConf = o2::its::TrackerParamConfig::Instance(); const auto& vertConf = o2::its::VertexerParamConfig::Instance(); - if (mMode == TrackingMode::Unset) { - mMode = (TrackingMode::Type)trackConf.trackingMode; - LOGP(info, "Tracking mode not set, trying to fetch it from configurable params to: {}", TrackingMode::toString(mMode)); + if (auto parmode = (TrackingMode::Type)trackConf.trackingMode; mMode == TrackingMode::Unset || (parmode != TrackingMode::Unset && mMode != parmode)) { + LOGP(info, "Tracking mode overwritten by configurable params from {} to {}", TrackingMode::toString(mMode), TrackingMode::toString(parmode)); + mMode = parmode; } auto trackParams = TrackingMode::getTrackingParameters(mMode); auto vertParams = TrackingMode::getVertexingParameters(mMode); From 980e564044e8dc68a6bee7243d1e23c456c9eae3 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 9 Jul 2025 18:06:37 +0200 Subject: [PATCH 138/315] TrackReference: possibility to have unknown DetectorID We've been using 0 as detectorID in generic "Stopping" TrackReferences. Unfortunately, 0 is also the ID of the ITS sensitive detector according to o2::detectors::DetID class. The commit changes this to using -1, where -1 means simply means "unknown". --- .../simulation/include/SimulationDataFormat/TrackReference.h | 2 +- Detectors/gconfig/src/StandardSteppingTrackRefHook.macro | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DataFormats/simulation/include/SimulationDataFormat/TrackReference.h b/DataFormats/simulation/include/SimulationDataFormat/TrackReference.h index f3d41a17208f0..34d1c57aa9f0b 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/TrackReference.h +++ b/DataFormats/simulation/include/SimulationDataFormat/TrackReference.h @@ -171,7 +171,7 @@ class TrackReference float mTrackLength = 0; ///< track length from its origin in cm float mTof = 0; ///< time of flight in cm Int_t mUserId = 0; ///< optional Id defined by user - Int_t mDetectorId = 0; ///< Detector Id + Int_t mDetectorId = -1; ///< sensitive Detector Id (-1 if unknown or in passive material) SimTrackStatus mStatus; ///< encoding the track status friend std::ostream& operator<<(std::ostream&, const TrackReference&); diff --git a/Detectors/gconfig/src/StandardSteppingTrackRefHook.macro b/Detectors/gconfig/src/StandardSteppingTrackRefHook.macro index e408bbff420b5..3888d3c74ca8d 100644 --- a/Detectors/gconfig/src/StandardSteppingTrackRefHook.macro +++ b/Detectors/gconfig/src/StandardSteppingTrackRefHook.macro @@ -8,7 +8,7 @@ o2::steer::O2MCApplicationBase::TrackRefFcn trackRefHook() { if (vmc->IsTrackStop() && stack->currentTrackLeftTrackRef()) { // we add a stopping TrackRef when the current track already // registered previous TrackRefs - stack->addTrackReference(o2::TrackReference(*vmc, 0)); + stack->addTrackReference(o2::TrackReference(*vmc, -1)); } }; } \ No newline at end of file From 0d508b3a38af55d5adb4e1623e6aa6b24cafb400 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 9 Jul 2025 08:36:45 +0200 Subject: [PATCH 139/315] AOD: TrackQA use outer ITS ref. for residuals to TPC @miranov25 after taking to @mpuccio and @hscheid, I realised that the current residuals are biased since they the take the innermost representation of the track while one should take the outermost one to compare to TPC. --- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 1cc89d54a030d..ac7fc06a2d5da 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -2717,7 +2717,7 @@ AODProducerWorkflowDPL::TrackQA AODProducerWorkflowDPL::processBarrelTrackQA(int if (auto itsContGID = data.getITSContributorGID(trackIndex); itsContGID.isIndexSet() && itsContGID.getSource() != GIndex::ITSAB) { const auto& itsOrig = data.getITSTrack(itsContGID); o2::track::TrackPar gloCopy = trackPar; - o2::track::TrackPar itsCopy = itsOrig; + o2::track::TrackPar itsCopy = itsOrig.getParamOut(); o2::track::TrackPar tpcCopy = tpcOrig; if (prop->propagateToX(gloCopy, o2::aod::track::trackQARefRadius, prop->getNominalBz(), o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, mMatCorr) && prop->propagateToAlphaX(tpcCopy, gloCopy.getAlpha(), o2::aod::track::trackQARefRadius, false, o2::base::Propagator::MAX_SIN_PHI, o2::base::Propagator::MAX_STEP, 1, mMatCorr) && From c26672b91edfd935ef3e40a324c7a4353334ab2c Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 24 Jun 2025 21:32:35 +0200 Subject: [PATCH 140/315] ITS: remove some printing Signed-off-by: Felix Schlepper --- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 3 --- Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx | 1 - 2 files changed, 4 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index e0bd94ed223c0..7a2e883e1b5e6 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -130,9 +130,6 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) auto nTracksA = mTimeFrame->getNumberOfTracks(); logger(std::format(" `-> found {} additional tracks", nTracksA - nTracksB)); } - if (mTrkParams[iteration].PrintMemory) { - mMemoryPool->print(); - } if constexpr (constants::DoTimeBenchmarks) { logger(std::format("=== TimeFrame {} processing completed in: {:.2f} ms using {} thread(s) ===", mTimeFrameCounter, total, mTraits->getNThreads())); } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index 604c6ad88080f..29dc55337bfc3 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -362,7 +362,6 @@ void ITSTrackingInterface::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) void ITSTrackingInterface::printSummary() const { - mMemoryPool->print(); mTracker->printSummary(); } From 6665ddd4f5b46f5f64d016335b5758a6421c96a7 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 9 Jul 2025 07:51:48 +0200 Subject: [PATCH 141/315] ITS: fix TypedAllocator for cuda thrust Signed-off-by: Felix Schlepper --- .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 8245aee33718c..38c59d520aa76 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -58,30 +58,43 @@ namespace gpu { template -class TypedAllocator : public thrust::device_allocator -{ - public: +struct TypedAllocator { using value_type = T; - using pointer = T*; + using pointer = thrust::device_ptr; + using const_pointer = thrust::device_ptr; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + + TypedAllocator() noexcept : mInternalAllocator(nullptr) {} + explicit TypedAllocator(ExternalAllocator* a) noexcept : mInternalAllocator(a) {} template - struct rebind { - using other = TypedAllocator; - }; + TypedAllocator(const TypedAllocator& o) noexcept : mInternalAllocator(o.mInternalAllocator) + { + } - explicit TypedAllocator(ExternalAllocator* allocPtr) - : mInternalAllocator(allocPtr) {} + pointer allocate(size_type n) + { + void* raw = mInternalAllocator->allocate(n * sizeof(T)); + return thrust::device_pointer_cast(static_cast(raw)); + } - T* allocate(size_t n) + void deallocate(pointer p, size_type n) noexcept { - return reinterpret_cast(mInternalAllocator->allocate(n * sizeof(T))); + if (!p) { + return; + } + void* raw = thrust::raw_pointer_cast(p); + mInternalAllocator->deallocate(static_cast(raw), n * sizeof(T)); } - void deallocate(T* p, size_t n) + bool operator==(TypedAllocator const& o) const noexcept + { + return mInternalAllocator == o.mInternalAllocator; + } + bool operator!=(TypedAllocator const& o) const noexcept { - char* raw_ptr = reinterpret_cast(p); - size_t bytes = n * sizeof(T); - mInternalAllocator->deallocate(raw_ptr, bytes); // redundant as internal dealloc is no-op. + return !(*this == o); } private: From 53be5c459c07a60bcc202494990330d3d7d80d07 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 11 Jul 2025 10:47:45 +0200 Subject: [PATCH 142/315] GPU Display OpenGL Backend: Use nullptr instead of 0 --- GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.cxx b/GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.cxx index 664734fe6dff0..0d9a6f052d617 100644 --- a/GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.cxx +++ b/GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.cxx @@ -330,9 +330,9 @@ int32_t GPUDisplayBackendOpenGL::InitBackendA() #if defined(GL_VERSION_4_6) && GL_VERSION_4_6 == 1 && defined(GPUCA_BUILD_EVENT_DISPLAY_VULKAN) if (getenv("USE_SPIRV_SHADERS") && atoi(getenv("USE_SPIRV_SHADERS"))) { CHKERR(glShaderBinary(1, &mVertexShader, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, _binary_shaders_shaders_vertex_vert_spv_start, _binary_shaders_shaders_vertex_vert_spv_len)); - CHKERR(glSpecializeShader(mVertexShader, "main", 0, 0, 0)); + CHKERR(glSpecializeShader(mVertexShader, "main", 0, nullptr, nullptr)); CHKERR(glShaderBinary(1, &mFragmentShader, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, _binary_shaders_shaders_fragmentUniform_frag_spv_start, _binary_shaders_shaders_fragmentUniform_frag_spv_len)); - CHKERR(glSpecializeShader(mFragmentShader, "main", 0, 0, 0)); + CHKERR(glSpecializeShader(mFragmentShader, "main", 0, nullptr, nullptr)); GPUInfo("Using SPIR-V shaders"); mSPIRVShaders = true; } else From 28d2dc3ceba7767be7e318ea6acca2cfa0152a0f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 11 Jul 2025 15:30:51 +0200 Subject: [PATCH 143/315] GPU QA: Make cluster cuts setable and adust defaults --- GPU/GPUTracking/Definitions/GPUSettingsList.h | 3 +++ GPU/GPUTracking/qa/GPUQA.cxx | 15 ++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 0ff8adb1cb957..51a0add7dbeea 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -512,6 +512,9 @@ AddOption(shipToQC, bool, false, "", 0, "Do not write output files but ship hist AddOption(shipToQCAsCanvas, bool, false, "", 0, "Send TCanvases with full layout to QC instead of individual histograms") AddOption(clusterRejectionHistograms, bool, false, "", 0, "Fill histograms with cluster rejection statistics") AddOption(histMaxNClusters, uint32_t, 500000000, "", 0, "Maximum number of clusters in rejection histograms") +AddOption(minNClFindable, uint32_t, 70, "", 0, "Minimum number of (weighted) MC clusters for a track to count as findable") +AddOption(minNClEff, uint32_t, 10, "", 0, "Minimum number of (weighted) MC clusters for a track to contribute to all-tracks efficiency histogramm") +AddOption(minNClRes, uint32_t, 40, "", 0, "Minimum number of (weighted) MC clusters for a track to contribute to resolution histogram") AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAinputHistogramsOnly") AddHelp("help", 'h') EndConfig() diff --git a/GPU/GPUTracking/qa/GPUQA.cxx b/GPU/GPUTracking/qa/GPUQA.cxx index 6f640578a8804..2e9c3a1870385 100644 --- a/GPU/GPUTracking/qa/GPUQA.cxx +++ b/GPU/GPUTracking/qa/GPUQA.cxx @@ -158,15 +158,12 @@ static constexpr float PT_MAX = 20; static constexpr float ETA_MAX = 1.5; static constexpr float ETA_MAX2 = 0.9; -static constexpr float MIN_WEIGHT_CLS = 40; -static constexpr float FINDABLE_WEIGHT_CLS = 70; - static constexpr bool CLUST_HIST_INT_SUM = false; static constexpr const int32_t COLORCOUNT = 12; static const constexpr char* EFF_TYPES[5] = {"Rec", "Clone", "Fake", "All", "RecAndClone"}; -static const constexpr char* FINDABLE_NAMES[2] = {"", "Findable"}; +static const constexpr char* FINDABLE_NAMES[2] = {"All", "Findable"}; static const constexpr char* PRIM_NAMES[2] = {"Prim", "Sec"}; static const constexpr char* PARAMETER_NAMES[5] = {"Y", "Z", "#Phi", "#lambda", "Relative #it{p}_{T}"}; static const constexpr char* PARAMETER_NAMES_NATIVE[5] = {"Y", "Z", "sin(#Phi)", "tan(#lambda)", "q/#it{p}_{T} (curvature)"}; @@ -1185,10 +1182,10 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx if (info.primDaughters) { continue; } - if (mc2.nWeightCls < MIN_WEIGHT_CLS) { + if (mc2.nWeightCls < mConfig.minNClEff) { continue; } - int32_t findable = mc2.nWeightCls >= FINDABLE_WEIGHT_CLS; + int32_t findable = mc2.nWeightCls >= mConfig.minNClFindable; if (info.pid < 0) { continue; } @@ -1217,9 +1214,9 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx float localY = -info.x * s + info.y * c; if (mConfig.dumpToROOT) { - static auto effdump = GPUROOTDump::getNew("eff", "alpha:x:y:z:mcphi:mceta:mcpt:rec:fake:findable:prim"); + static auto effdump = GPUROOTDump::getNew("eff", "alpha:x:y:z:mcphi:mceta:mcpt:rec:fake:findable:prim:ncls"); float localX = info.x * c + info.y * s; - effdump.Fill(alpha, localX, localY, info.z, mcphi, mceta, mcpt, mRecTracks[iCol][i], mFakeTracks[iCol][i], findable, info.prim); + effdump.Fill(alpha, localX, localY, info.z, mcphi, mceta, mcpt, mRecTracks[iCol][i], mFakeTracks[iCol][i], findable, info.prim, mc2.nWeightCls); } for (int32_t j = 0; j < 4; j++) { @@ -1304,7 +1301,7 @@ void GPUQA::RunQA(bool matchOnly, const std::vector* tracksEx if (mConfig.filterPID >= 0 && mc1.pid != mConfig.filterPID) { continue; } - if (mc2.nWeightCls < MIN_WEIGHT_CLS) { + if (mc2.nWeightCls < mConfig.minNClRes) { continue; } if (mConfig.resPrimaries == 1 && !mc1.prim) { From 662f8647889e81814428fdf6d1703440939b6f54 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 19 Jun 2025 11:00:22 +0200 Subject: [PATCH 144/315] ITS: add truth seeding Signed-off-by: Felix Schlepper --- Detectors/ITSMFT/ITS/tracking/CMakeLists.txt | 4 +- .../include/ITStracking/Configuration.h | 2 + .../include/ITStracking/TrackingConfigParam.h | 2 + .../tracking/include/ITStracking/Vertexer.h | 6 +- .../include/ITStracking/VertexerTraits.h | 2 + .../ITSMFT/ITS/tracking/src/Configuration.cxx | 2 + .../ITS/tracking/src/TrackingInterface.cxx | 4 +- .../ITSMFT/ITS/tracking/src/Vertexer.cxx | 14 +++-- .../ITS/tracking/src/VertexerTraits.cxx | 62 ++++++++++++++++++- 9 files changed, 84 insertions(+), 14 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index d3871b9e75d70..45080e19cacff 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -36,7 +36,9 @@ o2_add_library(ITStracking O2::ITSReconstruction O2::ITSMFTReconstruction O2::DataFormatsITS - PRIVATE_LINK_LIBRARIES TBB::tbb) + PRIVATE_LINK_LIBRARIES + O2::Steer + TBB::tbb) o2_add_library(ITSTrackingInterface TARGETVARNAME targetName diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 34b2d11fc16e6..8c46b2e72078a 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -112,6 +112,8 @@ struct VertexingParameters { int zSpan = -1; bool SaveTimeBenchmarks = false; + bool useTruthSeeding = false; // overwrite found vertices with MC events + int nThreads = 1; bool PrintMemory = false; // print allocator usage in epilog report size_t MaxMemory = std::numeric_limits::max(); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h index 039fe0756d6f6..8de80d5e4cd07 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h @@ -48,6 +48,8 @@ struct VertexerParamConfig : public o2::conf::ConfigurableParamHelper::max(); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h index 285e4d7e9547d..c8b3b0d4138d4 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h @@ -75,7 +75,8 @@ class Vertexer void validateTracklets(T&&... args); template void findVertices(T&&... args); - void findHistVertices(); + + void addTruthSeeds() { mTraits->addTruthSeedingVertices(); } template void initialiseVertexer(T&&... args); @@ -108,10 +109,11 @@ class Vertexer Trackleting, Validating, Finding, + TruthSeeding, NStates, }; State mCurState{Init}; - static constexpr std::array StateNames{"Initialisation", "Tracklet finding", "Tracklet validation", "Vertex finding"}; + static constexpr std::array StateNames{"Initialisation", "Tracklet finding", "Tracklet validation", "Vertex finding", "Truth seeding"}; }; template diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index a842f04abfc62..a2429fe7270a8 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -73,6 +73,8 @@ class VertexerTraits virtual void computeVertices(const int iteration = 0); virtual void adoptTimeFrame(TimeFrame7* tf) noexcept { mTimeFrame = tf; } virtual void updateVertexingParameters(const std::vector& vrtPar, const TimeFrameGPUParameters& gpuTfPar); + // truth tracking + void addTruthSeedingVertices(); void computeVerticesInRof(int, gsl::span&, diff --git a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx index 56aa52b25940e..1c2857413789b 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx @@ -282,6 +282,8 @@ std::vector TrackingMode::getVertexingParameters(TrackingMo p.nThreads = vc.nThreads; p.ZBins = vc.ZBins; p.PhiBins = vc.PhiBins; + + p.useTruthSeeding = vc.useTruthSeeding; } // set for now outside to not disturb status quo vertParams[0].vertNsigmaCut = vc.vertNsigmaCut; diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index 29dc55337bfc3..31dc68d03a7e8 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -187,13 +187,13 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) vtxROF.setNEntries(vtxSpan.size()); bool selROF = vtxSpan.empty(); for (auto iV{0}; iV < vtxSpan.size(); ++iV) { - auto& v = vtxSpan[iV]; + const auto& v = vtxSpan[iV]; if (multEstConf.isVtxMultCutRequested() && !multEstConf.isPassingVtxMultCut(v.getNContributors())) { continue; // skip vertex of unwanted multiplicity } selROF = true; vertices.push_back(v); - if (mIsMC) { + if (mIsMC && !VertexerParamConfig::Instance().useTruthSeeding) { allVerticesLabels.push_back(vMCRecInfo[iV].first); allVerticesPurities.push_back(vMCRecInfo[iV].second); } diff --git a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx index bd9d1402a1ebf..16de3d075ef75 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx @@ -36,6 +36,11 @@ Vertexer::Vertexer(VertexerTraits* traits) : mTraits(traits) float Vertexer::clustersToVertices(LogFunc logger) { LogFunc evalLog = [](const std::string&) {}; + + if (mTimeFrame->hasMCinformation() && mVertParams[0].useTruthSeeding) { + return evaluateTask(&Vertexer::addTruthSeeds, StateNames[mCurState = TruthSeeding], 0, evalLog); + } + TrackingParameters trkPars; TimeFrameGPUParameters tfGPUpar; mTraits->updateVertexingParameters(mVertParams, tfGPUpar); @@ -58,14 +63,11 @@ float Vertexer::clustersToVertices(LogFunc logger) logger(fmt::format("=== ITS {} Seeding vertexer iteration {} summary:", mTraits->getName(), iteration)); trkPars.PhiBins = mTraits->getVertexingParameters()[0].PhiBins; trkPars.ZBins = mTraits->getVertexingParameters()[0].ZBins; - auto timeInitIteration = evaluateTask( - &Vertexer::initialiseVertexer, StateNames[mCurState = Init], iteration, evalLog, trkPars, iteration); - auto timeTrackletIteration = evaluateTask( - &Vertexer::findTracklets, StateNames[mCurState = Trackleting], iteration, evalLog, iteration); + auto timeInitIteration = evaluateTask(&Vertexer::initialiseVertexer, StateNames[mCurState = Init], iteration, evalLog, trkPars, iteration); + auto timeTrackletIteration = evaluateTask(&Vertexer::findTracklets, StateNames[mCurState = Trackleting], iteration, evalLog, iteration); nTracklets01 = mTimeFrame->getTotalTrackletsTF(0); nTracklets12 = mTimeFrame->getTotalTrackletsTF(1); - auto timeSelectionIteration = evaluateTask( - &Vertexer::validateTracklets, StateNames[mCurState = Validating], iteration, evalLog, iteration); + auto timeSelectionIteration = evaluateTask(&Vertexer::validateTracklets, StateNames[mCurState = Validating], iteration, evalLog, iteration); auto timeVertexingIteration = evaluateTask(&Vertexer::findVertices, StateNames[mCurState = Finding], iteration, evalLog, iteration); printEpilog(logger, nTracklets01, nTracklets12, mTimeFrame->getNLinesTotal(), mTimeFrame->getTotVertIteration()[iteration], timeInitIteration, timeTrackletIteration, timeSelectionIteration, timeVertexingIteration); timeInit += timeInitIteration; diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index a7487200886e6..a0f044c5f62ca 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -10,10 +10,10 @@ // or submit itself to any jurisdiction. /// -#include #include -#include -#include +#include +#include +#include #include #include @@ -22,6 +22,9 @@ #include "ITStracking/BoundedAllocator.h" #include "ITStracking/ClusterLines.h" #include "ITStracking/Tracklet.h" +#include "SimulationDataFormat/DigitizationContext.h" +#include "Steer/MCKinematicsReader.h" +#include "ITSMFTBase/DPLAlpideParam.h" #ifdef VTX_DEBUG #include "TTree.h" @@ -693,6 +696,59 @@ void VertexerTraits::computeVerticesInRof(int rofId, verticesInRof.push_back(foundVertices); } +void VertexerTraits::addTruthSeedingVertices() +{ + LOGP(info, "Using truth seeds as vertices; will skip computations"); + mTimeFrame->resetRofPV(); + const auto dc = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); + const auto irs = dc->getEventRecords(); + int64_t roFrameBiasInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameBiasInBC; + int64_t roFrameLengthInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameLengthInBC; + o2::steer::MCKinematicsReader mcReader(dc); + std::map> vertices; + for (int iSrc{0}; iSrc < mcReader.getNSources(); ++iSrc) { + auto eveId2colId = dc->getCollisionIndicesForSource(iSrc); + for (int iEve{0}; iEve < mcReader.getNEvents(iSrc); ++iEve) { + const auto& ir = irs[eveId2colId[iEve]]; + if (!ir.isDummy()) { // do we need this, is this for diffractive events? + const auto& eve = mcReader.getMCEventHeader(iSrc, iEve); + int rofId = (ir.toLong() - roFrameBiasInBC) / roFrameLengthInBC; + if (!vertices.contains(rofId)) { + vertices[rofId] = bounded_vector(mMemoryPool.get()); + } + Vertex vert; + vert.setTimeStamp(rofId); + vert.setNContributors(std::ranges::count_if(mcReader.getTracks(iSrc, iEve), [](const auto& trk) { + return trk.isPrimary() && trk.GetPt() > 0.2 && std::abs(trk.GetEta()) < 1.3; + })); + vert.setXYZ((float)eve.GetX(), (float)eve.GetY(), (float)eve.GetZ()); + vert.setChi2(1); + constexpr float cov = 50e-9; + vert.setCov(cov, cov, cov, cov, cov, cov); + vertices[rofId].push_back(vert); + } + } + } + size_t nVerts{0}; + for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) { + bounded_vector verts(mMemoryPool.get()); + bounded_vector> polls(mMemoryPool.get()); + if (vertices.contains(iROF)) { + verts = vertices[iROF]; + nVerts += verts.size(); + for (size_t i{0}; i < verts.size(); ++i) { + o2::MCCompLabel lbl; // unset label for now + polls.emplace_back(lbl, 1.f); + } + } else { + mTimeFrame->getNoVertexROF()++; + } + mTimeFrame->addPrimaryVertices(verts, iROF, 0); + mTimeFrame->addPrimaryVerticesLabels(polls); + } + LOGP(info, "Found {}/{} ROFs with {} vertices -> ={:.2f}", vertices.size(), mTimeFrame->getNrof(), nVerts, (float)nVerts / (float)vertices.size()); +} + void VertexerTraits::setNThreads(int n, std::shared_ptr& arena) { #if defined(VTX_DEBUG) From 0c0f2b98ef96d31e3f6de4ced5263f0b27d20442 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 14 Jul 2025 09:35:29 +0200 Subject: [PATCH 145/315] ITS: Vertexer remove unused code (#14508) Signed-off-by: Felix Schlepper --- .../include/ITStracking/VertexerTraits.h | 16 +- .../ITS/tracking/src/VertexerTraits.cxx | 141 ------------------ 2 files changed, 1 insertion(+), 156 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index a2429fe7270a8..54424136fcfe1 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -73,24 +73,10 @@ class VertexerTraits virtual void computeVertices(const int iteration = 0); virtual void adoptTimeFrame(TimeFrame7* tf) noexcept { mTimeFrame = tf; } virtual void updateVertexingParameters(const std::vector& vrtPar, const TimeFrameGPUParameters& gpuTfPar); + // truth tracking void addTruthSeedingVertices(); - void computeVerticesInRof(int, - gsl::span&, - bounded_vector&, - bounded_vector&, - std::array&, - bounded_vector&, - bounded_vector&, - TimeFrame7*, - bounded_vector*, - const int iteration = 0); - - bounded_vector> selectClusters(const int* indexTable, - const std::array& selectedBinsRect, - const IndexTableUtils& utils); - // utils auto& getVertexingParameters() { return mVrtParams; } auto getVertexingParameters() const { return mVrtParams; } diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index a0f044c5f62ca..bf421a8f8d59d 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -144,26 +144,6 @@ void trackletSelectionKernelHost( } } -bounded_vector> VertexerTraits::selectClusters(const int* indexTable, - const std::array& selectedBinsRect, - const IndexTableUtils& utils) -{ - bounded_vector> filteredBins{mMemoryPool.get()}; - int phiBinsNum{selectedBinsRect[3] - selectedBinsRect[1] + 1}; - if (phiBinsNum < 0) { - phiBinsNum += utils.getNphiBins(); - } - filteredBins.reserve(phiBinsNum); - for (int iPhiBin{selectedBinsRect[1]}, iPhiCount{0}; iPhiCount < phiBinsNum; - iPhiBin = ++iPhiBin == utils.getNphiBins() ? 0 : iPhiBin, iPhiCount++) { - const int firstBinIndex{utils.getBinIndex(selectedBinsRect[0], iPhiBin)}; - filteredBins.emplace_back( - indexTable[firstBinIndex], - utils.countRowSelectedBins(indexTable, iPhiBin, selectedBinsRect[0], selectedBinsRect[2])); - } - return filteredBins; -} - void VertexerTraits::updateVertexingParameters(const std::vector& vrtPar, const TimeFrameGPUParameters& tfPar) { mVrtParams = vrtPar; @@ -575,127 +555,6 @@ void VertexerTraits::computeVertices(const int iteration) #endif } -void VertexerTraits::computeVerticesInRof(int rofId, - gsl::span& lines, - bounded_vector& usedLines, - bounded_vector& clusterLines, - std::array& beamPosXY, - bounded_vector& vertices, - bounded_vector& verticesInRof, - TimeFrame7* tf, - bounded_vector* labels, - const int iteration) -{ - int foundVertices{0}; - auto nsigmaCut{std::min(mVrtParams[iteration].vertNsigmaCut * mVrtParams[iteration].vertNsigmaCut * (mVrtParams[iteration].vertRadiusSigma * mVrtParams[iteration].vertRadiusSigma + mVrtParams[iteration].trackletSigma * mVrtParams[iteration].trackletSigma), 1.98f)}; - const int numTracklets{static_cast(lines.size())}; - for (int line1{0}; line1 < numTracklets; ++line1) { - if (usedLines[line1]) { - continue; - } - for (int line2{line1 + 1}; line2 < numTracklets; ++line2) { - if (usedLines[line2]) { - continue; - } - auto dca{Line::getDCA(lines[line1], lines[line2])}; - if (dca < mVrtParams[iteration].pairCut) { - clusterLines.emplace_back(line1, lines[line1], line2, lines[line2]); - std::array tmpVertex{clusterLines.back().getVertex()}; - if (tmpVertex[0] * tmpVertex[0] + tmpVertex[1] * tmpVertex[1] > 4.f) { - clusterLines.pop_back(); - break; - } - usedLines[line1] = true; - usedLines[line2] = true; - for (int tracklet3{0}; tracklet3 < numTracklets; ++tracklet3) { - if (usedLines[tracklet3]) { - continue; - } - if (Line::getDistanceFromPoint(lines[tracklet3], tmpVertex) < mVrtParams[iteration].pairCut) { - clusterLines.back().add(tracklet3, lines[tracklet3]); - usedLines[tracklet3] = true; - tmpVertex = clusterLines.back().getVertex(); - } - } - break; - } - } - } - - if (mVrtParams[iteration].allowSingleContribClusters) { - auto beamLine = Line{{tf->getBeamX(), tf->getBeamY(), -50.f}, {tf->getBeamX(), tf->getBeamY(), 50.f}}; // use beam position as contributor - for (size_t iLine{0}; iLine < numTracklets; ++iLine) { - if (!usedLines[iLine]) { - auto dca = Line::getDCA(lines[iLine], beamLine); - if (dca < mVrtParams[iteration].pairCut) { - clusterLines.emplace_back(iLine, lines[iLine], -1, beamLine); // beamline must be passed as second line argument - } - } - } - } - - // Cluster merging - std::sort(clusterLines.begin(), clusterLines.end(), [](ClusterLines& cluster1, ClusterLines& cluster2) { return cluster1.getSize() > cluster2.getSize(); }); - size_t nClusters{clusterLines.size()}; - for (int iCluster1{0}; iCluster1 < nClusters; ++iCluster1) { - std::array vertex1{clusterLines[iCluster1].getVertex()}; - std::array vertex2{}; - for (int iCluster2{iCluster1 + 1}; iCluster2 < nClusters; ++iCluster2) { - vertex2 = clusterLines[iCluster2].getVertex(); - if (o2::gpu::GPUCommonMath::Abs(vertex1[2] - vertex2[2]) < mVrtParams[iteration].clusterCut) { - float distance{(vertex1[0] - vertex2[0]) * (vertex1[0] - vertex2[0]) + - (vertex1[1] - vertex2[1]) * (vertex1[1] - vertex2[1]) + - (vertex1[2] - vertex2[2]) * (vertex1[2] - vertex2[2])}; - if (distance < mVrtParams[iteration].pairCut * mVrtParams[iteration].pairCut) { - for (auto label : clusterLines[iCluster2].getLabels()) { - clusterLines[iCluster1].add(label, lines[label]); - vertex1 = clusterLines[iCluster1].getVertex(); - } - clusterLines.erase(clusterLines.begin() + iCluster2); - --iCluster2; - --nClusters; - } - } - } - } - - std::sort(clusterLines.begin(), clusterLines.end(), - [](ClusterLines& cluster1, ClusterLines& cluster2) { return cluster1.getSize() > cluster2.getSize(); }); // ensure clusters are ordered by contributors, so that we can cut after the first. - bool atLeastOneFound{false}; - for (int iCluster{0}; iCluster < nClusters; ++iCluster) { - bool lowMultCandidate{false}; - double beamDistance2{(tf->getBeamX() - clusterLines[iCluster].getVertex()[0]) * (tf->getBeamX() - clusterLines[iCluster].getVertex()[0]) + - (tf->getBeamY() - clusterLines[iCluster].getVertex()[1]) * (tf->getBeamY() - clusterLines[iCluster].getVertex()[1])}; - - if (atLeastOneFound && (lowMultCandidate = clusterLines[iCluster].getSize() < mVrtParams[iteration].clusterContributorsCut)) { // We might have pile up with nContr > cut. - lowMultCandidate &= (beamDistance2 < mVrtParams[iteration].lowMultBeamDistCut * mVrtParams[iteration].lowMultBeamDistCut); - if (!lowMultCandidate) { // Not the first cluster and not a low multiplicity candidate, we can remove it - clusterLines.erase(clusterLines.begin() + iCluster); - nClusters--; - continue; - } - } - if (beamDistance2 < nsigmaCut && o2::gpu::GPUCommonMath::Abs(clusterLines[iCluster].getVertex()[2]) < mVrtParams[iteration].maxZPositionAllowed) { - atLeastOneFound = true; - ++foundVertices; - vertices.emplace_back(o2::math_utils::Point3D(clusterLines[iCluster].getVertex()[0], - clusterLines[iCluster].getVertex()[1], - clusterLines[iCluster].getVertex()[2]), - clusterLines[iCluster].getRMS2(), // Symm matrix. Diagonal: RMS2 components, - // off-diagonal: square mean of projections on planes. - clusterLines[iCluster].getSize(), // Contributors - clusterLines[iCluster].getAvgDistance2()); // In place of chi2 - vertices.back().setTimeStamp(clusterLines[iCluster].getROF()); - if (labels) { - for (auto& index : clusterLines[iCluster].getLabels()) { - labels->push_back(tf->getLinesLabel(rofId)[index]); // then we can use nContributors from vertices to get the labels - } - } - } - } - verticesInRof.push_back(foundVertices); -} - void VertexerTraits::addTruthSeedingVertices() { LOGP(info, "Using truth seeds as vertices; will skip computations"); From 6d2c1d30e73406b86f8ccd335ef4b0de87311330 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 14 Jul 2025 09:41:08 +0200 Subject: [PATCH 146/315] ITS: opt. vertex cont. output (#14507) Signed-off-by: Felix Schlepper --- .../include/ITStracking/Configuration.h | 1 + .../tracking/include/ITStracking/TimeFrame.h | 20 +++++++++++++++++ .../include/ITStracking/TrackingConfigParam.h | 3 ++- .../ITSMFT/ITS/tracking/src/Configuration.cxx | 1 + .../ITSMFT/ITS/tracking/src/TimeFrame.cxx | 22 +++++++++++++++++++ .../ITS/tracking/src/TrackingInterface.cxx | 16 +++++++++++++- .../ITS/tracking/src/VertexerTraits.cxx | 10 +++++++++ .../ITS/workflow/src/TrackWriterSpec.cxx | 7 ++++++ .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 1 + 9 files changed, 79 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h index 8c46b2e72078a..19c4617426304 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h @@ -113,6 +113,7 @@ struct VertexingParameters { bool SaveTimeBenchmarks = false; bool useTruthSeeding = false; // overwrite found vertices with MC events + bool outputContLabels = false; int nThreads = 1; bool PrintMemory = false; // print allocator usage in epilog report diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h index 230a46681385d..9434fc2292750 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h @@ -73,15 +73,18 @@ struct TimeFrame { gsl::span getPrimaryVertices(int rofId) const; gsl::span getPrimaryVertices(int romin, int romax) const; gsl::span> getPrimaryVerticesMCRecInfo(const int rofId) const; + gsl::span getPrimaryVerticesContributors(const int rofId) const; gsl::span> getPrimaryVerticesXAlpha(int rofId) const; void fillPrimaryVerticesXandAlpha(); int getPrimaryVerticesNum(int rofId = -1) const; void addPrimaryVertices(const bounded_vector& vertices); void addPrimaryVerticesLabels(bounded_vector>& labels); + void addPrimaryVerticesContributorLabels(bounded_vector& labels); void addPrimaryVertices(const bounded_vector& vertices, const int rofId, const int iteration); void addPrimaryVertices(const gsl::span& vertices, const int rofId, const int iteration); void addPrimaryVerticesInROF(const bounded_vector& vertices, const int rofId, const int iteration); void addPrimaryVerticesLabelsInROF(const bounded_vector>& labels, const int rofId); + void addPrimaryVerticesContributorLabelsInROF(const bounded_vector& labels, const int rofId); void removePrimaryVerticesInROf(const int rofId); int loadROFrameData(const o2::itsmft::ROFRecord& rof, gsl::span clusters, const dataformats::MCTruthContainer* mcLabels = nullptr); @@ -342,6 +345,7 @@ struct TimeFrame { std::array, 2> mTrackletsIndexROF; std::vector> mLinesLabels; std::vector> mVerticesMCRecInfo; + bounded_vector mVerticesContributorLabels; std::array mTotalTracklets = {0, 0}; unsigned int mNoVertexROF = 0; bounded_vector mTotVertPerIteration; @@ -371,6 +375,22 @@ inline gsl::span> TimeFrame::getPri return {&(mVerticesMCRecInfo[start]), static_cast>::size_type>(delta)}; } +template +inline gsl::span TimeFrame::getPrimaryVerticesContributors(const int rofId) const +{ + // count the number of cont. in rofs before target rof + unsigned int start{0}, delta{0}; + const auto& pvsBefore = getPrimaryVertices(0, rofId - 1); + for (const auto& pv : pvsBefore) { + start += pv.getNContributors(); + } + const auto& pvsIn = getPrimaryVertices(rofId); + for (const auto& pv : pvsIn) { + delta += pv.getNContributors(); + } + return {&(mVerticesContributorLabels[start]), static_cast::size_type>(delta)}; +} + template inline gsl::span TimeFrame::getPrimaryVertices(int romin, int romax) const { diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h index 8de80d5e4cd07..dacc2019356f4 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h @@ -48,7 +48,8 @@ struct VertexerParamConfig : public o2::conf::ConfigurableParamHelper TrackingMode::getVertexingParameters(TrackingMo p.PhiBins = vc.PhiBins; p.useTruthSeeding = vc.useTruthSeeding; + p.outputContLabels = vc.outputContLabels; } // set for now outside to not disturb status quo vertParams[0].vertNsigmaCut = vc.vertNsigmaCut; diff --git a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx index 9c683112791ab..ea57e5fa8e3b9 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx @@ -85,6 +85,12 @@ void TimeFrame::addPrimaryVerticesLabels(bounded_vector +void TimeFrame::addPrimaryVerticesContributorLabels(bounded_vector& labels) +{ + mVerticesContributorLabels.insert(mVerticesContributorLabels.end(), labels.begin(), labels.end()); +} + template void TimeFrame::addPrimaryVerticesInROF(const bounded_vector& vertices, const int rofId, const int iteration) { @@ -101,6 +107,18 @@ void TimeFrame::addPrimaryVerticesLabelsInROF(const bounded_vector +void TimeFrame::addPrimaryVerticesContributorLabelsInROF(const bounded_vector& labels, const int rofId) +{ + // count the number of cont. in rofs before and including the target rof + unsigned int n{0}; + const auto& pvs = getPrimaryVertices(0, rofId); + for (const auto& pv : pvs) { + n += pv.getNContributors(); + } + mVerticesContributorLabels.insert(mVerticesContributorLabels.begin() + n, labels.begin(), labels.end()); +} + template void TimeFrame::addPrimaryVertices(const gsl::span& vertices, const int rofId, const int iteration) { @@ -295,6 +313,7 @@ void TimeFrame::initialise(const int iteration, const TrackingParameter deepVectorClear(mLinesLabels); if (resetVertices) { deepVectorClear(mVerticesMCRecInfo); + deepVectorClear(mVerticesContributorLabels); } clearResizeBoundedVector(mTracks, mNrof, mMemoryPool.get()); clearResizeBoundedVector(mTracksLabel, mNrof, mMemoryPool.get()); @@ -646,6 +665,7 @@ void TimeFrame::setMemoryPool(std::shared_ptr& p initVector(mClusterSize); initVector(mPValphaX); initVector(mBogusClusters); + initVector(mVerticesContributorLabels); initArrays(mTrackletsIndexROF); initVectors(mTracks); initVectors(mTracklets); @@ -689,6 +709,8 @@ void TimeFrame::wipe() deepVectorClear(mBogusClusters); deepVectorClear(mTrackletsIndexROF); deepVectorClear(mPrimaryVertices); + deepVectorClear(mTrackletClusters); + deepVectorClear(mVerticesContributorLabels); } template class TimeFrame<7>; diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index 31dc68d03a7e8..f5fa195983240 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -117,6 +117,8 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) static pmr::vector dummyMCPurVerts; auto& allTrackLabels = mIsMC ? pc.outputs().make>(Output{"ITS", "TRACKSMCTR", 0}) : dummyMCLabTracks; auto& allVerticesLabels = mIsMC ? pc.outputs().make>(Output{"ITS", "VERTICESMCTR", 0}) : dummyMCLabVerts; + bool writeContLabels = mIsMC && o2::its::VertexerParamConfig::Instance().outputContLabels; + auto& allVerticesContLabels = writeContLabels ? pc.outputs().make>(Output{"ITS", "VERTICESMCTRCONT", 0}) : dummyMCLabVerts; auto& allVerticesPurities = mIsMC ? pc.outputs().make>(Output{"ITS", "VERTICESMCPUR", 0}) : dummyMCPurVerts; std::uint32_t roFrame = 0; @@ -159,6 +161,7 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) } const auto& multEstConf = FastMultEstConfig::Instance(); // parameters for mult estimation and cuts gsl::span> vMCRecInfo; + gsl::span vMCContLabels; for (auto iRof{0}; iRof < trackROFspan.size(); ++iRof) { std::vector vtxVecLoc; auto& vtxROF = vertROFvec.emplace_back(trackROFspan[iRof]); @@ -167,6 +170,9 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) auto vtxSpan = mTimeFrame->getPrimaryVertices(iRof); if (mIsMC) { vMCRecInfo = mTimeFrame->getPrimaryVerticesMCRecInfo(iRof); + if (o2::its::VertexerParamConfig::Instance().outputContLabels) { + vMCContLabels = mTimeFrame->getPrimaryVerticesContributors(iRof); + } } if (o2::its::TrackerParamConfig::Instance().doUPCIteration) { if (!vtxSpan.empty()) { @@ -186,9 +192,10 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) } vtxROF.setNEntries(vtxSpan.size()); bool selROF = vtxSpan.empty(); - for (auto iV{0}; iV < vtxSpan.size(); ++iV) { + for (int iV{0}, iVC{0}; iV < vtxSpan.size(); ++iV) { const auto& v = vtxSpan[iV]; if (multEstConf.isVtxMultCutRequested() && !multEstConf.isPassingVtxMultCut(v.getNContributors())) { + iVC += v.getNContributors(); continue; // skip vertex of unwanted multiplicity } selROF = true; @@ -196,7 +203,11 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) if (mIsMC && !VertexerParamConfig::Instance().useTruthSeeding) { allVerticesLabels.push_back(vMCRecInfo[iV].first); allVerticesPurities.push_back(vMCRecInfo[iV].second); + if (o2::its::VertexerParamConfig::Instance().outputContLabels) { + allVerticesContLabels.insert(allVerticesContLabels.end(), vMCContLabels.begin() + iVC, vMCContLabels.begin() + iVC + v.getNContributors()); + } } + iVC += v.getNContributors(); } if (processingMask[iRof] && !selROF) { // passed selection in clusters and not in vertex multiplicity LOGP(info, "ROF {} rejected by the vertex multiplicity selection [{},{}]", iRof, multEstConf.cutMultVtxLow, multEstConf.cutMultVtxHigh); @@ -291,6 +302,9 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) if (mIsMC) { LOGP(info, "ITSTracker pushed {} track labels", allTrackLabels.size()); LOGP(info, "ITSTracker pushed {} vertex labels", allVerticesLabels.size()); + if (!allVerticesContLabels.empty()) { + LOGP(info, "ITSTracker pushed {} vertex contributor labels", allVerticesContLabels.size()); + } LOGP(info, "ITSTracker pushed {} vertex purities", allVerticesPurities.size()); } } diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index bf421a8f8d59d..409ce8895aa36 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -388,6 +388,7 @@ void VertexerTraits::computeVertices(const int iteration) auto nsigmaCut{std::min(mVrtParams[iteration].vertNsigmaCut * mVrtParams[iteration].vertNsigmaCut * (mVrtParams[iteration].vertRadiusSigma * mVrtParams[iteration].vertRadiusSigma + mVrtParams[iteration].trackletSigma * mVrtParams[iteration].trackletSigma), 1.98f)}; bounded_vector vertices(mMemoryPool.get()); bounded_vector> polls(mMemoryPool.get()); + bounded_vector contLabels(mMemoryPool.get()); #ifdef VTX_DEBUG std::vector> dbg_clusLines(mTimeFrame->getNrof()); #endif @@ -511,6 +512,9 @@ void VertexerTraits::computeVertices(const int iteration) labels.push_back(mTimeFrame->getLinesLabel(rofId)[index]); // then we can use nContributors from vertices to get the labels } polls.push_back(computeMain(labels)); + if (mVrtParams[iteration].outputContLabels) { + contLabels.insert(contLabels.end(), labels.begin(), labels.end()); + } } } } @@ -518,11 +522,17 @@ void VertexerTraits::computeVertices(const int iteration) mTimeFrame->addPrimaryVertices(vertices, rofId, iteration); if (mTimeFrame->hasMCinformation()) { mTimeFrame->addPrimaryVerticesLabels(polls); + if (mVrtParams[iteration].outputContLabels) { + mTimeFrame->addPrimaryVerticesContributorLabels(contLabels); + } } } else { mTimeFrame->addPrimaryVerticesInROF(vertices, rofId, iteration); if (mTimeFrame->hasMCinformation()) { mTimeFrame->addPrimaryVerticesLabelsInROF(polls, rofId); + if (mVrtParams[iteration].outputContLabels) { + mTimeFrame->addPrimaryVerticesContributorLabelsInROF(contLabels, rofId); + } } } if (vertices.empty() && !(iteration && (int)mTimeFrame->getPrimaryVertices(rofId).size() > mVrtParams[iteration].vertPerRofThreshold)) { diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx index 5cb6aa199ab64..9fbb138b376b2 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackWriterSpec.cxx @@ -20,6 +20,7 @@ #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/MCTruthContainer.h" #include "ReconstructionDataFormats/Vertex.h" +#include "ITStracking/TrackingConfigParam.h" using namespace o2::framework; @@ -39,6 +40,7 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) { // Spectators for logging // this is only to restore the original behavior + const auto writeContLabels = VertexerParamConfig::Instance().outputContLabels && useMC; auto tracksSize = std::make_shared(0); auto tracksSizeGetter = [tracksSize](std::vector const& tracks) { *tracksSize = tracks.size(); @@ -69,6 +71,11 @@ DataProcessorSpec getTrackWriterSpec(bool useMC) "ITSVertexMCTruth", (useMC ? 1 : 0), // one branch if mc labels enabled ""}, + BranchDefinition{InputSpec{"labelsVerticesContributors", "ITS", "VERTICESMCTRCONT", 0}, + "ITSVertexMCTruthCont", + (writeContLabels ? 1 : 0), // one branch if + // requested + ""}, BranchDefinition{InputSpec{"MC2ROframes", "ITS", "ITSTrackMC2ROF", 0}, "ITSTracksMC2ROF", (useMC ? 1 : 0), // one branch if mc labels enabled diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index fedc42c017f7e..c8a785b6a3627 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -120,6 +120,7 @@ DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, Tracking inputs.emplace_back("itsmclabels", "ITS", "CLUSTERSMCTR", 0, Lifetime::Timeframe); inputs.emplace_back("ITSMC2ROframes", "ITS", "CLUSTERSMC2ROF", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "VERTICESMCTR", 0, Lifetime::Timeframe); + outputs.emplace_back("ITS", "VERTICESMCTRCONT", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "VERTICESMCPUR", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "TRACKSMCTR", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "ITSTrackMC2ROF", 0, Lifetime::Timeframe); From 3c7f5313b86998ce2774f40a2ddd7f82e01d05ec Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 1 Jul 2025 15:25:53 +0200 Subject: [PATCH 147/315] ITS: allow overriding number of iterations for tracker Signed-off-by: Felix Schlepper --- .../ITS/tracking/include/ITStracking/TrackingConfigParam.h | 1 + Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h index dacc2019356f4..ef6f925f1c29f 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h @@ -95,6 +95,7 @@ struct TrackerParamConfig : public o2::conf::ConfigurableParamHelper TrackingMode::getTrackingParameters(TrackingMode } } + if (trackParams.size() > tc.nIterations) { + trackParams.resize(tc.nIterations); + } + return trackParams; } From 30b301e4c44f2cb50ae6ef626cedbaaf5ee0ec88 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Fri, 4 Jul 2025 09:46:20 +0200 Subject: [PATCH 148/315] ITS: disable reco via configParams Signed-off-by: Felix Schlepper --- .../ITSMFT/ITS/workflow/src/RecoWorkflow.cxx | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx index a72c26a3681e1..948d2c1b53009 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/RecoWorkflow.cxx @@ -17,21 +17,15 @@ #include "ITSWorkflow/TrackerSpec.h" #include "ITSWorkflow/CookedTrackerSpec.h" #include "ITSWorkflow/TrackWriterSpec.h" +#include "ITStracking/TrackingConfigParam.h" #include "ITSMFTWorkflow/DigitReaderSpec.h" #include "GlobalTrackingWorkflowWriters/IRFrameWriterSpec.h" #include "GPUWorkflow/GPUWorkflowSpec.h" #include "Framework/CCDBParamSpec.h" // Dummy TPC completion policy data -using CompletionPolicyData = std::vector; -static CompletionPolicyData gPolicyData; -static std::shared_ptr gTask; -namespace o2 -{ -namespace its -{ -namespace reco_workflow +namespace o2::its::reco_workflow { framework::WorkflowSpec getWorkflow(bool useMC, @@ -56,14 +50,15 @@ framework::WorkflowSpec getWorkflow(bool useMC, if (!disableRootOutput) { specs.emplace_back(o2::its::getClusterWriterSpec(useMC)); } - if (trmode != TrackingMode::Off) { + if ((trmode != TrackingMode::Off) && (TrackerParamConfig::Instance().trackingMode != TrackingMode::Off)) { if (useCAtracker) { if (useGPUWF) { - o2::gpu::GPURecoWorkflowSpec::Config cfg; - cfg.runITSTracking = true; - cfg.itsTriggerType = useTrig; - cfg.itsOverrBeamEst = overrideBeamPosition; - cfg.processMC = useMC; + o2::gpu::GPURecoWorkflowSpec::Config cfg{ + .itsTriggerType = useTrig, + .processMC = useMC, + .runITSTracking = true, + .itsOverrBeamEst = overrideBeamPosition, + }; Inputs ggInputs; auto ggRequest = std::make_shared(false, true, false, true, true, @@ -73,18 +68,18 @@ framework::WorkflowSpec getWorkflow(bool useMC, ggRequest->addInput({"itsTGeo", "ITS", "GEOMTGEO", 0, Lifetime::Condition, framework::ccdbParamSpec("ITS/Config/Geometry")}, ggInputs); } - auto task = std::make_shared(&gPolicyData, cfg, std::vector(), 0, ggRequest); - gTask = task; + static std::vector policyData; + static std::shared_ptr task = std::make_shared(&policyData, cfg, std::vector(), 0, ggRequest); Inputs taskInputs = task->inputs(); Options taskOptions = task->options(); std::move(ggInputs.begin(), ggInputs.end(), std::back_inserter(taskInputs)); specs.emplace_back(DataProcessorSpec{ - "its-gpu-tracker", - taskInputs, - task->outputs(), - AlgorithmSpec{adoptTask(task)}, - taskOptions}); + .name = "its-gpu-tracker", + .inputs = taskInputs, + .outputs = task->outputs(), + .algorithm = AlgorithmSpec{adoptTask(task)}, + .options = taskOptions}); } else { specs.emplace_back(o2::its::getTrackerSpec(useMC, useGeom, useTrig, trmode, overrideBeamPosition, dtype)); } @@ -99,6 +94,4 @@ framework::WorkflowSpec getWorkflow(bool useMC, return specs; } -} // namespace reco_workflow -} // namespace its -} // namespace o2 +} // namespace o2::its::reco_workflow From 5b80babd7f2d5abe97c585e0c5085a05d90c1e62 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio Date: Tue, 15 Jul 2025 19:49:12 +0800 Subject: [PATCH 149/315] Add missing TPCNClsPID dynamic columns (#14503) When the data member was inserted, we forgot to add the corresponding dynamic column in the table. --- Framework/Core/include/Framework/AnalysisDataModel.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Framework/Core/include/Framework/AnalysisDataModel.h b/Framework/Core/include/Framework/AnalysisDataModel.h index e34b8210a0178..2a9e1b61ee6df 100644 --- a/Framework/Core/include/Framework/AnalysisDataModel.h +++ b/Framework/Core/include/Framework/AnalysisDataModel.h @@ -621,6 +621,7 @@ DECLARE_SOA_TABLE_FULL_VERSIONED(StoredTracksExtra_002, "TracksExtra", "AOD", "T track::HasITS, track::HasTPC, track::HasTRD, track::HasTOF, track::TPCNClsFound, + track::TPCNClsPID, track::TPCNClsCrossedRows, track::v001::ITSClusterMap, track::v001::ITSNCls, track::v001::ITSNClsInnerBarrel, track::v001::ITSClsSizeInLayer, From 0c69826c1eddc7c295e0b13421fb5b3be8a37fc3 Mon Sep 17 00:00:00 2001 From: swenzel Date: Sat, 12 Jul 2025 17:31:26 +0200 Subject: [PATCH 150/315] HepMC: Remove default backgrounding mode Removing the default & at the end of HepMC child processes. This should not be needed and actually leads to children be executed outside of the process tree of simulation. This in turn corrupts CPU and MEM monitoring in O2DPG MC workflows. Changing default for now but maybe we can eventually get rid of this completely. --- Generators/include/Generators/GeneratorFileOrCmdParam.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Generators/include/Generators/GeneratorFileOrCmdParam.h b/Generators/include/Generators/GeneratorFileOrCmdParam.h index d4023d01e6ac2..72bc3d00141fe 100644 --- a/Generators/include/Generators/GeneratorFileOrCmdParam.h +++ b/Generators/include/Generators/GeneratorFileOrCmdParam.h @@ -35,7 +35,7 @@ struct GeneratorFileOrCmdParam : public o2::conf::ConfigurableParamHelper Date: Tue, 15 Jul 2025 15:18:45 +0200 Subject: [PATCH 151/315] DPL: drop unneeded headers. --- Framework/Core/src/AODReaderHelpers.cxx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index 4dbd2877476be..ba68cbf15a6e9 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -10,29 +10,21 @@ // or submit itself to any jurisdiction. #include "Framework/AODReaderHelpers.h" -#include "Framework/TableTreeHelpers.h" #include "Framework/AnalysisHelpers.h" #include "Framework/AnalysisDataModelHelpers.h" #include "Framework/DataProcessingHelpers.h" #include "Framework/ExpressionHelpers.h" #include "Framework/AlgorithmSpec.h" -#include "Framework/ConfigParamRegistry.h" #include "Framework/ControlService.h" #include "Framework/CallbackService.h" #include "Framework/EndOfStreamContext.h" -#include "Framework/DeviceSpec.h" -#include "Framework/RawDeviceService.h" #include "Framework/DataSpecUtils.h" -#include "Framework/SourceInfoHeader.h" -#include "Framework/ChannelInfo.h" -#include "Framework/Logger.h" #include #include #include #include -#include #include #include @@ -40,8 +32,6 @@ #include #include -#include - namespace o2::framework::readers { auto setEOSCallback(InitContext& ic) From 36f656bafe7cf6e496d3dd7f84959636d228e211 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 16 Jul 2025 00:53:33 +0200 Subject: [PATCH 152/315] Add LIGHTNUCLEI flag, extend pp settings on BEAMTYPE leading to LIGHTNUCLEI=1 --- prodtests/full-system-test/dpl-workflow.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 202352730ddc7..ed9a230670c02 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -29,6 +29,8 @@ fi : ${CTF_FREE_DISK_WAIT:="10"} # if disk on EPNs is close to full, wait X seconds before retrying to write : ${CTF_MAX_FREE_DISK_WAIT:="600"} # if not enough disk space after this time throw error +[[ -z ${LIGHTNUCLEI:-} ]] && export LIGHTNUCLEI="0" # temporarily, in case O2DPG is not synced yet to the version knowing LIGHTNUCLEI + # entropy encoding/decoding mode, '' is equivalent to '--ans-version compat' (compatible with < 09/2023 data), # use '--ans-version 1.0 --ctf-dict none' for the new per-TF dictionary mode : ${RANS_OPT:="--ans-version 1.0 --ctf-dict none"} @@ -118,7 +120,7 @@ if [[ $SYNCMODE == 1 ]]; then ITS_CONFIG_KEY+="fastMultConfig.cutMultClusLow=${CUT_MULT_MIN_ITS:-100};fastMultConfig.cutMultClusHigh=${CUT_MULT_MAX_ITS:-200};fastMultConfig.cutMultVtxHigh=${CUT_MULT_VTX_ITS:-20};" MCH_CONFIG_KEY="MCHTracking.maxCandidates=50000;MCHTracking.maxTrackingDuration=20;" MFT_CONFIG_KEY+="MFTTracking.cutMultClusLow=0;MFTTracking.cutMultClusHigh=20000;" - elif [[ $BEAMTYPE == "pp" ]]; then + elif [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then ITS_CONFIG_KEY+="fastMultConfig.cutMultClusLow=${CUT_MULT_MIN_ITS:--1};fastMultConfig.cutMultClusHigh=${CUT_MULT_MAX_ITS:--1};fastMultConfig.cutMultVtxHigh=${CUT_MULT_VTX_ITS:--1};ITSVertexerParam.phiCut=0.5;ITSVertexerParam.clusterContributorsCut=3;ITSVertexerParam.tanLambdaCut=0.2;" MCH_CONFIG_KEY="MCHTracking.maxCandidates=20000;MCHTracking.maxTrackingDuration=10;" MFT_CONFIG_KEY+="MFTTracking.cutMultClusLow=0;MFTTracking.cutMultClusHigh=3000;" @@ -147,7 +149,7 @@ if [[ $SYNCMODE == 1 ]]; then has_detector ITS && TRD_FILTER_CONFIG+=" --filter-trigrec" else has_detectors_gpu TPC ITS && ITS_CONFIG_KEY+="ITSCATrackerParam.trackingMode=1;" # sets ITS gpu reco to async - if [[ $BEAMTYPE == "pp" ]]; then + if [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then ITS_CONFIG_KEY+="ITSVertexerParam.phiCut=0.5;ITSVertexerParam.clusterContributorsCut=3;ITSVertexerParam.tanLambdaCut=0.2;" elif [[ $BEAMTYPE == "PbPb" ]]; then ITS_CONFIG_KEY+="ITSVertexerParam.lowMultBeamDistCut=0;" @@ -169,6 +171,8 @@ if [[ $BEAMTYPE == "PbPb" ]]; then INTERACTION_TAG_CONFIG_KEY="ft0tag.minAmplitudeA=${INT_TAG_FT0A:-5};ft0tag.minAmplitudeC=${INT_TAG_FT0C:-5};ft0tag.minAmplitudeAC=${INT_TAG_FT0AC:-20};" elif [[ $BEAMTYPE == "pp" ]]; then PVERTEXING_CONFIG_KEY+="pvertexer.maxChi2TZDebris=10;" +elif [[ $LIGHTNUCLEI == "1" ]]; then + PVERTEXING_CONFIG_KEY+="pvertexer.maxChi2TZDebris=100;" fi if [[ $BEAMTYPE == "cosmic" ]]; then @@ -360,7 +364,7 @@ if has_processing_step MUON_SYNC_RECO; then [[ -z ${ARGS_EXTRA_PROCESS_o2_mch_reco_workflow:-} ]] && ARGS_EXTRA_PROCESS_o2_mch_reco_workflow="--digits" if [[ $IS_SIMULATED_DATA == 1 ]]; then MCH_CONFIG_KEY+="MCHTimeClusterizer.peakSearchSignalOnly=false;MCHDigitFilter.rejectBackground=false;" - elif [[ $RUNTYPE == "PHYSICS" && $BEAMTYPE == "pp" ]] || [[ $RUNTYPE == "COSMICS" ]]; then + elif [[ $RUNTYPE == "PHYSICS" && $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]] || [[ $RUNTYPE == "COSMICS" ]]; then MCH_CONFIG_KEY+="MCHTracking.chamberResolutionX=0.4;MCHTracking.chamberResolutionY=0.4;MCHTracking.sigmaCutForTracking=7.;MCHTracking.sigmaCutForImprovement=6.;" fi has_detector_reco ITS && [[ $RUNTYPE != "COSMICS" ]] && MCH_CONFIG_KEY+="MCHTimeClusterizer.irFramesOnly=true;" From 664d682cbd5d7edc89a46a878c7b46b21888a6a8 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 16 Jul 2025 17:46:11 +0200 Subject: [PATCH 153/315] dpl-workflow: Fix logic to mlock shm segments --- prodtests/full-system-test/dpl-workflow.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index ed9a230670c02..486be1a9160cd 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -48,7 +48,7 @@ source $GEN_TOPO_MYDIR/getCommonArgs.sh || { echo "getCommonArgs.sh failed" 1>&2 workflow_has_parameter CALIB && { source $O2DPG_ROOT/DATA/common/setenv_calib.sh; [[ $? != 0 ]] && echo "setenv_calib.sh failed" 1>&2 && exit 1; } [[ -z ${SHM_MANAGER_SHMID:-} ]] && ( [[ $EXTINPUT == 1 ]] || [[ $NUMAGPUIDS != 0 ]] ) && ARGS_ALL+=" --no-cleanup" -[[ $GPUTYPE != "CPU" || ( ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} && -z ${SETENV_NO_ULIMIT:-} ) ]] && ARGS_ALL+=" --shm-mlock-segment-on-creation 1" +[[ ( $GPUTYPE != "CPU" || -n ${OPTIMIZED_PARALLEL_ASYNC:-} ) && ${SETENV_NO_ULIMIT:-0} == 0 ]] && ARGS_ALL+=" --shm-mlock-segment-on-creation 1" if [[ $EPNSYNCMODE == 1 ]] || type numactl >/dev/null 2>&1 && [[ `numactl -H | grep "node . size" | wc -l` -ge 2 ]]; then [[ $NUMAGPUIDS != 0 ]] && ARGS_ALL+=" --child-driver 'numactl --membind $NUMAID --cpunodebind $NUMAID'" fi From 92375f9f0b675e4ba21426e524635fd633dd7214 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 16 Jul 2025 16:40:05 +0200 Subject: [PATCH 154/315] Extend run-time-span-file and invert-irframe-selection TF selections to raw-tf-reader --- Detectors/CTF/workflow/src/CTFReaderSpec.cxx | 6 +- Detectors/Raw/TFReaderDD/CMakeLists.txt | 1 + Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx | 142 +++++++++++++++++- Detectors/Raw/TFReaderDD/src/TFReaderSpec.h | 2 + .../Raw/TFReaderDD/src/tf-reader-workflow.cxx | 5 +- 5 files changed, 147 insertions(+), 9 deletions(-) diff --git a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx index e502b88611a3c..3810230637e5f 100644 --- a/Detectors/CTF/workflow/src/CTFReaderSpec.cxx +++ b/Detectors/CTF/workflow/src/CTFReaderSpec.cxx @@ -112,7 +112,7 @@ class CTFReaderSpec : public o2::framework::Task int mCTFCounterAcc = 0; int mNFailedFiles = 0; int mFilesRead = 0; - int mTFLength = 128; + int mTFLength = 32; int mNWaits = 0; int mRunNumberPrev = -1; long mTotalWaitTime = 0; @@ -234,7 +234,7 @@ void CTFReaderSpec::loadRunTimeSpans(const std::string& flname) { std::ifstream inputFile(flname); if (!inputFile) { - LOGP(fatal, "Failed to open selected run/timespans file {}", mInput.fileRunTimeSpans); + LOGP(fatal, "Failed to open selected run/timespans file {}", flname); } std::string line; size_t cntl = 0, cntr = 0; @@ -286,7 +286,7 @@ void CTFReaderSpec::loadRunTimeSpans(const std::string& flname) logError(); } } - LOGP(info, "Read {} time-spans for {} runs from {}", cntr, mRunTimeRanges.size(), mInput.fileRunTimeSpans); + LOGP(info, "Read {} time-spans for {} runs from {}", cntr, mRunTimeRanges.size(), flname); inputFile.close(); } diff --git a/Detectors/Raw/TFReaderDD/CMakeLists.txt b/Detectors/Raw/TFReaderDD/CMakeLists.txt index e58f0d50115f7..12ecc9ca8795d 100644 --- a/Detectors/Raw/TFReaderDD/CMakeLists.txt +++ b/Detectors/Raw/TFReaderDD/CMakeLists.txt @@ -16,6 +16,7 @@ o2_add_library(TFReaderDD O2::Headers O2::Framework O2::DetectorsRaw + O2::DataFormatsParameters O2::CommonUtils O2::Algorithm FairMQ::FairMQ) diff --git a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx index 07a62a7fd4a58..f4cd64377034e 100644 --- a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx +++ b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx @@ -31,8 +31,14 @@ #include "TFReaderSpec.h" #include "TFReaderDD/SubTimeFrameFileReader.h" #include "TFReaderDD/SubTimeFrameFile.h" +#include "CommonUtils/StringUtils.h" #include "CommonUtils/FileFetcher.h" #include "CommonUtils/FIFO.h" +#include "CommonUtils/IRFrameSelector.h" +#include "DataFormatsParameters/AggregatedRunInfo.h" +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/LHCConstants.h" +#include "Algorithm/RangeTokenizer.h" #include #include #include @@ -66,6 +72,8 @@ class TFReaderSpec : public o2f::Task void endOfStream(o2f::EndOfStreamContext& ec) final; private: + void loadRunTimeSpans(const std::string& flname); + void runTimeRangesToIRFrameSelector(int runNumber); void stopProcessing(o2f::ProcessingContext& ctx); void TFBuilder(); @@ -76,9 +84,13 @@ class TFReaderSpec : public o2f::Task o2::utils::FIFO> mTFQueue{}; // queued TFs // std::unordered_map> mSeenOutputMap; std::unordered_map mSeenOutputMap; + std::map>> mRunTimeRanges; + o2::utils::IRFrameSelector mIRFrameSelector; // optional IR frames selector + int mConvRunTimeRangesToOrbits = -1; // not defined yet int mTFCounter = 0; int mTFBuilderCounter = 0; int mNWaits = 0; + int mTFLength = 32; long mTotalWaitTime = 0; size_t mSelIDEntry = 0; // next TFID to select from the mInput.tfIDs (if non-empty) bool mRunning = false; @@ -105,6 +117,9 @@ void TFReaderSpec::init(o2f::InitContext& ic) mInput.maxTFsPerFile = mInput.maxTFsPerFile > 0 ? mInput.maxTFsPerFile : 0x7fffffff; mInput.maxTFCache = std::max(1, ic.options().get("max-cached-tf")); mInput.maxFileCache = std::max(1, ic.options().get("max-cached-files")); + if (!mInput.fileRunTimeSpans.empty()) { + loadRunTimeSpans(mInput.fileRunTimeSpans); + } mFileFetcher = std::make_unique(mInput.inpdata, mInput.tffileRegex, mInput.remoteRegex, mInput.copyCmd); mFileFetcher->setMaxFilesInQueue(mInput.maxFileCache); mFileFetcher->setMaxLoops(mInput.maxLoops); @@ -142,10 +157,6 @@ void TFReaderSpec::run(o2f::ProcessingContext& ctx) if (verbose && mInput.verbosity > 0) { LOGP(info, "Acknowledge: part {}/{} {}/{}/{:#x} size:{} split {}/{}", ip, np, hd->dataOrigin.as(), hd->dataDescription.as(), hd->subSpecification, msgh.GetSize() + parts[ip + 1].GetSize(), hd->splitPayloadIndex, hd->splitPayloadParts); } - if (dph->startTime != this->mTFCounter) { - LOGP(fatal, "Local tf counter {} != TF timeslice {} for {}", this->mTFCounter, dph->startTime, - o2::framework::DataSpecUtils::describe(o2::framework::OutputSpec{hd->dataOrigin, hd->dataDescription, hd->subSpecification})); - } if (hd->splitPayloadIndex == 0) { // check the 1st one only auto& entry = this->mSeenOutputMap[{hd->dataDescription.str, hd->dataOrigin.str}]; if (entry.count != this->mTFCounter) { @@ -412,8 +423,25 @@ void TFReaderSpec::TFBuilder() auto tf = reader.read(mDevice, mOutputRoutes, mInput.rawChannelConfig, mSelIDEntry, mInput.sup0xccdb, mInput.verbosity); bool acceptTF = true; if (tf) { + if (mRunTimeRanges.size()) { + const auto* dataptr = (*tf->begin()->second.get())[0].GetData(); + const auto* hd0 = o2h::get(dataptr); + static int runNumberPrev = -1; + if (runNumberPrev != hd0->runNumber) { + runNumberPrev = hd0->runNumber; + runTimeRangesToIRFrameSelector(runNumberPrev); + } + if (mIRFrameSelector.isSet()) { + o2::InteractionRecord ir0(0, hd0->firstTForbit); + o2::InteractionRecord ir1(o2::constants::lhc::LHCMaxBunches - 1, hd0->firstTForbit < 0xffffffff - (mTFLength - 1) ? hd0->firstTForbit + (mTFLength - 1) : 0xffffffff); + auto irSpan = mIRFrameSelector.getMatchingFrames({ir0, ir1}); + acceptTF = (irSpan.size() > 0) ? !mInput.invertIRFramesSelection : mInput.invertIRFramesSelection; + LOGP(info, "IRFrame selection contains {} frames for TF [{}] : [{}]: {}use this TF (selection inversion mode is {})", + irSpan.size(), ir0.asString(), ir1.asString(), acceptTF ? "" : "do not ", mInput.invertIRFramesSelection ? "ON" : "OFF"); + } + } locID++; - if (!mInput.tfIDs.empty()) { + if (!mInput.tfIDs.empty() && acceptTF) { acceptTF = false; if (mInput.tfIDs[mSelIDEntry] == mTFBuilderCounter) { mWaitSendingLast = false; @@ -448,6 +476,110 @@ void TFReaderSpec::TFBuilder() } } +//_________________________________________________________ +void TFReaderSpec::loadRunTimeSpans(const std::string& flname) +{ + std::ifstream inputFile(flname); + if (!inputFile) { + LOGP(fatal, "Failed to open selected run/timespans file {}", flname); + } + std::string line; + size_t cntl = 0, cntr = 0; + while (std::getline(inputFile, line)) { + cntl++; + for (char& ch : line) { // Replace semicolons and tabs with spaces for uniform processing + if (ch == ';' || ch == '\t' || ch == ',') { + ch = ' '; + } + } + o2::utils::Str::trim(line); + if (line.size() < 1 || line[0] == '#') { + continue; + } + auto tokens = o2::utils::Str::tokenize(line, ' '); + auto logError = [&cntl, &line]() { LOGP(error, "Expected format for selection is tripplet , failed on line#{}: {}", cntl, line); }; + if (tokens.size() >= 3) { + int run = 0; + long rmin, rmax; + try { + run = std::stoi(tokens[0]); + rmin = std::stol(tokens[1]); + rmax = std::stol(tokens[2]); + } catch (...) { + logError(); + continue; + } + + constexpr long ISTimeStamp = 1514761200000L; + int convmn = rmin > ISTimeStamp ? 1 : 0, convmx = rmax > ISTimeStamp ? 1 : 0; // values above ISTimeStamp are timestamps (need to be converted to orbits) + if (rmin > rmax) { + LOGP(fatal, "Provided range limits are not in increasing order, entry is {}", line); + } + if (mConvRunTimeRangesToOrbits == -1) { + if (convmn != convmx) { + LOGP(fatal, "Provided range limits should be both consistent either with orbit number or with unix timestamp in ms, entry is {}", line); + } + mConvRunTimeRangesToOrbits = convmn; // need to convert to orbit if time + LOGP(info, "Interpret selected time-spans input as {}", mConvRunTimeRangesToOrbits == 1 ? "timstamps(ms)" : "orbits"); + } else { + if (mConvRunTimeRangesToOrbits != convmn || mConvRunTimeRangesToOrbits != convmx) { + LOGP(fatal, "Provided range limits should are not consistent with previously determined {} input, entry is {}", mConvRunTimeRangesToOrbits == 1 ? "timestamps" : "orbits", line); + } + } + + mRunTimeRanges[run].emplace_back(rmin, rmax); + cntr++; + } else { + logError(); + } + } + LOGP(info, "Read {} time-spans for {} runs from {}", cntr, mRunTimeRanges.size(), flname); + inputFile.close(); +} + +//_________________________________________________________ +void TFReaderSpec::runTimeRangesToIRFrameSelector(int runNumber) +{ + // convert entries in the runTimeRanges to IRFrameSelector, if needed, convert time to orbit + mIRFrameSelector.clear(); + auto ent = mRunTimeRanges.find(runNumber); + if (ent == mRunTimeRanges.end()) { + LOGP(info, "RunTimeRanges selection was provided but run {} has no entries, all TFs will be processed", runNumber); + return; + } + o2::parameters::AggregatedRunInfo rinfo; + auto& ccdb = o2::ccdb::BasicCCDBManager::instance(); + rinfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(ccdb, runNumber); + if (rinfo.runNumber != runNumber || rinfo.orbitsPerTF < 1) { + LOGP(fatal, "failed to extract AggregatedRunInfo for run {}", runNumber); + } + mTFLength = rinfo.orbitsPerTF; + std::vector frames; + for (const auto& rng : ent->second) { + long orbMin = 0, orbMax = 0; + if (mConvRunTimeRangesToOrbits > 0) { + orbMin = rinfo.orbitSOR + (rng.first - rinfo.sor) / (o2::constants::lhc::LHCOrbitMUS * 0.001); + orbMax = rinfo.orbitSOR + (rng.second - rinfo.sor) / (o2::constants::lhc::LHCOrbitMUS * 0.001); + } else { + orbMin = rng.first; + orbMax = rng.second; + } + if (orbMin < 0) { + orbMin = 0; + } + if (orbMax < 0) { + orbMax = 0; + } + if (runNumber > 523897) { + orbMin = (orbMin / rinfo.orbitsPerTF) * rinfo.orbitsPerTF; + orbMax = (orbMax / rinfo.orbitsPerTF + 1) * rinfo.orbitsPerTF - 1; + } + LOGP(info, "TFs overlapping with orbits {}:{} will be {}", orbMin, orbMax, mInput.invertIRFramesSelection ? "rejected" : "selected"); + frames.emplace_back(o2::InteractionRecord{0, uint32_t(orbMin)}, o2::InteractionRecord{o2::constants::lhc::LHCMaxBunches, uint32_t(orbMax)}); + } + mIRFrameSelector.setOwnList(frames, true); +} + //_________________________________________________________ o2f::DataProcessorSpec o2::rawdd::getTFReaderSpec(o2::rawdd::TFReaderInp& rinp) { diff --git a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.h b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.h index e3a5b5c920010..9db18768c1bfe 100644 --- a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.h +++ b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.h @@ -32,6 +32,7 @@ struct TFReaderInp { std::string tffileRegex{}; std::string remoteRegex{}; std::string metricChannel{}; + std::string fileRunTimeSpans{}; o2::detectors::DetID::mask_t detMask{}; o2::detectors::DetID::mask_t detMaskRawOnly{}; o2::detectors::DetID::mask_t detMaskNonRawOnly{}; @@ -46,6 +47,7 @@ struct TFReaderInp { int maxTFsPerFile = -1; bool sendDummyForMissing = true; bool sup0xccdb = false; + bool invertIRFramesSelection = false; std::vector hdVec; std::vector tfIDs{}; }; diff --git a/Detectors/Raw/TFReaderDD/src/tf-reader-workflow.cxx b/Detectors/Raw/TFReaderDD/src/tf-reader-workflow.cxx index 7d8ee09fe474f..bc682127b0d3f 100644 --- a/Detectors/Raw/TFReaderDD/src/tf-reader-workflow.cxx +++ b/Detectors/Raw/TFReaderDD/src/tf-reader-workflow.cxx @@ -39,6 +39,8 @@ void customize(std::vector& workflowOptions) options.push_back(ConfigParamSpec{"disable-dummy-output", VariantType::Bool, false, {"Disable sending empty output if corresponding data is not found in the data"}}); options.push_back(ConfigParamSpec{"configKeyValues", VariantType::String, "", {"semicolon separated key=value strings"}}); options.push_back(ConfigParamSpec{"timeframes-shm-limit", VariantType::String, "0", {"Minimum amount of SHM required in order to publish data"}}); + options.push_back(ConfigParamSpec{"run-time-span-file", VariantType::String, "", {"If non empty, inject selected IRFrames from this text file (run, min/max orbit or unix time)"}}); + options.push_back(ConfigParamSpec{"invert-irframe-selection", VariantType::Bool, false, {"Select only frames mentioned in ir-frames-file (skip-skimmed-out-tf applied to TF not selected!)"}}); options.push_back(ConfigParamSpec{"metric-feedback-channel-format", VariantType::String, "name=metric-feedback,type=pull,method=connect,address=ipc://{}metric-feedback-{},transport=shmem,rateLogging=0", {"format for the metric-feedback channel for TF rate limiting"}}); // options for error-check suppression @@ -80,7 +82,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) if (rateLimitingIPCID > -1 && !chanFmt.empty()) { rinp.metricChannel = fmt::format(fmt::runtime(chanFmt), o2::framework::ChannelSpecHelpers::defaultIPCFolder(), rateLimitingIPCID); } - + rinp.fileRunTimeSpans = configcontext.options().get("run-time-span-file"); + rinp.invertIRFramesSelection = configcontext.options().get("invert-irframe-selection"); WorkflowSpec specs; specs.emplace_back(o2::rawdd::getTFReaderSpec(rinp)); return specs; From dfd37f923994aef7a4284935be75e426961523e7 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 16 Jul 2025 17:46:38 +0200 Subject: [PATCH 155/315] GPU: Fix checking for dmaTransferType with GPU memory registration disabled --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 423f0b782d095..9d2578731a30c 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -273,8 +273,8 @@ bool GPUChainTracking::ValidateSettings() GPUError("NStreams of %d insufficient for %d nTPCClustererLanes", mRec->NStreams(), (int32_t)GetProcessingSettings().nTPCClustererLanes); return false; } - if (GetProcessingSettings().noGPUMemoryRegistration && gatherMode != 3) { - GPUError("noGPUMemoryRegistration only possible with gather mode 3"); + if ((mRec->GetRecoStepsGPU() & GPUDataTypes::RecoStep::TPCCompression) && GetProcessingSettings().noGPUMemoryRegistration && gatherMode != 3) { + GPUError("noGPUMemoryRegistration only possible with gather mode 3 (set to %d / %d)", mRec->GetProcessingSettings().tpcCompressionGatherMode, gatherMode); return false; } if (GetProcessingSettings().doublePipeline) { From bbb5bb8e7405dda61337ffa83c8ae6e8de66f8c9 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 17 Jul 2025 13:58:32 +0200 Subject: [PATCH 156/315] GPU: Fix typo in getting default number of threads from env variables --- GPU/GPUTracking/Base/GPUReconstruction.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Base/GPUReconstruction.cxx b/GPU/GPUTracking/Base/GPUReconstruction.cxx index 4a67fae3b6376..c7b61a976021a 100644 --- a/GPU/GPUTracking/Base/GPUReconstruction.cxx +++ b/GPU/GPUTracking/Base/GPUReconstruction.cxx @@ -209,7 +209,7 @@ static uint32_t getDefaultNThreads() const char* ompEnv = getenv("OMP_NUM_THREADS"); uint32_t ompNum = ompEnv ? atoi(ompEnv) : 0; if (ompNum) { - return tbbNum; + return ompNum; } return tbb::info::default_concurrency(); } From d238d41c803bdae4a00834c8f9093725dced52f4 Mon Sep 17 00:00:00 2001 From: Felix Weiglhofer <9267733+fweig@users.noreply.github.com> Date: Thu, 17 Jul 2025 23:06:44 +0200 Subject: [PATCH 157/315] TPCFastTransformation: Resolve recursion at compile time with templates. (#14462) * TPCFastTransformation: Resolve recursion at compile time with templates. * TPCFastTransformation: Fix runtime parameters on CPU for polynoms. * Fix failing unittest. --- GPU/Common/GPUCommonDefAPI.h | 2 +- .../DataTypes/CalibdEdxTrackTopologyPol.h | 5 +- .../MultivariatePolynomial.h | 2 +- .../MultivariatePolynomialHelper.h | 164 ++++++++++++++---- .../NDPiecewisePolynomials.h | 25 ++- .../NDPiecewisePolynomials.inc | 4 +- 6 files changed, 157 insertions(+), 45 deletions(-) diff --git a/GPU/Common/GPUCommonDefAPI.h b/GPU/Common/GPUCommonDefAPI.h index 2494cd8dd6fe5..4d4e04f10b2fa 100644 --- a/GPU/Common/GPUCommonDefAPI.h +++ b/GPU/Common/GPUCommonDefAPI.h @@ -79,7 +79,7 @@ #define GPUdDefault() #define GPUhdDefault() #define GPUdi() inline - #define GPUdii() inline + #define GPUdii() __attribute__((always_inline)) inline #define GPUdni() #define GPUdnii() #define GPUh() INVALID_TRIGGER_ERROR_NO_HOST_CODE diff --git a/GPU/GPUTracking/DataTypes/CalibdEdxTrackTopologyPol.h b/GPU/GPUTracking/DataTypes/CalibdEdxTrackTopologyPol.h index a50cf63698a78..0a3816f9ddbd2 100644 --- a/GPU/GPUTracking/DataTypes/CalibdEdxTrackTopologyPol.h +++ b/GPU/GPUTracking/DataTypes/CalibdEdxTrackTopologyPol.h @@ -62,7 +62,10 @@ class CalibdEdxTrackTopologyPol : public o2::gpu::FlatObject /// \param region region of the TPC /// \param charge correction for maximum or total charge /// \param x coordinates where the correction is evaluated - GPUd() float getCorrection(const int32_t region, const ChargeType charge, float x[/*inpXdim*/]) const { return (charge == ChargeType::Tot) ? mCalibPolsqTot[region].eval(x) : mCalibPolsqMax[region].eval(x); } + GPUd() float getCorrection(const int32_t region, const ChargeType charge, float x[/*inpXdim*/]) const + { + return (charge == ChargeType::Tot) ? mCalibPolsqTot[region].eval(x) : mCalibPolsqMax[region].eval(x); + } /// \return returns the track topology correction /// \param region region of the TPC diff --git a/GPU/TPCFastTransformation/MultivariatePolynomial.h b/GPU/TPCFastTransformation/MultivariatePolynomial.h index 4fd2157409133..1454194f9e3b4 100644 --- a/GPU/TPCFastTransformation/MultivariatePolynomial.h +++ b/GPU/TPCFastTransformation/MultivariatePolynomial.h @@ -56,7 +56,7 @@ class MultivariatePolynomial : public FlatObject, public MultivariatePolynomialH /// constructor for compile time evaluation of polynomial formula template ::type = 0> - MultivariatePolynomial() : mNParams{this->getNParameters(Degree, Dim, InteractionOnly)} + MultivariatePolynomial() : mNParams{this->template getNParameters()} { construct(); } diff --git a/GPU/TPCFastTransformation/MultivariatePolynomialHelper.h b/GPU/TPCFastTransformation/MultivariatePolynomialHelper.h index 52c30b3241adc..2dd186a859ab0 100644 --- a/GPU/TPCFastTransformation/MultivariatePolynomialHelper.h +++ b/GPU/TPCFastTransformation/MultivariatePolynomialHelper.h @@ -57,15 +57,63 @@ struct MultivariatePolynomialContainer { class MultivariatePolynomialParametersHelper { public: + /// \returns number of parameters for given dimension and degree of polynomials at compile time + /// calculates the number of parameters for a multivariate polynomial for given degree: nParameters = (n+d-1 d) -> binomial coefficient + /// see: https://mathoverflow.net/questions/225953/number-of-polynomial-terms-for-certain-degree-and-certain-number-of-variables + template + GPUd() static constexpr uint32_t getNParametersAllTerms() + { + if constexpr (Degree == 0) { + return binomialCoeff(); + } else { + return binomialCoeff() + getNParametersAllTerms(); + } + } + /// \returns number of parameters for given dimension and degree of polynomials /// calculates the number of parameters for a multivariate polynomial for given degree: nParameters = (n+d-1 d) -> binomial coefficient /// see: https://mathoverflow.net/questions/225953/number-of-polynomial-terms-for-certain-degree-and-certain-number-of-variables - GPUd() static constexpr uint32_t getNParametersAllTerms(const uint32_t degree, const uint32_t dim) { return (degree == 0) ? binomialCoeff(dim - 1, 0) : binomialCoeff(dim - 1 + degree, degree) + getNParametersAllTerms(degree - 1, dim); } + GPUd() static constexpr uint32_t getNParametersAllTerms(uint32_t degree, uint32_t dim) + { + if (degree == 0) { + return binomialCoeff(dim - 1, 0); + } else { + return binomialCoeff(dim - 1 + degree, degree) + getNParametersAllTerms(degree - 1, dim); + } + } + + /// \returns the number of parameters at compile time for interaction terms only (see: https://en.wikipedia.org/wiki/Combination) + template + GPUd() static constexpr uint32_t getNParametersInteractionOnly() + { + if constexpr (Degree == 0) { + return binomialCoeff(); + } else { + return binomialCoeff() + getNParametersInteractionOnly(); + } + } /// \returns the number of parameters for interaction terms only (see: https://en.wikipedia.org/wiki/Combination) - GPUd() static constexpr uint32_t getNParametersInteractionOnly(const uint32_t degree, const uint32_t dim) { return (degree == 0) ? binomialCoeff(dim - 1, 0) : binomialCoeff(dim, degree) + getNParametersInteractionOnly(degree - 1, dim); } + GPUd() static constexpr uint32_t getNParametersInteractionOnly(uint32_t degree, uint32_t dim) + { + if (degree == 0) { + return binomialCoeff(dim - 1, 0); + } else { + return binomialCoeff(dim, degree) + getNParametersInteractionOnly(degree - 1, dim); + } + } + + template + GPUd() static constexpr uint32_t getNParameters() + { + if constexpr (InteractionOnly) { + return getNParametersInteractionOnly(); + } else { + return getNParametersAllTerms(); + } + } - GPUd() static constexpr uint32_t getNParameters(const uint32_t degree, const uint32_t dim, const bool interactionOnly) + GPUd() static constexpr uint32_t getNParameters(uint32_t degree, uint32_t dim, bool interactionOnly) { if (interactionOnly) { return getNParametersInteractionOnly(degree, dim); @@ -75,13 +123,36 @@ class MultivariatePolynomialParametersHelper } private: + /// calculate factorial of n at compile time + /// \return returns n! + template + GPUd() static constexpr uint32_t factorial() + { + if constexpr (N == 0 || N == 1) { + return 1; + } else { + return N * factorial(); + } + } + /// calculate factorial of n /// \return returns n! - GPUd() static constexpr uint32_t factorial(const uint32_t n) { return (n == 0) || (n == 1) ? 1 : n * factorial(n - 1); } + GPUd() static constexpr uint32_t factorial(uint32_t n) { return n == 0 || n == 1 ? 1 : n * factorial(n - 1); } + + /// calculates binomial coefficient at compile time + /// \return returns (n k) + template + GPUd() static constexpr uint32_t binomialCoeff() + { + return factorial() / (factorial() * factorial()); + } /// calculates binomial coefficient /// \return returns (n k) - GPUd() static constexpr uint32_t binomialCoeff(const uint32_t n, const uint32_t k) { return factorial(n) / (factorial(k) * factorial(n - k)); } + GPUd() static constexpr uint32_t binomialCoeff(uint32_t n, uint32_t k) + { + return factorial(n) / (factorial(k) * factorial(n - k)); + } }; /// Helper struct for evaluating a multidimensional polynomial using compile time evaluated formula @@ -103,7 +174,10 @@ class MultivariatePolynomialHelper : public MultivariatePolynomialParametersHelp /// evaluates the polynomial for given parameters and coordinates /// \param par parameters of the polynomials /// \param x input coordinates - GPUd() static constexpr float evalPol(GPUgeneric() const float par[/*number of parameters*/], const float x[/*number of dimensions*/]) { return par[0] + loopDegrees<1>(par, x); } + GPUd() static constexpr float evalPol(GPUgeneric() const float par[/*number of parameters*/], const float x[/*number of dimensions*/]) + { + return par[0] + loopDegrees<1>(par, x); + } /// \return returns number of dimensions of the polynomials GPUd() static constexpr uint32_t getDim() { return Dim; } @@ -118,19 +192,36 @@ class MultivariatePolynomialHelper : public MultivariatePolynomialParametersHelp /// computes power of 10 GPUd() static constexpr uint32_t pow10(const uint32_t n) { return n == 0 ? 1 : 10 * pow10(n - 1); } + template + GPUd() static constexpr uint32_t pow10() + { + if constexpr (N == 0) { + return 1; + } else { + return 10 * pow10(); + } + } + /// helper for modulo to extract the digit in an integer a at position b (can be obtained with pow10(digitposition)): e.g. a=1234 b=pow10(2)=100 -> returns 2 GPUd() static constexpr uint32_t mod10(const uint32_t a, const uint32_t b) { return (a / b) % 10; } + template + GPUd() static constexpr uint32_t mod10() + { + return (A / B) % 10; + } + /// resetting digits of pos for given position to refDigit GPUd() static constexpr uint32_t resetIndices(const uint32_t degreePol, const uint32_t pos, const uint32_t leftDigit, const uint32_t iter, const uint32_t refDigit); - GPUd() static constexpr uint32_t getNewPos(const uint32_t degreePol, const uint32_t pos, const uint32_t digitPos); + template + GPUd() static constexpr uint32_t getNewPos(); /// calculates term e.g. x^3*y /// \tparam DegreePol max degree of the polynomials /// \pos decoded information about the current term e.g. 1233 -> x[1]*x[2]*x[3]*x[3] (otherwise an array could be used) - template - GPUd() static constexpr float prodTerm(const float x[], const uint32_t pos); + template + GPUd() static constexpr float prodTerm(const float x[]); /// helper function for checking for interaction terms template @@ -203,7 +294,10 @@ class MultivariatePolynomialHelper<0, 0, false> : public MultivariatePolynomialP /// evaluating the polynomial /// \param par coefficients of the polynomial /// \param x input coordinates - float evalPol(const float par[/*number of parameters*/], const float x[/*number of dimensions*/]) const { return evalPol(par, x, mDegree, mDim, mInteractionOnly); } + float evalPol(const float par[/*number of parameters*/], const float x[/*number of dimensions*/]) const + { + return evalPol(par, x, mDegree, mDim, mInteractionOnly); + } /// evalutes the polynomial float evalPol(const float par[], const float x[], const uint32_t degree, const uint32_t dim, const bool interactionOnly) const; @@ -248,35 +342,39 @@ GPUd() constexpr uint32_t MultivariatePolynomialHelper -GPUd() constexpr uint32_t MultivariatePolynomialHelper::getNewPos(const uint32_t degreePol, const uint32_t pos, const uint32_t digitPos) +template +GPUd() constexpr uint32_t MultivariatePolynomialHelper::getNewPos() { - if (degreePol > digitPos) { + if constexpr (DegreePol > DigitPos) { // check if digit of current position is at is max position - if (mod10(pos, pow10(digitPos)) == Dim) { + if constexpr (mod10()>() == Dim) { // increase digit of left position - const uint32_t leftDigit = digitPos + 1; - const uint32_t posTmp = pos + pow10(leftDigit); - const uint32_t refDigit = mod10(posTmp, pow10(digitPos + 1)); + constexpr uint32_t LeftDigit = DigitPos + 1; + constexpr uint32_t PowLeftDigit = pow10(); + constexpr uint32_t PosTmp = Pos + PowLeftDigit; + constexpr uint32_t RefDigit = mod10(); // resetting digits to the right if digit exceeds number of dimensions - const uint32_t posReset = resetIndices(degreePol, posTmp, leftDigit - 1, degreePol - digitPos, refDigit); + constexpr uint32_t PosReset = resetIndices(DegreePol, PosTmp, LeftDigit - 1, DegreePol - DigitPos, RefDigit); // check next digit - return getNewPos(degreePol, posReset, digitPos + 1); + return getNewPos(); + } else { + return getNewPos(); } - return getNewPos(degreePol, pos, digitPos + 1); + } else { + return Pos; } - return pos; } template -template -GPUd() constexpr float MultivariatePolynomialHelper::prodTerm(const float x[], const uint32_t pos) +template +GPUd() constexpr float MultivariatePolynomialHelper::prodTerm(const float x[]) { if constexpr (DegreePol > 0) { // extract index of the dimension which is decoded in the digit - const uint32_t index = mod10(pos, pow10(DegreePol - 1)); - return x[index] * prodTerm(x, pos); + const uint32_t index = mod10()>(); + return x[index] * prodTerm(x); } return 1; } @@ -286,7 +384,7 @@ template constexpr bool MultivariatePolynomialHelper::checkInteraction() { if constexpr (DegreePol > 1) { - constexpr bool isInteraction = mod10(posNew, pow10(DegreePol - 1)) == mod10(posNew, pow10(DegreePol - 2)); + constexpr bool isInteraction = mod10()>() == mod10()>(); if constexpr (isInteraction) { return true; } @@ -300,16 +398,16 @@ template GPUd() constexpr float MultivariatePolynomialHelper::sumTerms(GPUgeneric() const float par[], const float x[]) { // checking if the current position is reasonable e.g. if the max dimension is x[4]: for Pos=15 -> x[1]*x[5] the position is set to 22 -> x[2]*x[2] - constexpr uint32_t posNew = getNewPos(DegreePol, Pos, 0); - if constexpr (mod10(posNew, pow10(DegreePol)) != 1) { + constexpr uint32_t PosNew = getNewPos(); + if constexpr (mod10()>() != 1) { // check if all digits in posNew are unequal: For interaction_only terms with x[Dim]*x[Dim]... etc. can be skipped - if constexpr (InteractionOnly && checkInteraction()) { - return sumTerms(par, x); + if constexpr (InteractionOnly && checkInteraction()) { + return sumTerms(par, x); + } else { + // sum up the term for corrent term and set posotion for next combination + return par[Index] * prodTerm(x) + sumTerms(par, x); } - - // sum up the term for corrent term and set posotion for next combination - return par[Index] * prodTerm(x, posNew) + sumTerms(par, x); } return 0; } @@ -319,7 +417,7 @@ template GPUd() constexpr float MultivariatePolynomialHelper::loopDegrees(GPUgeneric() const float par[], const float x[]) { if constexpr (DegreePol <= Degree) { - constexpr uint32_t index{getNParameters(DegreePol - 1, Dim, InteractionOnly)}; // offset of the index for accessing the parameters + constexpr uint32_t index{getNParameters()}; // offset of the index for accessing the parameters return sumTerms(par, x) + loopDegrees(par, x); } return 0; diff --git a/GPU/TPCFastTransformation/NDPiecewisePolynomials.h b/GPU/TPCFastTransformation/NDPiecewisePolynomials.h index e750bffd28f4b..0d56b65aa89b8 100644 --- a/GPU/TPCFastTransformation/NDPiecewisePolynomials.h +++ b/GPU/TPCFastTransformation/NDPiecewisePolynomials.h @@ -141,7 +141,10 @@ class NDPiecewisePolynomials : public FlatObject /// evaluate specific polynomial at given index for given coordinate /// \param x coordinates where to interpolate /// \param index index of the polynomial - GPUd() float evalPol(const float x[/* Dim */], const int32_t index[/* Dim */]) const { return MultivariatePolynomialHelper::evalPol(getParameters(index), x); } + GPUd() float evalPol(const float x[/* Dim */], const int32_t index[/* Dim */]) const + { + return MultivariatePolynomialHelper::evalPol(getParameters(index), x); + } /// \return returns min range for given dimension GPUd() float getXMin(const uint32_t dim) const { return mMin[dim]; } @@ -215,7 +218,7 @@ class NDPiecewisePolynomials : public FlatObject #endif // !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) /// \return returns the total number of stored parameters - uint32_t getNParameters() const { return getNPolynomials() * MultivariatePolynomialParametersHelper::getNParameters(Degree, Dim, InteractionOnly); } + uint32_t getNParameters() const { return getNPolynomials() * MultivariatePolynomialParametersHelper::getNParameters(); } /// \return returns number of dimensions of the polynomials GPUd() static constexpr uint32_t getDim() { return Dim; } @@ -241,11 +244,19 @@ class NDPiecewisePolynomials : public FlatObject /// returns terms which are needed to calculate the index for the grid for given dimension /// \param dim dimension - GPUd() uint32_t getTerms(const uint32_t dim) const { return (dim == 0) ? 1 : (mN[dim - 1] - 1) * getTerms(dim - 1); } + template + GPUd() uint32_t getTerms() const + { + if constexpr (TermDim == 0) { + return 1; + } else { + return (mN[TermDim - 1] - 1) * getTerms(); + } + } /// returns index for accessing the parameter on the grid /// \param ix index per dimension - GPUd() uint32_t getDataIndex(const int32_t ix[/* Dim */]) const { return getDataIndex(ix) * MultivariatePolynomialParametersHelper::getNParameters(Degree, Dim, InteractionOnly); } + GPUd() uint32_t getDataIndex(const int32_t ix[/* Dim */]) const { return getDataIndex(ix) * MultivariatePolynomialParametersHelper::getNParameters(); } /// helper function to get the index template @@ -325,7 +336,7 @@ void NDPiecewisePolynomials::setFromContainer(cons template void NDPiecewisePolynomials::setDefault() { - const auto nParamsPerPol = MultivariatePolynomialParametersHelper::getNParameters(Degree, Dim, InteractionOnly); + const auto nParamsPerPol = MultivariatePolynomialParametersHelper::getNParameters(); const auto nPols = getNPolynomials(); std::vector params(nParamsPerPol); params.front() = 1; @@ -429,10 +440,10 @@ void NDPiecewisePolynomials::setFutureBufferAddres template template -GPUdi() uint32_t NDPiecewisePolynomials::getDataIndex(const int32_t ix[/* Dim */]) const +GPUd() uint32_t NDPiecewisePolynomials::getDataIndex(const int32_t ix[/* Dim */]) const { if constexpr (DimTmp > 0) { - return ix[DimTmp] * getTerms(DimTmp) + getDataIndex(ix); + return ix[DimTmp] * getTerms() + getDataIndex(ix); } return ix[DimTmp]; } diff --git a/GPU/TPCFastTransformation/NDPiecewisePolynomials.inc b/GPU/TPCFastTransformation/NDPiecewisePolynomials.inc index 2538e30056448..1cbcf9cd8e23e 100644 --- a/GPU/TPCFastTransformation/NDPiecewisePolynomials.inc +++ b/GPU/TPCFastTransformation/NDPiecewisePolynomials.inc @@ -165,7 +165,7 @@ void NDPiecewisePolynomials::performFits(const std // check if data points are in the grid if (index == indexClamped) { // index of the polyniomial - const uint32_t idx = getDataIndex(index.data()) / MultivariatePolynomialParametersHelper::getNParameters(Degree, Dim, InteractionOnly); + const uint32_t idx = getDataIndex(index.data()) / MultivariatePolynomialParametersHelper::getNParameters(); // store index to data point dataPointsIndices[idx].emplace_back(i); @@ -216,7 +216,7 @@ void NDPiecewisePolynomials::performFits(const std const auto params = MultivariatePolynomialHelper<0, 0, false>::fit(fitter, xCords, response, error, true); // store parameters - std::copy(params.begin(), params.end(), &mParams[i * MultivariatePolynomialParametersHelper::getNParameters(Degree, Dim, InteractionOnly)]); + std::copy(params.begin(), params.end(), &mParams[i * MultivariatePolynomialParametersHelper::getNParameters()]); } } From 5d72482ed5c4c5a8bdaacc2b35d6b181ccfac85d Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 2 Jul 2025 10:41:38 +0200 Subject: [PATCH 158/315] ITS: cleanup unused classes Signed-off-by: Felix Schlepper --- Detectors/ITSMFT/ITS/tracking/CMakeLists.txt | 2 - .../tracking/include/ITStracking/ArrayUtils.h | 53 ---- .../tracking/include/ITStracking/IOUtils.h | 43 +-- .../ITS/tracking/include/ITStracking/Label.h | 41 --- .../tracking/include/ITStracking/ROframe.h | 190 ------------- .../tracking/include/ITStracking/Smoother.h | 5 +- .../tracking/include/ITStracking/Tracker.h | 1 - .../tracking/include/ITStracking/Vertexer.h | 7 - Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx | 89 +----- Detectors/ITSMFT/ITS/tracking/src/Label.cxx | 42 --- Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx | 65 ----- .../ITSMFT/ITS/tracking/src/Smoother.cxx | 256 +++++++++--------- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 1 - .../ITS/tracking/src/TrackingInterface.cxx | 8 +- .../ITSMFT/ITS/tracking/src/Vertexer.cxx | 3 +- .../ITS/workflow/src/CookedTrackerSpec.cxx | 2 - .../reconstruction/src/TrackingInterface.cxx | 1 + 17 files changed, 144 insertions(+), 665 deletions(-) delete mode 100644 Detectors/ITSMFT/ITS/tracking/include/ITStracking/ArrayUtils.h delete mode 100644 Detectors/ITSMFT/ITS/tracking/include/ITStracking/Label.h delete mode 100644 Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h delete mode 100644 Detectors/ITSMFT/ITS/tracking/src/Label.cxx delete mode 100644 Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index 45080e19cacff..f9565307d35f6 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -15,10 +15,8 @@ o2_add_library(ITStracking SOURCES src/ClusterLines.cxx src/Cluster.cxx src/Configuration.cxx - src/ROframe.cxx src/TimeFrame.cxx src/IOUtils.cxx - src/Label.cxx src/Tracker.cxx src/TrackerTraits.cxx src/TrackingConfigParam.cxx diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ArrayUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ArrayUtils.h deleted file mode 100644 index 971ae6a7fe83a..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ArrayUtils.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. -/// -/// \file ArrayUtils.h -/// \brief -/// - -#ifndef TRACKINGITSU_INCLUDE_ARRAYUTILS_H_ -#define TRACKINGITSU_INCLUDE_ARRAYUTILS_H_ - -#include -#include -#include - -namespace o2 -{ -namespace its -{ -namespace CA -{ - -namespace ArrayUtils -{ -template -constexpr std::array fillArray(Initializer, std::index_sequence); -template -constexpr std::array fillArray(Initializer); -} // namespace ArrayUtils - -template -constexpr std::array ArrayUtils::fillArray(Initializer initializer, std::index_sequence) -{ - return std::array{{initializer(Is)...}}; -} - -template -constexpr std::array ArrayUtils::fillArray(Initializer initializer) -{ - return ArrayUtils::fillArray(initializer, std::make_index_sequence{}); -} -} // namespace CA -} // namespace its -} // namespace o2 - -#endif /* TRACKINGITSU_INCLUDE_ARRAYUTILS_H_ */ diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h index 0ada9dfbc6188..8adacdf58d74d 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/IOUtils.h @@ -16,62 +16,27 @@ #ifndef TRACKINGITSU_INCLUDE_EVENTLOADER_H_ #define TRACKINGITSU_INCLUDE_EVENTLOADER_H_ -#include -#include -#include #include -#include "DataFormatsITSMFT/ROFRecord.h" -#include "ITStracking/Configuration.h" -#include "ITStracking/ROframe.h" -#include "ITStracking/Label.h" -#include "ITStracking/Road.h" -#include "ITStracking/TrackingConfigParam.h" #include "ITSMFTBase/SegmentationAlpide.h" #include "ReconstructionDataFormats/BaseCluster.h" -#include "ITSMFTReconstruction/ChipMappingITS.h" #include "DataFormatsITSMFT/CompCluster.h" #include "DataFormatsITSMFT/TopologyDictionary.h" +#include "DataFormatsITSMFT/ROFRecord.h" // TODO this is just included since the alignment code include it now -namespace o2 +namespace o2::its::ioutils { -class MCCompLabel; - -namespace dataformats -{ -template -class MCTruthContainer; -} - -namespace its -{ - -namespace ioutils -{ constexpr float DefClusErrorRow = o2::itsmft::SegmentationAlpide::PitchRow * 0.5; constexpr float DefClusErrorCol = o2::itsmft::SegmentationAlpide::PitchCol * 0.5; constexpr float DefClusError2Row = DefClusErrorRow * DefClusErrorRow; constexpr float DefClusError2Col = DefClusErrorCol * DefClusErrorCol; -void loadEventData(ROframe& events, gsl::span clusters, - gsl::span::iterator& pattIt, const itsmft::TopologyDictionary* dict, - const dataformats::MCTruthContainer* clsLabels = nullptr); -int loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& events, gsl::span clusters, - gsl::span::iterator& pattIt, const itsmft::TopologyDictionary* dict, - const dataformats::MCTruthContainer* mClsLabels = nullptr); - void convertCompactClusters(gsl::span clusters, gsl::span::iterator& pattIt, std::vector>& output, const itsmft::TopologyDictionary* dict); -inline static const o2::itsmft::ChipMappingITS& getChipMappingITS() -{ - static const o2::itsmft::ChipMappingITS MP; - return MP; -} - template o2::math_utils::Point3D extractClusterData(const itsmft::CompClusterExt& c, iterator& iter, const itsmft::TopologyDictionary* dict, T& sig2y, T& sig2z) { @@ -115,8 +80,6 @@ std::array extractClusterDataA(const itsmft::CompClusterExt& c, iterator& } } -} // namespace ioutils -} // namespace its -} // namespace o2 +} // namespace o2::its::ioutils #endif /* TRACKINGITSU_INCLUDE_EVENTLOADER_H_ */ diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Label.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Label.h deleted file mode 100644 index ec45e6587a974..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Label.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. -/// -/// \file Label.h -/// \brief -/// - -#ifndef TRACKINGITSU_INCLUDE_LABEL_H_ -#define TRACKINGITSU_INCLUDE_LABEL_H_ - -#include - -namespace o2 -{ -namespace its -{ - -struct Label final { - Label(const int, const float, const float, const float, const int, const int); - - int monteCarloId; - float transverseMomentum; - float phi; - float pseudorapidity; - int pdgCode; - int numberOfClusters; - - friend std::ostream& operator<<(std::ostream&, const Label&); -}; -} // namespace its -} // namespace o2 - -#endif /* TRACKINGITSU_INCLUDE_LABEL_H_ */ diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h deleted file mode 100644 index d35e5bc545904..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ROframe.h +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. -/// -/// \file ROframe.h -/// \brief -/// - -#ifndef TRACKINGITSU_INCLUDE_ROFRAME_H_ -#define TRACKINGITSU_INCLUDE_ROFRAME_H_ - -#include -#include -#include -#include -#include - -#include "ITStracking/Cluster.h" -#include "ITStracking/Constants.h" - -#include "ReconstructionDataFormats/Vertex.h" -#include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" - -namespace o2 -{ -namespace its -{ - -using Vertex = o2::dataformats::Vertex>; - -class ROframe final -{ - public: - ROframe(int ROframeId, int nLayers); - int getROFrameId() const; - const float3& getPrimaryVertex(const int) const; - int getPrimaryVerticesNum() const; - void addPrimaryVertex(const float, const float, const float); - void addPrimaryVertices(std::vector vertices); - void addPrimaryReconstructedVertex(const float, const float, const float); - void printPrimaryVertices() const; - int getTotalClusters() const; - bool empty() const; - - const auto& getClusters() const { return mClusters; } - const std::vector& getClustersOnLayer(int layerId) const; - const std::vector& getTrackingFrameInfoOnLayer(int layerId) const; - const auto& getTrackingFrameInfo() const { return mTrackingFrameInfo; } - - const TrackingFrameInfo& getClusterTrackingFrameInfo(int layerId, const Cluster& cl) const; - const MCCompLabel& getClusterFirstLabel(int layerId, const Cluster& cl) const; - const MCCompLabel& getClusterFirstLabel(int layerId, const int clId) const; - const gsl::span getClusterLabels(int layerId, const int clId) const; - const gsl::span getClusterLabels(int layerId, const Cluster& cl) const; - int getClusterExternalIndex(int layerId, const int clId) const; - std::vector getTracksId(const int layerId, const std::vector& cl); - - template - void addClusterToLayer(int layer, T&&... args); - template - void addTrackingFrameInfoToLayer(int layer, T&&... args); - void setMClabelsContainer(const dataformats::MCTruthContainer* ptr); - void addClusterExternalIndexToLayer(int layer, const int idx); - bool hasMCinformation() const; - - void clear(); - - private: - const int mROframeId; - const o2::dataformats::MCTruthContainer* mMClabels = nullptr; - std::vector mPrimaryVertices; - std::vector> mClusters; - std::vector> mTrackingFrameInfo; - std::vector> mClusterExternalIndices; -}; - -inline int ROframe::getROFrameId() const { return mROframeId; } - -inline const float3& ROframe::getPrimaryVertex(const int vertexIndex) const { return mPrimaryVertices[vertexIndex]; } - -inline int ROframe::getPrimaryVerticesNum() const { return mPrimaryVertices.size(); } - -inline bool ROframe::empty() const { return getTotalClusters() == 0; } - -inline const std::vector& ROframe::getClustersOnLayer(int layerId) const -{ - return mClusters[layerId]; -} - -inline const std::vector& ROframe::getTrackingFrameInfoOnLayer(int layerId) const -{ - return mTrackingFrameInfo[layerId]; -} - -inline const TrackingFrameInfo& ROframe::getClusterTrackingFrameInfo(int layerId, const Cluster& cl) const -{ - return mTrackingFrameInfo[layerId][cl.clusterId]; -} - -inline const MCCompLabel& ROframe::getClusterFirstLabel(int layerId, const Cluster& cl) const -{ - return getClusterFirstLabel(layerId, cl.clusterId); -} - -inline const MCCompLabel& ROframe::getClusterFirstLabel(int layerId, const int clId) const -{ - return *(mMClabels->getLabels(getClusterExternalIndex(layerId, clId)).begin()); -} - -inline const gsl::span ROframe::getClusterLabels(int layerId, const int clId) const -{ - return mMClabels->getLabels(getClusterExternalIndex(layerId, clId)); -} - -inline const gsl::span ROframe::getClusterLabels(int layerId, const Cluster& cl) const -{ - return getClusterLabels(layerId, cl.clusterId); -} - -inline int ROframe::getClusterExternalIndex(int layerId, const int clId) const -{ - return mClusterExternalIndices[layerId][clId]; -} - -inline std::vector ROframe::getTracksId(const int layerId, const std::vector& cl) -{ - std::vector tracksId; - for (auto& cluster : cl) { - tracksId.push_back(getClusterFirstLabel(layerId, cluster).isNoise() ? -1 : getClusterFirstLabel(layerId, cluster).getTrackID()); - } - return tracksId; -} - -template -void ROframe::addClusterToLayer(int layer, T&&... values) -{ - mClusters[layer].emplace_back(std::forward(values)...); -} - -template -void ROframe::addTrackingFrameInfoToLayer(int layer, T&&... values) -{ - mTrackingFrameInfo[layer].emplace_back(std::forward(values)...); -} - -inline void ROframe::setMClabelsContainer(const dataformats::MCTruthContainer* ptr) -{ - mMClabels = ptr; -} - -inline void ROframe::addClusterExternalIndexToLayer(int layer, const int idx) -{ - mClusterExternalIndices[layer].push_back(idx); -} - -inline void ROframe::clear() -{ - for (unsigned int iL = 0; iL < mClusters.size(); ++iL) { - mClusters[iL].clear(); - mTrackingFrameInfo[iL].clear(); - // mClusterLabels[iL].clear(); - mClusterExternalIndices[iL].clear(); - } - mPrimaryVertices.clear(); - mMClabels = nullptr; -} - -inline bool ROframe::hasMCinformation() const -{ - // for (const auto& vect : mClusterLabels) { - // if (!vect.empty()) { - // return true; - // } - // } - // return false; - return mMClabels; -} - -} // namespace its -} // namespace o2 - -#endif /* TRACKINGITSU_INCLUDE_ROFRAME_H_ */ diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Smoother.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Smoother.h index 2dcd521797837..101f4b8d72601 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Smoother.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Smoother.h @@ -17,7 +17,6 @@ #include "ReconstructionDataFormats/Track.h" #include "DataFormatsITS/TrackITS.h" #include "DetectorsBase/Propagator.h" -#include "ITStracking/ROframe.h" namespace o2 { @@ -28,14 +27,14 @@ template class Smoother { public: - Smoother(TrackITSExt& track, size_t layer, const ROframe& event, float bZ, o2::base::PropagatorF::MatCorrType corr); + // Smoother(TrackITSExt& track, size_t layer, const ROframe& event, float bZ, o2::base::PropagatorF::MatCorrType corr); ~Smoother(); bool isValidInit() const { return mInitStatus; } - bool testCluster(const int clusterId, const ROframe& event); + // bool testCluster(const int clusterId, const ROframe& event); bool getSmoothedTrack(); float getChi2() const { return mBestChi2; } float getLastChi2() const { return mLastChi2; } diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h index 78c290374a67d..3f80d239946b1 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracker.h @@ -32,7 +32,6 @@ #include "ITStracking/Configuration.h" #include "CommonConstants/MathConstants.h" #include "ITStracking/Definitions.h" -#include "ITStracking/ROframe.h" #include "ITStracking/MathUtils.h" #include "ITStracking/TimeFrame.h" #include "ITStracking/TrackerTraits.h" diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h index c8b3b0d4138d4..2b9bfabd80128 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Vertexer.h @@ -25,7 +25,6 @@ #include -#include "ITStracking/ROframe.h" #include "ITStracking/Constants.h" #include "ITStracking/Configuration.h" #include "ITStracking/TimeFrame.h" @@ -33,12 +32,6 @@ #include "ITStracking/BoundedAllocator.h" #include "ReconstructionDataFormats/Vertex.h" -#include "ITStracking/ClusterLines.h" -#include "ITStracking/Tracklet.h" -#include "ITStracking/Cluster.h" - -#include "GPUCommonLogger.h" - namespace o2::its { diff --git a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx index 2638b437d61f8..e2ce374ed1600 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/IOUtils.cxx @@ -17,20 +17,11 @@ #include #include -#include -#include -#include #include -#include -#include -#include -#include #include "ITSBase/GeometryTGeo.h" -#include "ITStracking/Constants.h" -#include "MathUtils/Utils.h" -#include "SimulationDataFormat/MCCompLabel.h" -#include "SimulationDataFormat/MCTruthContainer.h" +#include "ITStracking/TrackingConfigParam.h" +#include "ITSMFTReconstruction/ChipMappingITS.h" namespace { @@ -46,10 +37,10 @@ void ioutils::convertCompactClusters(gsl::span clu std::vector>& output, const itsmft::TopologyDictionary* dict) { + static const o2::itsmft::ChipMappingITS chmap; GeometryTGeo* geom = GeometryTGeo::Instance(); bool applyMisalignment = false; const auto& conf = TrackerParamConfig::Instance(); - const auto& chmap = getChipMappingITS(); for (int il = 0; il < chmap.NLayers; il++) { if (conf.sysErrY2[il] > 0.f || conf.sysErrZ2[il] > 0.f) { applyMisalignment = true; @@ -69,77 +60,3 @@ void ioutils::convertCompactClusters(gsl::span clu cl3d.setErrors(sigmaY2, sigmaZ2, sigmaYZ); } } - -void ioutils::loadEventData(ROframe& event, gsl::span clusters, - gsl::span::iterator& pattIt, const itsmft::TopologyDictionary* dict, - const dataformats::MCTruthContainer* clsLabels) -{ - if (clusters.empty()) { - std::cerr << "Missing clusters." << std::endl; - return; - } - event.clear(); - GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); - int clusterId{0}; - - for (const auto& c : clusters) { - const int layer = geom->getLayer(c.getSensorID()); - float sigmaY2{0}, sigmaZ2{0}, sigmaYZ{0}; - auto locXYZ = extractClusterData(c, pattIt, dict, sigmaY2, sigmaZ2); - auto sensorID = c.getSensorID(); - // Inverse transformation to the local --> tracking - auto trkXYZ = geom->getMatrixT2L(sensorID) ^ locXYZ; - // Transformation to the local --> global - auto gloXYZ = geom->getMatrixL2G(sensorID) * locXYZ; - - event.addTrackingFrameInfoToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), trkXYZ.x(), geom->getSensorRefAlpha(sensorID), - std::array{trkXYZ.y(), trkXYZ.z()}, - std::array{sigmaY2, sigmaYZ, sigmaZ2}); - - /// Rotate to the global frame - event.addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), event.getClustersOnLayer(layer).size()); - if (clsLabels) { - // event.addClusterLabelToLayer(layer, *(clsLabels->getLabels(clusterId).begin())); - event.setMClabelsContainer(clsLabels); - } - event.addClusterExternalIndexToLayer(layer, clusterId); - clusterId++; - } -} - -int ioutils::loadROFrameData(const o2::itsmft::ROFRecord& rof, ROframe& event, gsl::span clusters, gsl::span::iterator& pattIt, const itsmft::TopologyDictionary* dict, - const dataformats::MCTruthContainer* mcLabels) -{ - event.clear(); - GeometryTGeo* geom = GeometryTGeo::Instance(); - geom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); - int clusterId{0}; - - auto first = rof.getFirstEntry(); - auto clusters_in_frame = rof.getROFData(clusters); - for (const auto& c : clusters_in_frame) { - const int layer = geom->getLayer(c.getSensorID()); - float sigmaY2{0}, sigmaZ2{0}, sigmaYZ{0}; - auto locXYZ = extractClusterData(c, pattIt, dict, sigmaY2, sigmaZ2); - auto sensorID = c.getSensorID(); - // Inverse transformation to the local --> tracking - auto trkXYZ = geom->getMatrixT2L(sensorID) ^ locXYZ; - // Transformation to the local --> global - auto gloXYZ = geom->getMatrixL2G(sensorID) * locXYZ; - - event.addTrackingFrameInfoToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), trkXYZ.x(), geom->getSensorRefAlpha(sensorID), - std::array{trkXYZ.y(), trkXYZ.z()}, - std::array{sigmaY2, sigmaYZ, sigmaZ2}); - - /// Rotate to the global frame - event.addClusterToLayer(layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), event.getClustersOnLayer(layer).size()); - if (mcLabels) { - // event.addClusterLabelToLayer(layer, *(mcLabels->getLabels(first + clusterId).begin())); - event.setMClabelsContainer(mcLabels); - } - event.addClusterExternalIndexToLayer(layer, first + clusterId); - clusterId++; - } - return (int)clusters_in_frame.size(); -} diff --git a/Detectors/ITSMFT/ITS/tracking/src/Label.cxx b/Detectors/ITSMFT/ITS/tracking/src/Label.cxx deleted file mode 100644 index e195318828f51..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/src/Label.cxx +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. -/// -/// \file Label.cxx -/// \brief -/// - -#include "ITStracking/Label.h" - -namespace o2 -{ -namespace its -{ - -Label::Label(const int mcId, const float pT, const float phi, const float eta, const int pdg, const int ncl) - : monteCarloId{mcId}, - transverseMomentum{pT}, - phi{phi}, - pseudorapidity{eta}, - pdgCode{pdg}, - numberOfClusters{ncl} -{ - // Nothing to do -} - -std::ostream& operator<<(std::ostream& outputStream, const Label& label) -{ - outputStream << label.monteCarloId << "\t" << label.transverseMomentum << "\t" << label.phi << "\t" - << label.pseudorapidity << "\t" << label.pdgCode << "\t" << label.numberOfClusters; - - return outputStream; -} -} // namespace its -} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx b/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx deleted file mode 100644 index ee885db3c49ea..0000000000000 --- a/Detectors/ITSMFT/ITS/tracking/src/ROframe.cxx +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. -/// -/// \file ROframe.cxx -/// \brief -/// - -#include "ITStracking/ROframe.h" - -#include - -namespace o2 -{ -namespace its -{ - -ROframe::ROframe(int ROframeId, int nLayers) : mROframeId{ROframeId} -{ - mClusters.resize(nLayers); - mTrackingFrameInfo.resize(nLayers); - // mClusterLabels.resize(nLayers); - mClusterExternalIndices.resize(nLayers); -} - -void ROframe::addPrimaryVertex(const float xCoordinate, const float yCoordinate, const float zCoordinate) -{ - mPrimaryVertices.emplace_back(float3{xCoordinate, yCoordinate, zCoordinate}); -} - -void ROframe::addPrimaryVertices(std::vector vertices) -{ - for (Vertex& vertex : vertices) { - mPrimaryVertices.emplace_back(float3{vertex.getX(), vertex.getY(), vertex.getZ()}); - } -} - -void ROframe::printPrimaryVertices() const -{ - const int verticesNum{static_cast(mPrimaryVertices.size())}; - - for (int iVertex{0}; iVertex < verticesNum; ++iVertex) { - - const float3& currentVertex = mPrimaryVertices[iVertex]; - std::cout << "-1\t" << currentVertex.x << "\t" << currentVertex.y << "\t" << currentVertex.z << std::endl; - } -} - -int ROframe::getTotalClusters() const -{ - size_t totalClusters{0}; - for (auto& clusters : mClusters) { - totalClusters += clusters.size(); - } - return int(totalClusters); -} -} // namespace its -} // namespace o2 diff --git a/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx b/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx index 9bc65161c3cbb..f2f7dbc81398f 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Smoother.cxx @@ -25,92 +25,92 @@ constexpr std::array getInverseSymm2D(const std::array& ma } // Smoother -template -Smoother::Smoother(TrackITSExt& track, size_t smoothingLayer, const ROframe& event, float bZ, o2::base::PropagatorF::MatCorrType corr) : mLayerToSmooth{smoothingLayer}, - mBz(bZ), - mCorr(corr) -{ - - auto propInstance = o2::base::Propagator::Instance(); - const TrackingFrameInfo& originalTf = event.getTrackingFrameInfoOnLayer(mLayerToSmooth).at(track.getClusterIndex(mLayerToSmooth)); - - mOutwardsTrack = track; // This track will be propagated outwards inside the smoother! (as last step of fitting did inward propagation) - mInwardsTrack = {track.getParamOut(), // This track will be propagated inwards inside the smoother! - static_cast(mOutwardsTrack.getNumberOfClusters()), -999, static_cast(event.getROFrameId()), - mOutwardsTrack.getParamOut(), mOutwardsTrack.getClusterIndexes()}; - - mOutwardsTrack.resetCovariance(); - mOutwardsTrack.setChi2(0); - mInwardsTrack.resetCovariance(); - mInwardsTrack.setChi2(0); - - bool statusOutw{false}; - bool statusInw{false}; - - ////////////////////// - // Outward propagation - for (size_t iLayer{0}; iLayer < mLayerToSmooth; ++iLayer) { - if (mOutwardsTrack.getClusterIndex(iLayer) == constants::UnusedIndex) { // Shorter tracks - continue; - } - const TrackingFrameInfo& tF = event.getTrackingFrameInfoOnLayer(iLayer).at(mOutwardsTrack.getClusterIndex(iLayer)); - statusOutw = mOutwardsTrack.rotate(tF.alphaTrackingFrame); - statusOutw &= propInstance->propagateToX(mOutwardsTrack, - tF.xTrackingFrame, - mBz, - o2::base::PropagatorImpl::MAX_SIN_PHI, - o2::base::PropagatorImpl::MAX_STEP, - mCorr); - mOutwardsTrack.setChi2(mOutwardsTrack.getChi2() + mOutwardsTrack.getPredictedChi2(tF.positionTrackingFrame, tF.covarianceTrackingFrame)); - statusOutw &= mOutwardsTrack.o2::track::TrackParCov::update(tF.positionTrackingFrame, tF.covarianceTrackingFrame); - // LOG(info) << "Outwards loop on inwards track, layer: " << iLayer << " x: " << mOutwardsTrack.getX(); - } - - // Prediction on the previously outwards-propagated track is done on a copy, as the process seems to be not reversible - auto outwardsClone = mOutwardsTrack; - statusOutw = outwardsClone.rotate(originalTf.alphaTrackingFrame); - statusOutw &= propInstance->propagateToX(outwardsClone, - originalTf.xTrackingFrame, - mBz, - o2::base::PropagatorImpl::MAX_SIN_PHI, - o2::base::PropagatorImpl::MAX_STEP, - mCorr); - ///////////////////// - // Inward propagation - for (size_t iLayer{D - 1}; iLayer > mLayerToSmooth; --iLayer) { - if (mInwardsTrack.getClusterIndex(iLayer) == constants::UnusedIndex) { // Shorter tracks - continue; - } - const TrackingFrameInfo& tF = event.getTrackingFrameInfoOnLayer(iLayer).at(mInwardsTrack.getClusterIndex(iLayer)); - statusInw = mInwardsTrack.rotate(tF.alphaTrackingFrame); - statusInw &= propInstance->propagateToX(mInwardsTrack, - tF.xTrackingFrame, - mBz, - o2::base::PropagatorImpl::MAX_SIN_PHI, - o2::base::PropagatorImpl::MAX_STEP, - mCorr); - mInwardsTrack.setChi2(mInwardsTrack.getChi2() + mInwardsTrack.getPredictedChi2(tF.positionTrackingFrame, tF.covarianceTrackingFrame)); - statusInw &= mInwardsTrack.o2::track::TrackParCov::update(tF.positionTrackingFrame, tF.covarianceTrackingFrame); - // LOG(info) << "Inwards loop on outwards track, layer: " << iLayer << " x: " << mInwardsTrack.getX(); - } - - // Prediction on the previously inwards-propagated track is done on a copy, as the process seems to be not revesible - auto inwardsClone = mInwardsTrack; - statusInw = inwardsClone.rotate(originalTf.alphaTrackingFrame); - statusInw &= propInstance->propagateToX(inwardsClone, - originalTf.xTrackingFrame, - mBz, - o2::base::PropagatorImpl::MAX_SIN_PHI, - o2::base::PropagatorImpl::MAX_STEP, - mCorr); - // Compute weighted local chi2 - mInitStatus = statusInw && statusOutw; - if (mInitStatus) { - mBestChi2 = computeSmoothedPredictedChi2(inwardsClone, outwardsClone, originalTf.positionTrackingFrame, originalTf.covarianceTrackingFrame); - mLastChi2 = mBestChi2; - LOG(info) << "Smoothed chi2 on original cluster: " << mBestChi2; - } -} +// template +// Smoother::Smoother(TrackITSExt& track, size_t smoothingLayer, const ROframe& event, float bZ, o2::base::PropagatorF::MatCorrType corr) : mLayerToSmooth{smoothingLayer}, +// mBz(bZ), +// mCorr(corr) +// { +// +// auto propInstance = o2::base::Propagator::Instance(); +// const TrackingFrameInfo& originalTf = event.getTrackingFrameInfoOnLayer(mLayerToSmooth).at(track.getClusterIndex(mLayerToSmooth)); +// +// mOutwardsTrack = track; // This track will be propagated outwards inside the smoother! (as last step of fitting did inward propagation) +// mInwardsTrack = {track.getParamOut(), // This track will be propagated inwards inside the smoother! +// static_cast(mOutwardsTrack.getNumberOfClusters()), -999, static_cast(event.getROFrameId()), +// mOutwardsTrack.getParamOut(), mOutwardsTrack.getClusterIndexes()}; +// +// mOutwardsTrack.resetCovariance(); +// mOutwardsTrack.setChi2(0); +// mInwardsTrack.resetCovariance(); +// mInwardsTrack.setChi2(0); +// +// bool statusOutw{false}; +// bool statusInw{false}; +// +// ////////////////////// +// // Outward propagation +// for (size_t iLayer{0}; iLayer < mLayerToSmooth; ++iLayer) { +// if (mOutwardsTrack.getClusterIndex(iLayer) == constants::UnusedIndex) { // Shorter tracks +// continue; +// } +// const TrackingFrameInfo& tF = event.getTrackingFrameInfoOnLayer(iLayer).at(mOutwardsTrack.getClusterIndex(iLayer)); +// statusOutw = mOutwardsTrack.rotate(tF.alphaTrackingFrame); +// statusOutw &= propInstance->propagateToX(mOutwardsTrack, +// tF.xTrackingFrame, +// mBz, +// o2::base::PropagatorImpl::MAX_SIN_PHI, +// o2::base::PropagatorImpl::MAX_STEP, +// mCorr); +// mOutwardsTrack.setChi2(mOutwardsTrack.getChi2() + mOutwardsTrack.getPredictedChi2(tF.positionTrackingFrame, tF.covarianceTrackingFrame)); +// statusOutw &= mOutwardsTrack.o2::track::TrackParCov::update(tF.positionTrackingFrame, tF.covarianceTrackingFrame); +// // LOG(info) << "Outwards loop on inwards track, layer: " << iLayer << " x: " << mOutwardsTrack.getX(); +// } +// +// // Prediction on the previously outwards-propagated track is done on a copy, as the process seems to be not reversible +// auto outwardsClone = mOutwardsTrack; +// statusOutw = outwardsClone.rotate(originalTf.alphaTrackingFrame); +// statusOutw &= propInstance->propagateToX(outwardsClone, +// originalTf.xTrackingFrame, +// mBz, +// o2::base::PropagatorImpl::MAX_SIN_PHI, +// o2::base::PropagatorImpl::MAX_STEP, +// mCorr); +// ///////////////////// +// // Inward propagation +// for (size_t iLayer{D - 1}; iLayer > mLayerToSmooth; --iLayer) { +// if (mInwardsTrack.getClusterIndex(iLayer) == constants::UnusedIndex) { // Shorter tracks +// continue; +// } +// const TrackingFrameInfo& tF = event.getTrackingFrameInfoOnLayer(iLayer).at(mInwardsTrack.getClusterIndex(iLayer)); +// statusInw = mInwardsTrack.rotate(tF.alphaTrackingFrame); +// statusInw &= propInstance->propagateToX(mInwardsTrack, +// tF.xTrackingFrame, +// mBz, +// o2::base::PropagatorImpl::MAX_SIN_PHI, +// o2::base::PropagatorImpl::MAX_STEP, +// mCorr); +// mInwardsTrack.setChi2(mInwardsTrack.getChi2() + mInwardsTrack.getPredictedChi2(tF.positionTrackingFrame, tF.covarianceTrackingFrame)); +// statusInw &= mInwardsTrack.o2::track::TrackParCov::update(tF.positionTrackingFrame, tF.covarianceTrackingFrame); +// // LOG(info) << "Inwards loop on outwards track, layer: " << iLayer << " x: " << mInwardsTrack.getX(); +// } +// +// // Prediction on the previously inwards-propagated track is done on a copy, as the process seems to be not revesible +// auto inwardsClone = mInwardsTrack; +// statusInw = inwardsClone.rotate(originalTf.alphaTrackingFrame); +// statusInw &= propInstance->propagateToX(inwardsClone, +// originalTf.xTrackingFrame, +// mBz, +// o2::base::PropagatorImpl::MAX_SIN_PHI, +// o2::base::PropagatorImpl::MAX_STEP, +// mCorr); +// // Compute weighted local chi2 +// mInitStatus = statusInw && statusOutw; +// if (mInitStatus) { +// mBestChi2 = computeSmoothedPredictedChi2(inwardsClone, outwardsClone, originalTf.positionTrackingFrame, originalTf.covarianceTrackingFrame); +// mLastChi2 = mBestChi2; +// LOG(info) << "Smoothed chi2 on original cluster: " << mBestChi2; +// } +// } template Smoother::~Smoother() = default; @@ -173,48 +173,48 @@ float Smoother::computeSmoothedPredictedChi2(const o2::track::TrackParCov& fi return chi2; } -template -bool Smoother::testCluster(const int clusterId, const ROframe& event) -{ - if (!mInitStatus) { - return false; - } - auto propInstance = o2::base::Propagator::Instance(); - const TrackingFrameInfo& testTf = event.getTrackingFrameInfoOnLayer(mLayerToSmooth).at(clusterId); - - bool statusOutw{false}; - bool statusInw{false}; - - // Prediction on the previously outwards-propagated track is done on a copy, as the process seems to be not reversible - auto outwardsClone = mOutwardsTrack; - statusOutw = outwardsClone.rotate(testTf.alphaTrackingFrame); - statusOutw &= propInstance->propagateToX(outwardsClone, - testTf.xTrackingFrame, - mBz, - o2::base::PropagatorImpl::MAX_SIN_PHI, - o2::base::PropagatorImpl::MAX_STEP, - mCorr); - - // Prediction on the previously inwards-propagated track is done on a copy, as the process seems to be not reversible - auto inwardsClone = mInwardsTrack; - statusInw = inwardsClone.rotate(testTf.alphaTrackingFrame); - statusInw &= propInstance->propagateToX(inwardsClone, - testTf.xTrackingFrame, - mBz, - o2::base::PropagatorImpl::MAX_SIN_PHI, - o2::base::PropagatorImpl::MAX_STEP, - mCorr); - if (!(statusOutw && statusInw)) { - LOG(warning) << "Failed propagation in smoother!"; - return false; - } - - // Compute weighted local chi2 - mLastChi2 = computeSmoothedPredictedChi2(inwardsClone, outwardsClone, testTf.positionTrackingFrame, testTf.covarianceTrackingFrame); - LOG(info) << "Smoothed chi2 on tested cluster: " << mLastChi2; - - return true; -} +// template +// bool Smoother::testCluster(const int clusterId, const ROframe& event) +// { +// if (!mInitStatus) { +// return false; +// } +// auto propInstance = o2::base::Propagator::Instance(); +// const TrackingFrameInfo& testTf = event.getTrackingFrameInfoOnLayer(mLayerToSmooth).at(clusterId); +// +// bool statusOutw{false}; +// bool statusInw{false}; +// +// // Prediction on the previously outwards-propagated track is done on a copy, as the process seems to be not reversible +// auto outwardsClone = mOutwardsTrack; +// statusOutw = outwardsClone.rotate(testTf.alphaTrackingFrame); +// statusOutw &= propInstance->propagateToX(outwardsClone, +// testTf.xTrackingFrame, +// mBz, +// o2::base::PropagatorImpl::MAX_SIN_PHI, +// o2::base::PropagatorImpl::MAX_STEP, +// mCorr); +// +// // Prediction on the previously inwards-propagated track is done on a copy, as the process seems to be not reversible +// auto inwardsClone = mInwardsTrack; +// statusInw = inwardsClone.rotate(testTf.alphaTrackingFrame); +// statusInw &= propInstance->propagateToX(inwardsClone, +// testTf.xTrackingFrame, +// mBz, +// o2::base::PropagatorImpl::MAX_SIN_PHI, +// o2::base::PropagatorImpl::MAX_STEP, +// mCorr); +// if (!(statusOutw && statusInw)) { +// LOG(warning) << "Failed propagation in smoother!"; +// return false; +// } +// +// // Compute weighted local chi2 +// mLastChi2 = computeSmoothedPredictedChi2(inwardsClone, outwardsClone, testTf.positionTrackingFrame, testTf.covarianceTrackingFrame); +// LOG(info) << "Smoothed chi2 on tested cluster: " << mLastChi2; +// +// return true; +// } template class Smoother<7>; diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 7a2e883e1b5e6..aa93e32e1db9c 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -19,7 +19,6 @@ #include "ITStracking/Cell.h" #include "ITStracking/Constants.h" #include "ITStracking/IndexTableUtils.h" -#include "ITStracking/Smoother.h" #include "ITStracking/Tracklet.h" #include "ITStracking/TrackerTraits.h" #include "ITStracking/TrackingConfigParam.h" diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index f5fa195983240..a908f8b2a1f1e 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -9,15 +9,18 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include + +#include + #include "ITSMFTBase/DPLAlpideParam.h" #include "ITSBase/GeometryTGeo.h" #include "ITSReconstruction/FastMultEstConfig.h" #include "ITSReconstruction/FastMultEst.h" +#include "ITStracking/TrackingConfigParam.h" #include "ITStracking/TrackingInterface.h" -#include -#include #include "DataFormatsITSMFT/ROFRecord.h" #include "DataFormatsITSMFT/PhysTrigger.h" @@ -25,7 +28,6 @@ #include "CommonDataFormat/IRFrame.h" #include "DetectorsBase/GRPGeomHelper.h" #include "ITStracking/BoundedAllocator.h" -#include "ITStracking/TrackingConfigParam.h" #include "Framework/DeviceSpec.h" using namespace o2::framework; diff --git a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx index 16de3d075ef75..94d69f7968ac8 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Vertexer.cxx @@ -16,8 +16,9 @@ #include "ITStracking/Vertexer.h" #include "ITStracking/BoundedAllocator.h" #include "ITStracking/Cluster.h" -#include "ITStracking/ROframe.h" + #include "ITStracking/ClusterLines.h" +#include "ITStracking/Tracklet.h" #include "ITStracking/IndexTableUtils.h" #include "ITStracking/VertexerTraits.h" #include "ITStracking/TrackingConfigParam.h" diff --git a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx index 640265f881749..8a415d269d7f5 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx @@ -34,7 +34,6 @@ #include "DetectorsBase/Propagator.h" #include "ITSBase/GeometryTGeo.h" #include "CommonDataFormat/IRFrame.h" -#include "ITStracking/ROframe.h" #include "ITStracking/IOUtils.h" #include "DetectorsCommonDataFormats/DetectorNameConf.h" #include "CommonUtils/StringUtils.h" @@ -113,7 +112,6 @@ void CookedTrackerDPL::run(ProcessingContext& pc) mTracker.setMCTruthContainers(labels.get(), &trackLabels); } - o2::its::ROframe event(0, 7); mVertexerPtr->adoptTimeFrame(mTimeFrame); auto& vertROFvec = pc.outputs().make>(Output{"ITS", "VERTICESROF", 0}); diff --git a/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx b/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx index 99ac05e61baf8..3d18ab267bd46 100644 --- a/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx +++ b/Detectors/Upgrades/ITS3/reconstruction/src/TrackingInterface.cxx @@ -12,6 +12,7 @@ #include "ITS3Reconstruction/TrackingInterface.h" #include "ITS3Reconstruction/IOUtils.h" #include "ITSBase/GeometryTGeo.h" +#include "ITStracking/TrackingConfigParam.h" #include "ITSMFTBase/DPLAlpideParam.h" #include "DetectorsBase/GRPGeomHelper.h" #include "Framework/DeviceSpec.h" From 5074d714f0c459c75c06dbdd361a3e81516195d1 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sun, 13 Jul 2025 09:46:22 +0200 Subject: [PATCH 159/315] TRD: fix missing include Signed-off-by: Felix Schlepper --- Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx index b5a1530e83d8c..598ce3c35c98c 100644 --- a/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx +++ b/Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx @@ -18,6 +18,7 @@ #include "DetectorsBase/GlobalParams.h" #include "DetectorsBase/Propagator.h" #include "ReconstructionDataFormats/TrackTPCITS.h" +#include "ReconstructionDataFormats/Vertex.h" #include "DataFormatsTRD/Tracklet64.h" #include "DataFormatsTRD/CalibratedTracklet.h" #include "DataFormatsTRD/TriggerRecord.h" From 5cdac2fee9655731decf176af40be1303377addb Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 14 Jul 2025 11:12:02 +0200 Subject: [PATCH 160/315] ITS: fix CookedTracker due to memory refactor Signed-off-by: Felix Schlepper --- .../ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h | 5 +++++ Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h index 88e4b06a5c8ce..eb55081889c12 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/CookedTrackerSpec.h @@ -19,12 +19,15 @@ #include "ITStracking/TimeFrame.h" #include "ITStracking/Vertexer.h" #include "ITStracking/VertexerTraits.h" +#include "ITStracking/BoundedAllocator.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsITSMFT/TopologyDictionary.h" #include "Framework/Task.h" #include "TStopwatch.h" #include "DetectorsBase/GRPGeomHelper.h" +#include + using namespace o2::framework; namespace o2 @@ -57,6 +60,8 @@ class CookedTrackerDPL : public Task o2::its::CookedTracker mTracker; std::unique_ptr mVertexerTraitsPtr = nullptr; std::unique_ptr mVertexerPtr = nullptr; + std::shared_ptr mMemoryPool; + std::shared_ptr mTaskArena; TStopwatch mTimer; }; diff --git a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx index 8a415d269d7f5..98662e46269d1 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/CookedTrackerSpec.cxx @@ -64,6 +64,11 @@ void CookedTrackerDPL::init(InitContext& ic) o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); auto nthreads = ic.options().get("nthreads"); mTracker.setNumberOfThreads(nthreads); + mTaskArena = std::make_shared(nthreads); + mMemoryPool = std::make_unique(); + mVertexerPtr->setMemoryPool(mMemoryPool); + mVertexerPtr->setNThreads(nthreads, mTaskArena); + mVertexerTraitsPtr->setMemoryPool(mMemoryPool); } void CookedTrackerDPL::run(ProcessingContext& pc) @@ -104,6 +109,7 @@ void CookedTrackerDPL::run(ProcessingContext& pc) mc2rofs = pc.inputs().get>("MC2ROframes"); } TimeFrame mTimeFrame; + mTimeFrame.setMemoryPool(mMemoryPool); LOG(info) << "ITSCookedTracker pulled " << compClusters.size() << " clusters, in " << rofs.size() << " RO frames"; From aaf3d53e45066f0b0137b91f7ccc6a042fff6b31 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 17 Jul 2025 16:26:35 +0200 Subject: [PATCH 161/315] DPL: get rid of gsl::span. --- .../Core/include/Framework/DeviceMetricsInfo.h | 4 ++-- .../GUISupport/src/FrameworkGUIDebugger.cxx | 17 ++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Framework/Core/include/Framework/DeviceMetricsInfo.h b/Framework/Core/include/Framework/DeviceMetricsInfo.h index 30387f4e6becf..d55f1cb44f71d 100644 --- a/Framework/Core/include/Framework/DeviceMetricsInfo.h +++ b/Framework/Core/include/Framework/DeviceMetricsInfo.h @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include @@ -217,7 +217,7 @@ struct DeviceMetricsInfoHelpers { info.changed.clear(); } } - static size_t metricsStorageSize(gsl::span infos) + static size_t metricsStorageSize(std::span infos) { // Count the size of the metrics storage size_t totalSize = 0; diff --git a/Framework/GUISupport/src/FrameworkGUIDebugger.cxx b/Framework/GUISupport/src/FrameworkGUIDebugger.cxx index 112797d357458..33e7f794972ad 100644 --- a/Framework/GUISupport/src/FrameworkGUIDebugger.cxx +++ b/Framework/GUISupport/src/FrameworkGUIDebugger.cxx @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -210,8 +209,8 @@ enum MetricTypes { // so that we can display driver and device metrics in the same plot // without an if. struct AllMetricsStore { - gsl::span metrics[TOTAL_TYPES_OF_METRICS]; - gsl::span specs[TOTAL_TYPES_OF_METRICS]; + std::span metrics[TOTAL_TYPES_OF_METRICS]; + std::span specs[TOTAL_TYPES_OF_METRICS]; }; void displaySparks( @@ -376,8 +375,8 @@ void displayDeviceMetrics(const char* label, ImPlotAxisFlags axisFlags = 0; for (size_t si = 0; si < TOTAL_TYPES_OF_METRICS; ++si) { - gsl::span metricsInfos = metricStore.metrics[si]; - gsl::span specs = metricStore.specs[si]; + std::span metricsInfos = metricStore.metrics[si]; + std::span specs = metricStore.specs[si]; for (int di = 0; di < metricsInfos.size(); ++di) { for (size_t mi = 0; mi < metricsInfos[di].metrics.size(); ++mi) { if (state[gmi].visible == false) { @@ -1175,10 +1174,10 @@ std::function getGUIDebugger(std::vector const& infos, AllMetricsStore metricsStore; - metricsStore.metrics[DEVICE_METRICS] = gsl::span(metricsInfos); - metricsStore.metrics[DRIVER_METRICS] = gsl::span(&driverInfo.metrics, 1); - metricsStore.specs[DEVICE_METRICS] = gsl::span(deviceNodesInfos); - metricsStore.specs[DRIVER_METRICS] = gsl::span(driverNodesInfos); + metricsStore.metrics[DEVICE_METRICS] = std::span(metricsInfos); + metricsStore.metrics[DRIVER_METRICS] = std::span(&driverInfo.metrics, 1); + metricsStore.specs[DEVICE_METRICS] = std::span(deviceNodesInfos); + metricsStore.specs[DRIVER_METRICS] = std::span(driverNodesInfos); displayMetrics(guiState, driverInfo, infos, metadata, controls, metricsStore); displayDriverInfo(driverInfo, driverControl); From 2db94469033eb065f1a07629d97ebac464199a3d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 16 Jul 2025 15:10:40 +0200 Subject: [PATCH 162/315] DPL: move topological sort in a separate file Simplifies testing. --- Framework/Core/CMakeLists.txt | 2 + .../include/Framework/TopologyPolicyHelpers.h | 23 +++++ Framework/Core/src/TopologyPolicyHelpers.cxx | 92 +++++++++++++++++++ Framework/Core/src/runDataProcessing.cxx | 70 +------------- Framework/Core/test/test_TopologyPolicies.cxx | 59 ++++++++++++ 5 files changed, 178 insertions(+), 68 deletions(-) create mode 100644 Framework/Core/include/Framework/TopologyPolicyHelpers.h create mode 100644 Framework/Core/src/TopologyPolicyHelpers.cxx create mode 100644 Framework/Core/test/test_TopologyPolicies.cxx diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index 17320348d9272..d69194c83285e 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -133,6 +133,7 @@ o2_add_library(Framework src/TableConsumer.cxx src/TableTreeHelpers.cxx src/TopologyPolicy.cxx + src/TopologyPolicyHelpers.cxx src/TextDriverClient.cxx src/TimesliceIndex.cxx src/TimingHelpers.cxx @@ -248,6 +249,7 @@ add_executable(o2-test-framework-core test/test_TimeParallelPipelining.cxx test/test_TimesliceIndex.cxx test/test_TypeTraits.cxx + test/test_TopologyPolicies.cxx test/test_Variants.cxx test/test_WorkflowHelpers.cxx test/test_WorkflowSerialization.cxx diff --git a/Framework/Core/include/Framework/TopologyPolicyHelpers.h b/Framework/Core/include/Framework/TopologyPolicyHelpers.h new file mode 100644 index 0000000000000..71d40755f2d50 --- /dev/null +++ b/Framework/Core/include/Framework/TopologyPolicyHelpers.h @@ -0,0 +1,23 @@ +// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef O2_FRAMEWORK_TOPOLOGYPOLICYHELPERS_H_ +#define O2_FRAMEWORK_TOPOLOGYPOLICYHELPERS_H_ +#include "Framework/WorkflowSpec.h" +#include + +namespace o2::framework +{ +struct TopologyPolicyHelpers { + static auto buildEdges(WorkflowSpec& physicalWorkflow) -> std::vector>; +}; +} // namespace o2::framework +#endif // O2_FRAMEWORK_TOPOLOGYPOLICYHELPERS_H_ diff --git a/Framework/Core/src/TopologyPolicyHelpers.cxx b/Framework/Core/src/TopologyPolicyHelpers.cxx new file mode 100644 index 0000000000000..31423bf27e0ff --- /dev/null +++ b/Framework/Core/src/TopologyPolicyHelpers.cxx @@ -0,0 +1,92 @@ +// Copyright 2019-2025 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/TopologyPolicyHelpers.h" +#include "Framework/TopologyPolicy.h" + +namespace o2::framework +{ +namespace +{ +void describeDataProcessorSpec(std::ostream& stream, DataProcessorSpec const& spec) +{ + stream << spec.name; + if (!spec.labels.empty()) { + stream << "("; + bool first = false; + for (auto& label : spec.labels) { + stream << (first ? "" : ",") << label.value; + first = true; + } + stream << ")"; + } +} +} // namespace + +auto TopologyPolicyHelpers::buildEdges(WorkflowSpec& physicalWorkflow) -> std::vector> +{ + std::vector topologyPolicies = TopologyPolicy::createDefaultPolicies(); + std::vector dependencyCheckers; + dependencyCheckers.reserve(physicalWorkflow.size()); + + for (auto& spec : physicalWorkflow) { + for (auto& policy : topologyPolicies) { + if (policy.matcher(spec)) { + dependencyCheckers.push_back(policy.checkDependency); + break; + } + } + } + assert(dependencyCheckers.size() == physicalWorkflow.size()); + // check if DataProcessorSpec at i depends on j + auto checkDependencies = [&workflow = physicalWorkflow, + &dependencyCheckers](int i, int j) { + TopologyPolicy::DependencyChecker& checker = dependencyCheckers[i]; + return checker(workflow[i], workflow[j]); + }; + std::vector> edges; + for (size_t i = 0; i < physicalWorkflow.size() - 1; ++i) { + for (size_t j = i; j < physicalWorkflow.size(); ++j) { + if (i == j && checkDependencies(i, j)) { + throw std::runtime_error(physicalWorkflow[i].name + " depends on itself"); + } + bool both = false; + if (checkDependencies(i, j)) { + edges.emplace_back(j, i); + both = true; + } + if (checkDependencies(j, i)) { + edges.emplace_back(i, j); + if (both) { + std::ostringstream str; + describeDataProcessorSpec(str, physicalWorkflow[i]); + str << " has circular dependency with "; + describeDataProcessorSpec(str, physicalWorkflow[j]); + str << ":\n"; + for (auto x : {i, j}) { + str << physicalWorkflow[x].name << ":\n"; + str << "inputs:\n"; + for (auto& input : physicalWorkflow[x].inputs) { + str << "- " << input << " " << (int)input.lifetime << "\n"; + } + str << "outputs:\n"; + for (auto& output : physicalWorkflow[x].outputs) { + str << "- " << output << " " << (int)output.lifetime << "\n"; + } + } + throw std::runtime_error(str.str()); + } + } + } + } + return edges; +}; +} // namespace o2::framework diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index d691041a366cf..59bacc67fef31 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -9,6 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. #include +#include "Framework/TopologyPolicyHelpers.h" #define BOOST_BIND_GLOBAL_PLACEHOLDERS #include #include "Framework/BoostOptionsRetriever.h" @@ -2835,20 +2836,6 @@ std::unique_ptr createRegistry() return std::make_unique(); } -void describeDataProcessorSpec(std::ostream& stream, DataProcessorSpec const& spec) -{ - stream << spec.name; - if (!spec.labels.empty()) { - stream << "("; - bool first = false; - for (auto& label : spec.labels) { - stream << (first ? "" : ",") << label.value; - first = true; - } - stream << ")"; - } -} - // This is a toy executor for the workflow spec // What it needs to do is: // @@ -3034,65 +3021,12 @@ int doMain(int argc, char** argv, o2::framework::WorkflowSpec const& workflow, [](OutputSpec const& a, OutputSpec const& b) { return DataSpecUtils::describe(a) < DataSpecUtils::describe(b); }); } - std::vector topologyPolicies = TopologyPolicy::createDefaultPolicies(); - std::vector dependencyCheckers; - dependencyCheckers.reserve(physicalWorkflow.size()); - - for (auto& spec : physicalWorkflow) { - for (auto& policy : topologyPolicies) { - if (policy.matcher(spec)) { - dependencyCheckers.push_back(policy.checkDependency); - break; - } - } - } - assert(dependencyCheckers.size() == physicalWorkflow.size()); - // check if DataProcessorSpec at i depends on j - auto checkDependencies = [&workflow = physicalWorkflow, - &dependencyCheckers](int i, int j) { - TopologyPolicy::DependencyChecker& checker = dependencyCheckers[i]; - return checker(workflow[i], workflow[j]); - }; - // Create a list of all the edges, so that we can do a topological sort // before we create the graph. std::vector> edges; if (physicalWorkflow.size() > 1) { - for (size_t i = 0; i < physicalWorkflow.size() - 1; ++i) { - for (size_t j = i; j < physicalWorkflow.size(); ++j) { - if (i == j && checkDependencies(i, j)) { - throw std::runtime_error(physicalWorkflow[i].name + " depends on itself"); - } - bool both = false; - if (checkDependencies(i, j)) { - edges.emplace_back(j, i); - both = true; - } - if (checkDependencies(j, i)) { - edges.emplace_back(i, j); - if (both) { - std::ostringstream str; - describeDataProcessorSpec(str, physicalWorkflow[i]); - str << " has circular dependency with "; - describeDataProcessorSpec(str, physicalWorkflow[j]); - str << ":\n"; - for (auto x : {i, j}) { - str << physicalWorkflow[x].name << ":\n"; - str << "inputs:\n"; - for (auto& input : physicalWorkflow[x].inputs) { - str << "- " << input << " " << (int)input.lifetime << "\n"; - } - str << "outputs:\n"; - for (auto& output : physicalWorkflow[x].outputs) { - str << "- " << output << " " << (int)output.lifetime << "\n"; - } - } - throw std::runtime_error(str.str()); - } - } - } - } + edges = TopologyPolicyHelpers::buildEdges(physicalWorkflow); auto topoInfos = WorkflowHelpers::topologicalSort(physicalWorkflow.size(), &edges[0].first, &edges[0].second, sizeof(std::pair), edges.size()); if (topoInfos.size() != physicalWorkflow.size()) { diff --git a/Framework/Core/test/test_TopologyPolicies.cxx b/Framework/Core/test/test_TopologyPolicies.cxx new file mode 100644 index 0000000000000..82344c292ab15 --- /dev/null +++ b/Framework/Core/test/test_TopologyPolicies.cxx @@ -0,0 +1,59 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Mocking.h" +#include +#include "Framework/ChannelSpecHelpers.h" +#include "../src/DeviceSpecHelpers.h" +#include "../src/GraphvizHelpers.h" +#include "../src/WorkflowHelpers.h" +#include "Framework/DeviceSpec.h" +#include "Framework/WorkflowSpec.h" +#include "Framework/DataSpecUtils.h" +#include "../src/SimpleResourceManager.h" +#include "../src/ComputingResourceHelpers.h" +#include "test_HelperMacros.h" +#include "Framework/TopologyPolicyHelpers.h" + +using namespace o2::framework; + +// This is how you can define your processing in a declarative way +WorkflowSpec defineDataProcessingWithSporadic() +{ + return { + {.name = "input-proxy", .outputs = {OutputSpec{"QEMC", "CELL", 1}, OutputSpec{"CTF", "DONE", 0}}}, + {.name = "EMC-Cell-proxy", .inputs = Inputs{InputSpec{"a", "QEMC", "CELL", 1, Lifetime::Sporadic}}}, + {.name = "calib-output-proxy-barrel-tf", .inputs = {InputSpec{"a", "CTF", "DONE", 0}}}}; +} + +TEST_CASE("TestBrokenSporadic") +{ + auto workflow = defineDataProcessingWithSporadic(); + auto configContext = makeEmptyConfigContext(); + auto channelPolicies = ChannelConfigurationPolicy::createDefaultPolicies(*configContext); + auto completionPolicies = CompletionPolicy::createDefaultPolicies(); + auto callbacksPolicies = CallbacksPolicy::createDefaultPolicies(); + REQUIRE(channelPolicies.empty() == false); + REQUIRE(completionPolicies.empty() == false); + std::vector devices; + + std::vector resources{ComputingResourceHelpers::getLocalhostResource()}; + REQUIRE(resources.size() == 1); + REQUIRE(resources[0].startPort == 22000); + SimpleResourceManager rm(resources); + auto offers = rm.getAvailableOffers(); + REQUIRE(offers.size() == 1); + REQUIRE(offers[0].startPort == 22000); + REQUIRE(offers[0].rangeSize == 5000); + + DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(workflow, channelPolicies, completionPolicies, callbacksPolicies, devices, rm, "workflow-id", *configContext); + TopologyPolicyHelpers::buildEdges(workflow); +} From 9b9ef9a39e8da8a75e7c07111f5fb236c439ec82 Mon Sep 17 00:00:00 2001 From: nivram-phy Date: Fri, 18 Jul 2025 15:28:49 +0200 Subject: [PATCH 163/315] Propagating merged noise map to DCS (#14515) * Propagating merged noise map to DCS * adding some definitions in NoiseCalibratorSpec.h --------- Co-authored-by: Niveditha Ramasubramanian --- .../MFTCalibration/NoiseCalibratorSpec.h | 4 +- .../calibration/src/NoiseCalibratorSpec.cxx | 92 ++++++++++++++++--- 2 files changed, 83 insertions(+), 13 deletions(-) diff --git a/Detectors/ITSMFT/MFT/calibration/include/MFTCalibration/NoiseCalibratorSpec.h b/Detectors/ITSMFT/MFT/calibration/include/MFTCalibration/NoiseCalibratorSpec.h index c28e5d82ca46f..dee8fa4531bed 100644 --- a/Detectors/ITSMFT/MFT/calibration/include/MFTCalibration/NoiseCalibratorSpec.h +++ b/Detectors/ITSMFT/MFT/calibration/include/MFTCalibration/NoiseCalibratorSpec.h @@ -56,17 +56,17 @@ class NoiseCalibratorSpec : public Task void sendOutputCcdbMerge(DataAllocator& output); void sendOutputCcdbDcs(DataAllocator& output); void sendOutputDcs(DataAllocator& output); + void sendOutputDcsMerge(DataAllocator& output); void setOutputDcs(const o2::itsmft::NoiseMap& payload); o2::itsmft::NoiseMap mNoiseMap{936}; std::unique_ptr mCalibrator = nullptr; std::shared_ptr mCCDBRequest; std::string mPath; - std::string mPathMerge; + std::string mPathSingle; std::string mMeta; std::vector> mNoiseMapForDcs; std::string mPathDcs; - std::string mPathDcsMerge; std::string mOutputType; double mThresh; diff --git a/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx b/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx index a34d8cc5f2975..e958e6b1ba113 100644 --- a/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx +++ b/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx @@ -48,7 +48,7 @@ void NoiseCalibratorSpec::init(InitContext& ic) LOGP(info, "Setting the probability threshold to {} with relative error {}", probT, probTRelErr); mStopMeOnly = ic.options().get("stop-me-only"); mPath = ic.options().get("path-CCDB"); - mPathMerge = ic.options().get("path-CCDB-merge"); + mPathSingle = ic.options().get("path-CCDB-single"); mMeta = ic.options().get("meta"); mStart = ic.options().get("tstart"); @@ -173,7 +173,7 @@ void NoiseCalibratorSpec::sendOutputCcdbDcs(DataAllocator& output) const auto& payload = mCalibrator->getNoiseMap(); // const auto& payload = mCalibrator->getNoiseMap(starTF, endTF); //For TimeSlot calibration - o2::ccdb::CcdbObjectInfo info(mPath, "NoiseMap", "noise.root", meta, tstart, tend); + o2::ccdb::CcdbObjectInfo info(mPathSingle, "NoiseMap", "noise.root", meta, tstart, tend); auto flName = o2::ccdb::CcdbApi::generateFileName("noise"); auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); info.setFileName(flName); @@ -244,7 +244,7 @@ void NoiseCalibratorSpec::sendOutputCcdb(DataAllocator& output) const auto& payload = mCalibrator->getNoiseMap(); // const auto& payload = mCalibrator->getNoiseMap(starTF, endTF); //For TimeSlot calibration - o2::ccdb::CcdbObjectInfo info(mPath, "NoiseMap", "noise.root", meta, tstart, tend); + o2::ccdb::CcdbObjectInfo info(mPathSingle, "NoiseMap", "noise.root", meta, tstart, tend); auto flName = o2::ccdb::CcdbApi::generateFileName("noise"); auto image = o2::ccdb::CcdbApi::createObjectImage(&payload, &info); info.setFileName(flName); @@ -301,16 +301,16 @@ void NoiseCalibratorSpec::sendOutputCcdbMerge(DataAllocator& output) // const auto& payload = mCalibrator->getNoiseMap(starTF, endTF); //For TimeSlot calibration map headers; map filter; - auto* payloadPrev1 = api.retrieveFromTFileAny(mPath, filter, -1, &headers); + auto* payloadPrev1 = api.retrieveFromTFileAny(mPathSingle, filter, -1, &headers); long validtime = std::stol(headers["Valid-From"]); auto mergedPL = payload; if (validtime > 0) { validtime = validtime - 1; - auto* payloadPrev2 = api.retrieveFromTFileAny(mPath, filter, validtime, &headers); + auto* payloadPrev2 = api.retrieveFromTFileAny(mPathSingle, filter, validtime, &headers); auto bufferPL = payloadPrev2->merge(payloadPrev1); mergedPL = payload.merge(&bufferPL); } - o2::ccdb::CcdbObjectInfo info(mPathMerge, "NoiseMap", "noise.root", meta, tstart, tend); + o2::ccdb::CcdbObjectInfo info(mPath, "NoiseMap", "noise.root", meta, tstart, tend); auto flName = o2::ccdb::CcdbApi::generateFileName("noise"); auto image = o2::ccdb::CcdbApi::createObjectImage(&mergedPL, &info); info.setFileName(flName); @@ -382,6 +382,75 @@ void NoiseCalibratorSpec::sendOutputDcs(DataAllocator& output) output.snapshot(Output{clbUtilsDcs::gDataOriginCDBWrapper, "MFT_NoiseMap", 0}, infoDcs); } +void NoiseCalibratorSpec::sendOutputDcsMerge(DataAllocator& output) +{ + + LOG(info) << "DCS mode"; + + static bool done = false; + if (done) { + return; + } + done = true; + + mCalibrator->finalize(); + + long tstart = mStart; + if (tstart == -1) { + tstart = o2::ccdb::getCurrentTimestamp(); + } + long tend = mEnd; + if (tend == -1) { + constexpr long SECONDSPERYEAR = 365 * 24 * 60 * 60; + tend = o2::ccdb::getFutureTimestamp(SECONDSPERYEAR); + } + + std::map meta; + auto toKeyValPairs = [&meta](std::vector const& tokens) { + for (auto& token : tokens) { + auto keyval = Str::tokenize(token, '=', false); + if (keyval.size() != 2) { + LOG(error) << "Illegal command-line key/value string: " << token; + continue; + } + Str::trim(keyval[1]); + meta[keyval[0]] = keyval[1]; + } + }; + toKeyValPairs(Str::tokenize(mMeta, ';', true)); + + long startTF, endTF; + + auto payload = mCalibrator->getNoiseMap(); + // const auto& payload = mCalibrator->getNoiseMap(starTF, endTF); //For TimeSlot calibration + + map headers; + map filter; + auto* payloadPrev1 = api.retrieveFromTFileAny(mPathSingle, filter, -1, &headers); + long validtime = std::stol(headers["Valid-From"]); + auto mergedPL = payload; + if (validtime > 0) { + validtime = validtime - 1; + auto* payloadPrev2 = api.retrieveFromTFileAny(mPathSingle, filter, validtime, &headers); + auto bufferPL = payloadPrev2->merge(payloadPrev1); + mergedPL = payload.merge(&bufferPL); + } + + setOutputDcs(mergedPL); + o2::ccdb::CcdbObjectInfo infoDcs(mPathDcs, "NoiseMap", "noise.root", meta, tstart, tend); + auto flNameDcs = o2::ccdb::CcdbApi::generateFileName("noise"); + auto imageDcs = o2::ccdb::CcdbApi::createObjectImage(&mNoiseMapForDcs, &infoDcs); + infoDcs.setFileName(flNameDcs); + LOG(info) << "Sending object " << infoDcs.getPath() << "/" << infoDcs.getFileName() + << " of size " << imageDcs->size() + << " bytes, valid for " << infoDcs.getStartValidityTimestamp() + << " : " << infoDcs.getEndValidityTimestamp(); + + using clbUtilsDcs = o2::calibration::Utils; + output.snapshot(Output{clbUtilsDcs::gDataOriginCDBPayload, "MFT_NoiseMap", 0}, *imageDcs.get()); + output.snapshot(Output{clbUtilsDcs::gDataOriginCDBWrapper, "MFT_NoiseMap", 0}, infoDcs); +} + void NoiseCalibratorSpec::endOfStream(o2::framework::EndOfStreamContext& ec) { if (mOutputType.compare("CCDB") == 0) { @@ -390,11 +459,12 @@ void NoiseCalibratorSpec::endOfStream(o2::framework::EndOfStreamContext& ec) LOG(info) << "Sending an object to Production-CCDB-Merge"; sendOutputCcdbMerge(ec.outputs()); } else if (mOutputType.compare("DCS") == 0) { - LOG(info) << "Sending an object to DCS-CCDB"; - sendOutputDcs(ec.outputs()); + LOG(info) << "Sending an object to DCS-Merge"; + sendOutputDcsMerge(ec.outputs()); } else { - LOG(info) << "Sending an object to Production-CCDB and DCS-CCDB"; - sendOutputCcdbDcs(ec.outputs()); + LOG(info) << "Sending an object to Production-CCDB, Production-CCDB-Merge and DCS-Merge"; + sendOutputCcdb(ec.outputs()); + sendOutputDcsMerge(ec.outputs()); sendOutputCcdbMerge(ec.outputs()); } } @@ -454,7 +524,7 @@ DataProcessorSpec getNoiseCalibratorSpec(bool useDigits) {"tstart", VariantType::Int64, -1ll, {"Start of validity timestamp"}}, {"tend", VariantType::Int64, -1ll, {"End of validity timestamp"}}, {"path-CCDB", VariantType::String, "/MFT/Calib/NoiseMap", {"Path to write to in CCDB"}}, - {"path-CCDB-merge", VariantType::String, "/MFT/Calib/NoiseMapMerged", {"Path to write merged file to in CCDB"}}, + {"path-CCDB-single", VariantType::String, "/MFT/Calib/NoiseMapSingle", {"Path to write merged file to in CCDB"}}, {"path-DCS", VariantType::String, "/MFT/Config/NoiseMap", {"Path to write to in DCS"}}, {"meta", VariantType::String, "", {"meta data to write in CCDB"}}, {"send-to-server", VariantType::String, "CCDB-DCS", {"meta data to write in DCS-CCDB"}}, From da3a178e22d4303230413ddeafa3ac4a7b5c0bd5 Mon Sep 17 00:00:00 2001 From: Christian Sonnabend Date: Fri, 18 Jul 2025 16:29:02 +0200 Subject: [PATCH 164/315] NN clusterizer: Improve filling kernel speed (#14510) * First version of lookup tables * Simplifying computations + bug-fixes * Fixes for indexing and offsets * Adjusting CPU kernel * Please consider the following formatting changes * Fix for row-number access * Please consider the following formatting changes * Improve kernel speed by ~15%. Next test: for-loop in pad direction for coallesced access * IMproving kernel speed by 30% compared to original version. Next try: for-loop over row dimension as access is somewhat coalsced too * Please consider the following formatting changes * Minor improvements for MC handling * Beautifications to trigger the CI * Compile-fix * Fix int32_t error in fullCI build --------- Co-authored-by: ALICE Action Bot --- .../Global/GPUChainTrackingClusterizer.cxx | 2 + .../TPCClusterFinder/GPUTPCNNClusterizer.cxx | 27 -- .../TPCClusterFinder/GPUTPCNNClusterizer.h | 62 ++-- .../GPUTPCNNClusterizerHost.cxx | 49 ++- .../GPUTPCNNClusterizerHost.h | 2 + .../GPUTPCNNClusterizerKernels.cxx | 285 ++++++++++++------ .../GPUTPCNNClusterizerKernels.h | 2 +- 7 files changed, 289 insertions(+), 140 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx index 25bfe37f0db30..13455efe6cb47 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx @@ -706,6 +706,8 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) nnApplications[lane].initClusterizer(nn_settings, clustererNNShadow); } AllocateRegisteredMemory(clustererNN.mMemoryId); + // nnApplications[lane].createBoundary(clustererNNShadow); + // nnApplications[lane].createIndexLookup(clustererNNShadow); }); if (doGPU) { WriteToConstantMemory(RecoStep::TPCClusterFinding, (char*)&processors()->tpcNNClusterer - (char*)processors(), &processorsShadow()->tpcNNClusterer, sizeof(GPUTPCNNClusterizer) * NSECTORS, mRec->NStreams() - 1, &mEvents->init); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.cxx index da37c0771fe84..3dd8b0d621a56 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.cxx @@ -65,33 +65,6 @@ void* GPUTPCNNClusterizer::setIOPointers(void* mem) return mem; } -// std::vector GPUTPCNNClusterizer::pointerSizes() { -// std::vector sizes(7, -1); -// if (mNnClusterizerBatchedMode > 0) { -// if (mNnInferenceInputDType == 0 && mNnClusterizerElementSize > 0) { -// sizes[0] = mNnClusterizerBatchedMode * mNnClusterizerElementSize; // inputData16 -// } else if (mNnInferenceInputDType == 1 && mNnClusterizerElementSize > 0) { -// sizes[1] = mNnClusterizerBatchedMode * mNnClusterizerElementSize; // inputData32 -// } -// sizes[2] = 2 * mNnClusterizerBatchedMode; // mClusterFlags -// if (mNnClusterizerModelClassNumOutputNodes > 0) { -// sizes[3] = mNnClusterizerBatchedMode * mNnClusterizerModelClassNumOutputNodes; // modelProbabilities -// } -// if (!mNnClusterizerUseCfRegression) { -// if (mNnClusterizerModelReg1NumOutputNodes > 0) { -// sizes[4] = mNnClusterizerBatchedMode * mNnClusterizerModelReg1NumOutputNodes; // outputDataReg1 -// } -// if (mNnClusterizerModelReg2NumOutputNodes > 0) { -// sizes[5] = mNnClusterizerBatchedMode * mNnClusterizerModelReg2NumOutputNodes; // outputDataReg2 -// } -// } -// } -// if (mNnClusterizerTotalClusters > 0) { -// sizes[6] = mNnClusterizerTotalClusters; // mOutputDataClass -// } -// return sizes; -// } - void GPUTPCNNClusterizer::RegisterMemoryAllocation() { AllocateAndInitializeLate(); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h index 980c0977aca65..7c22d8123fdec 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h @@ -37,31 +37,51 @@ class GPUTPCNNClusterizer : public GPUProcessor // Neural network clusterization - int mNnClusterizerSizeInputRow = 3; - int mNnClusterizerSizeInputPad = 3; - int mNnClusterizerSizeInputTime = 3; - int mNnClusterizerElementSize = -1; - bool mNnClusterizerAddIndexData = true; + int32_t mNnClusterizerSizeInputRow = 3; + int32_t mNnClusterizerSizeInputPad = 3; + int32_t mNnClusterizerSizeInputTime = 3; + int32_t mNnClusterizerChargeArraySize = -1; + int32_t mNnClusterizerElementSize = -1; + int8_t mNnClusterizerAddIndexData = 1; float mNnClassThreshold = 0.01; - bool mNnSigmoidTrafoClassThreshold = 1; - bool mNnClusterizerSetDeconvolutionFlags = true; - int mNnClusterizerUseCfRegression = 0; - int mNnClusterizerBatchedMode = 1; - int mNnClusterizerTotalClusters = 1; - int mNnClusterizerVerbosity = 0; - int mNnClusterizerBoundaryFillValue = -1; - int mNnClusterizerModelClassNumOutputNodes = -1; - int mNnClusterizerModelReg1NumOutputNodes = -1; - int mNnClusterizerModelReg2NumOutputNodes = -1; - int mNnInferenceInputDType = 0; // 0: float16, 1: float32 - int mNnInferenceOutputDType = 0; // 0: float16, 1: float32 - int mISector = -1; - int mDeviceId = -1; + int8_t mNnSigmoidTrafoClassThreshold = 1; + int8_t mNnClusterizerSetDeconvolutionFlags = 1; + int32_t mNnClusterizerUseCfRegression = 0; + int32_t mNnClusterizerBatchedMode = 1; + int32_t mNnClusterizerTotalClusters = 1; + int32_t mNnClusterizerVerbosity = 0; + int32_t mNnClusterizerBoundaryFillValue = -1; + int32_t mNnClusterizerModelClassNumOutputNodes = -1; + int32_t mNnClusterizerModelReg1NumOutputNodes = -1; + int32_t mNnClusterizerModelReg2NumOutputNodes = -1; + int32_t mNnInferenceInputDType = 0; // 0: float16, 1: float32 + int32_t mNnInferenceOutputDType = 0; // 0: float16, 1: float32 + int32_t mISector = -1; + int32_t mDeviceId = -1; + + // GPU optimizations + uint32_t mNnClusterizerFullRowSize = 0; + uint32_t mNnClusterizerFullPadSize = 0; + uint32_t mNnClusterizerFullTimeSize = 0; + uint32_t mNnClusterizerPadTimeSize = 0; + uint32_t mNnClusterizerRowTimeSize = 0; + uint32_t mNnClusterizerRowTimeSizeFull = 0; + + // Boundary lookup table + // int32_t mBoundaryMapSizeRow = 0; + // int32_t mBoundaryMapSizePadsPerRow = 0; + // int32_t mBoundaryMapSize = 0; + // int32_t mBoundaryPadding = 11; // Padding on each side of the boundary map to account for pad_offset + // int8_t* mIsBoundary = nullptr; + + // Index lookup table + // int32_t mIndexLookupSize = 0; + // int32_t* mIndexLookup = nullptr; // Memory allocation for neural network - bool* mClusterFlags = nullptr; // mSplitInTime, mSplitInPad. Techincally both flags are set in the same way -> ClusterAccumulator.cx=nullptr - int* mOutputDataClass = nullptr; + int8_t* mClusterFlags = nullptr; // mSplitInTime, mSplitInPad. Techincally both flags are set in the same way -> ClusterAccumulator.cx=nullptr + int32_t* mOutputDataClass = nullptr; // FP32 float* mInputData_32 = nullptr; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx index 124320396d0d4..fd56d49de7921 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx @@ -19,6 +19,8 @@ #include "GPUSettings.h" #include "ML/3rdparty/GPUORTFloat16.h" #include "GPUReconstruction.h" +#include "GPUTPCGeometry.h" +#include "DataFormatsTPC/Constants.h" #ifdef GPUCA_HAS_ONNX #include @@ -87,8 +89,20 @@ void GPUTPCNNClusterizerHost::initClusterizer(const GPUSettingsProcessingNNclust clustererNN.mNnClusterizerSizeInputRow = settings.nnClusterizerSizeInputRow; clustererNN.mNnClusterizerSizeInputPad = settings.nnClusterizerSizeInputPad; clustererNN.mNnClusterizerSizeInputTime = settings.nnClusterizerSizeInputTime; + clustererNN.mNnClusterizerFullRowSize = 2 * settings.nnClusterizerSizeInputRow + 1; + clustererNN.mNnClusterizerFullPadSize = 2 * settings.nnClusterizerSizeInputPad + 1; + clustererNN.mNnClusterizerFullTimeSize = 2 * settings.nnClusterizerSizeInputTime + 1; + clustererNN.mNnClusterizerChargeArraySize = clustererNN.mNnClusterizerFullRowSize * clustererNN.mNnClusterizerFullPadSize * clustererNN.mNnClusterizerFullTimeSize; + clustererNN.mNnClusterizerPadTimeSize = clustererNN.mNnClusterizerFullPadSize * clustererNN.mNnClusterizerFullTimeSize; + clustererNN.mNnClusterizerRowTimeSize = clustererNN.mNnClusterizerFullRowSize * clustererNN.mNnClusterizerFullTimeSize; + clustererNN.mNnClusterizerRowTimeSizeFull = clustererNN.mNnClusterizerRowTimeSize + (settings.nnClusterizerAddIndexData ? 3 : 0); + clustererNN.mNnClusterizerElementSize = clustererNN.mNnClusterizerChargeArraySize + (settings.nnClusterizerAddIndexData ? 3 : 0); + // clustererNN.mBoundaryMapSizeRow = 3 * clustererNN.mNnClusterizerSizeInputRow + o2::tpc::constants::MAXGLOBALPADROW; + // clustererNN.mBoundaryPadding = 11; // padding on each side to account for pad_offset. N=11 since then mIsBoundary = 24320 ~< (1.5 x 2^14 = 24576) && N must be bigger than (NPads[row(end_iroc + 1)] - NPads[row(end_iroc)])/2 (=6) for pad_offset to work + // clustererNN.mBoundaryMapSizePadsPerRow = GPUTPCGeometry::NPads(o2::tpc::constants::MAXGLOBALPADROW - 1) + 2 * clustererNN.mBoundaryPadding; + // clustererNN.mBoundaryMapSize = clustererNN.mBoundaryMapSizeRow * clustererNN.mBoundaryMapSizePadsPerRow; + // clustererNN.mIndexLookupSize = 3 * clustererNN.mNnClusterizerChargeArraySize; // local row, pad, time shift from flat index clustererNN.mNnClusterizerAddIndexData = settings.nnClusterizerAddIndexData; - clustererNN.mNnClusterizerElementSize = ((2 * settings.nnClusterizerSizeInputRow + 1) * (2 * settings.nnClusterizerSizeInputPad + 1) * (2 * settings.nnClusterizerSizeInputTime + 1)) + (settings.nnClusterizerAddIndexData ? 3 : 0); clustererNN.mNnClusterizerBatchedMode = settings.nnClusterizerBatchedMode; clustererNN.mNnClusterizerBoundaryFillValue = settings.nnClusterizerBoundaryFillValue; clustererNN.mNnSigmoidTrafoClassThreshold = settings.nnSigmoidTrafoClassThreshold; @@ -116,6 +130,39 @@ void GPUTPCNNClusterizerHost::initClusterizer(const GPUSettingsProcessingNNclust } } +// void GPUTPCNNClusterizerHost::createBoundary(GPUTPCNNClusterizer& clustererNN) +// { +// // Call after init of the clustererNN elements +// for (int r = 0; r < clustererNN.mBoundaryMapSizeRow; r++) { +// int8_t skipCheckInRow = 0; +// for (int p = 0; p < clustererNN.mBoundaryMapSizePadsPerRow; p++) { +// int32_t i = r * clustererNN.mBoundaryMapSizePadsPerRow + p; +// clustererNN.mIsBoundary[i] = 1; +// if (!skipCheckInRow && (p >= clustererNN.mBoundaryPadding || r >= clustererNN.mNnClusterizerSizeInputRow)) { +// if (r < (GPUTPCGeometry::EndIROC() + clustererNN.mNnClusterizerSizeInputRow)) { +// clustererNN.mIsBoundary[i] = (int32_t)((p - clustererNN.mBoundaryPadding) >= static_cast(GPUTPCGeometry::NPads(r - clustererNN.mNnClusterizerSizeInputRow))); +// } else if (r >= (GPUTPCGeometry::EndIROC() + 2 * clustererNN.mNnClusterizerSizeInputRow) && r < (o2::tpc::constants::MAXGLOBALPADROW + 2 * clustererNN.mNnClusterizerSizeInputRow)) { +// clustererNN.mIsBoundary[i] = (int32_t)((p - clustererNN.mBoundaryPadding) >= static_cast(GPUTPCGeometry::NPads(r - 2 * clustererNN.mNnClusterizerSizeInputRow))); +// } +// skipCheckInRow = (clustererNN.mIsBoundary[i] == 1); // No need to check further pads in this row +// } +// } +// } +// } + +// void GPUTPCNNClusterizerHost::createIndexLookup(GPUTPCNNClusterizer& clustererNN) +// { +// for (int32_t i = 0; i < clustererNN.mNnClusterizerChargeArraySize; i++) { +// int32_t r = CAMath::Floor(i / ((2 * clustererNN.mNnClusterizerSizeInputPad + 1) * (2 * clustererNN.mNnClusterizerSizeInputTime + 1))) - clustererNN.mNnClusterizerSizeInputRow; +// int32_t rest_1 = i % ((2 * clustererNN.mNnClusterizerSizeInputPad + 1) * (2 * clustererNN.mNnClusterizerSizeInputTime + 1)); +// int32_t p = CAMath::Floor(rest_1 / (2 * clustererNN.mNnClusterizerSizeInputTime + 1)) - clustererNN.mNnClusterizerSizeInputPad; +// int32_t t = (rest_1 % (2 * clustererNN.mNnClusterizerSizeInputTime + 1)) - clustererNN.mNnClusterizerSizeInputTime; +// clustererNN.mIndexLookup[3 * i] = r; +// clustererNN.mIndexLookup[3 * i + 1] = p; +// clustererNN.mIndexLookup[3 * i + 2] = t; +// } +// } + // MockedOrtAllocator implementation to be able to use volatile assignment struct MockedOrtAllocator : OrtAllocator { MockedOrtAllocator(GPUReconstruction* = nullptr, OrtMemoryInfo* = nullptr); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h index a4449165261be..ed3c80320b632 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h @@ -49,6 +49,8 @@ class GPUTPCNNClusterizerHost void init(const GPUSettingsProcessingNNclusterizer&); void initClusterizer(const GPUSettingsProcessingNNclusterizer&, GPUTPCNNClusterizer&); + void createBoundary(GPUTPCNNClusterizer&); + void createIndexLookup(GPUTPCNNClusterizer&); // ONNX void directOrtAllocator(Ort::Env*, Ort::MemoryInfo*, GPUReconstruction*, bool = false); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx index 8cdc0684ad588..4cd0c094398df 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx @@ -53,63 +53,90 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint32_t batchStart) { - uint32_t glo_idx = get_global_id(0); auto& clusterer = processors.tpcClusterer[sector]; auto& clustererNN = processors.tpcNNClusterer[sector]; - uint32_t write_idx = glo_idx * clustererNN.mNnClusterizerElementSize; // Potential optimization: Either choose mNnClusterizerBatchedMode as a power of 2 or calculate from threadId and blockId + + uint32_t glo_idx = get_global_id(0); + if (glo_idx + batchStart >= clusterer.mPmemory->counters.nClusters) { + return; + } + + uint32_t write_idx = glo_idx * clustererNN.mNnClusterizerElementSize; CfArray2D chargeMap(reinterpret_cast(clusterer.mPchargeMap)); CfArray2D isPeakMap(clusterer.mPpeakMap); CfChargePos peak = clusterer.mPfilteredPeakPositions[CAMath::Min(glo_idx + batchStart, (uint32_t)(clusterer.mPmemory->counters.nClusters - 1))]; - int32_t row = static_cast(peak.row()), pad = static_cast(peak.pad()), time = static_cast(peak.time()); // Explicit casting to avoid conversion errors + int32_t row = static_cast(peak.row()); + int32_t pad = static_cast(peak.pad()); + int32_t time = static_cast(peak.time()); float central_charge = static_cast(chargeMap[peak].unpack()); int32_t row_offset = GPUTPCNNClusterizerKernels::rowOffset(row, clustererNN.mNnClusterizerSizeInputRow); - for (int32_t r = -clustererNN.mNnClusterizerSizeInputRow; r <= clustererNN.mNnClusterizerSizeInputRow; r++) { - bool is_row_boundary = ((row + r) > (o2::tpc::constants::MAXGLOBALPADROW - 1)) || ((row + r) < 0); - int32_t pad_offset = is_row_boundary ? 0 : GPUTPCNNClusterizerKernels::padOffset(row, row + r); - for (int32_t p = -clustererNN.mNnClusterizerSizeInputPad + pad_offset; p <= clustererNN.mNnClusterizerSizeInputPad + pad_offset; p++) { - bool is_boundary = is_row_boundary || GPUTPCNNClusterizerKernels::isBoundary(row + r + row_offset, pad + p, clustererNN.mNnClusterizerSizeInputRow); - for (int32_t t = -clustererNN.mNnClusterizerSizeInputTime; t <= clustererNN.mNnClusterizerSizeInputTime; t++) { - int32_t time_pos = time + t; - if (!is_boundary && (time_pos >= 0) && (time_pos < TPC_MAX_FRAGMENT_LEN_GPU)) { - CfChargePos tmp_pos(row + r, pad + p, time + t); - if (r == 0 && !clustererNN.mClusterFlags[2 * glo_idx] && CAMath::Abs(p) < 3 && CAMath::Abs(t) < 3 && p != 0 && t != 0) { // ordering is done for short circuit optimization - clustererNN.mClusterFlags[2 * glo_idx] += CfUtils::isPeak(isPeakMap[tmp_pos]); - clustererNN.mClusterFlags[2 * glo_idx + 1] = clustererNN.mClusterFlags[2 * glo_idx]; - } + for (int32_t r = -clustererNN.mNnClusterizerSizeInputRow; r <= clustererNN.mNnClusterizerSizeInputRow; ++r) { + int32_t target_row = row + r; + bool is_row_boundary = (target_row < 0) || (target_row >= o2::tpc::constants::MAXGLOBALPADROW); + int32_t pad_offset = is_row_boundary ? 0 : GPUTPCNNClusterizerKernels::padOffset(row, target_row); + + for (int32_t p = -clustererNN.mNnClusterizerSizeInputPad + pad_offset; p <= clustererNN.mNnClusterizerSizeInputPad + pad_offset; ++p) { + int32_t target_pad = pad + p; + bool is_boundary = is_row_boundary || GPUTPCNNClusterizerKernels::isBoundary(target_row + row_offset, target_pad, clustererNN.mNnClusterizerSizeInputRow); + + for (int32_t t = -clustererNN.mNnClusterizerSizeInputTime; t <= clustererNN.mNnClusterizerSizeInputTime; ++t) { + int32_t target_time = time + t; + + if (is_boundary || target_time < 0 || target_time >= TPC_MAX_FRAGMENT_LEN_GPU) { + // Fill boundary value + float boundary_value = static_cast(clustererNN.mNnClusterizerBoundaryFillValue); if (dtype == 0) { - clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)(static_cast(chargeMap[tmp_pos].unpack()) / central_charge); - } else if (dtype == 1) { - clustererNN.mInputData_32[write_idx] = static_cast(chargeMap[tmp_pos].unpack()) / central_charge; + clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)boundary_value; + } else { + clustererNN.mInputData_32[write_idx] = boundary_value; } } else { - // Filling boundary just to make sure that no values are left unintentionally + CfChargePos tmp_pos(target_row, target_pad, target_time); + float normalized_charge = static_cast(chargeMap[tmp_pos].unpack()) / central_charge; + + if (!clustererNN.mNnClusterizerSetDeconvolutionFlags && r == 0 && CAMath::Abs(p) < 3 && CAMath::Abs(t) < 3 && p != 0 && t != 0) { + clustererNN.mClusterFlags[2 * glo_idx] += CfUtils::isPeak(isPeakMap[tmp_pos]); + clustererNN.mClusterFlags[2 * glo_idx + 1] = clustererNN.mClusterFlags[2 * glo_idx]; + } + if (dtype == 0) { - clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)(static_cast(clustererNN.mNnClusterizerBoundaryFillValue)); + clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)normalized_charge; } else { - clustererNN.mInputData_32[write_idx] = static_cast(clustererNN.mNnClusterizerBoundaryFillValue); + clustererNN.mInputData_32[write_idx] = normalized_charge; } } + // if((CAMath::Abs(static_cast(clustererNN.mInputData_16_Test[write_idx]) - static_cast(clustererNN.mInputData_16[write_idx])) > 1e-4) && ((glo_idx + batchStart) < clusterer.mPmemory->counters.nClusters)) { + // printf("Warning: Input data mismatch at index %d, %d - row, pad, time: %d, %d, %d : %f -> %f\n", glo_idx, glo_idx + batchStart, r, p, t, + // static_cast(clustererNN.mInputData_16_Test[write_idx]), static_cast(clustererNN.mInputData_16[write_idx])); + // } write_idx++; } } } + if (clustererNN.mNnClusterizerAddIndexData) { + float sector_norm = sector / 36.f; + float row_norm = row / 152.f; + float pad_norm = static_cast(pad) / GPUTPCGeometry::NPads(row); + if (dtype == 0) { - clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)(sector / 36.f); - clustererNN.mInputData_16[write_idx + 1] = (OrtDataType::Float16_t)(row / 152.f); - clustererNN.mInputData_16[write_idx + 2] = (OrtDataType::Float16_t)(static_cast(pad) / GPUTPCGeometry::NPads(row)); + clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)sector_norm; + clustererNN.mInputData_16[write_idx + 1] = (OrtDataType::Float16_t)row_norm; + clustererNN.mInputData_16[write_idx + 2] = (OrtDataType::Float16_t)pad_norm; } else { - clustererNN.mInputData_32[write_idx] = sector / 36.f; - clustererNN.mInputData_32[write_idx + 1] = row / 152.f; - clustererNN.mInputData_32[write_idx + 2] = static_cast(pad) / GPUTPCGeometry::NPads(row); + clustererNN.mInputData_32[write_idx] = sector_norm; + clustererNN.mInputData_32[write_idx + 1] = row_norm; + clustererNN.mInputData_32[write_idx + 2] = pad_norm; } } + if (!clustererNN.mNnClusterizerSetDeconvolutionFlags) { clustererNN.mClusterFlags[2 * glo_idx] = 0; clustererNN.mClusterFlags[2 * glo_idx + 1] = 0; - for (uint16_t i = 0; i < 8; i++) { + + for (uint16_t i = 0; i < 8; ++i) { Delta2 d = cfconsts::InnerNeighbors[i]; CfChargePos tmp_pos = peak.delta(d); clustererNN.mClusterFlags[2 * glo_idx] += CfUtils::isPeak(isPeakMap[tmp_pos]); @@ -122,71 +149,111 @@ template <> GPUdii() void GPUTPCNNClusterizerKernels::Thread(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& processors, uint8_t sector, int8_t dtype, int8_t withMC, uint32_t batchStart) { uint32_t glo_idx = get_global_id(0); + auto& clusterer = processors.tpcClusterer[sector]; auto& clustererNN = processors.tpcNNClusterer[sector]; - uint32_t base_idx = CAMath::Floor(glo_idx / clustererNN.mNnClusterizerElementSize); - uint32_t transient_index = glo_idx - (base_idx * clustererNN.mNnClusterizerElementSize); + // Optimized division using bit operations + uint32_t base_idx = glo_idx / clustererNN.mNnClusterizerRowTimeSizeFull; + uint32_t transient_index = glo_idx - (base_idx * clustererNN.mNnClusterizerRowTimeSizeFull); + + // Early exit for out-of-bounds threads + if (base_idx + batchStart >= clusterer.mPmemory->counters.nClusters) { + return; + } CfArray2D chargeMap(reinterpret_cast(clusterer.mPchargeMap)); CfArray2D isPeakMap(clusterer.mPpeakMap); + + // Use dedicated neural network shared memory arrays for warp-level caching + // First thread in each warp loads shared data CfChargePos peak = clusterer.mPfilteredPeakPositions[CAMath::Min(base_idx + batchStart, (uint32_t)(clusterer.mPmemory->counters.nClusters - 1))]; - int32_t row = static_cast(peak.row()), pad = static_cast(peak.pad()); - - if (clustererNN.mNnClusterizerAddIndexData && (int32_t)transient_index == (clustererNN.mNnClusterizerElementSize - 1)) { - uint32_t top_idx = (base_idx + 1) * clustererNN.mNnClusterizerElementSize; - if (!clustererNN.mNnClusterizerSetDeconvolutionFlags) { // Only if deconvolution flags are not set - clustererNN.mClusterFlags[2 * base_idx] = 0; - clustererNN.mClusterFlags[2 * base_idx + 1] = 0; - for (uint16_t i = 0; i < 8; i++) { // This solution needs testing. It is not the same as the deconvolution flags - Delta2 d = cfconsts::InnerNeighbors[i]; - CfChargePos tmp_pos = peak.delta(d); - clustererNN.mClusterFlags[2 * base_idx] += CfUtils::isPeak(isPeakMap[tmp_pos]); - } - clustererNN.mClusterFlags[2 * base_idx + 1] = clustererNN.mClusterFlags[2 * base_idx]; - } + float central_charge = static_cast(chargeMap[peak].unpack()); + int32_t row = static_cast(peak.row()); + int32_t pad = static_cast(peak.pad()); + int32_t time = static_cast(peak.time()); + + // Handle index data with fewer branches + if (clustererNN.mNnClusterizerAddIndexData && transient_index >= clustererNN.mNnClusterizerRowTimeSize) { + int32_t data_idx = transient_index - clustererNN.mNnClusterizerRowTimeSize; + uint32_t write_idx = base_idx * clustererNN.mNnClusterizerElementSize + clustererNN.mNnClusterizerChargeArraySize + data_idx; + + float index_values[3] = { + sector / 36.f, + row / 152.f, + static_cast(pad) / GPUTPCGeometry::NPads(row)}; + if (dtype == 0) { - clustererNN.mInputData_16[top_idx - 3] = (OrtDataType::Float16_t)(sector / 36.f); - clustererNN.mInputData_16[top_idx - 2] = (OrtDataType::Float16_t)(row / 152.f); - clustererNN.mInputData_16[top_idx - 1] = (OrtDataType::Float16_t)(static_cast(pad) / GPUTPCGeometry::NPads(row)); + clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)index_values[data_idx]; } else { - clustererNN.mInputData_32[top_idx - 3] = sector / 36.f; - clustererNN.mInputData_32[top_idx - 2] = row / 152.f; - clustererNN.mInputData_32[top_idx - 1] = static_cast(pad) / GPUTPCGeometry::NPads(row); + clustererNN.mInputData_32[write_idx] = index_values[data_idx]; } - } else if ((int32_t)transient_index < (clustererNN.mNnClusterizerElementSize - 3)) { - int32_t time = static_cast(peak.time()); - int32_t r = CAMath::Floor(transient_index / ((2 * clustererNN.mNnClusterizerSizeInputPad + 1) * (2 * clustererNN.mNnClusterizerSizeInputTime + 1))) - clustererNN.mNnClusterizerSizeInputRow; - bool is_row_boundary = ((row + r) > (o2::tpc::constants::MAXGLOBALPADROW - 1)) || ((row + r) < 0); - if (is_row_boundary) { - if (dtype == 0) { - clustererNN.mInputData_16[glo_idx] = (OrtDataType::Float16_t)(static_cast(clustererNN.mNnClusterizerBoundaryFillValue)); - } else { - clustererNN.mInputData_32[glo_idx] = static_cast(clustererNN.mNnClusterizerBoundaryFillValue); - } - } else { - int32_t row_offset = GPUTPCNNClusterizerKernels::rowOffset(row, clustererNN.mNnClusterizerSizeInputRow); - int32_t pad_offset = GPUTPCNNClusterizerKernels::padOffset(row, row + r); - int32_t rest_1 = transient_index % ((2 * clustererNN.mNnClusterizerSizeInputPad + 1) * (2 * clustererNN.mNnClusterizerSizeInputTime + 1)); - int32_t p = CAMath::Floor(rest_1 / (2 * clustererNN.mNnClusterizerSizeInputTime + 1)) - clustererNN.mNnClusterizerSizeInputPad + pad_offset; - int32_t time_pos = (rest_1 % (2 * clustererNN.mNnClusterizerSizeInputTime + 1)) - clustererNN.mNnClusterizerSizeInputTime + time; - bool is_boundary = GPUTPCNNClusterizerKernels::isBoundary(row + r + row_offset, pad + p, clustererNN.mNnClusterizerSizeInputRow) && (time_pos < 0 || time_pos >= TPC_MAX_FRAGMENT_LEN_GPU); + // Handle deconvolution flags only once per cluster (last thread in element) + if (data_idx == 2 && !clustererNN.mNnClusterizerSetDeconvolutionFlags) { + uint8_t cluster_flags = 0; + for (uint16_t i = 0; i < 8; i++) { + Delta2 d = cfconsts::InnerNeighbors[i]; + CfChargePos tmp_pos = peak.delta(d); + cluster_flags += CfUtils::isPeak(isPeakMap[tmp_pos]); + } + clustererNN.mClusterFlags[2 * base_idx] = cluster_flags; + clustererNN.mClusterFlags[2 * base_idx + 1] = cluster_flags; + } + return; + } - if (!is_boundary) { - float central_charge = static_cast(chargeMap[peak].unpack()); - CfChargePos tmp_pos(row + r, pad + p, time_pos); - if (dtype == 0) { - clustererNN.mInputData_16[glo_idx] = (OrtDataType::Float16_t)(static_cast(chargeMap[tmp_pos].unpack()) / central_charge); - } else if (dtype == 1) { - clustererNN.mInputData_32[glo_idx] = static_cast(chargeMap[tmp_pos].unpack()) / central_charge; - } - } else { + // Main data processing - optimize index calculations + if (transient_index < clustererNN.mNnClusterizerRowTimeSize) { + // Optimize 3D index calculation + int32_t row_idx = transient_index / clustererNN.mNnClusterizerFullTimeSize; + int32_t r_local = row_idx - clustererNN.mNnClusterizerSizeInputRow; + int32_t time_idx = transient_index - row_idx * clustererNN.mNnClusterizerFullTimeSize; + int32_t t_local = time_idx - clustererNN.mNnClusterizerSizeInputTime; + int32_t write_idx = base_idx * clustererNN.mNnClusterizerElementSize + row_idx * clustererNN.mNnClusterizerPadTimeSize + time_idx; + + // Early boundary check for row + int32_t target_row = row + r_local; + int8_t is_row_boundary = (target_row < 0) || (target_row > (o2::tpc::constants::MAXGLOBALPADROW - 1)); + + // Calculate offsets + int32_t row_offset = GPUTPCNNClusterizerKernels::rowOffset(row, clustererNN.mNnClusterizerSizeInputRow); + int32_t pad_offset = GPUTPCNNClusterizerKernels::padOffset(row, target_row); + for (int32_t p_local = -clustererNN.mNnClusterizerSizeInputPad + pad_offset; p_local <= clustererNN.mNnClusterizerSizeInputPad + pad_offset; p_local++) { + if (is_row_boundary) { + // Use boundary fill value + float boundary_val = static_cast(clustererNN.mNnClusterizerBoundaryFillValue); if (dtype == 0) { - clustererNN.mInputData_16[glo_idx] = (OrtDataType::Float16_t)(static_cast(clustererNN.mNnClusterizerBoundaryFillValue)); + clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)boundary_val; } else { - clustererNN.mInputData_32[glo_idx] = static_cast(clustererNN.mNnClusterizerBoundaryFillValue); + clustererNN.mInputData_32[write_idx] = boundary_val; } + write_idx += clustererNN.mNnClusterizerFullTimeSize; // Move to next pad position + continue; } + + // Calculate target pad and time + int32_t target_pad = pad + p_local; + int32_t target_time = time + t_local; + + // Optimized boundary check + int8_t is_boundary = GPUTPCNNClusterizerKernels::isBoundary(target_row + row_offset, target_pad, clustererNN.mNnClusterizerSizeInputRow) || (target_time < 0) || (target_time >= TPC_MAX_FRAGMENT_LEN_GPU); + + float output_value; + if (is_boundary) { + output_value = static_cast(clustererNN.mNnClusterizerBoundaryFillValue); + } else { + // Coalesced memory access - create position and read charge + CfChargePos tmp_pos(target_row, target_pad, target_time); + output_value = static_cast(chargeMap[tmp_pos].unpack()) / central_charge; // Normalize by central charge + } + + // Write output with reduced branching + if (dtype == 0) { + clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)output_value; + } else { + clustererNN.mInputData_32[write_idx] = output_value; + } + write_idx += clustererNN.mNnClusterizerFullTimeSize; // Move to next pad position } } } @@ -242,9 +309,6 @@ GPUdii() void GPUTPCNNClusterizerKernels::Threadcounters.nClusters; uint32_t full_glo_idx = glo_idx + batchStart; - if (full_glo_idx >= maxClusterNum) { - return; - } int32_t model_output_index = glo_idx * clustererNN.mNnClusterizerModelReg1NumOutputNodes; CfArray2D chargeMap(reinterpret_cast(clusterer.mPchargeMap)); @@ -253,6 +317,24 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread= maxClusterNum) { + if (withMC) { + ClusterAccumulator dummy_pc; + CPU_ONLY(labelAcc->collect(peak, central_charge)); + GPUTPCCFClusterizer::buildCluster( + clusterer.Param().rec, + chargeMap, + peak, + smem.posBcast, + smem.buf, + smem.innerAboveThreshold, + &dummy_pc, + labelAcc); + } + return; + } + tpc::ClusterNative* clusterOut = (withMC) ? nullptr : clusterer.mPclusterByRow; // LOG(info) << glo_idx << " -- " << model_output_index << " / " << clustererNN.outputDataReg1.size() << " / " << clustererNN.mNnClusterizerModelReg1NumOutputNodes << " -- " << clusterer.peakPositions.size() << " -- " << clusterer.centralCharges.size(); @@ -340,6 +422,7 @@ GPUdii() void GPUTPCNNClusterizerKernels::Threadcounters.nClusters; CfArray2D chargeMap(reinterpret_cast(clusterer.mPchargeMap)); CfChargePos peak = clusterer.mPfilteredPeakPositions[CAMath::Min(glo_idx + batchStart, (uint32_t)(clusterer.mPmemory->counters.nClusters - 1))]; float central_charge = static_cast(chargeMap[peak].unpack()); @@ -348,6 +431,24 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread= maxClusterNum) { + if (withMC) { + ClusterAccumulator dummy_pc; + CPU_ONLY(labelAcc->collect(peak, central_charge)); + GPUTPCCFClusterizer::buildCluster( + clusterer.Param().rec, + chargeMap, + peak, + smem.posBcast, + smem.buf, + smem.innerAboveThreshold, + &dummy_pc, + labelAcc); + } + return; + } + uint32_t model_output_index = glo_idx * clustererNN.mNnClusterizerModelReg2NumOutputNodes; if (clustererNN.mOutputDataClass[full_glo_idx] > 0) { @@ -501,24 +602,28 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread= o2::tpc::constants::MAXGLOBALPADROW) { + return 0; // Short-circuit for negative rows + } else { + return (int)((GPUTPCGeometry::NPads(row_current) - GPUTPCGeometry::NPads(row_ref)) / 2); + } } -GPUd() int32_t GPUTPCNNClusterizerKernels::rowOffset(int32_t row, int32_t global_shift) +GPUd() int32_t GPUTPCNNClusterizerKernels::rowOffset(int32_t row, int32_t offset) { - return (row > 62 ? global_shift : 0); + return (row > 62 ? offset : 0); } -GPUd() bool GPUTPCNNClusterizerKernels::isBoundary(int32_t row, int32_t pad, int32_t global_shift) +GPUd() bool GPUTPCNNClusterizerKernels::isBoundary(int32_t row, int32_t pad, int32_t offset) { if (pad < 0 || row < 0) { // Faster short-circuit return true; } else if (row < 63) { - return (pad >= static_cast(GPUTPCGeometry::NPads(row))); - } else if (row < (63 + global_shift)) { // to account for the gap between IROC and OROC. Charge will be set to -1 in order to signal boundary to the neural network + return ((pad < 0) || (pad >= static_cast(GPUTPCGeometry::NPads(row)))); + } else if (row < (63 + offset)) { // to account for the gap between IROC and OROC. Charge will be set to the boundary fill value in order to signal boundaries to the neural network return true; - } else if (row < (o2::tpc::constants::MAXGLOBALPADROW + global_shift)) { - return (pad >= static_cast(GPUTPCGeometry::NPads(row - global_shift))); + } else if (row < (o2::tpc::constants::MAXGLOBALPADROW + offset)) { + return ((pad < 0) || (pad >= static_cast(GPUTPCGeometry::NPads(row - offset)))); } else { return true; } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h index a3858d47eb99b..5659c61894c85 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h @@ -65,7 +65,7 @@ class GPUTPCNNClusterizerKernels : public GPUKernelTemplate determineClass2Labels = 4, publishClass1Regression = 5, publishClass2Regression = 6, - publishDeconvolutionFlags = 7 + publishDeconvolutionFlags = 7, }; template From 51d4f860b1e6cec83dd9fb797d787aa9384a2e48 Mon Sep 17 00:00:00 2001 From: Martin Eide <43970264+mrtineide@users.noreply.github.com> Date: Fri, 18 Jul 2025 16:11:11 +0200 Subject: [PATCH 165/315] Add fully qualified names for std::string and std::map The header TJAlienCredentials.h polluted the global namespace, included usually with CCDB or something related. Many source files in O2 took advantage of this. This commit prepares for the removal of the polluted namespace. The libraries/repo with TJAlienCredentials is JAliEn-ROOT and libjalieno2. The problem was first noticed by @vkucera. --- CCDB/include/CCDB/CcdbApi.h | 2 +- CCDB/src/CcdbApi.cxx | 68 +++++++++---------- CCDB/test/testBasicCCDBManager.cxx | 4 +- CCDB/test/testCcdbApi.cxx | 30 ++++---- CCDB/test/testCcdbApiMultipleUrls.cxx | 10 +-- CCDB/test/testCcdbApi_ConfigParam.cxx | 10 +-- CCDB/test/testCcdbApi_alien.cxx | 4 +- .../Detectors/CTP/src/CTPRateFetcher.cxx | 2 +- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 10 +-- .../calib/macros/makeBadMapFromPedestalRun.C | 2 +- Detectors/CTP/macro/GetAndSave.C | 2 +- Detectors/CTP/macro/SaveInputsConfig.C | 2 +- Detectors/CTP/macro/TestFetcher.C | 2 +- Detectors/CTP/simulation/src/Digitizer.cxx | 2 +- .../workflowScalers/src/ctpCCDBManager.cxx | 16 ++--- Detectors/EMCAL/base/src/Geometry.cxx | 2 +- Detectors/FIT/FT0/macros/FT0Misaligner.C | 2 +- ...dChannelTimeOffsetFV0CalibObjectFromCCDB.C | 4 +- Detectors/FIT/FV0/macros/FV0Misaligner.C | 2 +- .../FITDCSConfigProcessorSpec.h | 2 +- .../calibration/src/GRPDCSDPsProcessor.cxx | 6 +- .../GRP/workflows/src/create-grp-ecs.cxx | 12 ++-- .../src/tpc-residual-aggregator.cxx | 2 +- .../src/TestDataReader.cxx | 4 +- .../ITSMFT/ITS/macros/test/ITSMisaligner.C | 2 +- .../include/ITSWorkflow/DCSParserSpec.h | 2 +- .../ITSMFT/ITS/workflow/src/DCSParserSpec.cxx | 8 +-- .../calibration/src/NoiseCalibratorSpec.cxx | 8 +-- .../MFT/condition/macros/readAlpideCCDB.C | 2 +- .../MUON/MCH/Align/src/AlignRecordSpec.cxx | 6 +- .../MUON/MCH/Align/src/AlignmentSpec.cxx | 16 ++--- Detectors/MUON/MCH/Geometry/Test/Helpers.cxx | 2 +- Detectors/MUON/MCH/Geometry/Test/misAlign.C | 2 +- .../TPC/calibration/src/CalculatedEdx.cxx | 6 +- .../TPCWorkflow/TPCCalibPadGainTracksSpec.h | 2 +- Detectors/TRD/base/macros/OCDB2CCDB.C | 2 +- .../TRD/base/macros/OCDB2CCDBTrapConfig.C | 2 +- Detectors/TRD/base/macros/PrintTrapConfig.C | 2 +- Detectors/TRD/base/macros/Readocdb.C | 2 +- .../include/TRDCalibration/DCSProcessor.h | 4 +- .../TRD/calibration/src/DCSProcessor.cxx | 8 +-- Detectors/ZDC/macro/CreateBaselineCalib.C | 2 +- .../ZDC/macro/CreateBaselineCalibConfig.C | 2 +- Detectors/ZDC/macro/CreateEnergyCalib.C | 2 +- Detectors/ZDC/macro/CreateInterCalibConfig.C | 2 +- Detectors/ZDC/macro/CreateModuleConfig.C | 2 +- Detectors/ZDC/macro/CreateRecoConfigZDC.C | 2 +- Detectors/ZDC/macro/CreateSimCondition.C | 2 +- Detectors/ZDC/macro/CreateSimCondition_pp.C | 2 +- Detectors/ZDC/macro/CreateTDCCalib.C | 2 +- Detectors/ZDC/macro/CreateTDCCalibConfig.C | 2 +- Detectors/ZDC/macro/CreateTDCCorr.C | 2 +- Detectors/ZDC/macro/CreateTowerCalib.C | 2 +- .../View/src/EventManagerFrame.cxx | 4 +- GPU/Workflow/src/GPUWorkflowTPC.cxx | 4 +- macro/CreateCTPOrbitResetObject.C | 2 +- macro/UploadDummyAlignment.C | 2 +- macro/UploadMatBudLUT.C | 2 +- 58 files changed, 158 insertions(+), 158 deletions(-) diff --git a/CCDB/include/CCDB/CcdbApi.h b/CCDB/include/CCDB/CcdbApi.h index 1308742b57fd0..cc8312d0bef0a 100644 --- a/CCDB/include/CCDB/CcdbApi.h +++ b/CCDB/include/CCDB/CcdbApi.h @@ -556,7 +556,7 @@ class CcdbApi //: public DatabaseInterface * @param tcl The TClass object describing the serialized type * @return raw pointer to created object */ - void* downloadFilesystemContent(std::string const& fullUrl, std::type_info const& tinfo, std::map* headers) const; + void* downloadFilesystemContent(std::string const& fullUrl, std::type_info const& tinfo, std::map* headers) const; // initialize the TGrid (Alien connection) bool initTGrid() const; diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index bb2b69e84c4f7..f187fbf57f558 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -297,7 +297,7 @@ void CcdbApi::updateMetaInformationInLocalFile(std::string const& filename, std: */ std::string sanitizeObjectName(const std::string& objectName) { - string tmpObjectName = objectName; + std::string tmpObjectName = objectName; tmpObjectName.erase(std::remove_if(tmpObjectName.begin(), tmpObjectName.end(), [](auto const& c) -> bool { return (!std::isalnum(c) && c != '_' && c != '/' && c != '.'); }), tmpObjectName.end()); @@ -431,7 +431,7 @@ int CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::strin CURLcode res = CURL_LAST; for (size_t hostIndex = 0; hostIndex < hostsPool.size() && res > 0; hostIndex++) { - string fullUrl = getFullUrlForStorage(curl, path, objectType, metadata, sanitizedStartValidityTimestamp, sanitizedEndValidityTimestamp, hostIndex); + std::string fullUrl = getFullUrlForStorage(curl, path, objectType, metadata, sanitizedStartValidityTimestamp, sanitizedEndValidityTimestamp, hostIndex); LOG(debug3) << "Full URL Encoded: " << fullUrl; /* what URL that receives this POST */ curl_easy_setopt(curl, CURLOPT_URL, fullUrl.c_str()); @@ -476,30 +476,30 @@ int CcdbApi::storeAsTFile(const TObject* rootObject, std::string const& path, st return storeAsBinaryFile(img->data(), img->size(), info.getFileName(), info.getObjectType(), path, metadata, startValidityTimestamp, endValidityTimestamp, maxSize); } -string CcdbApi::getFullUrlForStorage(CURL* curl, const string& path, const string& objtype, - const map& metadata, - long startValidityTimestamp, long endValidityTimestamp, int hostIndex) const +std::string CcdbApi::getFullUrlForStorage(CURL* curl, const std::string& path, const std::string& objtype, + const std::map& metadata, + long startValidityTimestamp, long endValidityTimestamp, int hostIndex) const { // Prepare timestamps - string startValidityString = getTimestampString(startValidityTimestamp < 0 ? getCurrentTimestamp() : startValidityTimestamp); - string endValidityString = getTimestampString(endValidityTimestamp < 0 ? getFutureTimestamp(60 * 60 * 24 * 1) : endValidityTimestamp); + std::string startValidityString = getTimestampString(startValidityTimestamp < 0 ? getCurrentTimestamp() : startValidityTimestamp); + std::string endValidityString = getTimestampString(endValidityTimestamp < 0 ? getFutureTimestamp(60 * 60 * 24 * 1) : endValidityTimestamp); // Get url - string url = getHostUrl(hostIndex); + std::string url = getHostUrl(hostIndex); // Build URL - string fullUrl = url + "/" + path + "/" + startValidityString + "/" + endValidityString + "/"; + std::string fullUrl = url + "/" + path + "/" + startValidityString + "/" + endValidityString + "/"; // Add type as part of metadata // we need to URL encode the object type, since in case it has special characters (like the "<", ">" for templated classes) it won't work otherwise char* objtypeEncoded = curl_easy_escape(curl, objtype.c_str(), objtype.size()); - fullUrl += "ObjectType=" + string(objtypeEncoded) + "/"; + fullUrl += "ObjectType=" + std::string(objtypeEncoded) + "/"; curl_free(objtypeEncoded); // Add general metadata for (auto& kv : metadata) { - string mfirst = kv.first; - string msecond = kv.second; + std::string mfirst = kv.first; + std::string msecond = kv.second; // same trick for the metadata as for the object type char* mfirstEncoded = curl_easy_escape(curl, mfirst.c_str(), mfirst.size()); char* msecondEncoded = curl_easy_escape(curl, msecond.c_str(), msecond.size()); - fullUrl += string(mfirstEncoded) + "=" + string(msecondEncoded) + "/"; + fullUrl += std::string(mfirstEncoded) + "=" + std::string(msecondEncoded) + "/"; curl_free(mfirstEncoded); curl_free(msecondEncoded); } @@ -507,26 +507,26 @@ string CcdbApi::getFullUrlForStorage(CURL* curl, const string& path, const strin } // todo make a single method of the one above and below -string CcdbApi::getFullUrlForRetrieval(CURL* curl, const string& path, const map& metadata, long timestamp, int hostIndex) const +std::string CcdbApi::getFullUrlForRetrieval(CURL* curl, const std::string& path, const std::map& metadata, long timestamp, int hostIndex) const { if (mInSnapshotMode) { return getSnapshotFile(mSnapshotTopPath, path); } // Prepare timestamps - string validityString = getTimestampString(timestamp < 0 ? getCurrentTimestamp() : timestamp); + std::string validityString = getTimestampString(timestamp < 0 ? getCurrentTimestamp() : timestamp); // Get host url - string hostUrl = getHostUrl(hostIndex); + std::string hostUrl = getHostUrl(hostIndex); // Build URL - string fullUrl = hostUrl + "/" + path + "/" + validityString + "/"; + std::string fullUrl = hostUrl + "/" + path + "/" + validityString + "/"; // Add metadata for (auto& kv : metadata) { - string mfirst = kv.first; - string msecond = kv.second; + std::string mfirst = kv.first; + std::string msecond = kv.second; // trick for the metadata in case it contains special characters char* mfirstEncoded = curl_easy_escape(curl, mfirst.c_str(), mfirst.size()); char* msecondEncoded = curl_easy_escape(curl, msecond.c_str(), msecond.size()); - fullUrl += string(mfirstEncoded) + "=" + string(msecondEncoded) + "/"; + fullUrl += std::string(mfirstEncoded) + "=" + std::string(msecondEncoded) + "/"; curl_free(mfirstEncoded); curl_free(msecondEncoded); } @@ -755,7 +755,7 @@ bool CcdbApi::receiveObject(void* dataHolder, std::string const& path, std::map< CURLcode curlResultCode = CURL_LAST; for (size_t hostIndex = 0; hostIndex < hostsPool.size() && (responseCode >= 400 || curlResultCode > 0); hostIndex++) { - string fullUrl = getFullUrlForRetrieval(curlHandle, path, metadata, timestamp, hostIndex); + std::string fullUrl = getFullUrlForRetrieval(curlHandle, path, metadata, timestamp, hostIndex); curl_easy_setopt(curlHandle, CURLOPT_URL, fullUrl.c_str()); curlResultCode = CURL_perform(curlHandle); @@ -885,7 +885,7 @@ void CcdbApi::snapshot(std::string const& ccdbrootpath, std::string const& local { // query all subpaths to ccdbrootpath const auto allfolders = getAllFolders(ccdbrootpath); - std::map metadata; + std::map metadata; for (auto& folder : allfolders) { retrieveBlob(folder, localDir, metadata, timestamp); } @@ -977,7 +977,7 @@ bool CcdbApi::initTGrid() const return gGrid != nullptr; } -void* CcdbApi::downloadFilesystemContent(std::string const& url, std::type_info const& tinfo, std::map* headers) const +void* CcdbApi::downloadFilesystemContent(std::string const& url, std::type_info const& tinfo, std::map* headers) const { if ((url.find("alien:/", 0) != std::string::npos) && !initTGrid()) { return nullptr; @@ -1016,7 +1016,7 @@ void* CcdbApi::interpretAsTMemFileAndExtract(char* contentptr, size_t contentsiz } // navigate sequence of URLs until TFile content is found; object is extracted and returned -void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string const& url, std::type_info const& tinfo, std::map* headers) const +void* CcdbApi::navigateURLsAndRetrieveContent(CURL* curl_handle, std::string const& url, std::type_info const& tinfo, std::map* headers) const { // a global internal data structure that can be filled with HTTP header information // static --> to avoid frequent alloc/dealloc as optimization @@ -1164,7 +1164,7 @@ void* CcdbApi::retrieveFromTFile(std::type_info const& tinfo, std::string const& CURL* curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, mUniqueAgentID.c_str()); - string fullUrl = getFullUrlForRetrieval(curl_handle, path, metadata, timestamp); // todo check if function still works correctly in case mInSnapshotMode + std::string fullUrl = getFullUrlForRetrieval(curl_handle, path, metadata, timestamp); // todo check if function still works correctly in case mInSnapshotMode // if we are in snapshot mode we can simply open the file; extract the object and return if (mInSnapshotMode) { auto res = extractFromLocalFile(fullUrl, tinfo, headers); @@ -1218,8 +1218,8 @@ std::string CcdbApi::list(std::string const& path, bool latestOnly, std::string curl_easy_setopt(curl, CURLOPT_USERAGENT, mUniqueAgentID.c_str()); struct curl_slist* headers = nullptr; - headers = curl_slist_append(headers, (string("Accept: ") + returnFormat).c_str()); - headers = curl_slist_append(headers, (string("Content-Type: ") + returnFormat).c_str()); + headers = curl_slist_append(headers, (std::string("Accept: ") + returnFormat).c_str()); + headers = curl_slist_append(headers, (std::string("Content-Type: ") + returnFormat).c_str()); if (createdNotAfter >= 0) { headers = curl_slist_append(headers, ("If-Not-After: " + std::to_string(createdNotAfter)).c_str()); } @@ -1230,7 +1230,7 @@ std::string CcdbApi::list(std::string const& path, bool latestOnly, std::string curlSetSSLOptions(curl); - string fullUrl; + std::string fullUrl; // Perform the request, res will get the return code for (size_t hostIndex = 0; hostIndex < hostsPool.size() && res != CURLE_OK; hostIndex++) { fullUrl = getHostUrl(hostIndex); @@ -1290,7 +1290,7 @@ void CcdbApi::truncate(std::string const& path) const CURLcode res; stringstream fullUrl; for (size_t i = 0; i < hostsPool.size(); i++) { - string url = getHostUrl(i); + std::string url = getHostUrl(i); fullUrl << url << "/truncate/" << path; curl = curl_easy_init(); @@ -1436,7 +1436,7 @@ std::map CcdbApi::retrieveHeaders(std::string const& p auto do_remote_header_call = [this, &path, &metadata, timestamp]() -> std::map { CURL* curl = curl_easy_init(); CURLcode res = CURL_LAST; - string fullUrl = getFullUrlForRetrieval(curl, path, metadata, timestamp); + std::string fullUrl = getFullUrlForRetrieval(curl, path, metadata, timestamp); std::map headers; if (curl != nullptr) { @@ -1632,12 +1632,12 @@ int CcdbApi::updateMetadata(std::string const& path, std::map " << hostReachable << std::endl; char hostname[_POSIX_HOST_NAME_MAX]; gethostname(hostname, _POSIX_HOST_NAME_MAX); - basePath = string("Test/") + hostname + "/pid" + getpid() + "/BasicCCDBManager/"; + basePath = std::string("Test/") + hostname + "/pid" + getpid() + "/BasicCCDBManager/"; std::cout << "Path we will use in this test suite : " + basePath << std::endl; } ~Fixture() diff --git a/CCDB/test/testCcdbApi.cxx b/CCDB/test/testCcdbApi.cxx index c834f2f30f64a..0ba037710cf62 100644 --- a/CCDB/test/testCcdbApi.cxx +++ b/CCDB/test/testCcdbApi.cxx @@ -45,8 +45,8 @@ using namespace o2::ccdb; namespace utf = boost::unit_test; namespace tt = boost::test_tools; -static string ccdbUrl; -static string basePath; +static std::string ccdbUrl; +static std::string basePath; bool hostReachable = false; /** @@ -63,7 +63,7 @@ struct Fixture { cout << "Is host reachable ? --> " << hostReachable << endl; char hostname[_POSIX_HOST_NAME_MAX]; gethostname(hostname, _POSIX_HOST_NAME_MAX); - basePath = string("Test/TestCcdbApi/") + hostname + "/pid" + getpid() + "/"; + basePath = std::string("Test/TestCcdbApi/") + hostname + "/pid" + getpid() + "/"; // Replace dashes by underscores to avoid problems in the creation of local directories std::replace(basePath.begin(), basePath.end(), '-','_'); cout << "Path we will use in this test suite : " + basePath << endl; @@ -72,7 +72,7 @@ struct Fixture { { if (hostReachable) { CcdbApi api; - map metadata; + std::map metadata; api.init(ccdbUrl); api.truncate(basePath + "*"); cout << "Test data truncated (" << basePath << ")" << endl; @@ -104,7 +104,7 @@ struct test_fixture { ~test_fixture() = default; CcdbApi api; - map metadata; + std::map metadata; }; BOOST_AUTO_TEST_CASE(storeTMemFile_test, *utf::precondition(if_reachable())) @@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(store_retrieve_TMemFile_templated_test, *utf::precondition( BOOST_CHECK(f.api.retrieveFromTFileAny(basePath + "CCDBPath", f.metadata) == nullptr); // try to get the headers back and to find the metadata - map md; + std::map md; path2 = f.api.retrieveFromTFileAny(basePath + "CCDBPath", f.metadata, -1, &md); BOOST_CHECK_EQUAL(md.count("Hello"), 1); BOOST_CHECK_EQUAL(md["Hello"], "World"); @@ -345,7 +345,7 @@ BOOST_AUTO_TEST_CASE(delete_test, *utf::precondition(if_reachable())) BOOST_CHECK(h2 == nullptr); } -void countItems(const string& s, int& countObjects, int& countSubfolders) +void countItems(const std::string& s, int& countObjects, int& countSubfolders) { countObjects = 0; countSubfolders = 0; @@ -368,7 +368,7 @@ BOOST_AUTO_TEST_CASE(list_test, *utf::precondition(if_reachable())) test_fixture f; // test non-empty top dir - string s = f.api.list("", "application/json"); // top dir + std::string s = f.api.list("", "application/json"); // top dir long nbLines = std::count(s.begin(), s.end(), '\n') + 1; BOOST_CHECK(nbLines > 5); @@ -436,7 +436,7 @@ BOOST_AUTO_TEST_CASE(TestHeaderParsing) BOOST_AUTO_TEST_CASE(TestFetchingHeaders, *utf::precondition(if_reachable())) { // first store the object - string objectPath = basePath + "objectETag"; + std::string objectPath = basePath + "objectETag"; test_fixture f; TH1F h1("objectETag", "objectETag", 100, 0, 99); f.api.storeAsTFile(&h1, objectPath, f.metadata); @@ -445,7 +445,7 @@ BOOST_AUTO_TEST_CASE(TestFetchingHeaders, *utf::precondition(if_reachable())) std::string etag; std::vector headers; std::vector pfns; - string path = objectPath + "/" + std::to_string(getCurrentTimestamp()); + std::string path = objectPath + "/" + std::to_string(getCurrentTimestamp()); auto updated = CcdbApi::getCCDBEntryHeaders("http://ccdb-test.cern.ch:8080/" + path, etag, headers); BOOST_CHECK_EQUAL(updated, true); BOOST_REQUIRE(headers.size() != 0); @@ -462,7 +462,7 @@ BOOST_AUTO_TEST_CASE(TestRetrieveHeaders, *utf::precondition(if_reachable())) TH1F h1("object1", "object1", 100, 0, 99); cout << "storing object 1 in " << basePath << "Test" << endl; - map metadata; + std::map metadata; metadata["custom"] = "whatever"; f.api.storeAsTFile(&h1, basePath + "Test", metadata); @@ -498,7 +498,7 @@ BOOST_AUTO_TEST_CASE(TestUpdateMetadata, *utf::precondition(if_reachable())) // upload an object TH1F h1("object1", "object1", 100, 0, 99); cout << "storing object 1 in " << basePath << "Test" << endl; - map metadata; + std::map metadata; metadata["custom"] = "whatever"; metadata["id"] = "first"; f.api.storeAsTFile(&h1, basePath + "Test", metadata); @@ -507,10 +507,10 @@ BOOST_AUTO_TEST_CASE(TestUpdateMetadata, *utf::precondition(if_reachable())) std::map headers = f.api.retrieveHeaders(basePath + "Test", metadata); BOOST_CHECK(headers.count("custom") > 0); BOOST_CHECK(headers.at("custom") == "whatever"); - string firstID = headers.at("ETag"); + std::string firstID = headers.at("ETag"); firstID.erase(std::remove(firstID.begin(), firstID.end(), '"'), firstID.end()); - map newMetadata; + std::map newMetadata; newMetadata["custom"] = "somethingelse"; // update the metadata and check @@ -529,7 +529,7 @@ BOOST_AUTO_TEST_CASE(TestUpdateMetadata, *utf::precondition(if_reachable())) // get id cout << "get id" << endl; headers = f.api.retrieveHeaders(basePath + "Test", metadata); - string secondID = headers.at("ETag"); + std::string secondID = headers.at("ETag"); secondID.erase(std::remove(secondID.begin(), secondID.end(), '"'), secondID.end()); // update the metadata by id diff --git a/CCDB/test/testCcdbApiMultipleUrls.cxx b/CCDB/test/testCcdbApiMultipleUrls.cxx index 331d0553c3aec..07ab0ddcb4dcf 100644 --- a/CCDB/test/testCcdbApiMultipleUrls.cxx +++ b/CCDB/test/testCcdbApiMultipleUrls.cxx @@ -24,8 +24,8 @@ using namespace o2::ccdb; namespace utf = boost::unit_test; namespace tt = boost::test_tools; -static string ccdbUrl; -static string basePath; +static std::string ccdbUrl; +static std::string basePath; bool hostReachable = false; /** @@ -40,14 +40,14 @@ struct Fixture { cout << "ccdb url: " << ccdbUrl << endl; hostReachable = api.isHostReachable(); cout << "Is host reachable ? --> " << hostReachable << endl; - basePath = string("Test/pid") + getpid() + "/"; + basePath = std::string("Test/pid") + getpid() + "/"; cout << "Path we will use in this test suite : " + basePath << endl; } ~Fixture() { if (hostReachable) { CcdbApi api; - map metadata; + std::map metadata; api.init(ccdbUrl); api.truncate(basePath + "*"); cout << "Test data truncated (" << basePath << ")" << endl; @@ -79,7 +79,7 @@ struct test_fixture { ~test_fixture() = default; CcdbApi api; - map metadata; + std::map metadata; }; BOOST_AUTO_TEST_CASE(storeAndRetrieve, *utf::precondition(if_reachable())) diff --git a/CCDB/test/testCcdbApi_ConfigParam.cxx b/CCDB/test/testCcdbApi_ConfigParam.cxx index 8b3521bfd468a..568669d05978f 100644 --- a/CCDB/test/testCcdbApi_ConfigParam.cxx +++ b/CCDB/test/testCcdbApi_ConfigParam.cxx @@ -47,8 +47,8 @@ using namespace o2::ccdb; namespace utf = boost::unit_test; namespace tt = boost::test_tools; -static string ccdbUrl; -static string basePath; +static std::string ccdbUrl; +static std::string basePath; bool hostReachable = false; /** @@ -64,14 +64,14 @@ struct Fixture { hostReachable = api.isHostReachable(); char hostname[_POSIX_HOST_NAME_MAX]; gethostname(hostname, _POSIX_HOST_NAME_MAX); - basePath = string("Test/") + hostname + "/pid" + getpid() + "/"; + basePath = std::string("Test/") + hostname + "/pid" + getpid() + "/"; cout << "Path we will use in this test suite : " + basePath << endl; } ~Fixture() { if (hostReachable) { CcdbApi api; - map metadata; + std::map metadata; api.init(ccdbUrl); api.truncate(basePath + "*"); cout << "Test data truncated (" << basePath << ")" << endl; @@ -103,7 +103,7 @@ struct test_fixture { ~test_fixture() = default; CcdbApi api; - map metadata; + std::map metadata; }; BOOST_AUTO_TEST_CASE(testConfigParamRetrieval, *utf::precondition(if_reachable())) diff --git a/CCDB/test/testCcdbApi_alien.cxx b/CCDB/test/testCcdbApi_alien.cxx index f11f579346524..c50f83466fe06 100644 --- a/CCDB/test/testCcdbApi_alien.cxx +++ b/CCDB/test/testCcdbApi_alien.cxx @@ -29,7 +29,7 @@ using namespace o2::ccdb; namespace utf = boost::unit_test; namespace tt = boost::test_tools; -static string ccdbUrl; +static std::string ccdbUrl; bool hostReachable = false; /** @@ -71,7 +71,7 @@ struct test_fixture { ~test_fixture() = default; CcdbApi api; - map metadata; + std::map metadata; }; // handle the case where the object comes from alien and redirect does not work with curl diff --git a/DataFormats/Detectors/CTP/src/CTPRateFetcher.cxx b/DataFormats/Detectors/CTP/src/CTPRateFetcher.cxx index d899fcafec47d..5f31fe5741240 100644 --- a/DataFormats/Detectors/CTP/src/CTPRateFetcher.cxx +++ b/DataFormats/Detectors/CTP/src/CTPRateFetcher.cxx @@ -254,7 +254,7 @@ void CTPRateFetcher::setupRun(int runNumber, o2::ccdb::BasicCCDBManager* ccdb, u return; } mLHCIFdata = *ptrLHCIFdata; - std::map metadata; + std::map metadata; metadata["runNumber"] = std::to_string(mRunNumber); auto ptrConfig = ccdb->getSpecific("CTP/Config/Config", timeStamp, metadata); if (ptrConfig == nullptr) { diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index ac7fc06a2d5da..7d9b6c7902360 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -1674,11 +1674,11 @@ void AODProducerWorkflowDPL::init(InitContext& ic) { mTimer.Stop(); o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest); - mLPMProdTag = ic.options().get("lpmp-prod-tag"); - mAnchorPass = ic.options().get("anchor-pass"); - mAnchorProd = ic.options().get("anchor-prod"); - mUser = ic.options().get("created-by"); - mRecoPass = ic.options().get("reco-pass"); + mLPMProdTag = ic.options().get("lpmp-prod-tag"); + mAnchorPass = ic.options().get("anchor-pass"); + mAnchorProd = ic.options().get("anchor-prod"); + mUser = ic.options().get("created-by"); + mRecoPass = ic.options().get("reco-pass"); mTFNumber = ic.options().get("aod-timeframe-id"); mRecoOnly = ic.options().get("reco-mctracks-only"); mTruncate = ic.options().get("enable-truncation"); diff --git a/Detectors/CPV/calib/macros/makeBadMapFromPedestalRun.C b/Detectors/CPV/calib/macros/makeBadMapFromPedestalRun.C index 3b5af09190fe7..9d62cf1a13baa 100644 --- a/Detectors/CPV/calib/macros/makeBadMapFromPedestalRun.C +++ b/Detectors/CPV/calib/macros/makeBadMapFromPedestalRun.C @@ -75,7 +75,7 @@ void makeBadMapFromPedestalRun(const char* ccdbURI = "http://ccdb-test.cern.ch:8 } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdbURI); // or http://localhost:8080 for a local installation api.storeAsTFileAny(&badMap, "CPV/Calib/BadChannelMap", metadata, timeStamp, timeStamp + 31536000000); } diff --git a/Detectors/CTP/macro/GetAndSave.C b/Detectors/CTP/macro/GetAndSave.C index 345bb1caf4a96..ff70a3055c957 100644 --- a/Detectors/CTP/macro/GetAndSave.C +++ b/Detectors/CTP/macro/GetAndSave.C @@ -44,7 +44,7 @@ void GetAndSave(std::string ccdbHost = "http://ccdb-test.cern.ch:8080") for (auto const& run : runs) { CTPConfiguration ctpcfg; CTPRunScalers scl; - map metadata; // can be empty + std::map metadata; // can be empty metadata["runNumber"] = run; CTPRunScalers* ctpscalers = mgr.getSpecific(CCDBPathCTPScalers, timestamps[i], metadata); if (ctpscalers == nullptr) { diff --git a/Detectors/CTP/macro/SaveInputsConfig.C b/Detectors/CTP/macro/SaveInputsConfig.C index 99cae77905541..459fbf4024c95 100644 --- a/Detectors/CTP/macro/SaveInputsConfig.C +++ b/Detectors/CTP/macro/SaveInputsConfig.C @@ -41,7 +41,7 @@ void SaveInputsConfig(std::string filename = "inputs.cfg", std::string ccdbHost long tmax = timeStamp + time365days; o2::ccdb::CcdbApi api; api.init(ccdbHost); // or http://localhost:8080 for a local installation - map metadata; // can be empty + std::map metadata; // can be empty // store abitrary user object in strongly typed manner api.storeAsTFileAny(&ctpcfginps, "CTP/Calib/Inputs", metadata, tmin, tmax); } diff --git a/Detectors/CTP/macro/TestFetcher.C b/Detectors/CTP/macro/TestFetcher.C index 2d73b83cd174e..b2b6912f49911 100644 --- a/Detectors/CTP/macro/TestFetcher.C +++ b/Detectors/CTP/macro/TestFetcher.C @@ -27,7 +27,7 @@ void TestFetcher(int runNumber = 557251) fetcher.setupRun(runNumber, &ccdb, ts, 0); ccdb.setURL("http://ali-qcdb-gpn.cern.ch:8083/"); std::string QCDBPathCTPScalers = "qc/CTP/Scalers"; - map metadata; // can be empty + std::map metadata; // can be empty std::string run = std::to_string(runNumber); metadata["runNumber"] = run; CTPRunScalers* ctpscalers = ccdb.getSpecific(QCDBPathCTPScalers, ts, metadata); diff --git a/Detectors/CTP/simulation/src/Digitizer.cxx b/Detectors/CTP/simulation/src/Digitizer.cxx index 55893cb0269da..b1d4ef40b7b0e 100644 --- a/Detectors/CTP/simulation/src/Digitizer.cxx +++ b/Detectors/CTP/simulation/src/Digitizer.cxx @@ -194,7 +194,7 @@ o2::ctp::CTPConfiguration* Digitizer::getDefaultCTPConfiguration() } auto& mgr = o2::ccdb::BasicCCDBManager::instance(); mgr.setURL(mCCDBServer); - map metadata = {}; + std::map metadata = {}; long timestamp = 1546300800000; auto config = mgr.getSpecific(o2::ctp::CCDBPathCTPConfig, timestamp, metadata); diff --git a/Detectors/CTP/workflowScalers/src/ctpCCDBManager.cxx b/Detectors/CTP/workflowScalers/src/ctpCCDBManager.cxx index 58850d88eb2c6..77d3f03bbbde2 100644 --- a/Detectors/CTP/workflowScalers/src/ctpCCDBManager.cxx +++ b/Detectors/CTP/workflowScalers/src/ctpCCDBManager.cxx @@ -40,7 +40,7 @@ int ctpCCDBManager::saveRunScalersToCCDB(CTPRunScalers& scalers, long timeStart, long tmin = timeStart - time10min; long tmax = timeStop + time3days; o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty metadata["runNumber"] = std::to_string(scalers.getRunNumber()); api.init(mCCDBHost.c_str()); // or http://localhost:8080 for a local installation // store abitrary user object in strongly typed manner @@ -68,7 +68,7 @@ int ctpCCDBManager::saveRunScalersToQCDB(CTPRunScalers& scalers, long timeStart, long tmin = timeStart - time10min; long tmax = timeStop + time3days; o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty metadata["runNumber"] = std::to_string(scalers.getRunNumber()); api.init(mQCDBHost.c_str()); // or http://localhost:8080 for a local installation // store abitrary user object in strongly typed manner @@ -95,7 +95,7 @@ int ctpCCDBManager::saveRunConfigToCCDB(CTPConfiguration* cfg, long timeStart) long tmin = timeStart - time10min; long tmax = timeStart + time3days; o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty metadata["runNumber"] = std::to_string(cfg->getRunNumber()); api.init(mCCDBHost.c_str()); // or http://localhost:8080 for a local installation // store abitrary user object in strongly typed manner @@ -125,7 +125,7 @@ int ctpCCDBManager::saveSoxOrbit(uint32_t runNumber, uint32_t soxOrbit, long tim long tmin = timestamp / 1000; long tmax = tmin + 381928219; o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty metadata["runNumber"] = std::to_string(runNumber); api.init(mCCDBHost.c_str()); // or http://localhost:8080 for a local installation @@ -155,7 +155,7 @@ int ctpCCDBManager::saveOrbitReset(long timeStamp) long tmin = timeStamp / 1000; long tmax = tmin + 381928219; o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(mCCDBHost.c_str()); // or http://localhost:8080 for a local installation // store abitrary user object in strongly typed manner @@ -184,7 +184,7 @@ int ctpCCDBManager::saveCtpCfg(uint32_t runNumber, long timeStart) long tmin = timeStart - time10min; long tmax = timeStart + time3days; o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty metadata["runNumber"] = std::to_string(runNumber); api.init(mCCDBHost.c_str()); // or http://localhost:8080 for a local installation // store abitrary user object in strongly typed manner @@ -201,7 +201,7 @@ CTPConfiguration ctpCCDBManager::getConfigFromCCDB(long timestamp, std::string r { auto& mgr = o2::ccdb::BasicCCDBManager::instance(); mgr.setURL(mCCDBHost); - map metadata; // can be empty + std::map metadata; // can be empty metadata["runNumber"] = run; auto ctpconfigdb = mgr.getSpecific(CCDBPathCTPConfig, timestamp, metadata); if (ctpconfigdb == nullptr) { @@ -228,7 +228,7 @@ CTPRunScalers ctpCCDBManager::getScalersFromCCDB(long timestamp, std::string run { auto& mgr = o2::ccdb::BasicCCDBManager::instance(); mgr.setURL(mCCDBHost); - map metadata; // can be empty + std::map metadata; // can be empty metadata["runNumber"] = run; auto ctpscalers = mgr.getSpecific(mCCDBPathCTPScalers, timestamp, metadata); if (ctpscalers == nullptr) { diff --git a/Detectors/EMCAL/base/src/Geometry.cxx b/Detectors/EMCAL/base/src/Geometry.cxx index 6039c18dd34e4..c194f570e47d1 100644 --- a/Detectors/EMCAL/base/src/Geometry.cxx +++ b/Detectors/EMCAL/base/src/Geometry.cxx @@ -1790,7 +1790,7 @@ void Geometry::SetMisalMatrixFromCcdb(const char* path, int timestamp) const { LOG(info) << "Using CCDB to obtain EMCal alignment."; o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init("http://alice-ccdb.cern.ch"); TObjArray* matrices = api.retrieveFromTFileAny(path, metadata, timestamp); diff --git a/Detectors/FIT/FT0/macros/FT0Misaligner.C b/Detectors/FIT/FT0/macros/FT0Misaligner.C index 9621d1a079bc9..16476ae3b8ccc 100644 --- a/Detectors/FIT/FT0/macros/FT0Misaligner.C +++ b/Detectors/FIT/FT0/macros/FT0Misaligner.C @@ -55,7 +55,7 @@ void FT0Misaligner(const std::string& ccdbHost = "http://ccdb-test.cern.ch:8080" std::string path = objectPath.empty() ? o2::base::DetectorNameConf::getAlignmentPath(detFT0) : objectPath; LOGP(info, "Storing alignment object on {}/{}", ccdbHost, path); o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdbHost.c_str()); // or http://localhost:8080 for a local installation // store abitrary user object in strongly typed manner api.storeAsTFileAny(¶ms, path, metadata, tmin, tmax); diff --git a/Detectors/FIT/FV0/calibration/macros/readChannelTimeOffsetFV0CalibObjectFromCCDB.C b/Detectors/FIT/FV0/calibration/macros/readChannelTimeOffsetFV0CalibObjectFromCCDB.C index 06b86e3c5015d..3f42c0219b101 100644 --- a/Detectors/FIT/FV0/calibration/macros/readChannelTimeOffsetFV0CalibObjectFromCCDB.C +++ b/Detectors/FIT/FV0/calibration/macros/readChannelTimeOffsetFV0CalibObjectFromCCDB.C @@ -22,8 +22,8 @@ int readChannelTimeOffsetFV0CalibObjectFromCCDB(const std::string url = "http:// { o2::ccdb::CcdbApi api; api.init(url); - map metadata; - map headers; + std::map metadata; + std::map headers; auto retrieved = api.retrieveFromTFileAny("FV0/Calib/ChannelTimeOffset", metadata, -1, &headers); std::cout << "--- HEADERS ---" << std::endl; diff --git a/Detectors/FIT/FV0/macros/FV0Misaligner.C b/Detectors/FIT/FV0/macros/FV0Misaligner.C index 88f7a0b82b8b3..61be50b48dede 100644 --- a/Detectors/FIT/FV0/macros/FV0Misaligner.C +++ b/Detectors/FIT/FV0/macros/FV0Misaligner.C @@ -54,7 +54,7 @@ void FV0Misaligner(const std::string& ccdbHost = "http://ccdb-test.cern.ch:8080" std::string path = objectPath.empty() ? o2::base::DetectorNameConf::getAlignmentPath(detFV0) : objectPath; LOGP(info, "Storing alignment object on {}/{}", ccdbHost, path); o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdbHost.c_str()); // or http://localhost:8080 for a local installation // store abitrary user object in strongly typed manner api.storeAsTFileAny(¶ms, path, metadata, tmin, tmax); diff --git a/Detectors/FIT/common/dcsmonitoring/include/FITDCSMonitoring/FITDCSConfigProcessorSpec.h b/Detectors/FIT/common/dcsmonitoring/include/FITDCSMonitoring/FITDCSConfigProcessorSpec.h index f3ed3229d9e55..18c0b593b0a02 100644 --- a/Detectors/FIT/common/dcsmonitoring/include/FITDCSMonitoring/FITDCSConfigProcessorSpec.h +++ b/Detectors/FIT/common/dcsmonitoring/include/FITDCSMonitoring/FITDCSConfigProcessorSpec.h @@ -47,7 +47,7 @@ class FITDCSConfigProcessor : public o2::framework::Task void init(o2::framework::InitContext& ic) final { initDCSConfigReader(); - mDCSConfigReader->setFileNameDChM(ic.options().get("filename-dchm")); + mDCSConfigReader->setFileNameDChM(ic.options().get("filename-dchm")); mDCSConfigReader->setValidDaysDChM(ic.options().get("valid-days-dchm")); mDCSConfigReader->setCcdbPathDChM(mDetectorName + "/Calib/DeadChannelMap"); mVerbose = ic.options().get("use-verbose-mode"); diff --git a/Detectors/GRP/calibration/src/GRPDCSDPsProcessor.cxx b/Detectors/GRP/calibration/src/GRPDCSDPsProcessor.cxx index c8fa7c2bff38b..aec4241f4f8db 100644 --- a/Detectors/GRP/calibration/src/GRPDCSDPsProcessor.cxx +++ b/Detectors/GRP/calibration/src/GRPDCSDPsProcessor.cxx @@ -277,13 +277,13 @@ bool GRPDCSDPsProcessor::processLHCIFDPs(const DPCOM& dpcom) } for (int ibeam = 0; ibeam < GRPLHCInfo::BeamAliases::NBeamAliases; ++ibeam) { - if (aliasStr.find(static_cast(GRPLHCInfo::beamAliases[ibeam])) != string::npos) { + if (aliasStr.find(static_cast(GRPLHCInfo::beamAliases[ibeam])) != std::string::npos) { updateVector(dpid, mLHCInfo.mIntensityBeam[ibeam], aliasStr, dpcomdata.get_epoch_time(), val); return true; } } - if (aliasStr.find("BPTX") != string::npos) { + if (aliasStr.find("BPTX") != std::string::npos) { if (aliasStr == static_cast(GRPLHCInfo::bptxAliases[GRPLHCInfo::BPTXAliases::BPTX_deltaT_B1_B2])) { updateVector(dpid, mLHCInfo.mBPTXdeltaT, aliasStr, dpcomdata.get_epoch_time(), val); return true; @@ -318,7 +318,7 @@ bool GRPDCSDPsProcessor::processLHCIFDPs(const DPCOM& dpcom) } for (int ibkg = 0; ibkg < 3; ++ibkg) { - if (aliasStr.find(static_cast(GRPLHCInfo::bkgAliases[ibkg])) != string::npos) { + if (aliasStr.find(static_cast(GRPLHCInfo::bkgAliases[ibkg])) != std::string::npos) { updateVector(dpid, mLHCInfo.mBackground[ibkg], aliasStr, dpcomdata.get_epoch_time(), val); return true; } diff --git a/Detectors/GRP/workflows/src/create-grp-ecs.cxx b/Detectors/GRP/workflows/src/create-grp-ecs.cxx index 873133e0dd46b..d9a73f0737799 100644 --- a/Detectors/GRP/workflows/src/create-grp-ecs.cxx +++ b/Detectors/GRP/workflows/src/create-grp-ecs.cxx @@ -268,10 +268,10 @@ int main(int argc, char** argv) add_option("run,r", bpo::value(), "run number"); add_option("run-type,t", bpo::value()->default_value(int(GRPECSObject::RunType::NONE)), "run type"); add_option("hbf-per-tf,n", bpo::value()->default_value(128), "number of HBFs per TF"); - add_option("detectors,d", bpo::value()->default_value("all"), "comma separated list of detectors"); - add_option("continuous,c", bpo::value()->default_value("ITS,TPC,TOF,MFT,MCH,MID,ZDC,FT0,FV0,FDD,CTP"), "comma separated list of detectors in continuous readout mode"); - add_option("triggering,g", bpo::value()->default_value("FT0,FV0"), "comma separated list of detectors providing a trigger"); - add_option("flps,f", bpo::value()->default_value(""), "comma separated list of FLPs in the data taking"); + add_option("detectors,d", bpo::value()->default_value("all"), "comma separated list of detectors"); + add_option("continuous,c", bpo::value()->default_value("ITS,TPC,TOF,MFT,MCH,MID,ZDC,FT0,FV0,FDD,CTP"), "comma separated list of detectors in continuous readout mode"); + add_option("triggering,g", bpo::value()->default_value("FT0,FV0"), "comma separated list of detectors providing a trigger"); + add_option("flps,f", bpo::value()->default_value(""), "comma separated list of FLPs in the data taking"); add_option("start-time,s", bpo::value()->default_value(0), "ECS run start time in ms, now() if 0"); add_option("end-time,e", bpo::value()->default_value(0), "ECS run end time in ms, start-time+3days is used if 0"); add_option("start-time-ctp", bpo::value()->default_value(0), "run start CTP time in ms, same as ECS if not set or 0"); @@ -279,7 +279,7 @@ int main(int argc, char** argv) add_option("ccdb-server", bpo::value()->default_value("http://alice-ccdb.cern.ch"), "CCDB server for upload, local file if empty"); add_option("ccdb-server-input", bpo::value()->default_value(""), "CCDB server for inputs (if needed, e.g. CTPConfig), dy default ccdb-server is used"); add_option("meta-data,m", bpo::value()->default_value("")->implicit_value(""), "metadata as key1=value1;key2=value2;.."); - add_option("refresh", bpo::value()->default_value("")->implicit_value("async"), R"(refresh server cache after upload: "none" (or ""), "async" (non-blocking) and "sync" (blocking))"); + add_option("refresh", bpo::value()->default_value("")->implicit_value("async"), R"(refresh server cache after upload: "none" (or ""), "async" (non-blocking) and "sync" (blocking))"); add_option("marginSOR", bpo::value()->default_value(4 * o2::ccdb::CcdbObjectInfo::DAY), "validity at SOR"); add_option("marginEOR", bpo::value()->default_value(10 * o2::ccdb::CcdbObjectInfo::MINUTE), "validity margin to add after EOR"); add_option("original-run,o", bpo::value()->default_value(0), "if >0, use as the source run to create CTP/Config/Config object"); @@ -313,7 +313,7 @@ int main(int argc, char** argv) std::cerr << opt_general << std::endl; exit(3); } - std::string refreshStr = vm["refresh"].as(); + std::string refreshStr = vm["refresh"].as(); CCDBRefreshMode refresh = CCDBRefreshMode::NONE; if (!refreshStr.empty() && refreshStr != "none") { if (refreshStr == "async") { diff --git a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-residual-aggregator.cxx b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-residual-aggregator.cxx index a127cf313d0e1..bd21b8ac22116 100644 --- a/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-residual-aggregator.cxx +++ b/Detectors/GlobalTrackingWorkflow/tpcinterpolationworkflow/src/tpc-residual-aggregator.cxx @@ -43,7 +43,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) bool writeUnbinnedResiduals = false; bool writeBinnedResiduals = false; bool writeTrackData = false; - auto outputType = configcontext.options().get("output-type"); + auto outputType = configcontext.options().get("output-type"); std::vector outputTypes; size_t pos = 0; while ((pos = outputType.find(",")) != std::string::npos) { diff --git a/Detectors/ITSMFT/ITS/QC/TestDataReaderWorkflow/src/TestDataReader.cxx b/Detectors/ITSMFT/ITS/QC/TestDataReaderWorkflow/src/TestDataReader.cxx index 964f342c58b15..1fc4442e3bdbf 100644 --- a/Detectors/ITSMFT/ITS/QC/TestDataReaderWorkflow/src/TestDataReader.cxx +++ b/Detectors/ITSMFT/ITS/QC/TestDataReaderWorkflow/src/TestDataReader.cxx @@ -210,7 +210,7 @@ void TestDataReader::run(ProcessingContext& pc) size_t pos = mNowFolderNames[i].find_last_of("/"); - if (pos != string::npos) { + if (pos != std::string::npos) { mRunID = mNowFolderNames[i].substr(pos + 1); } @@ -232,7 +232,7 @@ void TestDataReader::run(ProcessingContext& pc) // Getting the FileID string FileIDS; pos = mDiffFileNames[i][0].find_last_of("/"); - if (pos != string::npos) { + if (pos != std::string::npos) { FileIDS = mDiffFileNames[i][0].substr(pos + 1); } diff --git a/Detectors/ITSMFT/ITS/macros/test/ITSMisaligner.C b/Detectors/ITSMFT/ITS/macros/test/ITSMisaligner.C index e04c2ca572804..eb6cb7a39b41c 100644 --- a/Detectors/ITSMFT/ITS/macros/test/ITSMisaligner.C +++ b/Detectors/ITSMFT/ITS/macros/test/ITSMisaligner.C @@ -78,7 +78,7 @@ void ITSMisaligner(const std::string& ccdbHost = "http://localhost:8080", long t std::string path = objectPath.empty() ? o2::base::DetectorNameConf::getAlignmentPath(detITS) : objectPath; LOGP(info, "Storing alignment object on {}/{}", ccdbHost, path); o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdbHost.c_str()); // or http://localhost:8080 for a local installation // store abitrary user object in strongly typed manner api.storeAsTFileAny(¶ms, path, metadata, tmin, tmax); diff --git a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSParserSpec.h b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSParserSpec.h index eaacfab10f886..cd18fd459546d 100644 --- a/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSParserSpec.h +++ b/Detectors/ITSMFT/ITS/workflow/include/ITSWorkflow/DCSParserSpec.h @@ -136,7 +136,7 @@ class ITSDCSParser : public Task std::string mCcdbUrl = ""; // Vector containing all the staves listed in the EOR file - std::vector mSavedStaves = {}; + std::vector mSavedStaves = {}; // Disabled chip map o2::itsmft::NoiseMap mDeadMap; diff --git a/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx index a9e1121077f02..d504640588023 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/DCSParserSpec.cxx @@ -386,9 +386,9 @@ void ITSDCSParser::saveToOutput() void ITSDCSParser::saveMissingToOutput() { // Loop on the missing staves - std::vector missingStaves; - std::vector listStaves = this->listStaves(); - std::vector savedStaves = this->mSavedStaves; + std::vector missingStaves; + std::vector listStaves = this->listStaves(); + std::vector savedStaves = this->mSavedStaves; std::sort(savedStaves.begin(), savedStaves.end()); std::set_difference(listStaves.begin(), listStaves.end(), savedStaves.begin(), savedStaves.end(), std::inserter(missingStaves, missingStaves.begin())); @@ -557,7 +557,7 @@ std::vector ITSDCSParser::listStaves() std::string stavenum = ""; for (int i = 0; i < 7; i++) { for (int j = 0; j < stavesPerLayer[i]; j++) { - string stavestring = std::to_string(j); + std::string stavestring = std::to_string(j); int precision = 2 - std::min(2, (int)(stavestring.size())); stavenum = std::string(precision, '0').append(std::to_string(j)); std::string stave = "L" + std::to_string(i) + "_" + stavenum; diff --git a/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx b/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx index e958e6b1ba113..8359d6c89ab60 100644 --- a/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx +++ b/Detectors/ITSMFT/MFT/calibration/src/NoiseCalibratorSpec.cxx @@ -299,8 +299,8 @@ void NoiseCalibratorSpec::sendOutputCcdbMerge(DataAllocator& output) auto payload = mCalibrator->getNoiseMap(); // const auto& payload = mCalibrator->getNoiseMap(starTF, endTF); //For TimeSlot calibration - map headers; - map filter; + std::map headers; + std::map filter; auto* payloadPrev1 = api.retrieveFromTFileAny(mPathSingle, filter, -1, &headers); long validtime = std::stol(headers["Valid-From"]); auto mergedPL = payload; @@ -424,8 +424,8 @@ void NoiseCalibratorSpec::sendOutputDcsMerge(DataAllocator& output) auto payload = mCalibrator->getNoiseMap(); // const auto& payload = mCalibrator->getNoiseMap(starTF, endTF); //For TimeSlot calibration - map headers; - map filter; + std::map headers; + std::map filter; auto* payloadPrev1 = api.retrieveFromTFileAny(mPathSingle, filter, -1, &headers); long validtime = std::stol(headers["Valid-From"]); auto mergedPL = payload; diff --git a/Detectors/ITSMFT/MFT/condition/macros/readAlpideCCDB.C b/Detectors/ITSMFT/MFT/condition/macros/readAlpideCCDB.C index 31b8028e2b7ee..adc8aaa16ed70 100644 --- a/Detectors/ITSMFT/MFT/condition/macros/readAlpideCCDB.C +++ b/Detectors/ITSMFT/MFT/condition/macros/readAlpideCCDB.C @@ -14,7 +14,7 @@ void readAlpideCCDB(long timestamp = -1, float thresh = 0) o2::ccdb::CcdbApi api; // api.init("alice-ccdb.cern.ch"); api.init("ccdb-test.cern.ch"); - map headers; + std::map headers; map filter; auto calib = api.retrieveFromTFileAny>("MFT/Config/AlpideParam/", filter, timestamp, &headers); calib->printKeyValues(); diff --git a/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx b/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx index 0a61d38a36b2a..690a17952b033 100644 --- a/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx +++ b/Detectors/MUON/MCH/Align/src/AlignRecordSpec.cxx @@ -121,7 +121,7 @@ class AlignRecordTask mImproveCutChi2 = 2. * trackerParam.sigmaCutForImprovement * trackerParam.sigmaCutForImprovement; // Configuration for chamber fixing - auto input_fixchambers = ic.options().get("fix-chamber"); + auto input_fixchambers = ic.options().get("fix-chamber"); std::stringstream string_chambers(input_fixchambers); string_chambers >> std::ws; while (string_chambers.good()) { @@ -132,8 +132,8 @@ class AlignRecordTask } // Init for output saving - auto OutputRecFileName = ic.options().get("output-record-data"); - auto OutputConsFileName = ic.options().get("output-record-constraint"); + auto OutputRecFileName = ic.options().get("output-record-data"); + auto OutputConsFileName = ic.options().get("output-record-constraint"); mAlign.init(OutputRecFileName, OutputConsFileName); ic.services().get().set([this]() { diff --git a/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx b/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx index 9d92f18024d88..828cb0cb80242 100644 --- a/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx +++ b/Detectors/MUON/MCH/Align/src/AlignmentSpec.cxx @@ -167,7 +167,7 @@ class AlignmentTask LOG(info) << "Loading magnetic field and reference geometry from input files"; - auto grpFile = ic.options().get("grp-file"); + auto grpFile = ic.options().get("grp-file"); if (std::filesystem::exists(grpFile)) { const auto grp = parameters::GRPObject::loadFrom(grpFile); base::Propagator::initFieldFromGRP(grp); @@ -178,7 +178,7 @@ class AlignmentTask LOG(fatal) << "No GRP file"; } - IdealGeoFileName = ic.options().get("geo-file-ideal"); + IdealGeoFileName = ic.options().get("geo-file-ideal"); if (std::filesystem::exists(IdealGeoFileName)) { base::GeometryManager::loadGeometry(IdealGeoFileName.c_str()); transformation = geo::transformationFromTGeoManager(*gGeoManager); @@ -190,7 +190,7 @@ class AlignmentTask LOG(fatal) << "No ideal geometry"; } - RefGeoFileName = ic.options().get("geo-file-ref"); + RefGeoFileName = ic.options().get("geo-file-ref"); if (std::filesystem::exists(RefGeoFileName)) { base::GeometryManager::loadGeometry(RefGeoFileName.c_str()); transformation = geo::transformationFromTGeoManager(*gGeoManager); @@ -205,7 +205,7 @@ class AlignmentTask if (doReAlign) { LOG(info) << "Re-alignment mode"; LOG(info) << "Loading re-alignment geometry"; - NewGeoFileName = ic.options().get("geo-file-new"); + NewGeoFileName = ic.options().get("geo-file-new"); if (std::filesystem::exists(NewGeoFileName)) { base::GeometryManager::loadGeometry(NewGeoFileName.c_str()); transformation = geo::transformationFromTGeoManager(*gGeoManager); @@ -246,7 +246,7 @@ class AlignmentTask mImproveCutChi2 = 2. * trackerParam.sigmaCutForImprovement * trackerParam.sigmaCutForImprovement; // Fix chambers - TString chambersString = ic.options().get("fix-chamber"); + TString chambersString = ic.options().get("fix-chamber"); std::unique_ptr objArray(chambersString.Tokenize(",")); if (objArray->GetEntries() > 0) { for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { @@ -256,8 +256,8 @@ class AlignmentTask } // Fix DEs - TString DEString = ic.options().get("fix-de"); - TString MaskDEString = ic.options().get("mask-fix-de"); + TString DEString = ic.options().get("fix-de"); + TString MaskDEString = ic.options().get("mask-fix-de"); std::unique_ptr objArrayDE(DEString.Tokenize(",")); std::unique_ptr objArrayMask(MaskDEString.Tokenize(",")); if (objArrayDE->GetEntries() > 0) { @@ -271,7 +271,7 @@ class AlignmentTask } doMatched = ic.options().get("matched"); - outFileName = ic.options().get("output"); + outFileName = ic.options().get("output"); readFromRec = ic.options().get("use-record"); if (readFromRec) { diff --git a/Detectors/MUON/MCH/Geometry/Test/Helpers.cxx b/Detectors/MUON/MCH/Geometry/Test/Helpers.cxx index 685971a026b27..d5bf4cad2142d 100644 --- a/Detectors/MUON/MCH/Geometry/Test/Helpers.cxx +++ b/Detectors/MUON/MCH/Geometry/Test/Helpers.cxx @@ -166,7 +166,7 @@ void zeroMisAlignGeometry(const std::string& ccdbHost, const std::string& fileNa std::string path = objectPath.empty() ? o2::base::DetectorNameConf::getAlignmentPath(detMCH) : objectPath; LOGP(info, "Storing alignment object on {}/{}", ccdbHost, path); o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdbHost.c_str()); // or http://localhost:8080 for a local installation // store abitrary user object in strongly typed manner api.storeAsTFileAny(¶ms, path, metadata, tmin, tmax); diff --git a/Detectors/MUON/MCH/Geometry/Test/misAlign.C b/Detectors/MUON/MCH/Geometry/Test/misAlign.C index c49fe5717a36b..41312b1f223d4 100644 --- a/Detectors/MUON/MCH/Geometry/Test/misAlign.C +++ b/Detectors/MUON/MCH/Geometry/Test/misAlign.C @@ -89,7 +89,7 @@ void misAlign(Double_t xcartmisaligm = 0.01, Double_t xcartmisaligw = 0.0, std::string path = objectPath.empty() ? o2::base::DetectorNameConf::getAlignmentPath(detMCH) : objectPath; LOGP(info, "Storing alignment object on {}/{}", ccdbHost, path); o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdbHost.c_str()); // or http://localhost:8080 for a local installation // store abitrary user object in strongly typed manner api.storeAsTFileAny(¶ms, path, metadata, tmin, tmax); diff --git a/Detectors/TPC/calibration/src/CalculatedEdx.cxx b/Detectors/TPC/calibration/src/CalculatedEdx.cxx index 60e9ada7794d3..11f83f1c7189e 100644 --- a/Detectors/TPC/calibration/src/CalculatedEdx.cxx +++ b/Detectors/TPC/calibration/src/CalculatedEdx.cxx @@ -566,7 +566,7 @@ void CalculatedEdx::loadCalibsFromCCDB(long runNumberOrTimeStamp, const bool isM mCalibCont.setResidualCorrection(*residualCorr); // set the zero supression threshold map - std::unordered_map>* zeroSupressionThresholdMap = cm.getForTimeStamp>>(o2::tpc::CDBTypeMap.at(o2::tpc::CDBType::ConfigFEEPad), tRun); + std::unordered_map>* zeroSupressionThresholdMap = cm.getForTimeStamp>>(o2::tpc::CDBTypeMap.at(o2::tpc::CDBType::ConfigFEEPad), tRun); mCalibCont.setZeroSupresssionThreshold(zeroSupressionThresholdMap->at("ThresholdMap")); // set the magnetic field @@ -624,7 +624,7 @@ void CalculatedEdx::setGainMapResidualFromFile(const char* folder, const char* f std::unique_ptr gainMapResidualFile(TFile::Open(fmt::format("{}{}", folder, file).data())); if (!gainMapResidualFile->IsZombie()) { LOGP(info, "Using file: {}", gainMapResidualFile->GetName()); - std::unordered_map>* gainMapResidual = (std::unordered_map>*)gainMapResidualFile->Get(object); + std::unordered_map>* gainMapResidual = (std::unordered_map>*)gainMapResidualFile->Get(object); mCalibCont.setGainMapResidual(gainMapResidual->at("GainMap")); } } @@ -644,7 +644,7 @@ void CalculatedEdx::setZeroSuppressionThresholdFromFile(const char* folder, cons std::unique_ptr zeroSuppressionFile(TFile::Open(fmt::format("{}{}", folder, file).data())); if (!zeroSuppressionFile->IsZombie()) { LOGP(info, "Using file: {}", zeroSuppressionFile->GetName()); - std::unordered_map>* zeroSupressionThresholdMap = (std::unordered_map>*)zeroSuppressionFile->Get(object); + std::unordered_map>* zeroSupressionThresholdMap = (std::unordered_map>*)zeroSuppressionFile->Get(object); mCalibCont.setZeroSupresssionThreshold(zeroSupressionThresholdMap->at("ThresholdMap")); } } diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPadGainTracksSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPadGainTracksSpec.h index 7afc973d7a3ab..c5af27da7b8f7 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPadGainTracksSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/TPCCalibPadGainTracksSpec.h @@ -139,7 +139,7 @@ class TPCCalibPadGainTracksDevice : public o2::framework::Task if (matcher == ConcreteDataMatcher(gDataOriginTPC, "RESIDUALGAINMAP", 0)) { if (!mUsingDefaultGainMapForFirstIter) { LOGP(info, "Updating reference gain map from previous iteration from CCDB"); - const auto* gainMapResidual = static_cast>*>(obj); + const auto* gainMapResidual = static_cast>*>(obj); mPadGainTracks.setRefGainMap(gainMapResidual->at("GainMap")); } else { // just skip for the first time asking for an object -> not gain map will be used as reference diff --git a/Detectors/TRD/base/macros/OCDB2CCDB.C b/Detectors/TRD/base/macros/OCDB2CCDB.C index f7723089bd5a6..35cf86d05d22f 100644 --- a/Detectors/TRD/base/macros/OCDB2CCDB.C +++ b/Detectors/TRD/base/macros/OCDB2CCDB.C @@ -266,7 +266,7 @@ void OCDB2CCDB(long timeStamp = -1, TString ccdbPath = "http://localhost:8080", //Connect to CCDB // o2::ccdb::CcdbApi ccdb; - map metadata; // do we want to store any meta data? + std::map metadata; // do we want to store any meta data? ccdb.init(ccdbPath.Data()); AliTRDCalChamberStatus* chamberStatus = 0; diff --git a/Detectors/TRD/base/macros/OCDB2CCDBTrapConfig.C b/Detectors/TRD/base/macros/OCDB2CCDBTrapConfig.C index 0b4d93906efb5..edf8bfff15129 100644 --- a/Detectors/TRD/base/macros/OCDB2CCDBTrapConfig.C +++ b/Detectors/TRD/base/macros/OCDB2CCDBTrapConfig.C @@ -206,7 +206,7 @@ void OCDB2CCDBTrapConfig(TString ccdbPath = "http://localhost:8080", Int_t run = //Connect to CCDB // o2::ccdb::CcdbApi ccdb; - map metadata; // do we want to store any meta data? + std::map metadata; // do we want to store any meta data? metadata.emplace(std::make_pair("UploadedBy", "marten")); metadata.emplace(std::make_pair("Description", "Default TRAP config for Run 3 simulations in LS2")); ccdb.init(ccdbPath.Data()); diff --git a/Detectors/TRD/base/macros/PrintTrapConfig.C b/Detectors/TRD/base/macros/PrintTrapConfig.C index b9b0c3226dcc1..5ed22c32d45aa 100644 --- a/Detectors/TRD/base/macros/PrintTrapConfig.C +++ b/Detectors/TRD/base/macros/PrintTrapConfig.C @@ -236,7 +236,7 @@ void PrintTrapConfig(Int_t run, const Char_t* storageURI = "alien://folder=/alic //Connect to CCDB // o2::ccdb::CcdbApi ccdb; - map metadata; // do we want to store any meta data? + std::map metadata; // do we want to store any meta data? ccdb.init("http://ccdb-test.cern.ch:8080"); // or http://localhost:8080 for a local installation /* diff --git a/Detectors/TRD/base/macros/Readocdb.C b/Detectors/TRD/base/macros/Readocdb.C index 55bea0c2e9cf2..4839f11a41590 100644 --- a/Detectors/TRD/base/macros/Readocdb.C +++ b/Detectors/TRD/base/macros/Readocdb.C @@ -251,7 +251,7 @@ void Readocdb(Int_t run, const Char_t* storageURI = "alien://folder=/alice/data/ //Connect to CCDB // o2::ccdb::CcdbApi ccdb; - map metadata; // do we want to store any meta data? + std::map metadata; // do we want to store any meta data? ccdb.init("http://ccdb-test.cern.ch:8080"); // or http://localhost:8080 for a local installation AliTRDCalChamberStatus* chamberStatus = 0; diff --git a/Detectors/TRD/calibration/include/TRDCalibration/DCSProcessor.h b/Detectors/TRD/calibration/include/TRDCalibration/DCSProcessor.h index 27cba85a89941..8e4a99e5e85d3 100644 --- a/Detectors/TRD/calibration/include/TRDCalibration/DCSProcessor.h +++ b/Detectors/TRD/calibration/include/TRDCalibration/DCSProcessor.h @@ -96,7 +96,7 @@ class DCSProcessor const std::unordered_map& getTRDCurrentsDPsInfo() const { return mTRDDCSCurrents; } const std::unordered_map& getTRDEnvDPsInfo() const { return mTRDDCSEnv; } const std::array& getTRDFedChamberStatusDPsInfo() const { return mTRDDCSFedChamberStatus; } - const std::array& getTRDFedCFGtagDPsInfo() const { return mTRDDCSFedCFGtag; } + const std::array& getTRDFedCFGtagDPsInfo() const { return mTRDDCSFedCFGtag; } // settings void setCurrentTS(TFType tf) { mCurrentTS = tf; } @@ -124,7 +124,7 @@ class DCSProcessor std::unordered_map mTRDDCSVoltages; ///< anode and drift voltages std::unordered_map mTRDDCSEnv; ///< environment parameters (temperatures, pressures, humidity) std::array mTRDDCSFedChamberStatus; ///< fed chamber status - std::array mTRDDCSFedCFGtag; ///< fed config tag + std::array mTRDDCSFedCFGtag; ///< fed config tag // helper variables std::unordered_map mPids; ///< flag for each DP whether it has been processed at least once diff --git a/Detectors/TRD/calibration/src/DCSProcessor.cxx b/Detectors/TRD/calibration/src/DCSProcessor.cxx index 165bbbd6a6148..f110ba844791e 100644 --- a/Detectors/TRD/calibration/src/DCSProcessor.cxx +++ b/Detectors/TRD/calibration/src/DCSProcessor.cxx @@ -120,7 +120,7 @@ int DCSProcessor::processDP(const DPCOM& dpcom) } else if (type == DPVAL_INT) { LOG(info) << "Processing DP = " << dpcom << ", with value = " << o2::dcs::getValue(dpcom); } else if (type == DPVAL_STRING) { - LOG(info) << "Processing DP = " << dpcom << ", with value = " << o2::dcs::getValue(dpcom); + LOG(info) << "Processing DP = " << dpcom << ", with value = " << o2::dcs::getValue(dpcom); } } auto flags = dpcom.data.get_flags(); @@ -265,15 +265,15 @@ int DCSProcessor::processDP(const DPCOM& dpcom) int chamberId = getChamberIdFromAlias(dpid.get_alias()); auto& dpInfoFedCFGtag = mTRDDCSFedCFGtag[chamberId]; if (etime != mLastDPTimeStamps[dpid]) { - if (dpInfoFedCFGtag != o2::dcs::getValue(dpcom)) { + if (dpInfoFedCFGtag != o2::dcs::getValue(dpcom)) { // If value changes after processing and DPs should not be updated, log change as warning (for now) if (mPids[dpid] && !(mFedCFGtagCompleteDPs && mFirstRunEntryForFedCFGtagUpdate)) { // Issue an alarm if counter is lower than maximum, warning otherwise if (mFedCFGtagAlarmCounter < mFedAlarmCounterMax) { - LOG(alarm) << "CFGtag change " << dpid.get_alias() << " : " << dpInfoFedCFGtag << " -> " << o2::dcs::getValue(dpcom) << ", run = " << mCurrentRunNumber; + LOG(alarm) << "CFGtag change " << dpid.get_alias() << " : " << dpInfoFedCFGtag << " -> " << o2::dcs::getValue(dpcom) << ", run = " << mCurrentRunNumber; mFedCFGtagAlarmCounter++; } else if (mVerbosity > 0) { - LOG(warn) << "CFGtag change " << dpid.get_alias() << " : " << dpInfoFedCFGtag << " -> " << o2::dcs::getValue(dpcom) << ", run = " << mCurrentRunNumber; + LOG(warn) << "CFGtag change " << dpid.get_alias() << " : " << dpInfoFedCFGtag << " -> " << o2::dcs::getValue(dpcom) << ", run = " << mCurrentRunNumber; } } } diff --git a/Detectors/ZDC/macro/CreateBaselineCalib.C b/Detectors/ZDC/macro/CreateBaselineCalib.C index e6f2be3cb0f93..d04543fb52091 100644 --- a/Detectors/ZDC/macro/CreateBaselineCalib.C +++ b/Detectors/ZDC/macro/CreateBaselineCalib.C @@ -79,7 +79,7 @@ void CreateBaselineCalib(long tmin = 0, long tmax = -1, std::string ccdbHost = " } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/Detectors/ZDC/macro/CreateBaselineCalibConfig.C b/Detectors/ZDC/macro/CreateBaselineCalibConfig.C index be31f65941baa..c2fde8f1ab1a8 100644 --- a/Detectors/ZDC/macro/CreateBaselineCalibConfig.C +++ b/Detectors/ZDC/macro/CreateBaselineCalibConfig.C @@ -48,7 +48,7 @@ void CreateBaselineCalibConfig(long tmin = 0, long tmax = -1, std::string ccdbHo } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/Detectors/ZDC/macro/CreateEnergyCalib.C b/Detectors/ZDC/macro/CreateEnergyCalib.C index 23befda355768..3ff5ff5537cf7 100644 --- a/Detectors/ZDC/macro/CreateEnergyCalib.C +++ b/Detectors/ZDC/macro/CreateEnergyCalib.C @@ -58,7 +58,7 @@ void CreateEnergyCalib(long tmin = 0, long tmax = -1, std::string ccdbHost = "") } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/Detectors/ZDC/macro/CreateInterCalibConfig.C b/Detectors/ZDC/macro/CreateInterCalibConfig.C index 915b55b42d2eb..ce81b7f9ee3b5 100644 --- a/Detectors/ZDC/macro/CreateInterCalibConfig.C +++ b/Detectors/ZDC/macro/CreateInterCalibConfig.C @@ -61,7 +61,7 @@ void CreateInterCalibConfig(long tmin = 0, long tmax = -1, std::string ccdbHost } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/Detectors/ZDC/macro/CreateModuleConfig.C b/Detectors/ZDC/macro/CreateModuleConfig.C index 2d5fde58e3c41..d9d76dd85deb1 100644 --- a/Detectors/ZDC/macro/CreateModuleConfig.C +++ b/Detectors/ZDC/macro/CreateModuleConfig.C @@ -150,7 +150,7 @@ void CreateModuleConfig(long tmin = 0, long tmax = -1, std::string ccdbHost = "" } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/Detectors/ZDC/macro/CreateRecoConfigZDC.C b/Detectors/ZDC/macro/CreateRecoConfigZDC.C index c504241346787..838cd93b944c4 100644 --- a/Detectors/ZDC/macro/CreateRecoConfigZDC.C +++ b/Detectors/ZDC/macro/CreateRecoConfigZDC.C @@ -150,7 +150,7 @@ void CreateRecoConfigZDC(long tmin = 0, long tmax = -1, std::string ccdbHost = " } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/Detectors/ZDC/macro/CreateSimCondition.C b/Detectors/ZDC/macro/CreateSimCondition.C index 6349adbf5b66e..9f29aafc979bb 100644 --- a/Detectors/ZDC/macro/CreateSimCondition.C +++ b/Detectors/ZDC/macro/CreateSimCondition.C @@ -148,7 +148,7 @@ void CreateSimCondition(long tmin = 0, long tmax = -1, std::string ccdbHost = "" } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/Detectors/ZDC/macro/CreateSimCondition_pp.C b/Detectors/ZDC/macro/CreateSimCondition_pp.C index 6d3c530b6772b..f38634ef18fac 100644 --- a/Detectors/ZDC/macro/CreateSimCondition_pp.C +++ b/Detectors/ZDC/macro/CreateSimCondition_pp.C @@ -101,7 +101,7 @@ void CreateSimCondition_pp(long tmin = 0, long tmax = -1, std::string ccdbHost = conf.print(); o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty if (ccdbHost.size() == 0 || ccdbHost == "external") { ccdbHost = "http://alice-ccdb.cern.ch:8080"; } else if (ccdbHost == "internal") { diff --git a/Detectors/ZDC/macro/CreateTDCCalib.C b/Detectors/ZDC/macro/CreateTDCCalib.C index 1591e1e31f699..44e94f84334b1 100644 --- a/Detectors/ZDC/macro/CreateTDCCalib.C +++ b/Detectors/ZDC/macro/CreateTDCCalib.C @@ -63,7 +63,7 @@ void CreateTDCCalib(long tmin = 0, long tmax = -1, std::string ccdbHost = "", fl } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "Storing " << o2::zdc::CCDBPathTDCCalib << " on CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/Detectors/ZDC/macro/CreateTDCCalibConfig.C b/Detectors/ZDC/macro/CreateTDCCalibConfig.C index 4aafbf555f088..2511e4f832add 100644 --- a/Detectors/ZDC/macro/CreateTDCCalibConfig.C +++ b/Detectors/ZDC/macro/CreateTDCCalibConfig.C @@ -60,7 +60,7 @@ void CreateTDCCalibConfig(long tmin = 0, long tmax = -1, std::string ccdbHost = } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/Detectors/ZDC/macro/CreateTDCCorr.C b/Detectors/ZDC/macro/CreateTDCCorr.C index 9c089f532a408..45845dd669a81 100644 --- a/Detectors/ZDC/macro/CreateTDCCorr.C +++ b/Detectors/ZDC/macro/CreateTDCCorr.C @@ -99,7 +99,7 @@ void CreateTDCCorr(long tmin = 0, long tmax = -1, std::string ccdbHost = "") } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/Detectors/ZDC/macro/CreateTowerCalib.C b/Detectors/ZDC/macro/CreateTowerCalib.C index 16e67e448cd65..18e7dc145c154 100644 --- a/Detectors/ZDC/macro/CreateTowerCalib.C +++ b/Detectors/ZDC/macro/CreateTowerCalib.C @@ -75,7 +75,7 @@ void CreateTowerCalib(long tmin = 0, long tmax = -1, std::string ccdbHost = "") } o2::ccdb::CcdbApi api; - map metadata; // can be empty + std::map metadata; // can be empty api.init(ccdb_host.c_str()); LOG(info) << "CCDB server: " << api.getURL(); // store abitrary user object in strongly typed manner diff --git a/EventVisualisation/View/src/EventManagerFrame.cxx b/EventVisualisation/View/src/EventManagerFrame.cxx index 6af49953d7e40..6c9796be94ee0 100644 --- a/EventVisualisation/View/src/EventManagerFrame.cxx +++ b/EventVisualisation/View/src/EventManagerFrame.cxx @@ -398,12 +398,12 @@ void EventManagerFrame::createOutreachScreenshot() if (skipCounter > 0) { skipCounter--; } else { - string fileName = this->mEventManager->getInstance().getDataSource()->getEventName(); + std::string fileName = this->mEventManager->getInstance().getDataSource()->getEventName(); if (fileName.size() < 5) { return; } - string imageFolder = ConfigurationManager::getScreenshotPath("outreach"); + std::string imageFolder = ConfigurationManager::getScreenshotPath("outreach"); if (!std::filesystem::is_directory(imageFolder)) { std::filesystem::create_directory(imageFolder); } diff --git a/GPU/Workflow/src/GPUWorkflowTPC.cxx b/GPU/Workflow/src/GPUWorkflowTPC.cxx index 319d084cbcc6a..a0ed5813d90ca 100644 --- a/GPU/Workflow/src/GPUWorkflowTPC.cxx +++ b/GPU/Workflow/src/GPUWorkflowTPC.cxx @@ -250,14 +250,14 @@ void GPURecoWorkflowSpec::finaliseCCDBTPC(ConcreteDataMatcher& matcher, void* ob } else if (matcher == ConcreteDataMatcher(gDataOriginTPC, "PADGAINRESIDUAL", 0)) { LOGP(info, "Updating residual gain map from CCDB"); copyCalibsToBuffer(); - const auto* gainMapResidual = static_cast>*>(obj); + const auto* gainMapResidual = static_cast>*>(obj); const float minResidualGain = 0.7f; const float maxResidualGain = 1.3f; mdEdxCalibContainerBufferNew.get()->setGainMapResidual(gainMapResidual->at("GainMap"), minResidualGain, maxResidualGain); } else if (matcher == ConcreteDataMatcher(gDataOriginTPC, "PADTHRESHOLD", 0)) { LOGP(info, "Updating threshold map from CCDB"); copyCalibsToBuffer(); - const auto* thresholdMap = static_cast>*>(obj); + const auto* thresholdMap = static_cast>*>(obj); mdEdxCalibContainerBufferNew.get()->setZeroSupresssionThreshold(thresholdMap->at("ThresholdMap")); } else if (matcher == ConcreteDataMatcher(gDataOriginTPC, "TOPOLOGYGAIN", 0) && !(dEdxCalibContainer->isTopologyCorrectionSplinesSet())) { LOGP(info, "Updating Q topology correction from CCDB"); diff --git a/macro/CreateCTPOrbitResetObject.C b/macro/CreateCTPOrbitResetObject.C index 4243ecd9f74d6..65649b5c112b0 100644 --- a/macro/CreateCTPOrbitResetObject.C +++ b/macro/CreateCTPOrbitResetObject.C @@ -17,7 +17,7 @@ void CreateCTPOrbitResetObject(const std::string& ccdbHost = "http://ccdb-test.c const std::string objName{"CTP/Calib/OrbitReset"}; o2::ccdb::CcdbApi api; api.init(ccdbHost.c_str()); // or http://localhost:8080 for a local installation - map metadata; // can be empty + std::map metadata; // can be empty metadata["comment"] = "CTP Orbit reset"; api.storeAsTFileAny(&rt, objName, metadata, tmin, tmax); LOGP(info, "Uploaded CTP Oribt reset time {} to {}", t, objName); diff --git a/macro/UploadDummyAlignment.C b/macro/UploadDummyAlignment.C index f140737098519..a46f5e7f8c61f 100644 --- a/macro/UploadDummyAlignment.C +++ b/macro/UploadDummyAlignment.C @@ -24,7 +24,7 @@ void UploadDummyAlignment(const std::string& ccdbHost = "http://ccdb-test.cern.c if (!dets[id]) { continue; } - map metadata; // can be empty + std::map metadata; // can be empty DetID det(id); metadata["comment"] = fmt::format("Empty alignment object for {}", det.getName()); metadata["default"] = "true"; // tag default objects diff --git a/macro/UploadMatBudLUT.C b/macro/UploadMatBudLUT.C index 8952074336ea5..e452cb06e713f 100644 --- a/macro/UploadMatBudLUT.C +++ b/macro/UploadMatBudLUT.C @@ -21,7 +21,7 @@ bool UploadMatBudLUT(const std::string& matLUTFile, long tmin = 0, long tmax = - o2::ccdb::CcdbApi api; api.init(ccdbHost.c_str()); // or http://localhost:8080 for a local installation - map metadata; // can be empty + std::map metadata; // can be empty metadata["comment"] = "Material lookup table"; api.storeAsTFileAny(lut, url, metadata, tmin, tmax); return true; From c1b57b102085a926fc2b083dffa950cab843a67b Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 18 Jul 2025 13:06:06 +0200 Subject: [PATCH 166/315] Script cleanup: use -n instead of ! -z --- .../full-system-test/aggregator-workflow.sh | 36 +++++------ prodtests/full-system-test/calib-workflow.sh | 22 +++---- .../full-system-test/datadistribution.sh | 4 +- prodtests/full-system-test/dpl-workflow.sh | 64 +++++++++---------- .../run-workflow-on-inputlist.sh | 4 +- prodtests/full-system-test/start_tmux.sh | 2 +- prodtests/full-system-test/tf-reader.sh | 2 +- prodtests/full_system_test.sh | 6 +- 8 files changed, 70 insertions(+), 70 deletions(-) diff --git a/prodtests/full-system-test/aggregator-workflow.sh b/prodtests/full-system-test/aggregator-workflow.sh index 5783bb9a38ad6..bd0c9fea2a31a 100755 --- a/prodtests/full-system-test/aggregator-workflow.sh +++ b/prodtests/full-system-test/aggregator-workflow.sh @@ -145,11 +145,11 @@ fi # adding input proxies if workflow_has_parameter CALIB_PROXIES; then if [[ $AGGREGATOR_TASKS == BARREL_TF ]]; then - if [[ ! -z ${CALIBDATASPEC_BARREL_TF:-} ]]; then + if [[ -n ${CALIBDATASPEC_BARREL_TF:-} ]]; then add_W o2-dpl-raw-proxy "--dataspec \"$CALIBDATASPEC_BARREL_TF\" $(get_proxy_connection barrel_tf input timeframe)" "" 0 fi elif [[ $AGGREGATOR_TASKS == BARREL_SPORADIC ]]; then - if [[ ! -z ${CALIBDATASPEC_BARREL_SPORADIC:-} ]]; then + if [[ -n ${CALIBDATASPEC_BARREL_SPORADIC:-} ]]; then add_W o2-dpl-raw-proxy "--dataspec \"$CALIBDATASPEC_BARREL_SPORADIC\" $(get_proxy_connection barrel_sp input sporadic)" "" 0 fi elif [[ $AGGREGATOR_TASKS == TPC_IDCBOTH_SAC ]]; then @@ -158,7 +158,7 @@ if workflow_has_parameter CALIB_PROXIES; then fi CHANNELS_LIST= [[ $EPNSYNCMODE == 0 ]] && FLP_ADDRESS="tcp://localhost:29950" - if [[ ! -z ${CALIBDATASPEC_TPCIDC_A:-} ]] || [[ ! -z ${CALIBDATASPEC_TPCIDC_C:-} ]]; then + if [[ -n ${CALIBDATASPEC_TPCIDC_A:-} ]] || [[ -n ${CALIBDATASPEC_TPCIDC_C:-} ]]; then # define port for FLP : ${TPC_IDC_FLP_PORT:=29950} # expand FLPs; TPC uses from 001 to 145, but 145 is reserved for SAC @@ -173,47 +173,47 @@ if workflow_has_parameter CALIB_PROXIES; then done fi fi - if [[ ! -z ${CALIBDATASPEC_TPCSAC:-} ]]; then + if [[ -n ${CALIBDATASPEC_TPCSAC:-} ]]; then # define port for FLP [[ -z ${TPC_SAC_FLP_PORT:-} ]] && TPC_SAC_FLP_PORT=29951 [[ $EPNSYNCMODE == 1 ]] && FLP_ADDRESS="tcp://alio2-cr1-flp145-ib:${TPC_SAC_FLP_PORT}" CHANNELS_LIST+="type=pull,name=tpcidc_sac,transport=zeromq,address=$FLP_ADDRESS,method=connect,rateLogging=10;" fi - if [[ ! -z $CHANNELS_LIST ]]; then + if [[ -n $CHANNELS_LIST ]]; then DATASPEC_LIST= - if [[ ! -z ${CALIBDATASPEC_TPCIDC_A:-} ]]; then + if [[ -n ${CALIBDATASPEC_TPCIDC_A:-} ]]; then add_semicolon_separated DATASPEC_LIST "\"$CALIBDATASPEC_TPCIDC_A\"" fi - if [[ ! -z ${CALIBDATASPEC_TPCIDC_C:-} ]]; then + if [[ -n ${CALIBDATASPEC_TPCIDC_C:-} ]]; then add_semicolon_separated DATASPEC_LIST "\"$CALIBDATASPEC_TPCIDC_C\"" fi - if [[ ! -z ${CALIBDATASPEC_TPCSAC:-} ]]; then + if [[ -n ${CALIBDATASPEC_TPCSAC:-} ]]; then add_semicolon_separated DATASPEC_LIST "\"$CALIBDATASPEC_TPCSAC\"" fi add_W o2-dpl-raw-proxy "--proxy-name tpcidc --io-threads 2 --dataspec \"$DATASPEC_LIST\" --sporadic-outputs --channel-config \"$CHANNELS_LIST\" ${TIMEFRAME_SHM_LIMIT+--timeframes-shm-limit} $TIMEFRAME_SHM_LIMIT" "" 0 fi elif [[ $AGGREGATOR_TASKS == CALO_TF ]]; then - if [[ ! -z ${CALIBDATASPEC_CALO_TF:-} ]]; then + if [[ -n ${CALIBDATASPEC_CALO_TF:-} ]]; then add_W o2-dpl-raw-proxy "--dataspec \"$CALIBDATASPEC_CALO_TF\" $(get_proxy_connection calo_tf input timeframe)" "" 0 fi elif [[ $AGGREGATOR_TASKS == CALO_SPORADIC ]]; then - if [[ ! -z ${CALIBDATASPEC_CALO_SPORADIC:-} ]]; then + if [[ -n ${CALIBDATASPEC_CALO_SPORADIC:-} ]]; then add_W o2-dpl-raw-proxy "--dataspec \"$CALIBDATASPEC_CALO_SPORADIC\" $(get_proxy_connection calo_sp input sporadic)" "" 0 fi elif [[ $AGGREGATOR_TASKS == MUON_TF ]]; then - if [[ ! -z ${CALIBDATASPEC_MUON_TF:-} ]]; then + if [[ -n ${CALIBDATASPEC_MUON_TF:-} ]]; then add_W o2-dpl-raw-proxy "--dataspec \"$CALIBDATASPEC_MUON_TF\" $(get_proxy_connection muon_tf input timeframe)" "" 0 fi elif [[ $AGGREGATOR_TASKS == MUON_SPORADIC ]]; then - if [[ ! -z ${CALIBDATASPEC_MUON_SPORADIC:-} ]]; then + if [[ -n ${CALIBDATASPEC_MUON_SPORADIC:-} ]]; then add_W o2-dpl-raw-proxy "--dataspec \"$CALIBDATASPEC_MUON_SPORADIC\" $(get_proxy_connection muon_sp input sporadic)" "" 0 fi elif [[ $AGGREGATOR_TASKS == FORWARD_TF ]]; then - if [[ ! -z ${CALIBDATASPEC_FORWARD_TF:-} ]]; then + if [[ -n ${CALIBDATASPEC_FORWARD_TF:-} ]]; then add_W o2-dpl-raw-proxy "--dataspec \"$CALIBDATASPEC_FORWARD_TF\" $(get_proxy_connection fwd_tf input timeframe)" "" 0 fi elif [[ $AGGREGATOR_TASKS == FORWARD_SPORADIC ]]; then - if [[ ! -z ${CALIBDATASPEC_FORWARD_SPORADIC:-} ]]; then + if [[ -n ${CALIBDATASPEC_FORWARD_SPORADIC:-} ]]; then add_W o2-dpl-raw-proxy "--dataspec \"$CALIBDATASPEC_FORWARD_SPORADIC\" $(get_proxy_connection fwd_sp input sporadic)" "" 0 fi fi @@ -273,7 +273,7 @@ if [[ $AGGREGATOR_TASKS == BARREL_TF ]] || [[ $AGGREGATOR_TASKS == ALL ]]; then if [[ $CALIB_TRD_T0 == 1 ]]; then TRD_CALIB_CONFIG+=" --t0" fi - if [[ ! -z ${TRD_CALIB_CONFIG} ]]; then + if [[ -n ${TRD_CALIB_CONFIG} ]]; then add_W o2-calibration-trd-workflow "${TRD_CALIB_CONFIG}" fi fi @@ -404,13 +404,13 @@ if [[ "${GEN_TOPO_VERBOSE:-}" == "1" ]]; then fi fi -if [[ $CCDB_POPULATOR_UPLOAD_PATH != "none" ]] && [[ ! -z $WORKFLOW ]] && [[ $WORKFLOW != "echo '{}' | " ]]; then add_W o2-calibration-ccdb-populator-workflow "--ccdb-path $CCDB_POPULATOR_UPLOAD_PATH --environment \"DPL_DONT_DROP_OLD_TIMESLICE=1\" --sspec-min $CCDBPRO_SUBSPEC_MIN --sspec-max $CCDBPRO_SUBSPEC_MAX"; fi +if [[ $CCDB_POPULATOR_UPLOAD_PATH != "none" ]] && [[ -n $WORKFLOW ]] && [[ $WORKFLOW != "echo '{}' | " ]]; then add_W o2-calibration-ccdb-populator-workflow "--ccdb-path $CCDB_POPULATOR_UPLOAD_PATH --environment \"DPL_DONT_DROP_OLD_TIMESLICE=1\" --sspec-min $CCDBPRO_SUBSPEC_MIN --sspec-max $CCDBPRO_SUBSPEC_MAX"; fi -if [[ $CCDB_DCS_POPULATOR_UPLOAD_PATH != "none" ]] && [[ ! -z $WORKFLOW ]] && [[ $WORKFLOW != "echo '{}' | " ]] && [[ $NEED_DCS_CCDB_POPULATOR != 0 ]]; then add_W o2-calibration-ccdb-populator-workflow "--ccdb-path $CCDB_DCS_POPULATOR_UPLOAD_PATH --environment \"DPL_DONT_DROP_OLD_TIMESLICE=1\" --sspec-min $CCDBDCS_SUBSPEC_MIN --sspec-max $CCDBDCS_SUBSPEC_MAX --name-extention dcs"; fi +if [[ $CCDB_DCS_POPULATOR_UPLOAD_PATH != "none" ]] && [[ -n $WORKFLOW ]] && [[ $WORKFLOW != "echo '{}' | " ]] && [[ $NEED_DCS_CCDB_POPULATOR != 0 ]]; then add_W o2-calibration-ccdb-populator-workflow "--ccdb-path $CCDB_DCS_POPULATOR_UPLOAD_PATH --environment \"DPL_DONT_DROP_OLD_TIMESLICE=1\" --sspec-min $CCDBDCS_SUBSPEC_MIN --sspec-max $CCDBDCS_SUBSPEC_MAX --name-extention dcs"; fi if ! workflow_has_parameter CALIB_LOCAL_INTEGRATED_AGGREGATOR; then WORKFLOW+="o2-dpl-run $ARGS_ALL $GLOBALDPLOPT" [[ $WORKFLOWMODE != "print" ]] && WORKFLOW+=" --${WORKFLOWMODE} ${WORKFLOWMODE_FILE:-}" [[ $WORKFLOWMODE == "print" || "${PRINT_WORKFLOW:-}" == "1" ]] && echo "#Aggregator Workflow command:\n\n${WORKFLOW}\n" | sed -e "s/\\\\n/\n/g" -e"s/| */| \\\\\n/g" | eval cat $( [[ $WORKFLOWMODE == "dds" ]] && echo '1>&2') - if [[ $WORKFLOWMODE != "print" ]] && [[ ! -z $WORKFLOW ]] && [[ $WORKFLOW != "echo '{}' | " ]]; then eval $WORKFLOW; else true; fi + if [[ $WORKFLOWMODE != "print" ]] && [[ -n $WORKFLOW ]] && [[ $WORKFLOW != "echo '{}' | " ]]; then eval $WORKFLOW; else true; fi fi diff --git a/prodtests/full-system-test/calib-workflow.sh b/prodtests/full-system-test/calib-workflow.sh index 94e95eaab6567..3c05ca6cda303 100755 --- a/prodtests/full-system-test/calib-workflow.sh +++ b/prodtests/full-system-test/calib-workflow.sh @@ -55,14 +55,14 @@ if [[ $CALIB_ASYNC_EXTRACTTPCCURRENTS == 1 ]]; then fi if [[ $CALIB_ASYNC_EXTRACTTIMESERIES == 1 ]] ; then : ${CALIB_ASYNC_SAMPLINGFACTORTIMESERIES:=0.001} - if [[ ! -z ${CALIB_ASYNC_ENABLEUNBINNEDTIMESERIES:-} ]]; then + if [[ -n ${CALIB_ASYNC_ENABLEUNBINNEDTIMESERIES:-} ]]; then CONFIG_TPCTIMESERIES+=" --enable-unbinned-root-output --sample-unbinned-tsallis --threads ${TPCTIMESERIES_THREADS:-1}" fi - if [[ $ON_SKIMMED_DATA == 1 ]] || [[ ! -z "$CALIB_ASYNC_SAMPLINGFACTORTIMESERIES" ]]; then + if [[ $ON_SKIMMED_DATA == 1 ]] || [[ -n "$CALIB_ASYNC_SAMPLINGFACTORTIMESERIES" ]]; then if [[ $ON_SKIMMED_DATA == 1 ]]; then SAMPLINGFACTORTIMESERIES=0.1 fi - if [[ ! -z "$CALIB_ASYNC_SAMPLINGFACTORTIMESERIES" ]]; then # this takes priority, even if we were on skimmed data + if [[ -n "$CALIB_ASYNC_SAMPLINGFACTORTIMESERIES" ]]; then # this takes priority, even if we were on skimmed data SAMPLINGFACTORTIMESERIES=${CALIB_ASYNC_SAMPLINGFACTORTIMESERIES} fi CONFIG_TPCTIMESERIES+=" --sampling-factor ${SAMPLINGFACTORTIMESERIES}" @@ -74,28 +74,28 @@ fi # output-proxy for aggregator if workflow_has_parameter CALIB_PROXIES; then - if [[ ! -z ${CALIBDATASPEC_BARREL_TF:-} ]]; then + if [[ -n ${CALIBDATASPEC_BARREL_TF:-} ]]; then add_W o2-dpl-output-proxy "--dataspec \"$CALIBDATASPEC_BARREL_TF\" $(get_proxy_connection barrel_tf output timeframe)" "" 0 fi - if [[ ! -z ${CALIBDATASPEC_BARREL_SPORADIC:-} ]]; then + if [[ -n ${CALIBDATASPEC_BARREL_SPORADIC:-} ]]; then add_W o2-dpl-output-proxy "--dataspec \"$CALIBDATASPEC_BARREL_SPORADIC\" $(get_proxy_connection barrel_sp output sporadic)" "" 0 fi - if [[ ! -z ${CALIBDATASPEC_CALO_TF:-} ]]; then + if [[ -n ${CALIBDATASPEC_CALO_TF:-} ]]; then add_W o2-dpl-output-proxy "--dataspec \"$CALIBDATASPEC_CALO_TF\" $(get_proxy_connection calo_tf output timeframe)" "" 0 fi - if [[ ! -z ${CALIBDATASPEC_CALO_SPORADIC:-} ]]; then + if [[ -n ${CALIBDATASPEC_CALO_SPORADIC:-} ]]; then add_W o2-dpl-output-proxy "--dataspec \"$CALIBDATASPEC_CALO_SPORADIC\" $(get_proxy_connection calo_sp output sporadic)" "" 0 fi - if [[ ! -z ${CALIBDATASPEC_MUON_TF:-} ]]; then + if [[ -n ${CALIBDATASPEC_MUON_TF:-} ]]; then add_W o2-dpl-output-proxy "--dataspec \"$CALIBDATASPEC_MUON_TF\" $(get_proxy_connection muon_tf output timeframe)" "" 0 fi - if [[ ! -z ${CALIBDATASPEC_MUON_SPORADIC:-} ]]; then + if [[ -n ${CALIBDATASPEC_MUON_SPORADIC:-} ]]; then add_W o2-dpl-output-proxy "--dataspec \"$CALIBDATASPEC_MUON_SPORADIC\" $(get_proxy_connection muon_sp output sporadic)" "" 0 fi - if [[ ! -z ${CALIBDATASPEC_FORWARD_TF:-} ]]; then + if [[ -n ${CALIBDATASPEC_FORWARD_TF:-} ]]; then add_W o2-dpl-output-proxy "--dataspec \"$CALIBDATASPEC_FORWARD_TF\" $(get_proxy_connection fwd_tf output timeframe)" "" 0 fi - if [[ ! -z ${CALIBDATASPEC_FORWARD_SPORADIC:-} ]]; then + if [[ -n ${CALIBDATASPEC_FORWARD_SPORADIC:-} ]]; then add_W o2-dpl-output-proxy "--dataspec \"$CALIBDATASPEC_FORWARD_SPORADIC\" $(get_proxy_connection fwd_sp output sporadic)" "" 0 fi fi diff --git a/prodtests/full-system-test/datadistribution.sh b/prodtests/full-system-test/datadistribution.sh index 40fda852a7a6e..657d38b954583 100755 --- a/prodtests/full-system-test/datadistribution.sh +++ b/prodtests/full-system-test/datadistribution.sh @@ -11,7 +11,7 @@ fi # For benchmark only, do NOT copy&paste! [[ $NUMAGPUIDS == 1 ]] && [[ -z $SHM_MANAGER_SHMID ]] && export DATADIST_SHM_DELAY=10 -if [[ ! -z $DD_STARTUP_DELAY ]]; then +if [[ -n $DD_STARTUP_DELAY ]]; then sleep $DD_STARTUP_DELAY fi @@ -34,7 +34,7 @@ export TFRATE=$(awk "BEGIN {printf \"%.6f\",1/$TFDELAY}") ARGS_ALL="--session ${OVERRIDE_SESSION:-default} --severity $SEVERITY --shm-segment-id 2 --shm-segment-size 1000000 --no-cleanup" -[[ ! -z $SHM_MANAGER_SHMID ]] && SHM_TOOL_OPTIONS=" --shmid $SHM_MANAGER_SHMID --data-source-region-shmid 100 --data-source-header-shmid 101" +[[ -n $SHM_MANAGER_SHMID ]] && SHM_TOOL_OPTIONS=" --shmid $SHM_MANAGER_SHMID --data-source-region-shmid 100 --data-source-header-shmid 101" eval StfBuilder --id stfb --discovery-partition FST --transport shmem \ --dpl-channel-name dpl-chan --channel-config "name=dpl-chan,type=push,method=bind,address=ipc://${UDS_PREFIX}${INRAWCHANNAME},transport=shmem,rateLogging=1" \ diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 486be1a9160cd..55186dbff9c84 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -61,10 +61,10 @@ if [[ -z ${TIMEFRAME_RATE_LIMIT:-} ]] && [[ $DIGITINPUT != 1 ]]; then TIMEFRAME_RATE_LIMIT=$((12 * 230 / ${RECO_NUM_NODES_WORKFLOW_CMP} * ($NUMAGPUIDS != 0 ? 1 : 2) * 128 / $NHBPERTF)) [[ $BEAMTYPE != "PbPb" && ${HIGH_RATE_PP:-0} == 0 ]] && TIMEFRAME_RATE_LIMIT=$(($TIMEFRAME_RATE_LIMIT * 3)) ! has_detector TPC && TIMEFRAME_RATE_LIMIT=$(($TIMEFRAME_RATE_LIMIT * 4)) - [[ ! -z ${EPN_GLOBAL_SCALING:-} ]] && TIMEFRAME_RATE_LIMIT=$(($TIMEFRAME_RATE_LIMIT * $EPN_GLOBAL_SCALING)) + [[ -n ${EPN_GLOBAL_SCALING:-} ]] && TIMEFRAME_RATE_LIMIT=$(($TIMEFRAME_RATE_LIMIT * $EPN_GLOBAL_SCALING)) [[ ${TIMEFRAME_RATE_LIMIT} -ge 512 ]] && TIMEFRAME_RATE_LIMIT=512 fi -[[ ! -z ${TIMEFRAME_RATE_LIMIT:-} ]] && [[ $TIMEFRAME_RATE_LIMIT != 0 ]] && ARGS_ALL+=" --timeframes-rate-limit $TIMEFRAME_RATE_LIMIT --timeframes-rate-limit-ipcid ${O2JOBID:-$NUMAID}" +[[ -n ${TIMEFRAME_RATE_LIMIT:-} ]] && [[ $TIMEFRAME_RATE_LIMIT != 0 ]] && ARGS_ALL+=" --timeframes-rate-limit $TIMEFRAME_RATE_LIMIT --timeframes-rate-limit-ipcid ${O2JOBID:-$NUMAID}" if [[ $EPNSYNCMODE == 1 ]]; then SYNCRAWMODE=1 elif [[ -z ${SYNCRAWMODE:-} ]]; then @@ -125,7 +125,7 @@ if [[ $SYNCMODE == 1 ]]; then MCH_CONFIG_KEY="MCHTracking.maxCandidates=20000;MCHTracking.maxTrackingDuration=10;" MFT_CONFIG_KEY+="MFTTracking.cutMultClusLow=0;MFTTracking.cutMultClusHigh=3000;" fi - [[ ! -z ${CUT_RANDOM_FRACTION_ITS:-} ]] && ITS_CONFIG_KEY+="fastMultConfig.cutRandomFraction=$CUT_RANDOM_FRACTION_ITS;" + [[ -n ${CUT_RANDOM_FRACTION_ITS:-} ]] && ITS_CONFIG_KEY+="fastMultConfig.cutRandomFraction=$CUT_RANDOM_FRACTION_ITS;" ITS_CONFIG_KEY+="ITSCATrackerParam.trackletsPerClusterLimit=${CUT_TRACKLETSPERCLUSTER_MAX_ITS:--1};ITSCATrackerParam.cellsPerClusterLimit=${CUT_CELLSPERCLUSTER_MAX_ITS:--1};" if has_detector_reco ITS; then [[ $RUNTYPE != "COSMICS" ]] && MFT_CONFIG_KEY+="MFTTracking.irFramesOnly=1;" @@ -161,9 +161,9 @@ else fi fi [[ $CTFINPUT == 1 ]] && GPU_CONFIG_KEY+="GPU_proc.tpcInputWithClusterRejection=1;" -[[ ! -z $NTRDTRKTHREADS ]] && TRD_CONFIG_KEY+="GPU_proc.ompThreads=$NTRDTRKTHREADS;" -[[ ! -z $NGPURECOTHREADS ]] && GPU_CONFIG_KEY+="GPU_proc.ompThreads=$NGPURECOTHREADS;" -[[ ! -z $NMFTTHREADS ]] && MFT_CONFIG+=" --nThreads $NMFTTHREADS" +[[ -n $NTRDTRKTHREADS ]] && TRD_CONFIG_KEY+="GPU_proc.ompThreads=$NTRDTRKTHREADS;" +[[ -n $NGPURECOTHREADS ]] && GPU_CONFIG_KEY+="GPU_proc.ompThreads=$NGPURECOTHREADS;" +[[ -n $NMFTTHREADS ]] && MFT_CONFIG+=" --nThreads $NMFTTHREADS" [[ $ITSTRK_THREADS != 1 ]] && ITS_CONFIG_KEY+="ITSVertexerParam.nThreads=$ITSTRK_THREADS;ITSCATrackerParam.nThreads=$ITSTRK_THREADS;" if [[ $BEAMTYPE == "PbPb" ]]; then @@ -185,7 +185,7 @@ else fi if [[ $SYNCMODE == 1 ]] && [[ ${PRESCALE_ITS_WO_TRIGGER:-} != 1 ]]; then - if has_detector TRD && [[ ! -z ${PRESCALE_ITS_WITH_TRD:-} ]]; then + if has_detector TRD && [[ -n ${PRESCALE_ITS_WITH_TRD:-} ]]; then ITS_CONFIG+=" --select-with-triggers trd " else ITS_CONFIG+=" --select-with-triggers phys " @@ -248,7 +248,7 @@ if [[ $SYNCMODE == 1 && "0${ED_NO_ITS_ROF_FILTER:-}" != "01" && $BEAMTYPE == "Pb EVE_CONFIG+=";eveconf.filterITSROF=true;" fi -if [[ ! -z ${EVE_NTH_EVENT:-} ]]; then +if [[ -n ${EVE_NTH_EVENT:-} ]]; then EVE_CONFIG+=";eveconf.onlyNthEvent=$EVE_NTH_EVENT;" fi @@ -275,13 +275,13 @@ if [[ $GPUTYPE == "HIP" ]]; then GPU_CONFIG+=" --environment \"ROCR_VISIBLE_DEVICES={timeslice${TIMESLICEOFFSET}}\"" fi # serialization workaround for MI100 nodes: remove it again if the problem will be fixed in ROCm, then also remove the DISABLE_MI100_SERIALIZATION flag in the O2DPG parse script - [[ $EPNSYNCMODE == 1 || ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]] && [[ ${EPN_NODE_MI100:-} == "1" ]] && [[ ${DISABLE_MI100_SERIALIZATION:-0} != 1 ]] && GPU_CONFIG_KEY+="GPU_proc.amdMI100SerializationWorkaround=1;" + [[ $EPNSYNCMODE == 1 || -n ${OPTIMIZED_PARALLEL_ASYNC:-} ]] && [[ ${EPN_NODE_MI100:-} == "1" ]] && [[ ${DISABLE_MI100_SERIALIZATION:-0} != 1 ]] && GPU_CONFIG_KEY+="GPU_proc.amdMI100SerializationWorkaround=1;" #export HSA_TOOLS_LIB=/opt/rocm/lib/librocm-debug-agent.so.2 else GPU_CONFIG_KEY+="GPU_proc.deviceNum=-2;" fi -if [[ ! -z ${GPU_NUM_MEM_REG_CALLBACKS:-} ]]; then +if [[ -n ${GPU_NUM_MEM_REG_CALLBACKS:-} ]]; then GPU_CONFIG+=" --expected-region-callbacks $GPU_NUM_MEM_REG_CALLBACKS" fi @@ -352,7 +352,7 @@ fi ( workflow_has_parameter AOD || [[ -z "$DISABLE_ROOT_OUTPUT" ]] || needs_root_output o2-emcal-cell-writer-workflow ) && has_detector EMC && RAW_EMC_SUBSPEC=" --subspecification 1 " has_detector_reco MID && has_detector_matching MCHMID && MFTMCHConf="FwdMatching.useMIDMatch=true;" || MFTMCHConf="FwdMatching.useMIDMatch=false;" -[[ ! -z ${MFTMCH_NCANDIDATES_OPT:-} ]] && MFTMCHConf+="${MFTMCH_NCANDIDATES_OPT}" +[[ -n ${MFTMCH_NCANDIDATES_OPT:-} ]] && MFTMCHConf+="${MFTMCH_NCANDIDATES_OPT}" [[ $IS_SIMULATED_DATA == "1" ]] && EMCRAW2C_CONFIG+=" --no-checkactivelinks" @@ -368,12 +368,12 @@ if has_processing_step MUON_SYNC_RECO; then MCH_CONFIG_KEY+="MCHTracking.chamberResolutionX=0.4;MCHTracking.chamberResolutionY=0.4;MCHTracking.sigmaCutForTracking=7.;MCHTracking.sigmaCutForImprovement=6.;" fi has_detector_reco ITS && [[ $RUNTYPE != "COSMICS" ]] && MCH_CONFIG_KEY+="MCHTimeClusterizer.irFramesOnly=true;" - [[ ! -z ${CUT_RANDOM_FRACTION_MCH:-} ]] && MCH_CONFIG_KEY+="MCHTimeClusterizer.rofRejectionFraction=$CUT_RANDOM_FRACTION_MCH;" + [[ -n ${CUT_RANDOM_FRACTION_MCH:-} ]] && MCH_CONFIG_KEY+="MCHTimeClusterizer.rofRejectionFraction=$CUT_RANDOM_FRACTION_MCH;" MCH_CONFIG_KEY+="MCHStatusMap.useHV=false;MCHDigitFilter.statusMask=3;" [[ $RUNTYPE == "COSMICS" ]] && [[ -z ${CONFIG_EXTRA_PROCESS_o2_mft_reco_workflow:-} ]] && CONFIG_EXTRA_PROCESS_o2_mft_reco_workflow="MFTTracking.FullClusterScan=true" fi [[ $SYNCRAWMODE == 1 ]] && [[ -z ${CONFIG_EXTRA_PROCESS_o2_zdc_digits_reco:-} ]] && CONFIG_EXTRA_PROCESS_o2_zdc_digits_reco='RecoParamZDC.tdc_calib[9]=1;RecoParamZDC.tdc_calib[0]=1;RecoParamZDC.tdc_calib[8]=1;RecoParamZDC.tdc_calib[1]=1;RecoParamZDC.tdc_calib[3]=1;RecoParamZDC.tdc_calib[6]=1;RecoParamZDC.tdc_calib[5]=1;RecoParamZDC.tdc_calib[4]=1;RecoParamZDC.tdc_calib[2]=1;RecoParamZDC.tdc_calib[7]=1;RecoParamZDC.energy_calib[13]=1;RecoParamZDC.energy_calib[12]=1;RecoParamZDC.energy_calib[11]=1;RecoParamZDC.energy_calib[6]=1;RecoParamZDC.energy_calib[25]=1;RecoParamZDC.energy_calib[14]=1;RecoParamZDC.energy_calib[20]=1;RecoParamZDC.energy_calib[5]=1;RecoParamZDC.energy_calib[0]=1;RecoParamZDC.energy_calib[19]=1;RecoParamZDC.tower_calib[1]=1;RecoParamZDC.tower_calib[2]=1;RecoParamZDC.tower_calib[3]=1;RecoParamZDC.tower_calib[4]=1;RecoParamZDC.tower_calib[24]=1;RecoParamZDC.tower_calib[21]=1;RecoParamZDC.tower_calib[22]=1;RecoParamZDC.tower_calib[23]=1;RecoParamZDC.tower_calib[18]=1;RecoParamZDC.tower_calib[16]=1;RecoParamZDC.tower_calib[17]=1;RecoParamZDC.tower_calib[15]=1;RecoParamZDC.tower_calib[8]=1;RecoParamZDC.tower_calib[9]=1;RecoParamZDC.tower_calib[7]=1;RecoParamZDC.tower_calib[10]=1' -[[ $RUNTYPE != "COSMICS" ]] && [[ $RUNTYPE != "TECHNICAL" ]] && has_detectors_reco ITS && has_detector_matching PRIMVTX && [[ ! -z "$VERTEXING_SOURCES" ]] && EVE_CONFIG+=";eveconf.PVMode=true;" +[[ $RUNTYPE != "COSMICS" ]] && [[ $RUNTYPE != "TECHNICAL" ]] && has_detectors_reco ITS && has_detector_matching PRIMVTX && [[ -n "$VERTEXING_SOURCES" ]] && EVE_CONFIG+=";eveconf.PVMode=true;" [[ $SYNCRAWMODE == 1 ]] && [[ -z ${CONFIG_EXTRA_PROCESS_o2_trd_global_tracking:-} ]] && CONFIG_EXTRA_PROCESS_o2_trd_global_tracking='GPU_rec_trd.maxChi2=25;GPU_rec_trd.penaltyChi2=20;GPU_rec_trd.extraRoadY=4;GPU_rec_trd.extraRoadZ=10;GPU_rec_trd.applyDeflectionCut=0;GPU_rec_trd.trkltResRPhiIdeal=1' [[ $SYNCRAWMODE == 1 ]] && [[ -z ${ARGS_EXTRA_PROCESS_o2_phos_reco_workflow:-} ]] && ARGS_EXTRA_PROCESS_o2_phos_reco_workflow='--presamples 2 --fitmethod semigaus' [[ $SYNCRAWMODE == 1 ]] && [[ $BEAMTYPE == "PbPb" ]] && [[ -z ${CONFIG_EXTRA_PROCESS_o2_calibration_emcal_channel_calib_workflow:-} ]] && CONFIG_EXTRA_PROCESS_o2_calibration_emcal_channel_calib_workflow='EMCALCalibParams.selectedClassMasks=C0TVX-NONE-NOPF-EMC:c0tvxtsc-b-nopf-emc:C0TVXTCE-B-NOPF-EMC;EMCALCalibParams.fractionEvents_bc=0.3' @@ -390,7 +390,7 @@ INPUT_DETECTOR_LIST=$WORKFLOW_DETECTORS : ${GLOBAL_READER_OPTIONS:=} : ${GLOBAL_READER_NEEDS_PV:=} : ${GLOBAL_READER_NEEDS_SV:=} -if [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS} ]]; then +if [[ -n ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ -n ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS} ]]; then for i in ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS//,/ }; do export INPUT_DETECTOR_LIST=$(echo $INPUT_DETECTOR_LIST | sed -e "s/,$i,/,/g" -e "s/^$i,//" -e "s/,$i"'$'"//" -e "s/^$i"'$'"//") done @@ -402,7 +402,7 @@ if [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ ! -z ${WORKFL [[ $GLOBAL_READER_NEEDS_PV == 1 ]] && GLOBAL_READER_OPTIONS+=" --primary-vertices" [[ $GLOBAL_READER_NEEDS_SV == 1 ]] && GLOBAL_READER_OPTIONS+=" --secondary-vertices" - if [[ ! -z ${TIMEFRAME_RATE_LIMIT:-} ]] && [[ $TIMEFRAME_RATE_LIMIT != 0 ]]; then + if [[ -n ${TIMEFRAME_RATE_LIMIT:-} ]] && [[ $TIMEFRAME_RATE_LIMIT != 0 ]]; then HBFINI_OPTIONS=" --hbfutils-config o2_tfidinfo.root,upstream " add_W o2-reader-driver-workflow "$HBFINI_OPTIONS" else @@ -417,17 +417,17 @@ if [[ ! -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ ! -z ${WORKFL has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-clusters-reader-workflow "$HBFINI_OPTIONS" "" 0 has_detector MCH && has_detector_from_global_reader MCH && add_W o2-mch-preclusters-reader-workflow "$HBFINI_OPTIONS" "" 0 has_detector TRD && has_detector_from_global_reader TRD && add_W o2-trd-digit-reader-workflow "$DISABLE_MC --digit-subspec 0 --disable-trigrec $HBFINI_OPTIONS" - has_detector TRD && has_detector_from_global_reader TRD && [[ ! -z "$TRD_SOURCES" ]] && has_detector_from_global_reader_tracks "$(echo "$TRD_SOURCES" | cut -d',' -f1)-TRD" && add_W o2-trd-calib-reader-workflow "--trd-calib-infile trdcaliboutput.root $HBFINI_OPTIONS" + has_detector TRD && has_detector_from_global_reader TRD && [[ -n "$TRD_SOURCES" ]] && has_detector_from_global_reader_tracks "$(echo "$TRD_SOURCES" | cut -d',' -f1)-TRD" && add_W o2-trd-calib-reader-workflow "--trd-calib-infile trdcaliboutput.root $HBFINI_OPTIONS" has_detector TOF && has_detector_from_global_reader TOF && add_W o2-tof-reco-workflow "$DISABLE_MC --input-type digits --output-type NONE $HBFINI_OPTIONS" fi -if [[ ! -z $INPUT_DETECTOR_LIST ]]; then +if [[ -n $INPUT_DETECTOR_LIST ]]; then if [[ $CTFINPUT == 1 ]]; then GPU_INPUT=compressed-clusters-ctf TOF_INPUT=digits CTFName=`ls -t $RAWINPUTDIR/o2_ctf_*.root 2> /dev/null | head -n1` [[ -z $CTFName && $WORKFLOWMODE == "print" ]] && CTFName='$CTFName' - [[ ! -z ${INPUT_FILE_LIST:-} ]] && CTFName=$INPUT_FILE_LIST + [[ -n ${INPUT_FILE_LIST:-} ]] && CTFName=$INPUT_FILE_LIST if [[ -z $CTFName && $WORKFLOWMODE != "print" ]]; then echo "No CTF file given!"; exit 1; fi if [[ $NTIMEFRAMES == -1 ]]; then NTIMEFRAMES_CMD= ; else NTIMEFRAMES_CMD="--max-tf $NTIMEFRAMES"; fi CTF_EMC_SUBSPEC= @@ -436,7 +436,7 @@ if [[ ! -z $INPUT_DETECTOR_LIST ]]; then elif [[ $RAWTFINPUT == 1 ]]; then TFName=`ls -t $RAWINPUTDIR/o2_*.tf 2> /dev/null | head -n1` [[ -z $TFName && $WORKFLOWMODE == "print" ]] && TFName='$TFName' - [[ ! -z ${INPUT_FILE_LIST:-} ]] && TFName=$INPUT_FILE_LIST + [[ -n ${INPUT_FILE_LIST:-} ]] && TFName=$INPUT_FILE_LIST if [[ -z $TFName && $WORKFLOWMODE != "print" ]]; then echo "No raw file given!"; exit 1; fi if [[ $NTIMEFRAMES == -1 ]]; then NTIMEFRAMES_CMD= ; else NTIMEFRAMES_CMD="--max-tf $NTIMEFRAMES"; fi if [[ -z $WORKFLOW_DETECTORS_FLP_PROCESSING || $WORKFLOW_DETECTORS_FLP_PROCESSING == "NONE" ]]; then @@ -479,7 +479,7 @@ if [[ ! -z $INPUT_DETECTOR_LIST ]]; then PROXY_INSPEC+=";$PROXY_INNAME:$i/$j" done done - [[ ! -z ${TIMEFRAME_RATE_LIMIT:-} ]] && [[ $TIMEFRAME_RATE_LIMIT != 0 ]] && PROXY_CHANNEL+=";name=metric-feedback,type=pull,method=connect,address=ipc://${UDS_PREFIX}metric-feedback-${O2JOBID:-$NUMAID},transport=shmem,rateLogging=0" + [[ -n ${TIMEFRAME_RATE_LIMIT:-} ]] && [[ $TIMEFRAME_RATE_LIMIT != 0 ]] && PROXY_CHANNEL+=";name=metric-feedback,type=pull,method=connect,address=ipc://${UDS_PREFIX}metric-feedback-${O2JOBID:-$NUMAID},transport=shmem,rateLogging=0" if [[ $EPNSYNCMODE == 1 ]]; then RAWPROXY_CONFIG="--print-input-sizes 1000" else @@ -505,7 +505,7 @@ fi if [[ -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] && [[ -z ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS} ]]; then # if root output is requested, record info of processed TFs DataHeader for replay of root files ROOT_OUTPUT_ASKED=`declare -p | cut -d' ' -f3 | cut -d'=' -f1 | grep ENABLE_ROOT_OUTPUT_` - [[ -z "$DISABLE_ROOT_OUTPUT" ]] || [[ ! -z $ROOT_OUTPUT_ASKED ]] && add_W o2-tfidinfo-writer-workflow + [[ -z "$DISABLE_ROOT_OUTPUT" ]] || [[ -n $ROOT_OUTPUT_ASKED ]] && add_W o2-tfidinfo-writer-workflow fi # if TPC correction with IDC from CCDB was requested @@ -551,8 +551,8 @@ fi has_detector_reco FT0 && ! has_detector_from_global_reader FT0 && add_W o2-ft0-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N ft0-reconstructor FT0 REST 1)" has_detector_reco TRD && ! has_detector_from_global_reader TRD && add_W o2-trd-tracklet-transformer "--disable-irframe-reader $DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TRD_FILTER_CONFIG --pipeline $(get_N TRDTRACKLETTRANSFORMER TRD REST 1 TRDTRKTRANS)" has_detectors_reco ITS TPC && ! has_detector_from_global_reader_tracks ITS-TPC && has_detector_matching ITSTPC && add_W o2-tpcits-match-workflow "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $SEND_ITSTPC_DTGL $TPC_CORR_OPT --nthreads $ITSTPC_THREADS --pipeline $(get_N itstpc-track-matcher MATCH REST $ITSTPC_THREADS TPCITS)" "$ITSTPC_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" -has_detector_reco TRD && [[ ! -z "$TRD_SOURCES" ]] && ! has_detector_from_global_reader_tracks "$(echo "$TRD_SOURCES" | cut -d',' -f1)-TRD" && add_W o2-trd-global-tracking "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TRD_CONFIG $TRD_FILTER_CONFIG $TPC_CORR_OPT --track-sources $TRD_SOURCES --pipeline $(get_N trd-globaltracking_TPC_ITS-TPC_ TRD REST 1 TRDTRK),$(get_N trd-globaltracking_TPC_FT0_ITS-TPC_ TRD REST 1 TRDTRK),$(get_N trd-globaltracking_TPC_FT0_ITS-TPC_CTP_ TRD REST 1 TRDTRK)" "$TRD_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" -has_detector_reco TOF && [[ ! -z "$TOF_SOURCES" ]] && ! has_detector_from_global_reader_tracks "$(echo "$TOF_SOURCES" | cut -d',' -f1)-TOF" && add_W o2-tof-matcher-workflow "$TOF_MATCH_OPT $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TPC_CORR_OPT ${TOFMATCH_THREADS:+--tof-lanes ${TOFMATCH_THREADS}} --track-sources $TOF_SOURCES --pipeline $(get_N tof-matcher TOF REST 1 TOFMATCH)" "$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" +has_detector_reco TRD && [[ -n "$TRD_SOURCES" ]] && ! has_detector_from_global_reader_tracks "$(echo "$TRD_SOURCES" | cut -d',' -f1)-TRD" && add_W o2-trd-global-tracking "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TRD_CONFIG $TRD_FILTER_CONFIG $TPC_CORR_OPT --track-sources $TRD_SOURCES --pipeline $(get_N trd-globaltracking_TPC_ITS-TPC_ TRD REST 1 TRDTRK),$(get_N trd-globaltracking_TPC_FT0_ITS-TPC_ TRD REST 1 TRDTRK),$(get_N trd-globaltracking_TPC_FT0_ITS-TPC_CTP_ TRD REST 1 TRDTRK)" "$TRD_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" +has_detector_reco TOF && [[ -n "$TOF_SOURCES" ]] && ! has_detector_from_global_reader_tracks "$(echo "$TOF_SOURCES" | cut -d',' -f1)-TOF" && add_W o2-tof-matcher-workflow "$TOF_MATCH_OPT $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TPC_CORR_OPT ${TOFMATCH_THREADS:+--tof-lanes ${TOFMATCH_THREADS}} --track-sources $TOF_SOURCES --pipeline $(get_N tof-matcher TOF REST 1 TOFMATCH)" "$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" has_detectors TPC && [[ -z "$DISABLE_ROOT_OUTPUT" && "${SKIP_TPC_CLUSTERSTRACKS_OUTPUT:-}" != 1 ]] && ! has_detector_from_global_reader TPC && add_W o2-tpc-reco-workflow "--input-type pass-through --output-type clusters,tpc-triggers,tracks,send-clusters-per-sector $DISABLE_MC" # --------------------------------------------------------------------------------------------------------------------- @@ -564,7 +564,7 @@ has_detector FDD && ! has_detector_from_global_reader FDD && has_processing_step has_detector FV0 && ! has_detector_from_global_reader FV0 && has_processing_step FV0_RECO && add_W o2-fv0-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" has_detector ZDC && ! has_detector_from_global_reader ZDC && has_processing_step ZDC_RECO && add_W o2-zdc-digits-reco "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" has_detector HMP && ! has_detector_from_global_reader HMP && has_processing_step HMP_RECO && add_W o2-hmpid-digits-to-clusters-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT --pipeline $(get_N HMP-Clusterization HMP REST 1 HMPCLUS)" -has_detector HMP && [[ ! -z "$HMP_SOURCES" ]] && has_detector_matching HMP && ! has_detector_from_global_reader_tracks HMP && add_W o2-hmpid-matcher-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --track-sources $HMP_SOURCES --pipeline $(get_N hmp-matcher HMP REST 1 HMPMATCH)" +has_detector HMP && [[ -n "$HMP_SOURCES" ]] && has_detector_matching HMP && ! has_detector_from_global_reader_tracks HMP && add_W o2-hmpid-matcher-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --track-sources $HMP_SOURCES --pipeline $(get_N hmp-matcher HMP REST 1 HMPMATCH)" has_detectors_reco MCH MID && has_detector_matching MCHMID && ! has_detector_from_global_reader_tracks "MCH-MID" && add_W o2-muon-tracks-matcher-workflow "$DISABLE_ROOT_INPUT $DISABLE_MC $DISABLE_ROOT_OUTPUT --pipeline $(get_N muon-track-matcher MATCH REST 1)" has_detectors_reco MFT MCH && has_detector_matching MFTMCH && ! has_detector_from_global_reader_tracks "MFT-MCH" && add_W o2-globalfwd-matcher-workflow "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N globalfwd-track-matcher MATCH REST 1 FWDMATCH)" "$MFTMCHConf" @@ -595,9 +595,9 @@ has_detector_reco ITS && has_detector_gpu ITS TPC && [[ -z "$DISABLE_ROOT_OUTPUT # always run vertexing if requested and if there are some sources, but in cosmic mode we work in pass-trough mode (create record for non-associated tracks) ( [[ $BEAMTYPE == "cosmic" ]] || ! has_detector_reco ITS) && PVERTEX_CONFIG+=" --skip" -has_detector_matching PRIMVTX && [[ ! -z "$VERTEXING_SOURCES" ]] && [[ $GLOBAL_READER_NEEDS_PV != 1 ]] && add_W o2-primary-vertexing-workflow "$DISABLE_MC $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $PVERTEX_CONFIG --pipeline $(get_N primary-vertexing MATCH REST 1 PRIMVTX),$(get_N pvertex-track-matching MATCH REST 1 PRIMVTXMATCH)" "${PVERTEXING_CONFIG_KEY};${INTERACTION_TAG_CONFIG_KEY};" +has_detector_matching PRIMVTX && [[ -n "$VERTEXING_SOURCES" ]] && [[ $GLOBAL_READER_NEEDS_PV != 1 ]] && add_W o2-primary-vertexing-workflow "$DISABLE_MC $DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $PVERTEX_CONFIG --pipeline $(get_N primary-vertexing MATCH REST 1 PRIMVTX),$(get_N pvertex-track-matching MATCH REST 1 PRIMVTXMATCH)" "${PVERTEXING_CONFIG_KEY};${INTERACTION_TAG_CONFIG_KEY};" -if [[ $BEAMTYPE != "cosmic" ]] && has_detectors_reco ITS && has_detector_matching SECVTX && [[ ! -z "$SVERTEXING_SOURCES" ]]; then +if [[ $BEAMTYPE != "cosmic" ]] && has_detectors_reco ITS && has_detector_matching SECVTX && [[ -n "$SVERTEXING_SOURCES" ]]; then : ${REDUCESV_OPT:=} : ${REDUCESV_CONF:=} if [[ $SYNCMODE == 1 ]] && [[ $SECVTXK0ONLY != 0 ]] ; then @@ -613,7 +613,7 @@ fi # --------------------------------------------------------------------------------------------------------------------- # Entropy encoding / ctf creation workflows - disabled in async mode -if has_processing_step ENTROPY_ENCODER && [[ ! -z "$WORKFLOW_DETECTORS_CTF" ]] && [[ $WORKFLOW_DETECTORS_CTF != "NONE" ]]; then +if has_processing_step ENTROPY_ENCODER && [[ -n "$WORKFLOW_DETECTORS_CTF" ]] && [[ $WORKFLOW_DETECTORS_CTF != "NONE" ]]; then # Entropy encoder workflows has_detector_ctf MFT && add_W o2-itsmft-entropy-encoder-workflow "$RANS_OPT --mem-factor ${MFT_ENC_MEMFACT:-1.5} --runmft true --pipeline $(get_N mft-entropy-encoder MFT CTF 1)" has_detector_ctf FT0 && add_W o2-ft0-entropy-encoder-workflow "$RANS_OPT --mem-factor ${FT0_ENC_MEMFACT:-1.5} --pipeline $(get_N ft0-entropy-encoder FT0 CTF 1)" @@ -660,7 +660,7 @@ workflow_has_parameters CALIB CALIB_LOCAL_INTEGRATED_AGGREGATOR && { source ${CA # RS this is a temporary setting : ${ED_TRACKS:=$TRACK_SOURCES} : ${ED_CLUSTERS:=$TRACK_SOURCES} -workflow_has_parameter EVENT_DISPLAY && [[ $NUMAID == 0 ]] && [[ ! -z "$ED_TRACKS" ]] && [[ ! -z "$ED_CLUSTERS" ]] && [[ $EPNSYNCMODE == 0 || ${EPN_NODE_MI100:-0} == 0 ]] && add_W o2-eve-export-workflow "--display-tracks $ED_TRACKS --display-clusters $ED_CLUSTERS --skipOnEmptyInput $DISABLE_ROOT_INPUT $EVE_OPT $DISABLE_MC" "$ITSMFT_STROBES;$EVE_CONFIG" +workflow_has_parameter EVENT_DISPLAY && [[ $NUMAID == 0 ]] && [[ -n "$ED_TRACKS" ]] && [[ -n "$ED_CLUSTERS" ]] && [[ $EPNSYNCMODE == 0 || ${EPN_NODE_MI100:-0} == 0 ]] && add_W o2-eve-export-workflow "--display-tracks $ED_TRACKS --display-clusters $ED_CLUSTERS --skipOnEmptyInput $DISABLE_ROOT_INPUT $EVE_OPT $DISABLE_MC" "$ITSMFT_STROBES;$EVE_CONFIG" workflow_has_parameter GPU_DISPLAY && [[ $NUMAID == 0 ]] && add_W o2-gpu-display "${ED_TRACKS+--display-tracks} $ED_TRACKS ${ED_CLUSTERS+--display-clusters} $ED_CLUSTERS" @@ -668,7 +668,7 @@ workflow_has_parameter GPU_DISPLAY && [[ $NUMAID == 0 ]] && add_W o2-gpu-display # AOD [[ ${SECTVTX_ON:-} != "1" ]] && AODPROD_OPT+=" --disable-secondary-vertices " AODPROD_OPT+=" $STRTRACKING " -workflow_has_parameter AOD && [[ ! -z "$AOD_SOURCES" ]] && add_W o2-aod-producer-workflow "$AODPROD_OPT --info-sources $AOD_SOURCES $DISABLE_ROOT_INPUT --aod-writer-keep dangling --aod-writer-resfile \"AO2D\" --aod-writer-resmode UPDATE $DISABLE_MC --pipeline $(get_N aod-producer-workflow AOD REST 1 AODPROD)" +workflow_has_parameter AOD && [[ -n "$AOD_SOURCES" ]] && add_W o2-aod-producer-workflow "$AODPROD_OPT --info-sources $AOD_SOURCES $DISABLE_ROOT_INPUT --aod-writer-keep dangling --aod-writer-resfile \"AO2D\" --aod-writer-resmode UPDATE $DISABLE_MC --pipeline $(get_N aod-producer-workflow AOD REST 1 AODPROD)" # extra workflows in case we want to extra ITS/MFT info for dead channel maps to then go to CCDB for MC : ${ALIEN_JDL_PROCESSITSDEADMAP:=} @@ -681,15 +681,15 @@ workflow_has_parameter AOD && [[ ! -z "$AOD_SOURCES" ]] && add_W o2-aod-producer # Quality Control workflow_has_parameter QC && { source $O2DPG_ROOT/DATA/production/qc-workflow.sh; [[ $? != 0 ]] && echo "qc-workflow.sh failed" 1>&2 && exit 1; } -if [[ ! -z "${EXTRA_WORKFLOW:-}" ]]; then +if [[ -n "${EXTRA_WORKFLOW:-}" ]]; then WORKFLOW+="$EXTRA_WORKFLOW" fi -if [[ ! -z "${ADD_EXTRA_WORKFLOW:-}" ]]; then +if [[ -n "${ADD_EXTRA_WORKFLOW:-}" ]]; then OLD_IFS=$IFS IFS=',' for wf in $ADD_EXTRA_WORKFLOW; do - [[ ! -z "$wf" ]] && add_W $wf + [[ -n "$wf" ]] && add_W $wf done IFS="$OLD_IFS" fi diff --git a/prodtests/full-system-test/run-workflow-on-inputlist.sh b/prodtests/full-system-test/run-workflow-on-inputlist.sh index 63a2e3344428a..6622866afa745 100755 --- a/prodtests/full-system-test/run-workflow-on-inputlist.sh +++ b/prodtests/full-system-test/run-workflow-on-inputlist.sh @@ -18,7 +18,7 @@ if [[ $2 != "LOCAL" && ! -f $2 ]]; then fi for i in EXTINPUT CTFINPUT RAWTFINPUT DIGITINPUT; do - [[ ! -z ${!i} ]] && { echo "$i must not be set!"; exit 1; } + [[ -n ${!i} ]] && { echo "$i must not be set!"; exit 1; } done NUM_PROCS=0 @@ -87,7 +87,7 @@ fi TIMEOUT_PHASE=0 while [[ `jobs -rl | grep -v " $PID_LOG Running" | wc -l` -ne 0 ]]; do sleep 1 - if [[ ! -z $3 && $(date +%s) -ge $(($START_TIME + $TIMEOUT_PHASE * 20 + $3)) ]]; then + if [[ -n $3 && $(date +%s) -ge $(($START_TIME + $TIMEOUT_PHASE * 20 + $3)) ]]; then RETVAL=1 let TIMEOUT_PHASE=$TIMEOUT_PHASE+1 echo "Timeout reached ($3 seconds) - Sending SIGINT signal" diff --git a/prodtests/full-system-test/start_tmux.sh b/prodtests/full-system-test/start_tmux.sh index 3048943241627..39922ea5503d2 100755 --- a/prodtests/full-system-test/start_tmux.sh +++ b/prodtests/full-system-test/start_tmux.sh @@ -107,7 +107,7 @@ if [[ -z $SHM_MANAGER_SHMID ]]; then fi fi [[ ${O2_GPU_RTC:-0} == 1 ]] && FST_SLEEP2=60 -[[ ! -z $FST_TMUX_DD_WAIT ]] && FST_SLEEP2=$FST_TMUX_DD_WAIT +[[ -n $FST_TMUX_DD_WAIT ]] && FST_SLEEP2=$FST_TMUX_DD_WAIT if workflow_has_parameter CALIB_PROXIES; then CALIB_COMMAND="$GEN_TOPO_MYDIR/aggregator-workflow.sh" diff --git a/prodtests/full-system-test/tf-reader.sh b/prodtests/full-system-test/tf-reader.sh index 84b5877d194a2..d9740df7e6530 100755 --- a/prodtests/full-system-test/tf-reader.sh +++ b/prodtests/full-system-test/tf-reader.sh @@ -21,7 +21,7 @@ fi TFName=`ls -t $RAWINPUTDIR/o2_*.tf 2> /dev/null | head -n1` [[ -z $TFName && $WORKFLOWMODE == "print" ]] && TFName='$TFName' -[[ ! -z $INPUT_FILE_LIST ]] && TFName=$INPUT_FILE_LIST +[[ -n $INPUT_FILE_LIST ]] && TFName=$INPUT_FILE_LIST if [[ -z $TFName && $WORKFLOWMODE != "print" ]]; then echo "No raw file given!"; exit 1; fi o2-raw-tf-reader-workflow $ARGS_ALL --loop $NTIMEFRAMES --delay $TFDELAY --input-data ${TFName} ${INPUT_FILE_COPY_CMD+--copy-cmd} ${INPUT_FILE_COPY_CMD} --onlyDet $WORKFLOW_DETECTORS --raw-channel-config "name=dpl-chan,type=push,method=bind,address=ipc://${UDS_PREFIX}${INRAWCHANNAME},transport=shmem,rateLogging=0" $GLOBALDPLOPT --run diff --git a/prodtests/full_system_test.sh b/prodtests/full_system_test.sh index e8b298cc08d8c..6100e3ed87a2c 100755 --- a/prodtests/full_system_test.sh +++ b/prodtests/full_system_test.sh @@ -122,8 +122,8 @@ fi DIGITOPT= DIGITOPTKEYTRD="TRDSimParams.digithreads=${NJOBS};" DIGITOPTKEY=${HBFUTILPARAMS} -[[ ! -z $ITS_STROBE ]] && DIGITOPTKEY+="ITSAlpideParam.roFrameLengthInBC=$ITS_STROBE;" -[[ ! -z $MFT_STROBE ]] && DIGITOPTKEY+="MFTAlpideParam.roFrameLengthInBC=$MFT_STROBE;" +[[ -n $ITS_STROBE ]] && DIGITOPTKEY+="ITSAlpideParam.roFrameLengthInBC=$ITS_STROBE;" +[[ -n $MFT_STROBE ]] && DIGITOPTKEY+="MFTAlpideParam.roFrameLengthInBC=$MFT_STROBE;" if [ $SPLITTRDDIGI == "1" ]; then DIGITOPT+=" --skipDet TRD" DIGITOPTKEYTRD+=${HBFUTILPARAMS} @@ -202,7 +202,7 @@ STAGES+=" ASYNC" if [[ ${RANS_OPT:-} =~ (--ans-version +)(compat) ]] ; then # Give a possibility to run the FST with external existing dictionary (i.e. with CREATECTFDICT=0 full_system_test.sh) # In order to use CCDB dictionaries, pass CTFDICTFILE=ccdb CREATECTFDICT=0 - [[ ! -z "$CREATECTFDICT" ]] && SYNCMODEDOCTFDICT="$CREATECTFDICT" || SYNCMODEDOCTFDICT=1 + [[ -n "$CREATECTFDICT" ]] && SYNCMODEDOCTFDICT="$CREATECTFDICT" || SYNCMODEDOCTFDICT=1 # this is default local tree-based CTF dictionary file [[ -z "$CTFDICTFILE" ]] && CTFDICTFILE="ctf_dictionary.root" From 7423aa7f192cf59887d7d453aae9dff1f94add33 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 18 Jul 2025 14:13:25 +0200 Subject: [PATCH 167/315] TPC: Avoid using deprecated fmt::localtime --- Detectors/TPC/base/src/CDBInterface.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Detectors/TPC/base/src/CDBInterface.cxx b/Detectors/TPC/base/src/CDBInterface.cxx index 605413b205c2a..06f6a360670dc 100644 --- a/Detectors/TPC/base/src/CDBInterface.cxx +++ b/Detectors/TPC/base/src/CDBInterface.cxx @@ -722,6 +722,8 @@ void CDBStorage::printObjectSummary(std::string_view name, CDBType const type, M { std::time_t tstart(start / 1000); std::time_t tend(end / 1000); + std::tm ttstart = *std::localtime(&tstart); + std::tm ttend = *std::localtime(&tend); auto tstartms = start % 1000; auto tendms = end % 1000; @@ -729,7 +731,7 @@ void CDBStorage::printObjectSummary(std::string_view name, CDBType const type, M fmt::format(" to storage '{}'\n", mCCDB.getURL()) + fmt::format(" into path '{}'\n", CDBTypeMap.at(type)) + fmt::format(" with validity [{}, {}] :", start, end) + - fmt::format(" [{:%d.%m.%Y %H:%M:%S}.{:03d}, {:%d.%m.%Y %H:%M:%S}.{:03d}]\n", fmt::localtime(tstart), tstartms, fmt::localtime(tend), tendms) + + fmt::format(" [{:%d.%m.%Y %H:%M:%S}.{:03d}, {:%d.%m.%Y %H:%M:%S}.{:03d}]\n", ttstart, tstartms, ttend, tendms) + std::string(" Meta data:\n"); for (const auto& [key, value] : metadata) { From 8252a1f46af3e24c0d691a261f578942c1905e15 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 18 Jul 2025 23:59:47 +0200 Subject: [PATCH 168/315] DPL: out of line metrics related methods --- .../include/Framework/DeviceMetricsInfo.h | 60 +------------------ Framework/Core/src/DeviceMetricsInfo.cxx | 58 ++++++++++++++++++ 2 files changed, 61 insertions(+), 57 deletions(-) diff --git a/Framework/Core/include/Framework/DeviceMetricsInfo.h b/Framework/Core/include/Framework/DeviceMetricsInfo.h index d55f1cb44f71d..ad143b7ef9373 100644 --- a/Framework/Core/include/Framework/DeviceMetricsInfo.h +++ b/Framework/Core/include/Framework/DeviceMetricsInfo.h @@ -12,7 +12,6 @@ #ifndef O2_FRAMEWORK_DEVICEMETRICSINFO_H_ #define O2_FRAMEWORK_DEVICEMETRICSINFO_H_ -#include "Framework/RuntimeError.h" #include "Framework/CompilerBuiltins.h" #include "Framework/Traits.h" #include @@ -21,6 +20,7 @@ #include #include #include +#include namespace o2::framework { @@ -191,62 +191,8 @@ struct DeviceMetricsInfoHelpers { } } - static void clearMetrics(std::vector& infos) - { - for (auto& info : infos) { - info.intMetrics.clear(); - info.uint64Metrics.clear(); - info.stringMetrics.clear(); // We do not keep so many strings as metrics as history is less relevant. - info.floatMetrics.clear(); - info.enumMetrics.clear(); - info.intTimestamps.clear(); - info.uint64Timestamps.clear(); - info.floatTimestamps.clear(); - info.stringTimestamps.clear(); - info.enumTimestamps.clear(); - info.max.clear(); - info.min.clear(); - info.average.clear(); - info.minDomain.clear(); - info.maxDomain.clear(); - info.metricLabels.clear(); - info.metricPrefixes.clear(); - info.metricLabelsAlphabeticallySortedIdx.clear(); - info.metricLabelsPrefixesSortedIdx.clear(); - info.metrics.clear(); - info.changed.clear(); - } - } - static size_t metricsStorageSize(std::span infos) - { - // Count the size of the metrics storage - size_t totalSize = 0; - for (auto& info : infos) { - totalSize += info.intMetrics.size() * sizeof(MetricsStorage); - totalSize += info.uint64Metrics.size() * sizeof(MetricsStorage); - totalSize += info.stringMetrics.size() * sizeof(MetricsStorage); - totalSize += info.floatMetrics.size() * sizeof(MetricsStorage); - totalSize += info.enumMetrics.size() * sizeof(MetricsStorage); - totalSize += info.intTimestamps.size() * sizeof(TimestampsStorage); - totalSize += info.uint64Timestamps.size() * sizeof(TimestampsStorage); - totalSize += info.floatTimestamps.size() * sizeof(TimestampsStorage); - totalSize += info.stringTimestamps.size() * sizeof(TimestampsStorage); - totalSize += info.enumTimestamps.size() * sizeof(TimestampsStorage); - totalSize += info.max.size() * sizeof(float); - totalSize += info.min.size() * sizeof(float); - totalSize += info.average.size() * sizeof(float); - totalSize += info.minDomain.size() * sizeof(size_t); - totalSize += info.maxDomain.size() * sizeof(size_t); - totalSize += info.metricLabels.size() * sizeof(MetricLabel); - totalSize += info.metricPrefixes.size() * sizeof(MetricPrefix); - totalSize += info.metricLabelsAlphabeticallySortedIdx.size() * sizeof(MetricLabelIndex); - totalSize += info.metricLabelsPrefixesSortedIdx.size() * sizeof(MetricPrefixIndex); - totalSize += info.metrics.size() * sizeof(MetricInfo); - totalSize += info.changed.size() * sizeof(bool); - } - - return totalSize; - } + static void clearMetrics(std::vector& infos); + static size_t metricsStorageSize(std::span infos); }; } // namespace o2::framework diff --git a/Framework/Core/src/DeviceMetricsInfo.cxx b/Framework/Core/src/DeviceMetricsInfo.cxx index 9a208c4535554..ccb8d5d2e6d8f 100644 --- a/Framework/Core/src/DeviceMetricsInfo.cxx +++ b/Framework/Core/src/DeviceMetricsInfo.cxx @@ -50,4 +50,62 @@ std::ostream& operator<<(std::ostream& oss, MetricType const& val) return oss; } +void DeviceMetricsInfoHelpers::clearMetrics(std::vector& infos) +{ + for (auto& info : infos) { + info.intMetrics.clear(); + info.uint64Metrics.clear(); + info.stringMetrics.clear(); // We do not keep so many strings as metrics as history is less relevant. + info.floatMetrics.clear(); + info.enumMetrics.clear(); + info.intTimestamps.clear(); + info.uint64Timestamps.clear(); + info.floatTimestamps.clear(); + info.stringTimestamps.clear(); + info.enumTimestamps.clear(); + info.max.clear(); + info.min.clear(); + info.average.clear(); + info.minDomain.clear(); + info.maxDomain.clear(); + info.metricLabels.clear(); + info.metricPrefixes.clear(); + info.metricLabelsAlphabeticallySortedIdx.clear(); + info.metricLabelsPrefixesSortedIdx.clear(); + info.metrics.clear(); + info.changed.clear(); + } +} + +size_t DeviceMetricsInfoHelpers::metricsStorageSize(std::span infos) +{ + // Count the size of the metrics storage + size_t totalSize = 0; + for (auto& info : infos) { + totalSize += info.intMetrics.size() * sizeof(MetricsStorage); + totalSize += info.uint64Metrics.size() * sizeof(MetricsStorage); + totalSize += info.stringMetrics.size() * sizeof(MetricsStorage); + totalSize += info.floatMetrics.size() * sizeof(MetricsStorage); + totalSize += info.enumMetrics.size() * sizeof(MetricsStorage); + totalSize += info.intTimestamps.size() * sizeof(TimestampsStorage); + totalSize += info.uint64Timestamps.size() * sizeof(TimestampsStorage); + totalSize += info.floatTimestamps.size() * sizeof(TimestampsStorage); + totalSize += info.stringTimestamps.size() * sizeof(TimestampsStorage); + totalSize += info.enumTimestamps.size() * sizeof(TimestampsStorage); + totalSize += info.max.size() * sizeof(float); + totalSize += info.min.size() * sizeof(float); + totalSize += info.average.size() * sizeof(float); + totalSize += info.minDomain.size() * sizeof(size_t); + totalSize += info.maxDomain.size() * sizeof(size_t); + totalSize += info.metricLabels.size() * sizeof(MetricLabel); + totalSize += info.metricPrefixes.size() * sizeof(MetricPrefix); + totalSize += info.metricLabelsAlphabeticallySortedIdx.size() * sizeof(MetricLabelIndex); + totalSize += info.metricLabelsPrefixesSortedIdx.size() * sizeof(MetricPrefixIndex); + totalSize += info.metrics.size() * sizeof(MetricInfo); + totalSize += info.changed.size() * sizeof(bool); + } + + return totalSize; +} + } // namespace o2::framework From b8d64940c709e422fbc62dd7e7c555cdaef87348 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 21 Jul 2025 10:27:54 +0200 Subject: [PATCH 169/315] ITS: cleanup lines and tracklet/clusterlines changes (#14511) Signed-off-by: Felix Schlepper FullCi is green, merging. --- .../include/ITStracking/ClusterLines.h | 128 +++++++----------- .../tracking/include/ITStracking/Tracklet.h | 61 ++------- .../ITSMFT/ITS/tracking/src/ClusterLines.cxx | 49 ++++--- .../ITSMFT/ITS/tracking/src/TimeFrame.cxx | 2 + 4 files changed, 86 insertions(+), 154 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h index 3377b88e89069..3ffeda9adcfd5 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h @@ -15,25 +15,25 @@ #include #include #include "ITStracking/Cluster.h" -#include "ITStracking/Definitions.h" +#include "ITStracking/Constants.h" #include "ITStracking/Tracklet.h" +#include "GPUCommonRtypes.h" #include "GPUCommonMath.h" namespace o2::its { struct Line final { - GPUhd() Line(); + GPUhdDefault() Line() = default; GPUhd() Line(const Line&); Line(std::array firstPoint, std::array secondPoint); - GPUhd() Line(const float firstPoint[3], const float secondPoint[3]); GPUhd() Line(const Tracklet&, const Cluster*, const Cluster*); static float getDistanceFromPoint(const Line& line, const std::array& point); GPUhd() static float getDistanceFromPoint(const Line& line, const float point[3]); static std::array getDCAComponents(const Line& line, const std::array point); GPUhd() static void getDCAComponents(const Line& line, const float point[3], float destArray[6]); - GPUhd() static float getDCA(const Line&, const Line&, const float precision = 1e-14); - static bool areParallel(const Line&, const Line&, const float precision = 1e-14); + GPUhd() static float getDCA(const Line&, const Line&, const float precision = constants::Tolerance); + static bool areParallel(const Line&, const Line&, const float precision = constants::Tolerance); GPUhd() unsigned char isEmpty() const { return (originPoint[0] == 0.f && originPoint[1] == 0.f && originPoint[2] == 0.f) && (cosinesDirector[0] == 0.f && cosinesDirector[1] == 0.f && cosinesDirector[2] == 0.f); } GPUhdi() auto getDeltaROF() const { return rof[1] - rof[0]; } @@ -42,8 +42,9 @@ struct Line final { bool operator!=(const Line&) const; short getMinROF() const { return rof[0] < rof[1] ? rof[0] : rof[1]; } - float originPoint[3], cosinesDirector[3]; - float weightMatrix[6] = {1., 0., 0., 1., 0., 1.}; + float originPoint[3] = {0}; + float cosinesDirector[3] = {0}; + // float weightMatrix[6] = {1., 0., 0., 1., 0., 1.}; // weightMatrix is a symmetric matrix internally stored as // 0 --> row = 0, col = 0 // 1 --> 0,1 @@ -51,14 +52,10 @@ struct Line final { // 3 --> 1,1 // 4 --> 1,2 // 5 --> 2,2 - short rof[2]; -}; + short rof[2] = {-1, -1}; -GPUhdi() Line::Line() : weightMatrix{1., 0., 0., 1., 0., 1.} -{ - rof[0] = -1; - rof[1] = -1; -} + ClassDefNV(Line, 1); +}; GPUhdi() Line::Line(const Line& other) { @@ -66,32 +63,14 @@ GPUhdi() Line::Line(const Line& other) originPoint[i] = other.originPoint[i]; cosinesDirector[i] = other.cosinesDirector[i]; } - for (int i{0}; i < 6; ++i) { - weightMatrix[i] = other.weightMatrix[i]; - } + // for (int i{0}; i < 6; ++i) { + // weightMatrix[i] = other.weightMatrix[i]; + // } for (int i{0}; i < 2; ++i) { rof[i] = other.rof[i]; } } -GPUhdi() Line::Line(const float firstPoint[3], const float secondPoint[3]) -{ - for (int i{0}; i < 3; ++i) { - originPoint[i] = firstPoint[i]; - cosinesDirector[i] = secondPoint[i] - firstPoint[i]; - } - - float inverseNorm{1.f / o2::gpu::CAMath::Sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + - cosinesDirector[2] * cosinesDirector[2])}; - - for (int index{0}; index < 3; ++index) { - cosinesDirector[index] *= inverseNorm; - } - - rof[0] = -1; - rof[1] = -1; -} - GPUhdi() Line::Line(const Tracklet& tracklet, const Cluster* innerClusters, const Cluster* outerClusters) { originPoint[0] = innerClusters[tracklet.firstClusterIndex].xCoordinate; @@ -102,12 +81,10 @@ GPUhdi() Line::Line(const Tracklet& tracklet, const Cluster* innerClusters, cons cosinesDirector[1] = outerClusters[tracklet.secondClusterIndex].yCoordinate - innerClusters[tracklet.firstClusterIndex].yCoordinate; cosinesDirector[2] = outerClusters[tracklet.secondClusterIndex].zCoordinate - innerClusters[tracklet.firstClusterIndex].zCoordinate; - float inverseNorm{1.f / o2::gpu::CAMath::Sqrt(cosinesDirector[0] * cosinesDirector[0] + cosinesDirector[1] * cosinesDirector[1] + - cosinesDirector[2] * cosinesDirector[2])}; - - for (int index{0}; index < 3; ++index) { - cosinesDirector[index] *= inverseNorm; - } + float inverseNorm{1.f / o2::gpu::CAMath::Hypot(cosinesDirector[0], cosinesDirector[1], cosinesDirector[2])}; + cosinesDirector[0] *= inverseNorm; + cosinesDirector[1] *= inverseNorm; + cosinesDirector[2] *= inverseNorm; rof[0] = tracklet.rof[0]; rof[1] = tracklet.rof[1]; @@ -130,47 +107,38 @@ inline float Line::getDistanceFromPoint(const Line& line, const std::array precision) { - return o2::gpu::CAMath::Abs(distance / o2::gpu::CAMath::Sqrt(norm)); - } else { -#if defined(__CUDACC__) || defined(__HIPCC__) - float stdOriginPoint[3]; - for (int i{0}; i < 3; ++i) { - stdOriginPoint[i] = secondLine.originPoint[1]; - } -#else - std::array stdOriginPoint = {}; - std::copy_n(secondLine.originPoint, 3, stdOriginPoint.begin()); -#endif - return getDistanceFromPoint(firstLine, stdOriginPoint); + const float nx = (firstLine.cosinesDirector[1] * secondLine.cosinesDirector[2]) - + (firstLine.cosinesDirector[2] * secondLine.cosinesDirector[1]); + const float ny = -(firstLine.cosinesDirector[0] * secondLine.cosinesDirector[2]) + + (firstLine.cosinesDirector[2] * secondLine.cosinesDirector[0]); + const float nz = (firstLine.cosinesDirector[0] * secondLine.cosinesDirector[1]) - + (firstLine.cosinesDirector[1] * secondLine.cosinesDirector[0]); + const float norm2 = (nx * nx) + (ny * ny) + (nz * nz); + + if (norm2 <= precision * precision) { + return getDistanceFromPoint(firstLine, secondLine.originPoint); } + + const float dx = secondLine.originPoint[0] - firstLine.originPoint[0]; + const float dy = secondLine.originPoint[1] - firstLine.originPoint[1]; + const float dz = secondLine.originPoint[2] - firstLine.originPoint[2]; + const float triple = (dx * nx) + (dy * ny) + (dz * nz); + + return o2::gpu::CAMath::Abs(triple) / o2::gpu::CAMath::Sqrt(norm2); } GPUhdi() void Line::getDCAComponents(const Line& line, const float point[3], float destArray[6]) @@ -199,11 +167,7 @@ inline bool Line::operator==(const Line& rhs) const inline bool Line::operator!=(const Line& rhs) const { - bool val; - for (int i{0}; i < 3; ++i) { - val &= this->originPoint[i] != rhs.originPoint[i]; - } - return val; + return !(*this == rhs); } GPUhdi() void Line::print() const diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h index e0ae23c8bedde..ba3474e6e86c6 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h @@ -20,53 +20,48 @@ #include "GPUCommonRtypes.h" #include "GPUCommonMath.h" #include "GPUCommonDef.h" +#include "GPUCommonLogger.h" #ifndef GPUCA_GPUCODE_DEVICE +#ifndef GPU_NO_FMT #include +#include +#endif #endif namespace o2::its { struct Tracklet final { - GPUhdi() Tracklet(); + GPUhdDefault() Tracklet() = default; GPUhdi() Tracklet(const int, const int, const Cluster&, const Cluster&, short rof0, short rof1); GPUhdi() Tracklet(const int, const int, float tanL, float phi, short rof0, short rof1); - GPUhdi() bool operator==(const Tracklet&) const; - GPUhdi() bool operator!=(const Tracklet&) const; + GPUhdDefault() bool operator==(const Tracklet&) const = default; GPUhdi() unsigned char isEmpty() const { return firstClusterIndex < 0 || secondClusterIndex < 0; } GPUhdi() auto getDeltaRof() const { return rof[1] - rof[0]; } - GPUhdi() void dump(); GPUhdi() void dump() const; - GPUhdi() void dump(const int, const int); GPUhdi() void dump(const int, const int) const; GPUhdi() unsigned char operator<(const Tracklet&) const; -#ifndef GPUCA_GPUCODE_DEVICE +#if !defined(GPUCA_NO_FMT) && !defined(GPUCA_GPUCODE_DEVICE) std::string asString() const { - return "fClIdx: " + std::to_string(firstClusterIndex) + " sClIdx: " + std::to_string(secondClusterIndex) + - " rof1: " + std::to_string(rof[0]) + " rof2: " + std::to_string(rof[1]) + " delta: " + std::to_string(getDeltaRof()); + return fmt::format("fClIdx:{} fROF:{} sClIdx:{} sROF:{} (DROF:{})", firstClusterIndex, rof[0], secondClusterIndex, rof[1], getDeltaRof()); } + void print() const { LOG(info) << asString(); } #endif - int firstClusterIndex; - int secondClusterIndex; - float tanLambda; - float phi; - short rof[2]; + int firstClusterIndex{-1}; + int secondClusterIndex{-1}; + float tanLambda{-999}; + float phi{-999}; + short rof[2] = {-1, -1}; ClassDefNV(Tracklet, 1); }; -GPUhdi() Tracklet::Tracklet() : firstClusterIndex{-1}, secondClusterIndex{-1}, tanLambda{0.0f}, phi{0.0f} -{ - rof[0] = -1; - rof[1] = -1; -} - GPUhdi() Tracklet::Tracklet(const int firstClusterOrderingIndex, const int secondClusterOrderingIndex, const Cluster& firstCluster, const Cluster& secondCluster, short rof0 = -1, short rof1 = -1) : firstClusterIndex{firstClusterOrderingIndex}, @@ -90,24 +85,6 @@ GPUhdi() Tracklet::Tracklet(const int idx0, const int idx1, float tanL, float ph // Nothing to do } -GPUhdi() bool Tracklet::operator==(const Tracklet& rhs) const -{ - return this->firstClusterIndex == rhs.firstClusterIndex && - this->secondClusterIndex == rhs.secondClusterIndex && - this->tanLambda == rhs.tanLambda && - this->phi == rhs.phi && - this->rof[0] == rhs.rof[0] && - this->rof[1] == rhs.rof[1]; -} - -GPUhdi() bool Tracklet::operator!=(const Tracklet& rhs) const -{ - return this->firstClusterIndex != rhs.firstClusterIndex || - this->secondClusterIndex != rhs.secondClusterIndex || - this->tanLambda != rhs.tanLambda || - this->phi != rhs.phi; -} - GPUhdi() unsigned char Tracklet::operator<(const Tracklet& t) const { if (isEmpty()) { @@ -116,21 +93,11 @@ GPUhdi() unsigned char Tracklet::operator<(const Tracklet& t) const return true; } -GPUhdi() void Tracklet::dump(const int offsetFirst, const int offsetSecond) -{ - printf("fClIdx: %d sClIdx: %d rof1: %hu rof2: %hu\n", firstClusterIndex + offsetFirst, secondClusterIndex + offsetSecond, rof[0], rof[1]); -} - GPUhdi() void Tracklet::dump(const int offsetFirst, const int offsetSecond) const { printf("fClIdx: %d sClIdx: %d rof1: %hu rof2: %hu\n", firstClusterIndex + offsetFirst, secondClusterIndex + offsetSecond, rof[0], rof[1]); } -GPUhdi() void Tracklet::dump() -{ - printf("fClIdx: %d sClIdx: %d rof1: %hu rof2: %hu\n", firstClusterIndex, secondClusterIndex, rof[0], rof[1]); -} - GPUhdi() void Tracklet::dump() const { printf("fClIdx: %d sClIdx: %d rof1: %hu rof2: %hu\n", firstClusterIndex, secondClusterIndex, rof[0], rof[1]); diff --git a/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx b/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx index 570f58ca2695d..1a0fa1d3908a4 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/ClusterLines.cxx @@ -19,7 +19,6 @@ namespace its { Line::Line(std::array firstPoint, std::array secondPoint) - : weightMatrix{1., 0., 0., 1., 0., 1.} // dummy, ATM { for (int index{0}; index < 3; ++index) { originPoint[index] = firstPoint.data()[index]; @@ -95,9 +94,9 @@ ClusterLines::ClusterLines(const int firstLabel, const Line& firstLine, const in std::array covarianceFirst{1., 1., 1.}; std::array covarianceSecond{1., 1., 1.}; - for (int i{0}; i < 6; ++i) { - mWeightMatrix[i] = firstLine.weightMatrix[i] + secondLine.weightMatrix[i]; - } + // for (int i{0}; i < 6; ++i) { + // mWeightMatrix[i] = firstLine.weightMatrix[i] + secondLine.weightMatrix[i]; + // } float determinantFirst = firstLine.cosinesDirector[2] * firstLine.cosinesDirector[2] * covarianceFirst[0] * covarianceFirst[1] + @@ -193,9 +192,9 @@ ClusterLines::ClusterLines(const Line& firstLine, const Line& secondLine) std::array covarianceSecond{1., 1., 1.}; updateROFPoll(firstLine); updateROFPoll(secondLine); - for (int i{0}; i < 6; ++i) { - mWeightMatrix[i] = firstLine.weightMatrix[i] + secondLine.weightMatrix[i]; - } + // for (int i{0}; i < 6; ++i) { + // mWeightMatrix[i] = firstLine.weightMatrix[i] + secondLine.weightMatrix[i]; + // } float determinantFirst = firstLine.cosinesDirector[2] * firstLine.cosinesDirector[2] * covarianceFirst[0] * covarianceFirst[1] + @@ -281,9 +280,9 @@ void ClusterLines::add(const int& lineLabel, const Line& line, const bool& weigh updateROFPoll(line); std::array covariance{1., 1., 1.}; - for (int i{0}; i < 6; ++i) { - mWeightMatrix[i] += line.weightMatrix[i]; - } + // for (int i{0}; i < 6; ++i) { + // mWeightMatrix[i] += line.weightMatrix[i]; + // } // if(weight) line->GetSigma2P0(covariance); double determinant{line.cosinesDirector[2] * line.cosinesDirector[2] * covariance[0] * covariance[1] + @@ -370,25 +369,25 @@ bool ClusterLines::operator==(const ClusterLines& rhs) const GPUhdi() void ClusterLines::updateROFPoll(const Line& line) { // option 1: Boyer-Moore voting for rof label - // if (mROFWeight == 0) { - // mROF = line.getMinROF(); - // mROFWeight = 1; - // } else { - // if (mROF == line.getMinROF()) { - // mROFWeight++; - // } else { - // mROFWeight--; - // } - // } - - // option 2 - if (mROF == -1) { + if (mROFWeight == 0) { mROF = line.getMinROF(); + mROFWeight = 1; } else { - if (line.getMinROF() < mROF) { - mROF = line.getMinROF(); + if (mROF == line.getMinROF()) { + mROFWeight++; + } else { + mROFWeight--; } } + + // option 2 + // if (mROF == -1) { + // mROF = line.getMinROF(); + // } else { + // if (line.getMinROF() < mROF) { + // mROF = line.getMinROF(); + // } + // } } } // namespace its diff --git a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx index ea57e5fa8e3b9..4115726756e73 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx @@ -711,6 +711,8 @@ void TimeFrame::wipe() deepVectorClear(mPrimaryVertices); deepVectorClear(mTrackletClusters); deepVectorClear(mVerticesContributorLabels); + deepVectorClear(mLines); + deepVectorClear(mLinesLabels); } template class TimeFrame<7>; From d53e9d97c47971cd0bd2089475c2fa52e94729f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Wed, 9 Jul 2025 17:49:12 +0200 Subject: [PATCH 170/315] IWYU: TimeDeadMap.h --- .../ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h index 5a93cbb712931..6c7c01dc888b7 100644 --- a/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h +++ b/DataFormats/Detectors/ITSMFT/common/include/DataFormatsITSMFT/TimeDeadMap.h @@ -14,9 +14,12 @@ #ifndef ALICEO2_ITSMFT_TIMEDEADMAP_H #define ALICEO2_ITSMFT_TIMEDEADMAP_H -#include "Rtypes.h" -#include +#include + +#include #include +#include +#include namespace o2 { From ac2ac36b5eb805be6b82622aa30eecea7a096a75 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 22 Jul 2025 11:06:51 +0200 Subject: [PATCH 171/315] ITS: print deltaRof option (#14531) --- Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx index 6b2d80424b5bb..144b9a1dfc7c4 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx @@ -24,8 +24,8 @@ using namespace o2::its; std::string TrackingParameters::asString() const { - std::string str = std::format("NZb:{} NPhB:{} NROFIt:{} PerVtx:{} DropFail:{} ClSh:{} TtklMinPt:{:.2f} MinCl:{}", - ZBins, PhiBins, nROFsPerIterations, PerPrimaryVertexProcessing, DropTFUponFailure, ClusterSharing, TrackletMinPt, MinTrackLength); + std::string str = std::format("NZb:{} NPhB:{} NROFIt:{} DRof:{} PerVtx:{} DropFail:{} ClSh:{} TtklMinPt:{:.2f} MinCl:{}", + ZBins, PhiBins, nROFsPerIterations, DeltaROF, PerPrimaryVertexProcessing, DropTFUponFailure, ClusterSharing, TrackletMinPt, MinTrackLength); bool first = true; for (int il = NLayers; il >= MinTrackLength; il--) { int slot = NLayers - il; From 3922d501a300cb3ebeb557de4af898ae5b779622 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 22 Jul 2025 11:07:19 +0200 Subject: [PATCH 172/315] ITS: add CheckDROF macro (#14533) --- .../ITSMFT/ITS/macros/test/CMakeLists.txt | 5 + Detectors/ITSMFT/ITS/macros/test/CheckDROF.C | 1426 +++++++++++++++++ 2 files changed, 1431 insertions(+) create mode 100644 Detectors/ITSMFT/ITS/macros/test/CheckDROF.C diff --git a/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt b/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt index 2ed11fc852c8b..dd6aacf65db99 100644 --- a/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/macros/test/CMakeLists.txt @@ -113,3 +113,8 @@ o2_add_test_root_macro(CheckDuplicates.C PUBLIC_LINK_LIBRARIES O2::DataFormatsITS O2::DataFormatsITSMFT LABELS its) + +o2_add_test_root_macro(CheckDROF.C + PUBLIC_LINK_LIBRARIES O2::DataFormatsITS + O2::DataFormatsITSMFT + LABELS its) diff --git a/Detectors/ITSMFT/ITS/macros/test/CheckDROF.C b/Detectors/ITSMFT/ITS/macros/test/CheckDROF.C new file mode 100644 index 0000000000000..21428ea4fcbc2 --- /dev/null +++ b/Detectors/ITSMFT/ITS/macros/test/CheckDROF.C @@ -0,0 +1,1426 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include +#include +#include +#include +#include + +#include +#include +#include +#include "TH1F.h" +#include +#include "TH2D.h" +#include "TH3D.h" +#include +#include +#include +#include +#include +#include + +#include "ITSBase/GeometryTGeo.h" +#include "SimulationDataFormat/MCEventHeader.h" +#include "DetectorsBase/Propagator.h" +#include "SimulationDataFormat/TrackReference.h" +#include "SimulationDataFormat/MCTrack.h" +#include "SimulationDataFormat/MCCompLabel.h" +#include "SimulationDataFormat/MCTruthContainer.h" +#include "DataFormatsITSMFT/CompCluster.h" +#include "DataFormatsITS/TrackITS.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "SimulationDataFormat/DigitizationContext.h" + +#endif + +using namespace std; +using Vertex = o2::dataformats::Vertex>; + +void plotHistos(TFile* fWO, TFile* f, const char* append = ""); + +struct ParticleInfo { // particle level information for tracks + int event; + int pdg; + float pt; + float eta; + float phi; + int mother; + int first; + float pvx{}; + float pvy{}; + float pvz{}; + float dcaxy; + float dcaz; + unsigned short clusters = 0u; + unsigned char isReco = 0u; + unsigned char isFake = 0u; + bool isPrimary = false; + int bcInROF{-1}; + int rofId{-1}; + unsigned char storedStatus = 2; /// not stored = 2, fake = 1, good = 0 + o2::its::TrackITS track; + + void print() const + { + LOGP(info, "event={} pdg={} pt={} eta={} phi={} mother={} clusters={:7b} isReco={} isFake={} isPrimary={} bcInROF={} rofId={} | {}", event, pdg, pt, eta, phi, mother, clusters, isReco, isFake, isPrimary, bcInROF, rofId, track.asString()); + } + + int getNClusters() const noexcept + { + int nCl{0}; + for (unsigned int bit{0}; bit < sizeof(ParticleInfo::clusters) * 8; ++bit) { + nCl += bool(clusters & (1 << bit)); + } + return nCl; + } + + bool isReconstructable() const noexcept + { + return isPrimary && (7 == getNClusters()) && bcInROF >= 0; + } +}; +#pragma link C++ class ParticleInfo + ; +#pragma link C++ class std::vector < ParticleInfo> + ; + +struct VertexInfo { // Vertex level info + float purity; // fraction of main cont. labels to all + Vertex vertex; // reconstructed vertex + int bcInROF{-1}; + int rofId{-1}; + int event{-1}; // corresponding MC event + std::vector labels; // contributor labels + o2::MCCompLabel mainLabel; // main label + + void computeMain() + { + std::unordered_map freq; + size_t totalSet = 0; + + // Count frequencies of set labels + for (auto const& lab : labels) { + if (lab.isSet()) { + ++freq[lab]; + ++totalSet; + } + } + if (totalSet == 0) { + return; + } + // Find the label with maximum count + auto best = std::max_element(freq.begin(), freq.end(), [](auto const& a, auto const& b) { return a.second < b.second; }); + size_t maxCount = best->second; + + // If there's no majority (all counts == 1), fall back to first set label + o2::MCCompLabel mainLab; + if (maxCount == 1) { + for (auto const& lab : labels) { + if (lab.isSet()) { + mainLab = lab; + break; + } + } + } else { + mainLab = best->first; + } + purity = (float)maxCount / (float)labels.size(); + } +}; +#pragma link C++ class VertexInfo + ; + +using namespace o2::itsmft; +using namespace o2::its; + +void CheckDROF(bool plot = false, bool write = false, const std::string& tracfile = "o2trac_its.root", + const std::string& magfile = "o2sim_grp.root", + const std::string& clusfile = "o2clus_its.root", + const std::string& kinefile = "o2sim_Kine.root") +{ + constexpr int64_t roFrameLengthInBC = 198; // for pp=198 + constexpr int64_t roFrameBiasInBC = 64; // ITS delay accounted for in digitization + constexpr float roFbins{roFrameLengthInBC + 2.f}; + constexpr int bcValStart{60}, bcValEnd{140}; // adjustable region of validation train + + if (!plot) { + int trackID, evID, srcID; + bool fake; + + // Magnetic field and Propagator + o2::base::Propagator::initFieldFromGRP(magfile); + float bz = o2::base::Propagator::Instance()->getNominalBz(); + + // Geometry + o2::base::GeometryManager::loadGeometry(); + auto gman = o2::its::GeometryTGeo::Instance(); + + // MC tracks + TFile* file0 = TFile::Open(kinefile.data()); + TTree* mcTree = (TTree*)gFile->Get("o2sim"); + mcTree->SetBranchStatus("*", 0); // disable all branches + mcTree->SetBranchStatus("MCTrack*", 1); + mcTree->SetBranchStatus("MCEventHeader*", 1); + std::vector* mcArr = nullptr; + mcTree->SetBranchAddress("MCTrack", &mcArr); + o2::dataformats::MCEventHeader* mcEvent = nullptr; + mcTree->SetBranchAddress("MCEventHeader.", &mcEvent); + + auto* dc = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); + const auto& irs = dc->getEventRecords(); + dc->printCollisionSummary(false, 20); + + // Clusters + TFile::Open(clusfile.data()); + TTree* clusTree = (TTree*)gFile->Get("o2sim"); + std::vector* clusArr = nullptr; + clusTree->SetBranchAddress("ITSClusterComp", &clusArr); + + // Cluster MC labels + o2::dataformats::MCTruthContainer* clusLabArr = nullptr; + clusTree->SetBranchAddress("ITSClusterMCTruth", &clusLabArr); + + // Reconstructed tracks + TFile* file1 = TFile::Open(tracfile.data()); + TTree* recTree = (TTree*)gFile->Get("o2sim"); + std::vector* recArr = nullptr; + recTree->SetBranchAddress("ITSTrack", &recArr); + // Track MC labels + std::vector* trkLabArr = nullptr; + recTree->SetBranchAddress("ITSTrackMCTruth", &trkLabArr); + std::vector rofRecVec, *rofRecVecP = &rofRecVec; + recTree->SetBranchAddress("ITSTracksROF", &rofRecVecP); + // Vertices + std::vector* recVerArr = nullptr; + recTree->SetBranchAddress("Vertices", &recVerArr); + std::vector* recVerROFArr = nullptr; + recTree->SetBranchAddress("VerticesROF", &recVerROFArr); + std::vector* recVerLabelsArr = nullptr; + recTree->SetBranchAddress("ITSVertexMCTruth", &recVerLabelsArr); + std::vector* recVerPurityArr = nullptr; + recTree->SetBranchAddress("ITSVertexMCPurity", &recVerPurityArr); + + std::cout << "** Filling particle table ... " << std::flush; + int lastEventIDcl = -1, cf = 0; + const int nev = mcTree->GetEntriesFast(); + std::vector> info; + info.resize(nev); + TH1D* hZvertex = new TH1D("hZvertex", "Z vertex", 100, -20, 20); + for (int n = 0; n < nev; n++) { // loop over MC events + mcTree->GetEvent(n); + info[n].resize(mcArr->size()); + hZvertex->Fill(mcEvent->GetZ()); + const auto& ir = irs[mcEvent->GetEventID() - 1]; // event id start from 1 + for (unsigned int mcI{0}; mcI < mcArr->size(); ++mcI) { + auto part = mcArr->at(mcI); + info[n][mcI].event = n; + info[n][mcI].pdg = part.GetPdgCode(); + info[n][mcI].pvx = mcEvent->GetX(); + info[n][mcI].pvy = mcEvent->GetY(); + info[n][mcI].pvz = mcEvent->GetZ(); + info[n][mcI].pt = part.GetPt(); + info[n][mcI].phi = part.GetPhi(); + info[n][mcI].eta = part.GetEta(); + info[n][mcI].isPrimary = part.isPrimary(); + if (!ir.isDummy()) { + info[n][mcI].bcInROF = (ir.toLong() - roFrameBiasInBC) % roFrameLengthInBC; + info[n][mcI].rofId = (ir.toLong() - roFrameBiasInBC) / roFrameLengthInBC; + } + } + } + std::cout << "done." << std::endl; + + std::cout << "** Creating particle/clusters correspondance ... " << std::flush; + for (int frame = 0; frame < clusTree->GetEntriesFast(); frame++) { // Cluster frames + if (!clusTree->GetEvent(frame)) { + continue; + } + + for (unsigned int iClus{0}; iClus < clusArr->size(); ++iClus) { + auto lab = (clusLabArr->getLabels(iClus))[0]; + if (!lab.isValid() || lab.getSourceID() != 0 || !lab.isCorrect()) { + continue; + } + + int trackID, evID, srcID; + bool fake; + lab.get(trackID, evID, srcID, fake); + if (evID < 0 || evID >= (int)info.size()) { + std::cout << "Cluster MC label eventID out of range" << std::endl; + continue; + } + if (trackID < 0 || trackID >= (int)info[evID].size()) { + std::cout << "Cluster MC label trackID out of range" << std::endl; + continue; + } + + const CompClusterExt& c = (*clusArr)[iClus]; + auto layer = gman->getLayer(c.getSensorID()); + info[evID][trackID].clusters |= 1 << layer; + } + } + std::cout << "done." << std::endl; + + std::cout << "** Analysing tracks... " << std::flush; + int unaccounted{0}, good{0}, fakes{0}, total{0}, length{0}; + for (int frame = 0; frame < recTree->GetEntriesFast(); frame++) { // Cluster frames + if (!recTree->GetEvent(frame)) { + continue; + } + total += trkLabArr->size(); + for (unsigned int iTrack{0}; iTrack < trkLabArr->size(); ++iTrack) { + auto lab = trkLabArr->at(iTrack); + if (!lab.isSet()) { + unaccounted++; + continue; + } + lab.get(trackID, evID, srcID, fake); + if (evID < 0 || evID >= (int)info.size()) { + unaccounted++; + continue; + } + if (trackID < 0 || trackID >= (int)info[evID].size()) { + unaccounted++; + continue; + } + info[evID][trackID].isReco += !fake; + info[evID][trackID].isFake += fake; + /// We keep the best track we would keep in the data + if (recArr->at(iTrack).isBetter(info[evID][trackID].track, 1.e9)) { + info[evID][trackID].track = recArr->at(iTrack); + info[evID][trackID].storedStatus = fake; + static float ip[2]{0., 0.}; + info[evID][trackID].track.getImpactParams(info[evID][trackID].pvx, info[evID][trackID].pvy, info[evID][trackID].pvz, bz, ip); + info[evID][trackID].dcaxy = ip[0]; + info[evID][trackID].dcaz = ip[1]; + } + + fakes += fake; + good += !fake; + if (!fake) { + for (unsigned int bit{0}; bit < 7; ++bit) { + length += bool(info[evID][trackID].clusters & (1 << bit)); + } + } + } + } + std::cout << "done." << std::endl; + std::cout << "** Some statistics:" << std::endl; + std::cout << "\t- Total number of tracks: " << total << std::endl; + std::cout << "\t- Total number of tracks not corresponding to particles: " << unaccounted << " (" << unaccounted * 100. / total << "%)" << std::endl; + std::cout << "\t- Total number of fakes: " << fakes << " (" << fakes * 100. / total << "%)" << std::endl; + std::cout << "\t- Total number of good: " << good << " (" << good * 100. / total << "%)" << std::endl; + std::cout << "\t- Average length of good tracks: " << (double)length / (double)good << std::endl; + + TFile* fOut{nullptr}; + if (write) { + fOut = TFile::Open("checkDROF.root", "RECREATE"); + } + + const int nb = 100; + double xbins[nb + 1], ptcutl = 0.01, ptcuth = 10.; + double a = std::log(ptcuth / ptcutl) / nb; + for (int i = 0; i <= nb; i++) { + xbins[i] = ptcutl * std::exp(i * a); + } + + ////////////////////// + // Eff Tracks + { + auto num = new TH2D("num", ";#it{p}_{T} (GeV/#it{c});NCls;Efficiency (fake-track rate)", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + num->Sumw2(); + auto fak = new TH2D("fak", ";#it{p}_{T} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + fak->Sumw2(); + auto multiFak = new TH2D("multiFak", ";#it{p}_{T} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + multiFak->Sumw2(); + auto clone = new TH2D("clone", ";#it{p}_{T} (GeV/#it{c});NCls;Clone", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + clone->Sumw2(); + auto den = new TH2D("den", ";#it{p}_{T} (GeV/#it{c});NCls;Den", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + den->Sumw2(); + auto numMC = new TH2D("numMC", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Efficiency (fake-track rate)", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + numMC->Sumw2(); + auto fakMC = new TH2D("fakMC", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + fakMC->Sumw2(); + auto multiFakMC = new TH2D("multiFakMC", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + multiFakMC->Sumw2(); + auto cloneMC = new TH2D("cloneMC", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Clone", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + cloneMC->Sumw2(); + auto denMC = new TH2D("denMC", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Den", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + denMC->Sumw2(); + + auto numVal = new TH2D("numVal", ";#it{p}_{T} (GeV/#it{c});NCls;Efficiency (fake-track rate)", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + numVal->Sumw2(); + auto fakVal = new TH2D("fakVal", ";#it{p}_{T} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + fakVal->Sumw2(); + auto multiFakVal = new TH2D("multiFakVal", ";#it{p}_{T} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + multiFakVal->Sumw2(); + auto cloneVal = new TH2D("cloneVal", ";#it{p}_{T} (GeV/#it{c});NCls;Clone", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + cloneVal->Sumw2(); + auto denVal = new TH2D("denVal", ";#it{p}_{T} (GeV/#it{c});NCls;Den", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + denVal->Sumw2(); + auto numMCVal = new TH2D("numMCVal", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Efficiency (fake-track rate)", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + numMCVal->Sumw2(); + auto fakMCVal = new TH2D("fakMCVal", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + fakMCVal->Sumw2(); + auto multiFakMCVal = new TH2D("multiFakMCVal", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + multiFakMCVal->Sumw2(); + auto cloneMCVal = new TH2D("cloneMCVal", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Clone", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + cloneMCVal->Sumw2(); + auto denMCVal = new TH2D("denMCVal", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Den", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + denMCVal->Sumw2(); + + auto numMig = new TH2D("numMig", ";#it{p}_{T} (GeV/#it{c});NCls;Efficiency (fake-track rate)", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + numMig->Sumw2(); + auto fakMig = new TH2D("fakMig", ";#it{p}_{T} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + fakMig->Sumw2(); + auto multiFakMig = new TH2D("multiFakMig", ";#it{p}_{T} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + multiFakMig->Sumw2(); + auto cloneMig = new TH2D("cloneMig", ";#it{p}_{T} (GeV/#it{c});NCls;Clone", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + cloneMig->Sumw2(); + auto denMig = new TH2D("denMig", ";#it{p}_{T} (GeV/#it{c});NCls;Den", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + denMig->Sumw2(); + auto numMCMig = new TH2D("numMCMig", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Efficiency (fake-track rate)", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + numMCMig->Sumw2(); + auto fakMCMig = new TH2D("fakMCMig", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + fakMCMig->Sumw2(); + auto multiFakMCMig = new TH2D("multiFakMCMig", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Fak", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + multiFakMCMig->Sumw2(); + auto cloneMCMig = new TH2D("cloneMCMig", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Clone", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + cloneMCMig->Sumw2(); + auto denMCMig = new TH2D("denMCMig", ";#it{p}_{T,MC} (GeV/#it{c});NCls;Den", nb, xbins, 4, 4 - 0.5, 8 - 0.5); + denMCMig->Sumw2(); + + TProfile* avgClsZ = new TProfile("avgClsZ", "good attachment;z_{MC};", 25, -20, 20); + avgClsZ->SetLineColor(kBlack); + TProfile* avgClsZGood = new TProfile("avgClsZGood", "good attachment;z_{MC};", 25, -20, 20); + avgClsZGood->SetLineColor(kBlue); + TProfile* avgClsZFake = new TProfile("avgClsZFake", "fake attachment;z_{MC};", 25, -20, 20); + avgClsZFake->SetLineColor(kRed); + + for (auto& evInfo : info) { + for (auto& part : evInfo) { + if (!part.isReconstructable()) { + continue; + } + den->Fill(part.track.getPt(), part.track.getNClusters()); + denMC->Fill(part.pt, part.track.getNClusters()); + if (part.isReco) { + num->Fill(part.track.getPt(), part.track.getNClusters()); + numMC->Fill(part.pt, part.track.getNClusters()); + if (part.isReco > 1) { + for (int _i{0}; _i < part.isReco - 1; ++_i) { + clone->Fill(part.track.getPt(), part.track.getNClusters()); + cloneMC->Fill(part.pt, part.track.getNClusters()); + } + } + } + if (part.isFake) { + fak->Fill(part.track.getPt(), part.track.getNClusters()); + fakMC->Fill(part.pt, part.track.getNClusters()); + if (part.isFake > 1) { + for (int _i{0}; _i < part.isFake - 1; ++_i) { + multiFak->Fill(part.track.getPt(), part.track.getNClusters()); + multiFakMC->Fill(part.pt, part.track.getNClusters()); + } + } + } + + // sep into validation and migration region + if (bcValStart < part.bcInROF && part.bcInROF < bcValEnd) { + denVal->Fill(part.track.getPt(), part.track.getNClusters()); + denMCVal->Fill(part.pt, part.track.getNClusters()); + if (part.isReco) { + numVal->Fill(part.track.getPt(), part.track.getNClusters()); + numMCVal->Fill(part.pt, part.track.getNClusters()); + if (part.isReco > 1) { + for (int _i{0}; _i < part.isReco - 1; ++_i) { + cloneVal->Fill(part.track.getPt(), part.track.getNClusters()); + cloneMCVal->Fill(part.pt, part.track.getNClusters()); + } + } + } + if (part.isFake) { + fakVal->Fill(part.track.getPt(), part.track.getNClusters()); + fakMCVal->Fill(part.pt, part.track.getNClusters()); + if (part.isFake > 1) { + for (int _i{0}; _i < part.isFake - 1; ++_i) { + multiFakVal->Fill(part.track.getPt(), part.track.getNClusters()); + multiFakMCVal->Fill(part.pt, part.track.getNClusters()); + } + } + } + } else { + denMig->Fill(part.track.getPt(), part.track.getNClusters()); + denMCMig->Fill(part.pt, part.track.getNClusters()); + if (part.isReco) { + numMig->Fill(part.track.getPt(), part.track.getNClusters()); + numMCMig->Fill(part.pt, part.track.getNClusters()); + if (part.isReco > 1) { + for (int _i{0}; _i < part.isReco - 1; ++_i) { + cloneMig->Fill(part.track.getPt(), part.track.getNClusters()); + cloneMCMig->Fill(part.pt, part.track.getNClusters()); + } + } + } + if (part.isFake) { + fakMig->Fill(part.track.getPt(), part.track.getNClusters()); + fakMCMig->Fill(part.pt, part.track.getNClusters()); + if (part.isFake > 1) { + for (int _i{0}; _i < part.isFake - 1; ++_i) { + multiFakMig->Fill(part.track.getPt(), part.track.getNClusters()); + multiFakMCMig->Fill(part.pt, part.track.getNClusters()); + } + } + } + } + + int nCl = part.getNClusters(); + avgClsZ->Fill(part.pvz, nCl); + if (part.isReco) { + avgClsZGood->Fill(part.pvz, nCl); + } + if (part.isFake) { + avgClsZFake->Fill(part.pvz, nCl); + } + } + } + + auto sum = (TH2D*)num->Clone("sum"); + auto sumMC = (TH2D*)numMC->Clone("sumMC"); + sum->Add(fak); + sumMC->Add(fakMC); + sum->SetLineColor(kBlack); + sumMC->SetLineColor(kBlack); + fak->SetLineColor(2); + fakMC->SetLineColor(2); + multiFak->SetLineColor(kRed + 1); + multiFakMC->SetLineColor(kRed + 1); + + auto sumVal = (TH2D*)numVal->Clone("sumVal"); + auto sumMCVal = (TH2D*)numMCVal->Clone("sumMCVal"); + sumVal->Add(fakVal); + sumMCVal->Add(fakMCVal); + sumVal->SetLineColor(kBlack); + sumMCVal->SetLineColor(kBlack); + fakVal->SetLineColor(2); + fakMCVal->SetLineColor(2); + multiFakVal->SetLineColor(kRed + 1); + multiFakMCVal->SetLineColor(kRed + 1); + + auto sumMig = (TH2D*)numMig->Clone("sumMig"); + auto sumMCMig = (TH2D*)numMCMig->Clone("sumMCMig"); + sumMig->Add(fakMig); + sumMCMig->Add(fakMCMig); + sumMig->SetLineColor(kBlack); + sumMCMig->SetLineColor(kBlack); + fakMig->SetLineColor(2); + fakMCMig->SetLineColor(2); + multiFakMig->SetLineColor(kRed + 1); + multiFakMCMig->SetLineColor(kRed + 1); + + if (write) { + num->Write(); + den->Write(); + sum->Write(); + fak->Write(); + multiFak->Write(); + numMC->Write(); + denMC->Write(); + sumMC->Write(); + fakMC->Write(); + multiFakMC->Write(); + + numVal->Write(); + denVal->Write(); + sumVal->Write(); + fakVal->Write(); + multiFakVal->Write(); + numMCVal->Write(); + denMCVal->Write(); + sumMCVal->Write(); + fakMCVal->Write(); + multiFakMCVal->Write(); + + numMig->Write(); + denMig->Write(); + sumMig->Write(); + fakMig->Write(); + multiFakMig->Write(); + numMCMig->Write(); + denMCMig->Write(); + sumMCMig->Write(); + fakMCMig->Write(); + multiFakMCMig->Write(); + } else { + TCanvas* c1 = new TCanvas; + c1->SetLogx(); + c1->SetGrid(); + gPad->DrawFrame(ptcutl, 0.05, ptcuth, 1.03, ";#it{p}_{T} (GeV/#it{c});Efficiency (fake-track rate)"); + + auto denp = den->ProjectionX(); + auto nump = num->ProjectionX(); + auto fakp = fak->ProjectionX(); + auto multiFakp = multiFak->ProjectionX(); + auto sump = sum->ProjectionX(); + auto clonep = clone->ProjectionX(); + + sump->Divide(sump, denp, 1, 1, "B"); + sump->Draw("hist;same"); + nump->Divide(nump, denp, 1, 1, "B"); + nump->Draw("hist;same"); + fakp->Divide(fakp, denp, 1, 1, "B"); + fakp->Draw("hist;same"); + multiFakp->Divide(multiFakp, denp, 1, 1, "B"); + multiFakp->Draw("hist;same"); + clonep->Divide(clonep, denp, 1, 1, "B"); + clonep->SetLineColor(3); + clonep->Draw("hist;same"); + + TCanvas* c2 = new TCanvas; + c2->Divide(2, 1); + c2->cd(1); + hZvertex->Draw(); + c2->cd(2); + avgClsZ->Draw(); + avgClsZGood->Draw("same"); + avgClsZFake->Draw("same"); + } + } + + ////////////////////// + // DROF Tracks + { + auto hBC = new TH1F("hBC", "Distance in BC;bcInROF;counts.", roFbins, -0.5, roFbins - 0.5); + auto hBCTracksDen = new TH2F("hBCTracksDen", "BC Den Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + auto hBCTracksNum = new TH2F("hBCTracksNum", "BC Num Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + auto hBCTracksFake = new TH2F("hBCTracksFake", "BC Fake Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + auto hBCTracksSum = new TH2F("hBCTracksSum", "BC Sum Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + + // control region + auto hBCTracksDenVal = new TH2F("hBCTracksDenVal", "Val BC Den Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + auto hBCTracksNumVal = new TH2F("hBCTracksNumVal", "Val BC Num Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + auto hBCTracksFakeVal = new TH2F("hBCTracksFakeVal", "Val BC Fake Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + auto hBCTracksSumVal = new TH2F("hBCTracksSumVal", "Val BC Sum Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + + // migration region + auto hBCTracksDenMig = new TH2F("hBCTracksDenMig", "MigBC Den Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + auto hBCTracksNumMig = new TH2F("hBCTracksNumMig", "MigBC Num Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + auto hBCTracksFakeMig = new TH2F("hBCTracksFakeMig", "MigBC Fake Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + auto hBCTracksSumMig = new TH2F("hBCTracksSumMig", "MigBC Sum Tracks;bcInROF;NCls;eff.", roFbins, -0.5, roFbins - 0.5, 4, 4 - 0.5, 8 - 0.5); + + for (auto& evInfo : info) { + for (auto& part : evInfo) { + if (!part.isReconstructable()) { + continue; + } + hBC->Fill(part.bcInROF); + hBCTracksDen->Fill(part.bcInROF, part.track.getNClusters()); + if (part.isReco) { + hBCTracksNum->Fill(part.bcInROF, part.track.getNClusters()); + } + if (part.isFake) { + hBCTracksFake->Fill(part.bcInROF, part.track.getNClusters()); + } + + if (bcValStart < part.bcInROF && part.bcInROF < bcValEnd) { + hBCTracksDenVal->Fill(part.bcInROF, part.track.getNClusters()); + if (part.isReco) { + hBCTracksNumVal->Fill(part.bcInROF, part.track.getNClusters()); + } + if (part.isFake) { + hBCTracksFakeVal->Fill(part.bcInROF, part.track.getNClusters()); + } + } else { + hBCTracksDenMig->Fill(part.bcInROF, part.track.getNClusters()); + if (part.isReco) { + hBCTracksNumMig->Fill(part.bcInROF, part.track.getNClusters()); + } + if (part.isFake) { + hBCTracksFakeMig->Fill(part.bcInROF, part.track.getNClusters()); + } + } + } + } + + hBCTracksSum->Add(hBCTracksNum); + hBCTracksSum->Add(hBCTracksFake); + hBCTracksSum->SetLineColor(kBlack); + hBCTracksFake->SetLineColor(2); + + hBCTracksSumVal->Add(hBCTracksNum); + hBCTracksSumVal->Add(hBCTracksFake); + hBCTracksSumVal->SetLineColor(kBlack); + hBCTracksFakeVal->SetLineColor(2); + + hBCTracksSumMig->Add(hBCTracksNum); + hBCTracksSumMig->Add(hBCTracksFake); + hBCTracksSumMig->SetLineColor(kBlack); + hBCTracksFakeMig->SetLineColor(2); + + if (write) { + hBCTracksDen->Write(); + hBCTracksNum->Write(); + hBCTracksFake->Write(); + hBCTracksSum->Write(); + + hBCTracksDenVal->Write(); + hBCTracksNumVal->Write(); + hBCTracksFakeVal->Write(); + hBCTracksSumVal->Write(); + + hBCTracksDenMig->Write(); + hBCTracksNumMig->Write(); + hBCTracksFakeMig->Write(); + hBCTracksSumMig->Write(); + } else { + auto hBCTracksDenp = hBCTracksDen->ProjectionX(); + auto hBCTracksSump = hBCTracksSum->ProjectionX(); + auto hBCTracksNump = hBCTracksNum->ProjectionX(); + auto hBCTracksFakep = hBCTracksFake->ProjectionX(); + + hBCTracksSump->Divide(hBCTracksSump, hBCTracksDenp, 1., 1., "B"); + hBCTracksNump->Divide(hBCTracksNump, hBCTracksDenp, 1., 1., "B"); + hBCTracksFakep->Divide(hBCTracksFakep, hBCTracksDenp, 1., 1., "B"); + + auto c = new TCanvas; + c->Divide(2, 1); + c->cd(1); + hBC->Draw(); + c->cd(2); + gPad->DrawFrame(-0.5, 1e-3, roFbins - 0.5, 1.1, "Tracking >4 ITS cls;bcInROF;eff."); + gPad->SetGrid(); + hBCTracksSump->Draw("histe;same"); + hBCTracksNump->Draw("histe;same"); + hBCTracksFakep->Draw("histe;same"); + auto leg = new TLegend; + leg->AddEntry(hBCTracksSump, "Sum"); + leg->AddEntry(hBCTracksNump, "Good"); + leg->AddEntry(hBCTracksFakep, "Fake"); + leg->Draw(); + } + } + + ////////////////////// + // DROF Vertices + if constexpr (false) { + std::vector vertexInfo; + std::cout << "** Creating vertices/particles correspondance ... " << std::flush; + for (int frame = 0; frame < recTree->GetEntriesFast(); frame++) { // Vertices frames + if (!recTree->GetEvent(frame)) { + continue; + } + int contLabIdx{0}; // contributor labels are stored as flat vector + for (size_t iRecord{0}; iRecord < recVerROFArr->size(); ++iRecord) { + auto& rec = recVerROFArr->at(iRecord); + auto verStartIdx = rec.getFirstEntry(), verSize = rec.getNEntries(); + for (int iVertex{rec.getFirstEntry()}; iVertex < verStartIdx + verSize; ++iVertex) { + auto& info = vertexInfo.emplace_back(); + info.vertex = recVerArr->at(iVertex); + info.mainLabel = recVerLabelsArr->at(contLabIdx); + info.purity = recVerPurityArr->at(contLabIdx); + info.event = info.mainLabel.getEventID(); + ++contLabIdx; + if (info.mainLabel.isSet()) { + const auto& ir = irs[info.event]; + // LOGP(info, "iROF={} {} to {}", iRecord, info.mainLabel.asString(), ir.asString()); + if (!ir.isDummy()) { + info.bcInROF = (ir.toLong() - roFrameBiasInBC) % roFrameLengthInBC; + info.rofId = (ir.toLong() - roFrameBiasInBC) / roFrameLengthInBC; + } + } + } + } + } + std::cout << "done." << std::endl; + + auto hMCVtxZ = new TH1F("hMCVtxZ", "MC Vertex;Z", 50, -16, 16); + auto hReVtxZ = new TH1F("hRecoVtxZ", "Reco Vertex;Z", 50, -16, 16); + + auto hBCVtxDen = new TH1F("hBCVtxDen;bcInROF;eff.", "BC Den Vertices", roFbins, -0.5, roFbins - 0.5); + auto hBCVtxNum = new TH1F("hBCVtxNum;bcInROF;eff.", "BC Num Vertices", roFbins, -0.5, roFbins - 0.5); + + auto hBCVtxZDen = new TH2F("hBCVtxDen;bcInROF;z;eff.", "BC Den Vertices vs. z position", roFbins, -0.5, roFbins - 0.5, 40, -20, 20); + auto hBCVtxZNum = new TH2F("hBCVtxNum;bcInROF;z;eff.", "BC Num Vertices vs. z position", roFbins, -0.5, roFbins - 0.5, 40, -20, 20); + + auto pBCPurity = new TProfile("pBCProfile", ";bcInROF;", roFbins, -0.5, roFbins - 0.5); + auto pBCPurityDup = new TProfile("pBCProfileDup", ";bcInROF;", roFbins, -0.5, roFbins - 0.5); + pBCPurityDup->SetLineColor(kRed); + + auto hVtxMCx = new TH2F("hVtxMCx", ";MC_{x};Vtx_{x}", 100, -0.3, 0.3, 100, -0.3, 0.3); + auto hVtxMCy = new TH2F("hVtxMCy", ";MC_{y};Vtx_{y}", 100, -0.3, 0.3, 100, -0.3, 0.3); + auto hVtxMCz = new TH2F("hVtxMCz", ";MC_{z};Vtx_{z}", 100, -20, 20, 100, -20, 20); + + for (int n = 0; n < nev; n++) { // loop over MC events + mcTree->GetEvent(n); + hMCVtxZ->Fill(mcEvent->GetZ()); + const auto& ir = irs[mcEvent->GetEventID() - 1]; // event id start from 1 + if (!ir.isDummy()) { + int bcInROF = (ir.toLong() - roFrameBiasInBC) % roFrameLengthInBC; + hBCVtxDen->Fill(bcInROF); + hBCVtxZDen->Fill(bcInROF, mcEvent->GetZ()); + } + } + std::unordered_map seenMCEvent; + for (const auto& vtx : vertexInfo) { + ++seenMCEvent[vtx.mainLabel]; + } + // for (const auto& [k, f] : seenMCEvent) { + // LOGP(info, "{}:{} -> {} ({:.1f}%)", k.getSourceID(), k.getEventID(), f, 100.f * ((float)f / (float)vertexInfo.size())); + // } + LOGP(info, "received {} unique vertices", seenMCEvent.size()); + for (const auto& vtx : vertexInfo) { + if (!vtx.mainLabel.isValid() || vtx.bcInROF < 0 || vtx.event < 0) { + continue; + } + mcTree->GetEvent(vtx.event); + hVtxMCx->Fill(mcEvent->GetX(), vtx.vertex.getX()); + hVtxMCy->Fill(mcEvent->GetY(), vtx.vertex.getY()); + hVtxMCz->Fill(mcEvent->GetZ(), vtx.vertex.getZ()); + if (seenMCEvent[vtx.mainLabel] > 1) { + pBCPurityDup->Fill(vtx.bcInROF, vtx.purity); + } else { + hReVtxZ->Fill(vtx.vertex.getZ()); + hBCVtxNum->Fill(vtx.bcInROF); + hBCVtxZNum->Fill(vtx.bcInROF, vtx.vertex.getZ()); + pBCPurity->Fill(vtx.bcInROF, vtx.purity); + } + } + + auto hBCVtxNumClone = (TH1F*)hBCVtxNum->Clone(); + hBCVtxNumClone->SetTitle("unique Vertex;bcInROF;efficiency"); + hBCVtxNum->Divide(hBCVtxNum, hBCVtxDen, 1., 1., "b"); + + auto hBCVtxZNumClone = (TH2F*)hBCVtxZNum->Clone(); + hBCVtxZNumClone->SetTitle("unique Vertex;bcInROF;vtx.z;efficiency"); + hBCVtxZNumClone->Divide(hBCVtxZNum, hBCVtxZDen, 1., 1., "b"); + + hReVtxZ->Sumw2(); + hReVtxZ->SetLineColor(kRed); + + auto c = new TCanvas; + c->Divide(3, 2); + + c->cd(1); + auto hRatioVtxZ = new TRatioPlot(hReVtxZ, hMCVtxZ); + hRatioVtxZ->Draw(); + hRatioVtxZ->GetUpperPad()->cd(); + TLegend* legend = new TLegend(0.3, 0.7, 0.7, 0.85); + legend->SetHeader(Form("MC=%.0f Reco=%.0f", hMCVtxZ->GetEntries(), hReVtxZ->GetEntries())); + legend->AddEntry(hReVtxZ, "Reco", "l"); + legend->AddEntry(hMCVtxZ, "MC", "le"); + legend->Draw(); + gPad->Update(); + double max1 = hReVtxZ->GetMaximum(); + double max2 = hMCVtxZ->GetMaximum(); + double maxY = std::max(max1, max2); + hReVtxZ->GetYaxis()->SetRangeUser(0, maxY * 1.1); + + c->cd(2); + gPad->DrawFrame(-0.5, 1e-3, roFbins - 0.5, 1.1, "Vertex ;bcInROF;eff."); + hBCVtxNum->Draw("histe;same"); + + c->cd(3); + gPad->DrawFrame(-0.5, 1e-3, roFbins - 0.5, 1.1, "Purity;bcInROF;"); + pBCPurity->Draw(); + pBCPurityDup->Draw("same"); + c->Draw(); + + c->cd(4); + hBCVtxDen->Draw(); + c->cd(5); + hBCVtxNumClone->Draw(); + c->cd(6); + hBCVtxZNumClone->Draw(); + c->Draw(); + + c = new TCanvas; + c->Divide(3, 1); + c->cd(1); + hVtxMCx->Draw("colz"); + c->cd(2); + hVtxMCy->Draw("colz"); + c->cd(3); + hVtxMCz->Draw("colz"); + c->Draw(); + } + ////////////////////// + // Fake clusters + if (write) { + const int nby{4}, nbz{7}; + double ybins[nby + 1], zbins[nbz + 1]; + for (int i{0}; i < nby + 1; ++i) { + ybins[i] = (4 + i) - 0.5; + } + for (int i{0}; i < nbz + 1; ++i) { + zbins[i] = (0 + i) - 0.5; + } + auto hFakVal = new TH3D("fakClsVal", "Fake cluster attachment;#it{p}_{T} (GeV/#it{c});NCls;Fake;(fake-cluster rate)", nb, xbins, nby, ybins, nbz, zbins); + auto hFakMig = new TH3D("fakClsMig", "Fake cluster attachment;#it{p}_{T} (GeV/#it{c});NCls;Fake;(fake-cluster rate)", nb, xbins, nby, ybins, nbz, zbins); + + for (auto& event : info) { + for (auto& part : event) { + if (!part.isReconstructable()) { + continue; + } + + const auto& trk = part.track; + for (int iL{0}; iL < 7; ++iL) { + if (!trk.hasHitOnLayer(iL) || !trk.isFakeOnLayer(iL) || (part.clusters & (0x1 << iL)) == 0) { + continue; + } + if (trk.hasHitInNextROF()) { + hFakMig->Fill(trk.getPt(), trk.getNClusters(), iL); + } else { + hFakVal->Fill(trk.getPt(), trk.getNClusters(), iL); + } + } + } + } + + hFakMig->Write(); + hFakVal->Write(); + } + if (fOut) { + fOut->Close(); + } + } else { + auto fWO = TFile::Open("checkDROF_wo.root"); + auto f = TFile::Open("checkDROF_w.root"); + plotHistos(fWO, f, ""); + plotHistos(fWO, f, "Val"); + plotHistos(fWO, f, "Mig"); + } +} + +void plotHistos(TFile* fWO, TFile* f, const char* append) +{ + TLegend* leg; + TH1* h; + const int woStyle = 1001; + const int wStyle = 3003; + const int ww{3840}, hh{2160}; + + const char* titlename = ""; + if (strcmp(append, "Val") == 0) { + titlename = ", Validation region"; + } else if (strcmp(append, "Mig") == 0) { + titlename = ", Migration region"; + } + + auto hWODen2 = fWO->Get(Form("den%s", append)); + hWODen2->SetName(Form("%s_wo", hWODen2->GetName())); + auto hWONum2 = fWO->Get(Form("num%s", append)); + hWONum2->SetName(Form("%s_wo", hWONum2->GetName())); + auto hWOFak2 = fWO->Get(Form("fak%s", append)); + hWOFak2->SetName(Form("%s_wo", hWOFak2->GetName())); + auto hWOSum2 = fWO->Get(Form("sum%s", append)); + hWOSum2->SetName(Form("%s_wo", hWOSum2->GetName())); + auto hWOMultiFak2 = fWO->Get(Form("multiFak%s", append)); + hWOMultiFak2->SetName(Form("%s_wo", hWOMultiFak2->GetName())); + + auto hWODenMC2 = fWO->Get(Form("denMC%s", append)); + hWODenMC2->SetName(Form("%s_wo", hWODenMC2->GetName())); + auto hWONumMC2 = fWO->Get(Form("numMC%s", append)); + hWONumMC2->SetName(Form("%s_wo", hWONumMC2->GetName())); + auto hWOFakMC2 = fWO->Get(Form("fakMC%s", append)); + hWOFakMC2->SetName(Form("%s_wo", hWOFakMC2->GetName())); + auto hWOSumMC2 = fWO->Get(Form("sumMC%s", append)); + hWOSumMC2->SetName(Form("%s_wo", hWOSumMC2->GetName())); + auto hWOMultiFakMC2 = fWO->Get(Form("multiFakMC%s", append)); + hWOMultiFakMC2->SetName(Form("%s_wo", hWOMultiFakMC2->GetName())); + + auto hWOBCTracksDen2 = fWO->Get(Form("hBCTracksDen%s", append)); + hWOBCTracksDen2->SetName(Form("%s_wo", hWOBCTracksDen2->GetName())); + auto hWOBCTracksNum2 = fWO->Get(Form("hBCTracksNum%s", append)); + hWOBCTracksNum2->SetName(Form("%s_wo", hWOBCTracksNum2->GetName())); + auto hWOBCTracksFake2 = fWO->Get(Form("hBCTracksFake%s", append)); + hWOBCTracksFake2->SetName(Form("%s_wo", hWOBCTracksFake2->GetName())); + auto hWOBCTracksSum2 = fWO->Get(Form("hBCTracksSum%s", append)); + hWOBCTracksSum2->SetName(Form("%s_wo", hWOBCTracksSum2->GetName())); + + auto setColor = [](TH1* h, EColor c) { + h->SetLineColor(c); + h->SetMarkerColor(c); + }; + auto hDen2 = f->Get(Form("den%s", append)); + setColor(hDen2, kBlack); + auto hNum2 = f->Get(Form("num%s", append)); + setColor(hNum2, kCyan); + auto hFak2 = f->Get(Form("fak%s", append)); + setColor(hFak2, kOrange); + auto hSum2 = f->Get(Form("sum%s", append)); + setColor(hSum2, kGray); + auto hMultiFak2 = f->Get(Form("multiFak%s", append)); + setColor(hMultiFak2, kMagenta); + + auto hDenMC2 = f->Get(Form("denMC%s", append)); + setColor(hDenMC2, kBlack); + auto hNumMC2 = f->Get(Form("numMC%s", append)); + setColor(hNumMC2, kCyan); + auto hFakMC2 = f->Get(Form("fakMC%s", append)); + setColor(hFakMC2, kOrange); + auto hSumMC2 = f->Get(Form("sumMC%s", append)); + setColor(hSumMC2, kGray); + auto hMultiFakMC2 = f->Get(Form("multiFakMC%s", append)); + setColor(hMultiFakMC2, kMagenta); + + auto hBCTracksDen2 = f->Get(Form("hBCTracksDen%s", append)); + setColor(hBCTracksDen2, kBlack); + auto hBCTracksNum2 = f->Get(Form("hBCTracksNum%s", append)); + setColor(hBCTracksNum2, kCyan); + auto hBCTracksFake2 = f->Get(Form("hBCTracksFake%s", append)); + setColor(hBCTracksFake2, kOrange); + auto hBCTracksSum2 = f->Get(Form("hBCTracksSum%s", append)); + setColor(hBCTracksSum2, kGray); + + int k = 0; + TCanvas *cEff = nullptr, *cBC = nullptr, *cCont = nullptr, *cRatio = nullptr; + { + auto plotTrkEff = [&](int i, int j) { + auto hWONum = hWONumMC2->ProjectionX(Form("%s_%d_%d_eff_px", hWONumMC2->GetName(), i, j), i, j); + auto hWODen = hWODenMC2->ProjectionX(Form("%s_%d_%d_eff_px", hWODenMC2->GetName(), i, j), 0, 5); + auto hWOFak = hWOFakMC2->ProjectionX(Form("%s_%d_%d_eff_px", hWOFakMC2->GetName(), i, j), i, j); + auto hWOMultiFak = hWOMultiFakMC2->ProjectionX(Form("%s_%d_%d_eff_px", hWOMultiFakMC2->GetName(), i, j), i, j); + auto hWOSum = (TH1D*)hWONum->Clone(Form("%s_sum_eff__%d", hWONum->GetName(), j)); + hWOSum->Add(hWOFak); + + hWOSum->Divide(hWOSum, hWODen, 1., 1., "B"); + hWOSum->SetFillColorAlpha(hWOSum2->GetLineColor(), 0.5); + hWOSum->SetFillStyle(woStyle); + hWOSum->Draw("histe;same"); + + hWONum->Divide(hWONum, hWODen, 1., 1., "B"); + hWONum->SetFillColorAlpha(hWONum2->GetLineColor(), 0.5); + hWONum->SetFillStyle(woStyle); + hWONum->Draw("histe;same"); + + hWOFak->Divide(hWOFak, hWODen, 1., 1., "B"); + hWOFak->SetFillColorAlpha(hWOFak2->GetLineColor(), 0.5); + hWOFak->SetFillStyle(woStyle); + hWOFak->Draw("histe;same"); + + hWOMultiFak->Divide(hWOMultiFak, hWODen, 1., 1., "B"); + hWOMultiFak->SetLineColor(hWOMultiFak2->GetLineColor()); + hWOMultiFak->SetFillColorAlpha(hWOMultiFak2->GetLineColor(), 0.5); + hWOMultiFak->SetFillStyle(woStyle); + // hWOMultiFak->Draw("histe;same"); + + auto hNum = hNum2->ProjectionX(Form("%s_%d_%d_eff_px", hNumMC2->GetName(), i, j), i, j); + auto hDen = hDen2->ProjectionX(Form("%s_%d_%d_eff_px", hDenMC2->GetName(), i, j), 0, 5); + auto hFak = hFak2->ProjectionX(Form("%s_%d_%d_eff_px", hFakMC2->GetName(), i, j), i, j); + auto hMultiFak = hMultiFak2->ProjectionX(Form("%s_%d_%d_px", hMultiFakMC2->GetName(), i, j), i, j); + auto hSum = (TH1D*)hNum->Clone(Form("%s_sum_eff_%d", hNum->GetName(), j)); + hSum->Add(hFak); + + hSum->Divide(hSum, hDen, 1., 1., "B"); + hSum->SetFillColor(hSum2->GetLineColor()); + hSum->SetLineColor(hSum2->GetLineColor()); + hSum->SetFillStyle(wStyle); + hSum->Draw("histe;same"); + + hNum->Divide(hNum, hDen, 1., 1., "B"); + hNum->SetFillColor(hNum2->GetLineColor()); + hNum->SetLineColor(hNum2->GetLineColor()); + hNum->SetFillStyle(wStyle); + hNum->Draw("histe;same"); + + hFak->Divide(hFak, hDen, 1., 1., "B"); + hFak->SetFillColor(hFak2->GetLineColor()); + hFak->SetLineColor(hFak2->GetLineColor()); + hFak->SetFillStyle(wStyle); + hFak->Draw("histe;same"); + + hMultiFak->Divide(hMultiFak, hDen, 1., 1., "B"); + hMultiFak->SetLineColor(hMultiFak2->GetLineColor()); + hMultiFak->SetFillColor(hMultiFak2->GetLineColor()); + hMultiFak->SetFillStyle(wStyle); + // hMultiFak->Draw("histe;same"); + + if (i == 1 && i == j) { + leg = new TLegend(0.1, 0.1, 0.9, 0.9); + leg->AddEntry((TObject*)0, "deltaRof=0", ""); + leg->AddEntry(hWOSum, "sum"); + leg->AddEntry(hWONum, "good"); + leg->AddEntry(hWOFak, "fake"); + // leg->AddEntry(hWOMultiFak, "multifake"); + leg->AddEntry((TObject*)0, "deltaRof=1", ""); + leg->AddEntry(hSum, "sum"); + leg->AddEntry(hNum, "good"); + leg->AddEntry(hFak, "fake"); + // leg->AddEntry(hMultiFak, "multifake"); + } + }; + + cEff = new TCanvas(Form("pteff%s", append), "", ww, hh); + cEff->Divide(3, 2); + k = 0; + for (int i{1}; i <= 4; ++i) { + if (i == 3) { + ++k; + } + cEff->cd(i + k); + h = gPad->DrawFrame( + 0.02, 0, 10, 1.02, + Form("Tracking Efficiency #times Fraction (7 MC hits, %d-point " + "tracks%s);#it{p}_{T,MC} GeV/#it{c};eff. (fake-rate)", + 3 + i, titlename)); + h->GetXaxis()->SetTitleOffset(1.4); + + plotTrkEff(i, i); + + gPad->SetLogx(); + gPad->SetGrid(); + gPad->RedrawAxis("g"); + } + cEff->cd(3); + h = gPad->DrawFrame( + 0.02, 0, 10, 1.02, + Form("Tracking Efficiency (7 MC hits, all point " + "tracks%s);#it{p}_{T,MC} GeV/#it{c};eff. (fake-rate)", + titlename)); + h->GetXaxis()->SetTitleOffset(1.4); + + plotTrkEff(1, 4); + + gPad->SetLogx(); + gPad->SetGrid(); + gPad->RedrawAxis("g"); + + cEff->cd(6); + leg->Draw(); + } + + { + auto plotRatios = [&](int i, int j, TPad* upper, TPad* lower) { + auto hWONum = hWONumMC2->ProjectionX(Form("%s_%d_%d_ratio_px", hWONumMC2->GetName(), i, j), i, j); + auto hWOFak = hWOFakMC2->ProjectionX(Form("%s_%d_%d_ratio_px", hWOFakMC2->GetName(), i, j), i, j); + + hWONum->SetFillColorAlpha(hWONum2->GetLineColor(), 0.5); + hWONum->SetLineColor(hWONum2->GetLineColor()); + // hWONum->SetFillStyle(woStyle); + + hWOFak->SetFillColorAlpha(hWOFak2->GetLineColor(), 0.5); + hWOFak->SetLineColor(hWOFak2->GetLineColor()); + // hWOFak->SetFillStyle(woStyle); + + auto hNum = hNum2->ProjectionX(Form("%s_%d_%d_ratio_px", hNumMC2->GetName(), i, j), i, j); + auto hFak = hFak2->ProjectionX(Form("%s_%d_%d_ratio_px", hFakMC2->GetName(), i, j), i, j); + + hNum->SetFillColor(hNum2->GetLineColor()); + hNum->SetLineColor(hNum2->GetLineColor()); + // hNum->SetFillStyle(wStyle); + + hFak->SetFillColor(hFak2->GetLineColor()); + hFak->SetLineColor(hFak2->GetLineColor()); + // hFak->SetFillStyle(wStyle); + // + upper->cd(); + upper->SetLogx(); + upper->SetGrid(); + hWONum->Draw("hist"); + hWOFak->Draw("hist same"); + hNum->Draw("hist same"); + hFak->Draw("hist same"); + double ymax = 1.1 * std::max({hNum->GetMaximum(), hFak->GetMaximum(), hWONum->GetMaximum(), hWOFak->GetMaximum()}); + hWONum->GetYaxis()->SetRangeUser(0, ymax); + gPad->RedrawAxis("g"); + + auto rNum = (TH1*)hNum->Clone(Form("rNum_%s_%d_%d", hNum->GetName(), i, j)); + auto rFak = (TH1*)hFak->Clone(Form("rFak_%s_%d_%d", hFak->GetName(), i, j)); + rNum->GetYaxis()->SetTitle("(deltaRof=1) / (deltaRof=0)"); + rNum->Divide(hWONum); + rFak->Divide(hWOFak); + + // rNum->SetMarkerStyle(20); + // rFak->SetMarkerStyle(21); + rNum->SetLineWidth(2); + rFak->SetLineWidth(2); + rNum->SetFillStyle(0); + rFak->SetFillStyle(0); + setColor(rNum, kBlue); + setColor(rFak, kRed); + double ymin = std::min(rNum->GetMinimum(0.0), rFak->GetMinimum(0.0)); + ymax = std::max(rNum->GetMaximum(), rFak->GetMaximum()); + double ypad = 0.1 * (ymax - ymin); + ymin -= ypad; + ymax += ypad; + + lower->cd(); + lower->SetLogx(); + lower->SetGrid(); + rNum->GetYaxis()->SetRangeUser(ymin, ymax); + rNum->Draw("hist"); + rFak->Draw("hist;same"); + gPad->RedrawAxis("g"); + + if (i == 1 && i == j) { + leg = new TLegend(0.1, 0.1, 0.9, 0.9); + leg->AddEntry((TObject*)0, "deltaRof=0", ""); + leg->AddEntry(hWONum, "good"); + leg->AddEntry(hWOFak, "fake"); + leg->AddEntry((TObject*)0, "deltaRof=1", ""); + leg->AddEntry(hNum, "good"); + leg->AddEntry(hFak, "fake"); + leg->AddEntry((TObject*)0, "Ratios", ""); + leg->AddEntry(rNum, "good", "l"); + leg->AddEntry(rFak, "fake", "l"); + } + }; + + cRatio = new TCanvas(Form("ptratio%s", append), "", ww, hh); + cRatio->Divide(3, 2); + k = 0; + for (int i{1}; i <= 4; ++i) { + if (i == 3) { + ++k; + } + cRatio->cd(i + k); + TPad* up = new TPad(Form("up%d", k), "", 0, 0.5, 1, 1); + TPad* dn = new TPad(Form("dn%d", k), "", 0, 0, 1, 0.5); + up->SetBottomMargin(0); + dn->SetTopMargin(0); + up->Draw(); + dn->Draw(); + + plotRatios(i, i, up, dn); + } + cRatio->cd(3); + TPad* up = new TPad(Form("up_e_%d", k), "", 0, 0.5, 1, 1); + TPad* dn = new TPad(Form("dn_e_%d", k), "", 0, 0, 1, 0.5); + up->SetBottomMargin(0); + dn->SetTopMargin(0); + up->Draw(); + dn->Draw(); + plotRatios(1, 4, up, dn); + + cRatio->cd(6); + leg->Draw(); + } + + { + auto plotTrkCont = [&](int i, int j) { + auto hWONum = hWONum2->ProjectionX(Form("%s_%d_%d_cont_px", hWONum2->GetName(), i, j), i, j); + auto hWODen = hWODen2->ProjectionX(Form("%s_%d_%d_cont_px", hWODen2->GetName(), i, j), 0, 5); + auto hWOFak = hWOFak2->ProjectionX(Form("%s_%d_%d_cont_px", hWOFak2->GetName(), i, j), i, j); + auto hWOMultiFak = hWOMultiFak2->ProjectionX(Form("%s_%d_%d_cont_px", hWOMultiFak2->GetName(), i, j), i, j); + auto hWOSum = (TH1D*)hWONum->Clone(Form("%s_sum_cont_%d", hWONum->GetName(), j)); + hWOSum->Add(hWOFak); + + hWOSum->Divide(hWOSum, hWODen, 1., 1., "B"); + hWOSum->SetFillColorAlpha(hWOSum2->GetLineColor(), 0.5); + hWOSum->SetFillStyle(woStyle); + // hWOSum->Draw("histe;same"); + + hWONum->Divide(hWONum, hWODen, 1., 1., "B"); + hWONum->SetFillColorAlpha(hWONum2->GetLineColor(), 0.5); + hWONum->SetFillStyle(woStyle); + hWONum->Draw("histe;same"); + + hWOFak->Divide(hWOFak, hWODen, 1., 1., "B"); + hWOFak->SetFillColorAlpha(hWOFak2->GetLineColor(), 0.5); + hWOFak->SetFillStyle(woStyle); + hWOFak->Draw("histe;same"); + + hWOMultiFak->Divide(hWOMultiFak, hWODen, 1., 1., "B"); + hWOMultiFak->SetLineColor(hWOMultiFak2->GetLineColor()); + hWOMultiFak->SetFillColorAlpha(hWOMultiFak2->GetLineColor(), 0.5); + hWOMultiFak->SetFillStyle(woStyle); + // hWOMultiFak->Draw("histe;same"); + + auto hNum = hNum2->ProjectionX(Form("%s_%d_%d_cont_px", hNum2->GetName(), i, j), i, j); + auto hDen = hDen2->ProjectionX(Form("%s_%d_%d_cont_px", hDen2->GetName(), i, j), 0, 5); + auto hFak = hFak2->ProjectionX(Form("%s_%d_%d_cont_px", hFak2->GetName(), i, j), i, j); + auto hMultiFak = hMultiFak2->ProjectionX(Form("%s_%d_%d_px", hMultiFak2->GetName(), i, j), i, j); + auto hSum = (TH1D*)hNum->Clone(Form("%s_sum_cont_%d", hNum->GetName(), j)); + hSum->Add(hFak); + + hSum->Divide(hSum, hDen, 1., 1., "B"); + hSum->SetFillColor(hSum2->GetLineColor()); + hSum->SetFillStyle(wStyle); + // hSum->Draw("histe;same"); + + hNum->Divide(hNum, hDen, 1., 1., "B"); + hNum->SetFillColor(hNum2->GetLineColor()); + hNum->SetFillStyle(wStyle); + hNum->Draw("histe;same"); + + hFak->Divide(hFak, hDen, 1., 1., "B"); + hFak->SetFillColor(hFak2->GetLineColor()); + hFak->SetFillStyle(wStyle); + hFak->Draw("histe;same"); + + hMultiFak->Divide(hMultiFak, hDen, 1., 1., "B"); + hMultiFak->SetLineColor(hMultiFak2->GetLineColor()); + hMultiFak->SetFillColor(hMultiFak2->GetLineColor()); + hMultiFak->SetFillStyle(wStyle); + // hMultiFak->Draw("histe;same"); + + if (i == 1 && i == j) { + leg = new TLegend(0.1, 0.1, 0.9, 0.9); + leg->AddEntry((TObject*)0, "deltaRof=0", ""); + leg->AddEntry(hWONum, "good"); + leg->AddEntry(hWOFak, "fake"); + // leg->AddEntry(hWOMultiFak, "multifake"); + leg->AddEntry((TObject*)0, "deltaRof=1", ""); + leg->AddEntry(hNum, "DROF:good"); + leg->AddEntry(hFak, "DROF:fake"); + // leg->AddEntry(hMultiFak, "DROF:multifake"); + } + }; + + cCont = new TCanvas(Form("ptcont%s", append), "", ww, hh); + cCont->Divide(3, 2); + k = 0; + for (int i{1}; i <= 4; ++i) { + if (i == 3) { + ++k; + } + cCont->cd(i + k); + h = gPad->DrawFrame( + 0.02, 0, 10, 1.02, + Form("Tracking Contribution #times Fraction (7 MC hits, %d-point " + "tracks%s);#it{p}_{T,Reco} GeV/#it{c};contribtution", + 3 + i, titlename)); + h->GetXaxis()->SetTitleOffset(1.4); + + plotTrkCont(i, i); + + gPad->SetLogx(); + gPad->SetGrid(); + gPad->RedrawAxis("g"); + } + cCont->cd(3); + h = gPad->DrawFrame(0.02, 0, 10, 1.02, + Form("Tracking Contribution (7 MC hits, all point " + "tracks%s);#it{p}_{T,Reco} GeV/#it{c};contribution", + titlename)); + h->GetXaxis()->SetTitleOffset(1.4); + + plotTrkCont(1, 4); + + gPad->SetLogx(); + gPad->SetGrid(); + gPad->RedrawAxis("g"); + + cCont->cd(6); + leg->Draw(); + } + + { + auto plotBCEff = [&](int i, int j) { + auto hWOBCTracksNum = hWOBCTracksNum2->ProjectionX(Form("%s_%d_%d_bc_px", hWOBCTracksNum2->GetName(), i, j), i, j); + auto hWOBCTracksDen = hWOBCTracksDen2->ProjectionX(Form("%s_%d_%d_bc_px", hWOBCTracksDen2->GetName(), i, j), 0, 5); + auto hWOBCTracksFake = hWOBCTracksFake2->ProjectionX(Form("%s_%d_%d_bc_px", hWOBCTracksFake2->GetName(), i, j), i, j); + auto hWOBCTracksSum = (TH1F*)hWOBCTracksNum->Clone(Form("%s_%d_sum", hWOBCTracksNum->GetName(), j)); + hWOBCTracksSum->Add(hWOBCTracksFake); + + hWOBCTracksSum->Divide(hWOBCTracksSum, hWOBCTracksDen, 1., 1., "B"); + hWOBCTracksSum->SetLineColor(hWOSum2->GetLineColor()); + hWOBCTracksSum->SetFillColorAlpha(hWOSum2->GetLineColor(), 0.5); + hWOBCTracksSum->SetFillStyle(woStyle); + hWOBCTracksSum->Draw("histe;same"); + + hWOBCTracksNum->Divide(hWOBCTracksNum, hWOBCTracksDen, 1., 1., "B"); + hWOBCTracksNum->SetLineColor(hWONum2->GetLineColor()); + hWOBCTracksNum->SetFillColorAlpha(hWONum2->GetLineColor(), 0.5); + hWOBCTracksNum->SetFillStyle(woStyle); + hWOBCTracksNum->Draw("histe;same"); + + hWOBCTracksFake->Divide(hWOBCTracksFake, hWOBCTracksDen, 1., 1., "B"); + hWOBCTracksFake->SetLineColor(hWOFak2->GetLineColor()); + hWOBCTracksFake->SetFillColorAlpha(hWOFak2->GetLineColor(), 0.5); + hWOBCTracksFake->SetFillStyle(woStyle); + hWOBCTracksFake->Draw("histe;same"); + + auto hBCTracksNum = hBCTracksNum2->ProjectionX(Form("%s_%d_%d_bc_px", hBCTracksNum2->GetName(), i, j), i, j); + auto hBCTracksDen = hBCTracksDen2->ProjectionX(Form("%s_%d_%d_bc_px", hBCTracksDen2->GetName(), i, j), 0, 5); + auto hBCTracksFake = hBCTracksFake2->ProjectionX(Form("%s_%d_%d_bc_px", hBCTracksFake2->GetName(), i, j), i, j); + auto hBCTracksSum = (TH1F*)hBCTracksNum->Clone(Form("%s_%d_sum", hBCTracksNum->GetName(), j)); + hBCTracksSum->Add(hBCTracksFake); + + hBCTracksSum->Divide(hBCTracksSum, hBCTracksDen, 1., 1., "B"); + hBCTracksSum->SetLineColor(hSum2->GetLineColor()); + hBCTracksSum->SetFillColor(hSum2->GetLineColor()); + hBCTracksSum->SetFillStyle(wStyle); + hBCTracksSum->Draw("histe;same"); + + hBCTracksNum->Divide(hBCTracksNum, hBCTracksDen, 1., 1., "B"); + hBCTracksNum->SetLineColor(hNum2->GetLineColor()); + hBCTracksNum->SetFillColor(hNum2->GetLineColor()); + hBCTracksNum->SetFillStyle(wStyle); + hBCTracksNum->Draw("histe;same"); + + hBCTracksFake->Divide(hBCTracksFake, hBCTracksDen, 1., 1., "B"); + hBCTracksFake->SetLineColor(hFak2->GetLineColor()); + hBCTracksFake->SetFillColor(hFak2->GetLineColor()); + hBCTracksFake->SetFillStyle(wStyle); + hBCTracksFake->Draw("histe;same"); + + if (i == 1 && i == j) { + leg = new TLegend(0.1, 0.1, 0.9, 0.9); + leg->AddEntry((TObject*)0, "deltaRof=0", ""); + leg->AddEntry(hWOBCTracksNum, "good"); + leg->AddEntry(hWOBCTracksFake, "fake"); + leg->AddEntry(hWOBCTracksSum, "sum"); + leg->AddEntry((TObject*)0, "deltaRof=1", ""); + leg->AddEntry(hBCTracksNum, "good"); + leg->AddEntry(hBCTracksFake, "fake"); + leg->AddEntry(hBCTracksSum, "sum"); + } + }; + + cBC = new TCanvas(Form("bceff%s", append), "", ww, hh); + cBC->Divide(3, 2); + k = 0; + for (int i{1}; i <= 4; ++i) { + if (i == 3) { + ++k; + } + cBC->cd(i + k); + gPad->DrawFrame(-0.5, 0, 200 - 0.5, 1.02, + Form("Tracking Efficiency #times Fraction (#it{p}_{T} " + "integrated, %d-point " + "tracks%s);BC in " + "ROF;eff. (fake-rate)", + 3 + i, titlename)); + plotBCEff(i, i); + gPad->SetGrid(); + gPad->RedrawAxis("g"); + } + cBC->cd(3); + gPad->DrawFrame(-0.5, 0, 200 - 0.5, 1.02, + Form("Tracking Efficiency (#it{p}_{T} " + "integrated, all point " + "tracks%s);BC in " + "ROF;eff. (fake-rate)", + titlename)); + plotBCEff(1, 4); + gPad->SetGrid(); + gPad->RedrawAxis("g"); + + cBC->cd(6); + leg->Draw(); + } + + TString outname = TString::Format("trkeff%s.pdf", append); + cEff->cd(); + cEff->Update(); + cEff->Print(TString::Format("%s(", outname.Data()), "Title:Tracking Efficiency"); + cRatio->cd(); + cRatio->Update(); + cRatio->Print(outname.Data(), "Title:Ratios"); + cCont->cd(); + cCont->Update(); + cCont->Print(outname.Data(), "Title:Contribution"); + cBC->cd(); + cBC->Update(); + cBC->Print(TString::Format("%s)", outname.Data()), "Title:BC"); +} From 792df66197f28e4ee8e25b2a6e35dc954528c807 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 22 Jul 2025 11:07:42 +0200 Subject: [PATCH 173/315] ITS: fix opt. label output if firstOrbit!=0 (#14532) --- .../ITS/tracking/src/VertexerTraits.cxx | 25 ++++++++++++++----- .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 5 +++- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index 409ce8895aa36..1069f1808fb2a 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -25,6 +25,7 @@ #include "SimulationDataFormat/DigitizationContext.h" #include "Steer/MCKinematicsReader.h" #include "ITSMFTBase/DPLAlpideParam.h" +#include "DetectorsRaw/HBFUtils.h" #ifdef VTX_DEBUG #include "TTree.h" @@ -574,16 +575,25 @@ void VertexerTraits::addTruthSeedingVertices() int64_t roFrameBiasInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameBiasInBC; int64_t roFrameLengthInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameLengthInBC; o2::steer::MCKinematicsReader mcReader(dc); - std::map> vertices; + struct VertInfo { + bounded_vector vertices; + bounded_vector srcs; + bounded_vector events; + }; + std::map vertices; for (int iSrc{0}; iSrc < mcReader.getNSources(); ++iSrc) { auto eveId2colId = dc->getCollisionIndicesForSource(iSrc); for (int iEve{0}; iEve < mcReader.getNEvents(iSrc); ++iEve) { const auto& ir = irs[eveId2colId[iEve]]; if (!ir.isDummy()) { // do we need this, is this for diffractive events? const auto& eve = mcReader.getMCEventHeader(iSrc, iEve); - int rofId = (ir.toLong() - roFrameBiasInBC) / roFrameLengthInBC; + int rofId = ((ir - raw::HBFUtils::Instance().getFirstSampledTFIR()).toLong() - roFrameBiasInBC) / roFrameLengthInBC; if (!vertices.contains(rofId)) { - vertices[rofId] = bounded_vector(mMemoryPool.get()); + vertices[rofId] = { + .vertices = bounded_vector(mMemoryPool.get()), + .srcs = bounded_vector(mMemoryPool.get()), + .events = bounded_vector(mMemoryPool.get()), + }; } Vertex vert; vert.setTimeStamp(rofId); @@ -594,7 +604,9 @@ void VertexerTraits::addTruthSeedingVertices() vert.setChi2(1); constexpr float cov = 50e-9; vert.setCov(cov, cov, cov, cov, cov, cov); - vertices[rofId].push_back(vert); + vertices[rofId].vertices.push_back(vert); + vertices[rofId].srcs.push_back(iSrc); + vertices[rofId].events.push_back(iEve); } } } @@ -603,10 +615,11 @@ void VertexerTraits::addTruthSeedingVertices() bounded_vector verts(mMemoryPool.get()); bounded_vector> polls(mMemoryPool.get()); if (vertices.contains(iROF)) { - verts = vertices[iROF]; + const auto& vertInfo = vertices[iROF]; + verts = vertInfo.vertices; nVerts += verts.size(); for (size_t i{0}; i < verts.size(); ++i) { - o2::MCCompLabel lbl; // unset label for now + o2::MCCompLabel lbl(o2::MCCompLabel::maxTrackID(), vertInfo.events[i], vertInfo.srcs[i], false); polls.emplace_back(lbl, 1.f); } } else { diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index c8a785b6a3627..c825ec39d3499 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -15,6 +15,7 @@ #include "Framework/ConfigParamRegistry.h" #include "Framework/CCDBParamSpec.h" #include "ITSWorkflow/TrackerSpec.h" +#include "ITStracking/TrackingConfigParam.h" namespace o2 { @@ -120,10 +121,12 @@ DataProcessorSpec getTrackerSpec(bool useMC, bool useGeom, int trgType, Tracking inputs.emplace_back("itsmclabels", "ITS", "CLUSTERSMCTR", 0, Lifetime::Timeframe); inputs.emplace_back("ITSMC2ROframes", "ITS", "CLUSTERSMC2ROF", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "VERTICESMCTR", 0, Lifetime::Timeframe); - outputs.emplace_back("ITS", "VERTICESMCTRCONT", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "VERTICESMCPUR", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "TRACKSMCTR", 0, Lifetime::Timeframe); outputs.emplace_back("ITS", "ITSTrackMC2ROF", 0, Lifetime::Timeframe); + if (VertexerParamConfig::Instance().outputContLabels) { + outputs.emplace_back("ITS", "VERTICESMCTRCONT", 0, Lifetime::Timeframe); + } } return DataProcessorSpec{ From a69009b82334a2026b025313a0ce109f26874248 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Wed, 23 Jul 2025 08:40:36 +0200 Subject: [PATCH 174/315] Eov for orbitreset (#14534) * dev:orbitReset EOV * clang * fix --- Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx b/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx index 7dedcacbf6047..e35b6574db92f 100644 --- a/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx +++ b/Detectors/CTP/workflowScalers/src/ctp-ccdb-orbit.cxx @@ -124,7 +124,14 @@ int main(int argc, char** argv) ret = api.storeAsTFileAny(&(vect), ccdbPath, metadata, tmin, tmax); } else { std::cout << "Storing:" << ccdbPath << " tmin:" << tmin << " tmax:" << tmax << " ts:" << tt << std::endl; - ret = api.storeAsTFileAny(&(vect), ccdbPath, metadata, tmin, tmax); + std::string filename = "orbitReset.root"; + TClass* tcls = TClass::GetClass(typeid(vect)); + auto ti = tcls->GetTypeInfo(); + auto classname = "std::vector"; + metadata["adjustableEOV"] = "true"; + ret = api.storeAsTFile_impl(&(vect), *ti, ccdbPath, metadata, tmin, tmax); + o2::ccdb::CcdbObjectInfo oi(ccdbPath, classname, filename, metadata, tmin, tmax); + adjustOverriddenEOV(api, oi); } } // From 6cd3538c18db2d09279f44baf5db796b4d59fcf0 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Wed, 23 Jul 2025 13:55:10 +0530 Subject: [PATCH 175/315] Added Lambda1520 PDG code to PhysicsConstants.h (#14377) * Added Lambda1520 PDG code to PhysicsConstants.h * Added Lambda1520 PDG - following standard procedure * rollback the changes * Added Lambda1520 to the header * Update PhysicsConstants.h * Updated block with output * Update kLambda1520_Py * Added kLambda1520_Py * Updated --- Common/Constants/include/CommonConstants/PhysicsConstants.h | 4 +++- Common/Constants/include/CommonConstants/make_pdg_header.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Common/Constants/include/CommonConstants/PhysicsConstants.h b/Common/Constants/include/CommonConstants/PhysicsConstants.h index da34230662ef6..f0198f7a7f61d 100644 --- a/Common/Constants/include/CommonConstants/PhysicsConstants.h +++ b/Common/Constants/include/CommonConstants/PhysicsConstants.h @@ -88,7 +88,8 @@ enum Pdg { kHyperHydrogen4 = 1010010040, kHyperHelium4 = 1010020040, kHyperHelium5 = 1010020050, - kHyperHelium4Sigma = 1110020040 + kHyperHelium4Sigma = 1110020040, + kLambda1520_Py = 102134 }; /// \brief Declarations of masses for additional particles @@ -150,6 +151,7 @@ constexpr double MassHyperHydrogen4 = 3.922434; constexpr double MassHyperHelium4 = 3.921728; constexpr double MassHyperHelium5 = 4.839961; constexpr double MassHyperHelium4Sigma = 3.995; +constexpr double MassLambda1520_Py = 1.5195; /// \brief Declarations of masses for particles in ROOT PDG_t constexpr double MassDown = 0.00467; diff --git a/Common/Constants/include/CommonConstants/make_pdg_header.py b/Common/Constants/include/CommonConstants/make_pdg_header.py index b94cc34599d5e..ad24d66e2c3a5 100755 --- a/Common/Constants/include/CommonConstants/make_pdg_header.py +++ b/Common/Constants/include/CommonConstants/make_pdg_header.py @@ -144,7 +144,7 @@ class Pdg(Enum): kHyperHelium4 = 1010020040 kHyperHelium5 = 1010020050 kHyperHelium4Sigma = 1110020040 - + kLambda1520_Py = 102134 # PYTHIA code different from PDG dbPdg = ROOT.o2.O2DatabasePDG From 7fce8d8ff491bfd15c7b2189b78dcbc86e614a1e Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 23 Jul 2025 21:57:48 +0200 Subject: [PATCH 176/315] ITS: last mod. for deltaROF and perVertex (#14538) --- .../include/ITStracking/BoundedAllocator.h | 8 + .../ITS/tracking/include/ITStracking/Cell.h | 28 +- .../include/ITStracking/ClusterLines.h | 8 +- .../tracking/include/ITStracking/TimeFrame.h | 9 +- .../tracking/include/ITStracking/Tracklet.h | 22 +- .../include/ITStracking/VertexerTraits.h | 5 + .../ITSMFT/ITS/tracking/src/TimeFrame.cxx | 47 +- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 4 +- .../ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 360 ++++++++------ .../ITS/tracking/src/TrackingInterface.cxx | 4 +- .../ITS/tracking/src/VertexerTraits.cxx | 452 ++++++++++++------ 11 files changed, 583 insertions(+), 364 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/BoundedAllocator.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/BoundedAllocator.h index eced0c64c73a5..ac9f72089602d 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/BoundedAllocator.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/BoundedAllocator.h @@ -174,6 +174,14 @@ void clearResizeBoundedArray(std::array, S>& arr, size_t size, } } +template +std::vector toSTDVector(const bounded_vector& b) +{ + std::vector t(b.size()); + std::copy(b.cbegin(), b.cend(), t.begin()); + return t; +} + } // namespace o2::its #endif diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h index d81ba4426ca55..fcea96abbfa82 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Cell.h @@ -15,12 +15,8 @@ #ifndef TRACKINGITSU_INCLUDE_CACELL_H_ #define TRACKINGITSU_INCLUDE_CACELL_H_ -#ifndef GPUCA_GPUCODE_DEVICE -#include -#include -#include -#endif +#include "ITStracking/Constants.h" #include "GPUCommonDef.h" namespace o2::its @@ -39,12 +35,12 @@ class Cell final GPUhd() int* getLevelPtr() { return &mLevel; } private: - int mFirstClusterIndex{0}; - int mSecondClusterIndex{0}; - int mThirdClusterIndex{0}; - int mFirstTrackletIndex{0}; - int mSecondTrackletIndex{0}; - int mLevel{0}; + int mFirstClusterIndex{constants::UnusedIndex}; + int mSecondClusterIndex{constants::UnusedIndex}; + int mThirdClusterIndex{constants::UnusedIndex}; + int mFirstTrackletIndex{constants::UnusedIndex}; + int mSecondTrackletIndex{constants::UnusedIndex}; + int mLevel{constants::UnusedIndex}; }; class CellSeed final : public o2::track::TrackParCovF @@ -82,14 +78,14 @@ class CellSeed final : public o2::track::TrackParCovF GPUhd() int getCluster(int i) const { return mClusters[i]; } GPUhd() void printCell() const { - printf("trkl: %d, %d\t lvl: %d\t chi2: %f\n", mTracklets[0], mTracklets[1], mLevel, mChi2); + printf("trkl: %d, %d\t lvl: %d\t chi2: %f\tcls: [%d | %d | %d | %d | %d | %d | %d]\n", mTracklets[0], mTracklets[1], mLevel, mChi2, mClusters[0], mClusters[1], mClusters[2], mClusters[3], mClusters[4], mClusters[5], mClusters[6]); } private: - float mChi2 = 0.f; - int mLevel = 0; - int mTracklets[2] = {-1, -1}; - int mClusters[7] = {-1, -1, -1, -1, -1, -1, -1}; + float mChi2 = -999.f; + int mLevel = constants::UnusedIndex; + int mTracklets[2] = {constants::UnusedIndex, constants::UnusedIndex}; + int mClusters[7] = {constants::UnusedIndex, constants::UnusedIndex, constants::UnusedIndex, constants::UnusedIndex, constants::UnusedIndex, constants::UnusedIndex, constants::UnusedIndex}; }; } // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h index 3ffeda9adcfd5..0e7ad474ae455 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/ClusterLines.h @@ -42,8 +42,8 @@ struct Line final { bool operator!=(const Line&) const; short getMinROF() const { return rof[0] < rof[1] ? rof[0] : rof[1]; } - float originPoint[3] = {0}; - float cosinesDirector[3] = {0}; + float originPoint[3] = {0, 0, 0}; + float cosinesDirector[3] = {0, 0, 0}; // float weightMatrix[6] = {1., 0., 0., 1., 0., 1.}; // weightMatrix is a symmetric matrix internally stored as // 0 --> row = 0, col = 0 @@ -52,7 +52,7 @@ struct Line final { // 3 --> 1,1 // 4 --> 1,2 // 5 --> 2,2 - short rof[2] = {-1, -1}; + short rof[2] = {constants::UnusedIndex, constants::UnusedIndex}; ClassDefNV(Line, 1); }; @@ -207,7 +207,7 @@ class ClusterLines final std::array mRMS2 = {0.f}; // symmetric matrix: diagonal is RMS2 float mAvgDistance2 = 0.f; // substitute for chi2 int mROFWeight = 0; // rof weight for voting - short mROF = -1; // rof + short mROF = constants::UnusedIndex; // rof }; } // namespace o2::its diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h index 9434fc2292750..3f0d291d5e51d 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h @@ -77,11 +77,9 @@ struct TimeFrame { gsl::span> getPrimaryVerticesXAlpha(int rofId) const; void fillPrimaryVerticesXandAlpha(); int getPrimaryVerticesNum(int rofId = -1) const; - void addPrimaryVertices(const bounded_vector& vertices); void addPrimaryVerticesLabels(bounded_vector>& labels); void addPrimaryVerticesContributorLabels(bounded_vector& labels); - void addPrimaryVertices(const bounded_vector& vertices, const int rofId, const int iteration); - void addPrimaryVertices(const gsl::span& vertices, const int rofId, const int iteration); + void addPrimaryVertices(const bounded_vector& vertices, const int iteration); void addPrimaryVerticesInROF(const bounded_vector& vertices, const int rofId, const int iteration); void addPrimaryVerticesLabelsInROF(const bounded_vector>& labels, const int rofId); void addPrimaryVerticesContributorLabelsInROF(const bounded_vector& labels, const int rofId); @@ -397,7 +395,8 @@ inline gsl::span TimeFrame::getPrimaryVertices(int romin, if (mPrimaryVertices.empty()) { return {}; } - return {&mPrimaryVertices[mROFramesPV[romin]], static_cast::size_type>(mROFramesPV[romax + 1] - mROFramesPV[romin])}; + const int stop_idx = romax >= mNrof - 1 ? mNrof : romax + 1; + return {&mPrimaryVertices[mROFramesPV[romin]], static_cast::size_type>(mROFramesPV[stop_idx] - mROFramesPV[romin])}; } template @@ -594,7 +593,7 @@ inline gsl::span TimeFrame::getExclusiveNTrackletsCluster(int rofI template inline gsl::span TimeFrame::getFoundTracklets(int rofId, int combId) { - if (rofId < 0 || rofId >= mNrof) { + if (rofId < 0 || rofId >= mNrof || mTracklets[combId].empty()) { return {}; } auto startIdx{mNTrackletsPerROF[combId][rofId]}; diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h index ba3474e6e86c6..5741a9fc65947 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h @@ -16,6 +16,7 @@ #ifndef TRACKINGITS_INCLUDE_TRACKLET_H_ #define TRACKINGITS_INCLUDE_TRACKLET_H_ +#include "ITStracking/Constants.h" #include "ITStracking/Cluster.h" #include "GPUCommonRtypes.h" #include "GPUCommonMath.h" @@ -41,9 +42,10 @@ struct Tracklet final { { return firstClusterIndex < 0 || secondClusterIndex < 0; } + GPUhdi() auto getMinRof() const noexcept { return o2::gpu::CAMath::Min(rof[0], rof[1]); } + GPUhdi() auto getMaxRof() const noexcept { return o2::gpu::CAMath::Max(rof[0], rof[1]); } GPUhdi() auto getDeltaRof() const { return rof[1] - rof[0]; } - GPUhdi() void dump() const; - GPUhdi() void dump(const int, const int) const; + GPUhdi() auto getSpanRof(const Tracklet& o) const noexcept { return o2::gpu::CAMath::Max(getMaxRof(), o.getMaxRof()) - o2::gpu::CAMath::Min(getMinRof(), o.getMinRof()); } GPUhdi() unsigned char operator<(const Tracklet&) const; #if !defined(GPUCA_NO_FMT) && !defined(GPUCA_GPUCODE_DEVICE) std::string asString() const @@ -53,11 +55,11 @@ struct Tracklet final { void print() const { LOG(info) << asString(); } #endif - int firstClusterIndex{-1}; - int secondClusterIndex{-1}; + int firstClusterIndex{constants::UnusedIndex}; + int secondClusterIndex{constants::UnusedIndex}; float tanLambda{-999}; float phi{-999}; - short rof[2] = {-1, -1}; + short rof[2] = {constants::UnusedIndex, constants::UnusedIndex}; ClassDefNV(Tracklet, 1); }; @@ -93,16 +95,6 @@ GPUhdi() unsigned char Tracklet::operator<(const Tracklet& t) const return true; } -GPUhdi() void Tracklet::dump(const int offsetFirst, const int offsetSecond) const -{ - printf("fClIdx: %d sClIdx: %d rof1: %hu rof2: %hu\n", firstClusterIndex + offsetFirst, secondClusterIndex + offsetSecond, rof[0], rof[1]); -} - -GPUhdi() void Tracklet::dump() const -{ - printf("fClIdx: %d sClIdx: %d rof1: %hu rof2: %hu\n", firstClusterIndex, secondClusterIndex, rof[0], rof[1]); -} - } // namespace o2::its #endif /* TRACKINGITS_INCLUDE_TRACKLET_H_ */ diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h index 54424136fcfe1..1213ad0a423b8 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/VertexerTraits.h @@ -119,6 +119,11 @@ class VertexerTraits private: std::shared_ptr mMemoryPool; std::shared_ptr mTaskArena; + + // debug output + void debugComputeTracklets(int iteration); + void debugComputeTrackletMatching(int iteration); + void debugComputeVertices(int iteration); }; inline void VertexerTraits::initialise(const TrackingParameters& trackingParams, const int iteration) diff --git a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx index 4115726756e73..2e9ce23719f90 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx @@ -59,24 +59,19 @@ TimeFrame::~TimeFrame() } template -void TimeFrame::addPrimaryVertices(const bounded_vector& vertices) +void TimeFrame::addPrimaryVertices(const bounded_vector& vertices, const int iteration) { for (const auto& vertex : vertices) { - mPrimaryVertices.emplace_back(vertex); - if (!isBeamPositionOverridden) { + mPrimaryVertices.emplace_back(vertex); // put a copy in the present + mTotVertPerIteration[iteration]++; + if (!isBeamPositionOverridden) { // beam position is updated only at first occurrence of the vertex. A bit sketchy if we have past/future vertices, it should not impact too much. const float w = vertex.getNContributors(); mBeamPos[0] = (mBeamPos[0] * mBeamPosWeight + vertex.getX() * w) / (mBeamPosWeight + w); mBeamPos[1] = (mBeamPos[1] * mBeamPosWeight + vertex.getY() * w) / (mBeamPosWeight + w); mBeamPosWeight += w; } } - mROFramesPV.push_back(mPrimaryVertices.size()); -} - -template -void TimeFrame::addPrimaryVertices(const bounded_vector& vertices, const int rofId, const int iteration) -{ - addPrimaryVertices(gsl::span(vertices), rofId, iteration); + mROFramesPV.push_back(mPrimaryVertices.size()); // current rof must have number of vertices up to present } template @@ -119,34 +114,6 @@ void TimeFrame::addPrimaryVerticesContributorLabelsInROF(const bounded_ mVerticesContributorLabels.insert(mVerticesContributorLabels.begin() + n, labels.begin(), labels.end()); } -template -void TimeFrame::addPrimaryVertices(const gsl::span& vertices, const int rofId, const int iteration) -{ - bounded_vector futureVertices(mMemoryPool.get()); - for (const auto& vertex : vertices) { - if (vertex.getTimeStamp().getTimeStamp() < rofId) { // put a copy in the past - insertPastVertex(vertex, iteration); - } else { - if (vertex.getTimeStamp().getTimeStamp() > rofId) { // or put a copy in the future - futureVertices.emplace_back(vertex); - } - } - mPrimaryVertices.emplace_back(vertex); // put a copy in the present - mTotVertPerIteration[iteration]++; - if (!isBeamPositionOverridden) { // beam position is updated only at first occurrence of the vertex. A bit sketchy if we have past/future vertices, it should not impact too much. - const float w = vertex.getNContributors(); - mBeamPos[0] = (mBeamPos[0] * mBeamPosWeight + vertex.getX() * w) / (mBeamPosWeight + w); - mBeamPos[1] = (mBeamPos[1] * mBeamPosWeight + vertex.getY() * w) / (mBeamPosWeight + w); - mBeamPosWeight += w; - } - } - mROFramesPV.push_back(mPrimaryVertices.size()); // current rof must have number of vertices up to present - for (auto& vertex : futureVertices) { - mPrimaryVertices.emplace_back(vertex); - mTotVertPerIteration[iteration]++; - } -} - template int TimeFrame::loadROFrameData(gsl::span rofs, gsl::span clusters, @@ -395,7 +362,7 @@ void TimeFrame::initialise(const int iteration, const TrackingParameter if (iLayer < (int)mCells.size()) { deepVectorClear(mCells[iLayer]); deepVectorClear(mTrackletsLookupTable[iLayer]); - mTrackletsLookupTable[iLayer].resize(mClusters[iLayer + 1].size(), 0); + mTrackletsLookupTable[iLayer].resize(mClusters[iLayer + 1].size() + 1, 0); deepVectorClear(mCellLabels[iLayer]); } @@ -686,8 +653,8 @@ void TimeFrame::wipe() deepVectorClear(mCellsLookupTable); deepVectorClear(mTotVertPerIteration); deepVectorClear(mPrimaryVertices); - deepVectorClear(mROFramesPV); deepVectorClear(mClusters); + deepVectorClear(mTrackletsLookupTable); deepVectorClear(mTrackingFrameInfo); deepVectorClear(mClusterExternalIndices); deepVectorClear(mROFramesClusters); diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index aa93e32e1db9c..ba722c410f95c 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -52,7 +52,9 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) int maxNvertices{-1}; if (mTrkParams[0].PerPrimaryVertexProcessing) { for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) { - maxNvertices = std::max(maxNvertices, (int)mTimeFrame->getPrimaryVertices(iROF).size()); + int minRof = o2::gpu::CAMath::Max(0, iROF - mTrkParams[0].DeltaROF); + int maxRof = o2::gpu::CAMath::Min(mTimeFrame->getNrof(), iROF + mTrkParams[0].DeltaROF); + maxNvertices = std::max(maxNvertices, (int)mTimeFrame->getPrimaryVertices(minRof, maxRof).size()); } } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index da7f31bd678b5..136ebc647cc38 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -21,6 +21,7 @@ #ifdef OPTIMISATION_OUTPUT #include +#include #endif #include @@ -42,8 +43,6 @@ using o2::base::PropagatorF; namespace o2::its { -static constexpr int debugLevel{0}; - struct PassMode { using OnePass = std::integral_constant; using TwoPassCount = std::integral_constant; @@ -73,130 +72,173 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF int endROF{o2::gpu::GPUCommonMath::Min(mTrkParams[iteration].nROFsPerIterations > 0 ? (iROFslice + 1) * mTrkParams[iteration].nROFsPerIterations + mTrkParams[iteration].DeltaROF : mTimeFrame->getNrof(), mTimeFrame->getNrof())}; mTaskArena->execute([&] { - for (int rof0{startROF}; rof0 < endROF; ++rof0) { - gsl::span primaryVertices = mTrkParams[iteration].UseDiamond ? diamondSpan : mTimeFrame->getPrimaryVertices(rof0); - const int startVtx{iVertex >= 0 ? iVertex : 0}; - const int endVtx{iVertex >= 0 ? o2::gpu::CAMath::Min(iVertex + 1, static_cast(primaryVertices.size())) : static_cast(primaryVertices.size())}; - int minRof = o2::gpu::CAMath::Max(startROF, rof0 - mTrkParams[iteration].DeltaROF); - int maxRof = o2::gpu::CAMath::Min(endROF - 1, rof0 + mTrkParams[iteration].DeltaROF); + auto forTracklets = [&](auto Tag, int iLayer, int pivotROF, int base, int& offset) -> int { + int minROF = o2::gpu::CAMath::Max(startROF, pivotROF - mTrkParams[iteration].DeltaROF); + int maxROF = o2::gpu::CAMath::Min(endROF - 1, pivotROF + mTrkParams[iteration].DeltaROF); + gsl::span primaryVertices = mTrkParams[iteration].UseDiamond ? diamondSpan : mTimeFrame->getPrimaryVertices(minROF, maxROF); + if (primaryVertices.empty()) { + return 0; + } + const int startVtx = iVertex >= 0 ? iVertex : 0; + const int endVtx = iVertex >= 0 ? o2::gpu::CAMath::Min(iVertex + 1, int(primaryVertices.size())) : int(primaryVertices.size()); + if (endVtx <= startVtx) { + return 0; + } - tbb::parallel_for( - tbb::blocked_range(0, mTrkParams[iteration].TrackletsPerRoad()), - [&](const tbb::blocked_range& Layers) { - for (int iLayer = Layers.begin(); iLayer < Layers.end(); ++iLayer) { - gsl::span layer0 = mTimeFrame->getClustersOnLayer(rof0, iLayer); - if (layer0.empty()) { + int localCount = 0; + auto& tracklets = mTimeFrame->getTracklets()[iLayer]; + for (int targetROF0{minROF}; targetROF0 <= maxROF; ++targetROF0) { + if (!mTimeFrame->mMultiplicityCutMask[targetROF0]) { + continue; + } + auto layer0 = mTimeFrame->getClustersOnLayer(targetROF0, iLayer); + if (layer0.empty()) { + continue; + } + const float meanDeltaR = mTrkParams[iteration].LayerRadii[iLayer + 1] - mTrkParams[iteration].LayerRadii[iLayer]; + + for (int iCluster = 0; iCluster < int(layer0.size()); ++iCluster) { + const Cluster& currentCluster = layer0[iCluster]; + const int currentSortedIndex = mTimeFrame->getSortedIndex(targetROF0, iLayer, iCluster); + if (mTimeFrame->isClusterUsed(iLayer, currentCluster.clusterId)) { + continue; + } + const float inverseR0 = 1.f / currentCluster.radius; + + for (int iV = startVtx; iV < endVtx; ++iV) { + const auto& pv = primaryVertices[iV]; + if (pv.isFlagSet(Vertex::Flags::UPCMode) && iteration != 3) { continue; } - float meanDeltaR{mTrkParams[iteration].LayerRadii[iLayer + 1] - mTrkParams[iteration].LayerRadii[iLayer]}; - - const int currentLayerClustersNum{static_cast(layer0.size())}; - for (int iCluster{0}; iCluster < currentLayerClustersNum; ++iCluster) { - const Cluster& currentCluster{layer0[iCluster]}; - const int currentSortedIndex{mTimeFrame->getSortedIndex(rof0, iLayer, iCluster)}; + const float resolution = o2::gpu::CAMath::Sqrt(math_utils::Sq(mTimeFrame->getPositionResolution(iLayer)) + math_utils::Sq(mTrkParams[iteration].PVres) / float(pv.getNContributors())); + const float tanLambda = (currentCluster.zCoordinate - pv.getZ()) * inverseR0; + const float zAtRmin = tanLambda * (mTimeFrame->getMinR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate; + const float zAtRmax = tanLambda * (mTimeFrame->getMaxR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate; + const float sqInvDeltaZ0 = 1.f / (math_utils::Sq(currentCluster.zCoordinate - pv.getZ()) + constants::Tolerance); + const float sigmaZ = o2::gpu::CAMath::Sqrt( + math_utils::Sq(resolution) * math_utils::Sq(tanLambda) * ((math_utils::Sq(inverseR0) + sqInvDeltaZ0) * math_utils::Sq(meanDeltaR) + 1.f) + math_utils::Sq(meanDeltaR * mTimeFrame->getMSangle(iLayer))); + + auto bins = getBinsRect(currentCluster, iLayer + 1, zAtRmin, zAtRmax, sigmaZ * mTrkParams[iteration].NSigmaCut, mTimeFrame->getPhiCut(iLayer)); + if (bins.x == 0 && bins.y == 0 && bins.z == 0 && bins.w == 0) { + continue; + } + int phiBinsNum = bins.w - bins.y + 1; + if (phiBinsNum < 0) { + phiBinsNum += mTrkParams[iteration].PhiBins; + } - if (mTimeFrame->isClusterUsed(iLayer, currentCluster.clusterId)) { + for (int targetROF1{minROF}; targetROF1 <= maxROF; ++targetROF1) { + if (!mTimeFrame->mMultiplicityCutMask[targetROF1] || std::abs(targetROF0 - targetROF1) > mTrkParams[iteration].DeltaROF) { continue; } - const float inverseR0{1.f / currentCluster.radius}; - - for (int iV{startVtx}; iV < endVtx; ++iV) { - const auto& primaryVertex{primaryVertices[iV]}; - if (primaryVertex.isFlagSet(2) && iteration != 3) { - continue; - } - const float resolution = o2::gpu::CAMath::Sqrt(math_utils::Sq(mTrkParams[iteration].PVres) / primaryVertex.getNContributors() + math_utils::Sq(mTimeFrame->getPositionResolution(iLayer))); - - const float tanLambda{(currentCluster.zCoordinate - primaryVertex.getZ()) * inverseR0}; - - const float zAtRmin{tanLambda * (mTimeFrame->getMinR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate}; - const float zAtRmax{tanLambda * (mTimeFrame->getMaxR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate}; - - const float sqInverseDeltaZ0{1.f / (math_utils::Sq(currentCluster.zCoordinate - primaryVertex.getZ()) + 2.e-8f)}; /// protecting from overflows adding the detector resolution - const float sigmaZ{o2::gpu::CAMath::Sqrt(math_utils::Sq(resolution) * math_utils::Sq(tanLambda) * ((math_utils::Sq(inverseR0) + sqInverseDeltaZ0) * math_utils::Sq(meanDeltaR) + 1.f) + math_utils::Sq(meanDeltaR * mTimeFrame->getMSangle(iLayer)))}; - - const int4 selectedBinsRect{getBinsRect(currentCluster, iLayer + 1, zAtRmin, zAtRmax, sigmaZ * mTrkParams[iteration].NSigmaCut, mTimeFrame->getPhiCut(iLayer))}; - if (selectedBinsRect.x == 0 && selectedBinsRect.y == 0 && selectedBinsRect.z == 0 && selectedBinsRect.w == 0) { - continue; - } - - int phiBinsNum{selectedBinsRect.w - selectedBinsRect.y + 1}; - - if (phiBinsNum < 0) { - phiBinsNum += mTrkParams[iteration].PhiBins; - } - - for (int rof1{minRof}; rof1 <= maxRof; ++rof1) { - auto layer1 = mTimeFrame->getClustersOnLayer(rof1, iLayer + 1); - if (layer1.empty()) { + auto layer1 = mTimeFrame->getClustersOnLayer(targetROF1, iLayer + 1); + if (layer1.empty()) { + continue; + } + for (int iPhi = 0; iPhi < phiBinsNum; ++iPhi) { + int iPhiBin = (bins.y + iPhi) % mTrkParams[iteration].PhiBins; + int firstBinIdx = mTimeFrame->mIndexTableUtils.getBinIndex(bins.x, iPhiBin); + int maxBinIdx = firstBinIdx + (bins.z - bins.x) + 1; + int firstRow = mTimeFrame->getIndexTable(targetROF1, iLayer + 1)[firstBinIdx]; + int lastRow = mTimeFrame->getIndexTable(targetROF1, iLayer + 1)[maxBinIdx]; + for (int iNext = firstRow; iNext < lastRow; ++iNext) { + if (iNext >= int(layer1.size())) { + break; + } + const Cluster& nextCluster = layer1[iNext]; + if (mTimeFrame->isClusterUsed(iLayer + 1, nextCluster.clusterId)) { continue; } - for (int iPhiCount{0}; iPhiCount < phiBinsNum; iPhiCount++) { - int iPhiBin = (selectedBinsRect.y + iPhiCount) % mTrkParams[iteration].PhiBins; - const int firstBinIndex{mTimeFrame->mIndexTableUtils.getBinIndex(selectedBinsRect.x, iPhiBin)}; - const int maxBinIndex{firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1}; - if constexpr (debugLevel) { - if (firstBinIndex < 0 || firstBinIndex > mTimeFrame->getIndexTable(rof1, iLayer + 1).size() || - maxBinIndex < 0 || maxBinIndex > mTimeFrame->getIndexTable(rof1, iLayer + 1).size()) { - std::cout << iLayer << "\t" << iCluster << "\t" << zAtRmin << "\t" << zAtRmax << "\t" << sigmaZ * mTrkParams[iteration].NSigmaCut << "\t" << mTimeFrame->getPhiCut(iLayer) << std::endl; - std::cout << currentCluster.zCoordinate << "\t" << primaryVertex.getZ() << "\t" << currentCluster.radius << std::endl; - std::cout << mTimeFrame->getMinR(iLayer + 1) << "\t" << currentCluster.radius << "\t" << currentCluster.zCoordinate << std::endl; - std::cout << "Illegal access to IndexTable " << firstBinIndex << "\t" << maxBinIndex << "\t" << selectedBinsRect.z << "\t" << selectedBinsRect.x << std::endl; - exit(1); - } - } - const int firstRowClusterIndex = mTimeFrame->getIndexTable(rof1, iLayer + 1)[firstBinIndex]; - const int maxRowClusterIndex = mTimeFrame->getIndexTable(rof1, iLayer + 1)[maxBinIndex]; - for (int iNextCluster{firstRowClusterIndex}; iNextCluster < maxRowClusterIndex; ++iNextCluster) { - if (iNextCluster >= (int)layer1.size()) { - break; - } - - const Cluster& nextCluster{layer1[iNextCluster]}; - if (mTimeFrame->isClusterUsed(iLayer + 1, nextCluster.clusterId)) { - continue; - } - - const float deltaPhi{o2::gpu::GPUCommonMath::Abs(currentCluster.phi - nextCluster.phi)}; - const float deltaZ{o2::gpu::GPUCommonMath::Abs(tanLambda * (nextCluster.radius - currentCluster.radius) + - currentCluster.zCoordinate - nextCluster.zCoordinate)}; + float deltaPhi = o2::gpu::GPUCommonMath::Abs(currentCluster.phi - nextCluster.phi); + float deltaZ = o2::gpu::GPUCommonMath::Abs((tanLambda * (nextCluster.radius - currentCluster.radius)) + currentCluster.zCoordinate - nextCluster.zCoordinate); #ifdef OPTIMISATION_OUTPUT - MCCompLabel label; - int currentId{currentCluster.clusterId}; - int nextId{nextCluster.clusterId}; - for (auto& lab1 : mTimeFrame->getClusterLabels(iLayer, currentId)) { - for (auto& lab2 : mTimeFrame->getClusterLabels(iLayer + 1, nextId)) { - if (lab1 == lab2 && lab1.isValid()) { - label = lab1; - break; - } - } - if (label.isValid()) { - break; - } + MCCompLabel label; + int currentId{currentCluster.clusterId}; + int nextId{nextCluster.clusterId}; + for (auto& lab1 : mTimeFrame->getClusterLabels(iLayer, currentId)) { + for (auto& lab2 : mTimeFrame->getClusterLabels(iLayer + 1, nextId)) { + if (lab1 == lab2 && lab1.isValid()) { + label = lab1; + break; } - off << std::format("{}\t{:d}\t{}\t{}\t{}\t{}", iLayer, label.isValid(), (tanLambda * (nextCluster.radius - currentCluster.radius) + currentCluster.zCoordinate - nextCluster.zCoordinate) / sigmaZ, tanLambda, resolution, sigmaZ) << std::endl; + } + if (label.isValid()) { + break; + } + } + off << std::format("{}\t{:d}\t{}\t{}\t{}\t{}", iLayer, label.isValid(), (tanLambda * (nextCluster.radius - currentCluster.radius) + currentCluster.zCoordinate - nextCluster.zCoordinate) / sigmaZ, tanLambda, resolution, sigmaZ) << std::endl; #endif - if (deltaZ / sigmaZ < mTrkParams[iteration].NSigmaCut && - (deltaPhi < mTimeFrame->getPhiCut(iLayer) || - o2::gpu::GPUCommonMath::Abs(deltaPhi - o2::constants::math::TwoPI) < mTimeFrame->getPhiCut(iLayer))) { - if (iLayer > 0) { - mTimeFrame->getTrackletsLookupTable()[iLayer - 1][currentSortedIndex]++; - } - const float phi{o2::gpu::GPUCommonMath::ATan2(currentCluster.yCoordinate - nextCluster.yCoordinate, - currentCluster.xCoordinate - nextCluster.xCoordinate)}; - const float tanL{(currentCluster.zCoordinate - nextCluster.zCoordinate) / - (currentCluster.radius - nextCluster.radius)}; - mTimeFrame->getTracklets()[iLayer].emplace_back(currentSortedIndex, mTimeFrame->getSortedIndex(rof1, iLayer + 1, iNextCluster), tanL, phi, rof0, rof1); - } + if (deltaZ / sigmaZ < mTrkParams[iteration].NSigmaCut && + (deltaPhi < mTimeFrame->getPhiCut(iLayer) || + o2::gpu::GPUCommonMath::Abs(deltaPhi - o2::constants::math::TwoPI) < mTimeFrame->getPhiCut(iLayer))) { + float phi = o2::gpu::GPUCommonMath::ATan2(currentCluster.yCoordinate - nextCluster.yCoordinate, currentCluster.xCoordinate - nextCluster.xCoordinate); + float tanL = (currentCluster.zCoordinate - nextCluster.zCoordinate) / (currentCluster.radius - nextCluster.radius); + if constexpr (decltype(Tag)::value == PassMode::OnePass::value) { + tracklets.emplace_back(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF1, iLayer + 1, iNext), tanL, phi, targetROF0, targetROF1); + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassCount::value) { + ++localCount; + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassInsert::value) { + const int idx = base + offset++; + tracklets[idx] = Tracklet(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF1, iLayer + 1, iNext), tanL, phi, targetROF0, targetROF1); } } } } } } + } + } + return localCount; + }; + + int dummy{0}; + if (mTaskArena->max_concurrency() <= 1) { + for (int pivotROF{startROF}; pivotROF < endROF; ++pivotROF) { + for (int iLayer{0}; iLayer < mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) { + forTracklets(PassMode::OnePass{}, iLayer, pivotROF, 0, dummy); + } + } + } else { + bounded_vector> perROFCount(mTrkParams[iteration].TrackletsPerRoad(), bounded_vector(endROF - startROF + 1, 0, mMemoryPool.get()), mMemoryPool.get()); + tbb::parallel_for( + tbb::blocked_range2d(0, mTrkParams[iteration].TrackletsPerRoad(), 1, + startROF, endROF, 1), + [&](auto const& Range) { + for (int iLayer{Range.rows().begin()}; iLayer < Range.rows().end(); ++iLayer) { + for (int pivotROF = Range.cols().begin(); pivotROF < Range.cols().end(); ++pivotROF) { + perROFCount[iLayer][pivotROF - startROF] = forTracklets(PassMode::TwoPassCount{}, iLayer, pivotROF, 0, dummy); + } + } + }); + + tbb::parallel_for( + tbb::blocked_range(0, mTrkParams[iteration].TrackletsPerRoad()), + [&](auto const& Layers) { + for (int iLayer{Layers.begin()}; iLayer < Layers.end(); ++iLayer) { + std::exclusive_scan(perROFCount[iLayer].begin(), perROFCount[iLayer].end(), perROFCount[iLayer].begin(), 0); + mTimeFrame->getTracklets()[iLayer].resize(perROFCount[iLayer].back()); + } + }); + + tbb::parallel_for( + tbb::blocked_range2d(0, mTrkParams[iteration].TrackletsPerRoad(), 1, + startROF, endROF, 1), + [&](auto const& Range) { + for (int iLayer{Range.rows().begin()}; iLayer < Range.rows().end(); ++iLayer) { + if (perROFCount[iLayer].back() == 0) { + continue; + } + for (int pivotROF = Range.cols().begin(); pivotROF < Range.cols().end(); ++pivotROF) { + int baseIdx = perROFCount[iLayer][pivotROF - startROF]; + if (baseIdx == perROFCount[iLayer][pivotROF - startROF + 1]) { + continue; + } + int localIdx = 0; + forTracklets(PassMode::TwoPassInsert{}, iLayer, pivotROF, baseIdx, localIdx); + } + } }); } @@ -217,42 +259,43 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF trkl.shrink_to_fit(); if (iLayer > 0) { /// recalculate lut auto& lut{mTimeFrame->getTrackletsLookupTable()[iLayer - 1]}; - std::fill(lut.begin(), lut.end(), 0); - if (trkl.empty()) { - return; - } - for (const auto& tkl : trkl) { - lut[tkl.firstClusterIndex]++; + if (!trkl.empty()) { + for (const auto& tkl : trkl) { + lut[tkl.firstClusterIndex + 1]++; + } + std::inclusive_scan(lut.begin(), lut.end(), lut.begin()); } - std::exclusive_scan(lut.begin(), lut.end(), lut.begin(), 0); - lut.push_back(trkl.size()); } } }); - }); - /// Create tracklets labels - if (mTimeFrame->hasMCinformation()) { - for (int iLayer{0}; iLayer < mTrkParams[iteration].TrackletsPerRoad(); ++iLayer) { - for (auto& trk : mTimeFrame->getTracklets()[iLayer]) { - MCCompLabel label; - int currentId{mTimeFrame->getClusters()[iLayer][trk.firstClusterIndex].clusterId}; - int nextId{mTimeFrame->getClusters()[iLayer + 1][trk.secondClusterIndex].clusterId}; - for (auto& lab1 : mTimeFrame->getClusterLabels(iLayer, currentId)) { - for (auto& lab2 : mTimeFrame->getClusterLabels(iLayer + 1, nextId)) { - if (lab1 == lab2 && lab1.isValid()) { - label = lab1; - break; + /// Create tracklets labels + if (mTimeFrame->hasMCinformation()) { + tbb::parallel_for( + tbb::blocked_range(0, mTrkParams[iteration].TrackletsPerRoad()), + [&](const tbb::blocked_range& Layers) { + for (int iLayer = Layers.begin(); iLayer < Layers.end(); ++iLayer) { + for (auto& trk : mTimeFrame->getTracklets()[iLayer]) { + MCCompLabel label; + int currentId{mTimeFrame->getClusters()[iLayer][trk.firstClusterIndex].clusterId}; + int nextId{mTimeFrame->getClusters()[iLayer + 1][trk.secondClusterIndex].clusterId}; + for (const auto& lab1 : mTimeFrame->getClusterLabels(iLayer, currentId)) { + for (const auto& lab2 : mTimeFrame->getClusterLabels(iLayer + 1, nextId)) { + if (lab1 == lab2 && lab1.isValid()) { + label = lab1; + break; + } + } + if (label.isValid()) { + break; + } + } + mTimeFrame->getTrackletsLabel(iLayer).emplace_back(label); } } - if (label.isValid()) { - break; - } - } - mTimeFrame->getTrackletsLabel(iLayer).emplace_back(label); - } + }); } - } + }); } template @@ -277,17 +320,19 @@ void TrackerTraits::computeLayerCells(const int iteration) auto forTrackletCells = [&](auto Tag, int iLayer, bounded_vector& layerCells, int iTracklet, int offset = 0) -> int { const Tracklet& currentTracklet{mTimeFrame->getTracklets()[iLayer][iTracklet]}; const int nextLayerClusterIndex{currentTracklet.secondClusterIndex}; - const int nextLayerFirstTrackletIndex{ - mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex]}; - const int nextLayerLastTrackletIndex{ - mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex + 1]}; - + const int nextLayerFirstTrackletIndex{mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex]}; + const int nextLayerLastTrackletIndex{mTimeFrame->getTrackletsLookupTable()[iLayer][nextLayerClusterIndex + 1]}; int foundCells{0}; for (int iNextTracklet{nextLayerFirstTrackletIndex}; iNextTracklet < nextLayerLastTrackletIndex; ++iNextTracklet) { + const Tracklet& nextTracklet{mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet]}; + const auto& nextLbl = mTimeFrame->getTrackletsLabel(iLayer + 1)[iNextTracklet]; + bool print = false; if (mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet].firstClusterIndex != nextLayerClusterIndex) { break; } - const Tracklet& nextTracklet{mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet]}; + if (mTrkParams[iteration].DeltaROF && currentTracklet.getSpanRof(nextTracklet) > mTrkParams[iteration].DeltaROF) { // TODO this has to be improved for the staggering + continue; + } const float deltaTanLambda{std::abs(currentTracklet.tanLambda - nextTracklet.tanLambda)}; #ifdef OPTIMISATION_OUTPUT @@ -414,19 +459,13 @@ void TrackerTraits::computeLayerCells(const int iteration) /// Create cells labels if (mTimeFrame->hasMCinformation()) { for (int iLayer{0}; iLayer < mTrkParams[iteration].CellsPerRoad(); ++iLayer) { - for (auto& cell : mTimeFrame->getCells()[iLayer]) { + for (const auto& cell : mTimeFrame->getCells()[iLayer]) { MCCompLabel currentLab{mTimeFrame->getTrackletsLabel(iLayer)[cell.getFirstTrackletIndex()]}; MCCompLabel nextLab{mTimeFrame->getTrackletsLabel(iLayer + 1)[cell.getSecondTrackletIndex()]}; mTimeFrame->getCellsLabel(iLayer).emplace_back(currentLab == nextLab ? currentLab : MCCompLabel()); } } } - - if constexpr (debugLevel) { - for (int iLayer{0}; iLayer < mTrkParams[iteration].CellsPerRoad(); ++iLayer) { - std::cout << "Cells on layer " << iLayer << " " << mTimeFrame->getCells()[iLayer].size() << std::endl; - } - } } template @@ -464,6 +503,16 @@ void TrackerTraits::findCellsNeighbours(const int iteration) break; } + if (mTrkParams[iteration].DeltaROF) { // TODO this has to be improved for the staggering + const auto& trkl00 = mTimeFrame->getTracklets()[iLayer][currentCellSeed.getFirstTrackletIndex()]; + const auto& trkl01 = mTimeFrame->getTracklets()[iLayer + 1][currentCellSeed.getSecondTrackletIndex()]; + const auto& trkl10 = mTimeFrame->getTracklets()[iLayer + 1][nextCellSeed.getFirstTrackletIndex()]; + const auto& trkl11 = mTimeFrame->getTracklets()[iLayer + 2][nextCellSeed.getSecondTrackletIndex()]; + if ((std::max({trkl00.getMaxRof(), trkl01.getMaxRof(), trkl10.getMaxRof(), trkl11.getMaxRof()}) - std::min({trkl00.getMinRof(), trkl01.getMinRof(), trkl10.getMinRof(), trkl10.getMinRof()})) > mTrkParams[0].DeltaROF) { + continue; + } + } + if (!nextCellSeed.rotate(currentCellSeed.getAlpha()) || !nextCellSeed.propagateTo(currentCellSeed.getX(), getBz())) { continue; @@ -607,6 +656,21 @@ void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bou CA_DEBUGGER(failed[0]++); continue; } + if (mTrkParams[0].DeltaROF) { // TODO this has to be improved for the staggering + const auto& trklNeigh = mTimeFrame->getTracklets()[iLayer - 1][neighbourCell.getFirstTrackletIndex()]; + short minRof{std::numeric_limits::max()}, maxRof{std::numeric_limits::min()}; + for (int iLayer{0}; iLayer < mTrkParams[0].NLayers; ++iLayer) { + if (const auto clsId = currentCell.getCluster(iLayer); clsId != constants::UnusedIndex) { + const short clsROF = mTimeFrame->getClusterROF(iLayer, clsId); + minRof = std::min(minRof, clsROF); + maxRof = std::max(maxRof, clsROF); + } + } + if ((std::max(trklNeigh.getMaxRof(), maxRof) - std::min(trklNeigh.getMinRof(), minRof)) > mTrkParams[0].DeltaROF) { + continue; + } + } + /// Let's start the fitting procedure CellSeed seed{currentCell}; const auto& trHit = mTimeFrame->getTrackingFrameInfoOnLayer(iLayer - 1)[neighbourCell.getFirstClusterIndex()]; diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index a908f8b2a1f1e..00a69a37cb51a 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -165,7 +165,7 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) gsl::span> vMCRecInfo; gsl::span vMCContLabels; for (auto iRof{0}; iRof < trackROFspan.size(); ++iRof) { - std::vector vtxVecLoc; + bounded_vector vtxVecLoc; auto& vtxROF = vertROFvec.emplace_back(trackROFspan[iRof]); vtxROF.setFirstEntry(vertices.size()); if (mRunVertexer) { @@ -223,7 +223,7 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) for (auto& v : vtxVecLoc) { vertices.push_back(v); } - mTimeFrame->addPrimaryVertices(vtxVecLoc, iRof, 0); + mTimeFrame->addPrimaryVertices(vtxVecLoc, 0); } } if (mRunVertexer) { diff --git a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx index 1069f1808fb2a..bcafa98972d78 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/VertexerTraits.cxx @@ -26,18 +26,12 @@ #include "Steer/MCKinematicsReader.h" #include "ITSMFTBase/DPLAlpideParam.h" #include "DetectorsRaw/HBFUtils.h" - -#ifdef VTX_DEBUG -#include "TTree.h" -#include "TFile.h" -#include -#include -#endif +#include "CommonUtils/TreeStreamRedirector.h" using namespace o2::its; template -void trackleterKernelHost( +static void trackleterKernelHost( const gsl::span& clustersNextLayer, // 0 2 const gsl::span& clustersCurrentLayer, // 1 1 const gsl::span& usedClustersNextLayer, // 0 2 @@ -97,21 +91,22 @@ void trackleterKernelHost( } } -void trackletSelectionKernelHost( +static void trackletSelectionKernelHost( const gsl::span clusters0, // 0 const gsl::span clusters1, // 1 gsl::span usedClusters0, // Layer 0 gsl::span usedClusters2, // Layer 2 const gsl::span& tracklets01, const gsl::span& tracklets12, - bounded_vector& usedTracklets, + bounded_vector& usedTracklets, const gsl::span foundTracklets01, const gsl::span foundTracklets12, bounded_vector& lines, const gsl::span& trackletLabels, bounded_vector& linesLabels, - const short pivotRofId, - const short targetRofId, + const short targetRofId0, + const short targetRofId2, + bool safeWrites = false, const float tanLambdaCut = 0.025f, const float phiCut = 0.005f, const int maxTracklets = static_cast(1e2)) @@ -121,16 +116,27 @@ void trackletSelectionKernelHost( int validTracklets{0}; for (int iTracklet12{offset12}; iTracklet12 < offset12 + foundTracklets12[iCurrentLayerClusterIndex]; ++iTracklet12) { for (int iTracklet01{offset01}; iTracklet01 < offset01 + foundTracklets01[iCurrentLayerClusterIndex]; ++iTracklet01) { + if (usedTracklets[iTracklet01]) { + continue; + } + const auto& tracklet01{tracklets01[iTracklet01]}; const auto& tracklet12{tracklets12[iTracklet12]}; - if (tracklet01.rof[0] != targetRofId || tracklet12.rof[1] != targetRofId) { + + if (tracklet01.rof[0] != targetRofId0 || tracklet12.rof[1] != targetRofId2) { continue; } + const float deltaTanLambda{o2::gpu::GPUCommonMath::Abs(tracklet01.tanLambda - tracklet12.tanLambda)}; const float deltaPhi{o2::gpu::GPUCommonMath::Abs(math_utils::smallestAngleDifference(tracklet01.phi, tracklet12.phi))}; - if (!usedTracklets[iTracklet01] && deltaTanLambda < tanLambdaCut && deltaPhi < phiCut && validTracklets != maxTracklets) { - usedClusters0[tracklet01.firstClusterIndex] = true; - usedClusters2[tracklet12.secondClusterIndex] = true; + if (deltaTanLambda < tanLambdaCut && deltaPhi < phiCut && validTracklets != maxTracklets) { + if (safeWrites) { + __atomic_store_n(&usedClusters0[tracklet01.firstClusterIndex], 1, __ATOMIC_RELAXED); + __atomic_store_n(&usedClusters2[tracklet12.secondClusterIndex], 1, __ATOMIC_RELAXED); + } else { + usedClusters0[tracklet01.firstClusterIndex] = 1; + usedClusters2[tracklet12.secondClusterIndex] = 1; + } usedTracklets[iTracklet01] = true; lines.emplace_back(tracklet01, clusters0.data(), clusters1.data()); if (!trackletLabels.empty()) { @@ -273,46 +279,7 @@ void VertexerTraits::computeTracklets(const int iteration) } #ifdef VTX_DEBUG - // Dump on file - TFile* trackletFile = TFile::Open("artefacts_tf.root", "recreate"); - TTree* tr_tre = new TTree("tracklets", "tf"); - std::vector trkl_vec_0(0); - std::vector trkl_vec_1(0); - std::vector clus0(0); - std::vector clus1(0); - std::vector clus2(0); - tr_tre->Branch("Tracklets0", &trkl_vec_0); - tr_tre->Branch("Tracklets1", &trkl_vec_1); - for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - trkl_vec_0.clear(); - trkl_vec_1.clear(); - for (auto& tr : mTimeFrame->getFoundTracklets(rofId, 0)) { - trkl_vec_0.push_back(tr); - } - for (auto& tr : mTimeFrame->getFoundTracklets(rofId, 1)) { - trkl_vec_1.push_back(tr); - } - tr_tre->Fill(); - } - trackletFile->cd(); - tr_tre->Write(); - trackletFile->Close(); - - std::ofstream out01("NTC01_cpu.txt"), out12("NTC12_cpu.txt"); - for (int iRof{0}; iRof < mTimeFrame->getNrof(); ++iRof) { - out01 << "ROF: " << iRof << std::endl; - out12 << "ROF: " << iRof << std::endl; - std::copy(mTimeFrame->getNTrackletsCluster(iRof, 0).begin(), mTimeFrame->getNTrackletsCluster(iRof, 0).end(), std::ostream_iterator(out01, "\t")); - out01 << std::endl; - std::copy(mTimeFrame->getExclusiveNTrackletsCluster(iRof, 0).begin(), mTimeFrame->getExclusiveNTrackletsCluster(iRof, 0).end(), std::ostream_iterator(out01, "\t")); - std::copy(mTimeFrame->getNTrackletsCluster(iRof, 1).begin(), mTimeFrame->getNTrackletsCluster(iRof, 1).end(), std::ostream_iterator(out12, "\t")); - out12 << std::endl; - std::copy(mTimeFrame->getExclusiveNTrackletsCluster(iRof, 1).begin(), mTimeFrame->getExclusiveNTrackletsCluster(iRof, 1).end(), std::ostream_iterator(out12, "\t")); - out01 << std::endl; - out12 << std::endl; - } - out01.close(); - out12.close(); + debugComputeTracklets(iteration); #endif } @@ -326,62 +293,52 @@ void VertexerTraits::computeTrackletMatching(const int iteration) if (iteration && (int)mTimeFrame->getPrimaryVertices(pivotRofId).size() > mVrtParams[iteration].vertPerRofThreshold) { continue; } + if (mTimeFrame->getFoundTracklets(pivotRofId, 0).empty()) { + continue; + } mTimeFrame->getLines(pivotRofId).reserve(mTimeFrame->getNTrackletsCluster(pivotRofId, 0).size()); - bounded_vector usedTracklets(mTimeFrame->getFoundTracklets(pivotRofId, 0).size(), false, mMemoryPool.get()); + bounded_vector usedTracklets(mTimeFrame->getFoundTracklets(pivotRofId, 0).size(), false, mMemoryPool.get()); short startROF{std::max((short)0, static_cast(pivotRofId - mVrtParams[iteration].deltaRof))}; short endROF{std::min(static_cast(mTimeFrame->getNrof()), static_cast(pivotRofId + mVrtParams[iteration].deltaRof + 1))}; - for (short targetRofId = startROF; targetRofId < endROF; ++targetRofId) { - trackletSelectionKernelHost( - mTimeFrame->getClustersOnLayer(targetRofId, 0), - mTimeFrame->getClustersOnLayer(pivotRofId, 1), - mTimeFrame->getUsedClustersROF(targetRofId, 0), - mTimeFrame->getUsedClustersROF(targetRofId, 2), - mTimeFrame->getFoundTracklets(pivotRofId, 0), - mTimeFrame->getFoundTracklets(pivotRofId, 1), - usedTracklets, - mTimeFrame->getNTrackletsCluster(pivotRofId, 0), - mTimeFrame->getNTrackletsCluster(pivotRofId, 1), - mTimeFrame->getLines(pivotRofId), - mTimeFrame->getLabelsFoundTracklets(pivotRofId, 0), - mTimeFrame->getLinesLabel(pivotRofId), - pivotRofId, - targetRofId, - mVrtParams[iteration].tanLambdaCut, - mVrtParams[iteration].phiCut); + + // needed only if multi-threaded using deltaRof and only at the overlap edges of the ranges + bool safeWrite = mTaskArena->max_concurrency() > 1 && mVrtParams[iteration].deltaRof != 0 && ((Rofs.begin() - startROF < 0) || (endROF - Rofs.end() > 0)); + + for (short targetRofId0 = startROF; targetRofId0 < endROF; ++targetRofId0) { + for (short targetRofId2 = startROF; targetRofId2 < endROF; ++targetRofId2) { + if (std::abs(targetRofId0 - targetRofId2) > mVrtParams[iteration].deltaRof) { // do not allow over 3 ROFs + continue; + } + trackletSelectionKernelHost( + mTimeFrame->getClustersOnLayer(targetRofId0, 0), + mTimeFrame->getClustersOnLayer(pivotRofId, 1), + mTimeFrame->getUsedClustersROF(targetRofId0, 0), + mTimeFrame->getUsedClustersROF(targetRofId2, 2), + mTimeFrame->getFoundTracklets(pivotRofId, 0), + mTimeFrame->getFoundTracklets(pivotRofId, 1), + usedTracklets, + mTimeFrame->getNTrackletsCluster(pivotRofId, 0), + mTimeFrame->getNTrackletsCluster(pivotRofId, 1), + mTimeFrame->getLines(pivotRofId), + mTimeFrame->getLabelsFoundTracklets(pivotRofId, 0), + mTimeFrame->getLinesLabel(pivotRofId), + targetRofId0, + targetRofId2, + safeWrite, + mVrtParams[iteration].tanLambdaCut, + mVrtParams[iteration].phiCut); + } } } }); }); #ifdef VTX_DEBUG - TFile* trackletFile = TFile::Open("artefacts_tf.root", "update"); - TTree* ln_tre = new TTree("lines", "tf"); - std::vector lines_vec(0); - std::vector nTrackl01(0); - std::vector nTrackl12(0); - ln_tre->Branch("Lines", &lines_vec); - ln_tre->Branch("NTrackletCluster01", &nTrackl01); - ln_tre->Branch("NTrackletCluster12", &nTrackl12); - for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - lines_vec.clear(); - nTrackl01.clear(); - nTrackl12.clear(); - for (auto& ln : mTimeFrame->getLines(rofId)) { - lines_vec.push_back(ln); - } - for (auto& n : mTimeFrame->getNTrackletsCluster(rofId, 0)) { - nTrackl01.push_back(n); - } - for (auto& n : mTimeFrame->getNTrackletsCluster(rofId, 1)) { - nTrackl12.push_back(n); - } - - ln_tre->Fill(); - } - trackletFile->cd(); - ln_tre->Write(); - trackletFile->Close(); + debugComputeTrackletMatching(iteration); #endif + + // from here on we do not use tracklets from L1-2 anymore, so let's free them + deepVectorClear(mTimeFrame->getTracklets()[1]); } void VertexerTraits::computeVertices(const int iteration) @@ -390,9 +347,6 @@ void VertexerTraits::computeVertices(const int iteration) bounded_vector vertices(mMemoryPool.get()); bounded_vector> polls(mMemoryPool.get()); bounded_vector contLabels(mMemoryPool.get()); -#ifdef VTX_DEBUG - std::vector> dbg_clusLines(mTimeFrame->getNrof()); -#endif bounded_vector noClustersVec(mTimeFrame->getNrof(), 0, mMemoryPool.get()); for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { if (iteration && (int)mTimeFrame->getPrimaryVertices(rofId).size() > mVrtParams[iteration].vertPerRofThreshold) { @@ -473,12 +427,7 @@ void VertexerTraits::computeVertices(const int iteration) } for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { std::sort(mTimeFrame->getTrackletClusters(rofId).begin(), mTimeFrame->getTrackletClusters(rofId).end(), - [](ClusterLines& cluster1, ClusterLines& cluster2) { return cluster1.getSize() > cluster2.getSize(); }); // ensure clusters are ordered by contributors, so that we can cat after the first. -#ifdef VTX_DEBUG - for (auto& cl : mTimeFrame->getTrackletClusters(rofId)) { - dbg_clusLines[rofId].push_back(cl); - } -#endif + [](const ClusterLines& cluster1, const ClusterLines& cluster2) { return cluster1.getSize() > cluster2.getSize(); }); // ensure clusters are ordered by contributors, so that we can cat after the first. bool atLeastOneFound{false}; for (int iCluster{0}; iCluster < noClustersVec[rofId]; ++iCluster) { bool lowMultCandidate{false}; @@ -520,7 +469,7 @@ void VertexerTraits::computeVertices(const int iteration) } } if (!iteration) { - mTimeFrame->addPrimaryVertices(vertices, rofId, iteration); + mTimeFrame->addPrimaryVertices(vertices, iteration); if (mTimeFrame->hasMCinformation()) { mTimeFrame->addPrimaryVerticesLabels(polls); if (mVrtParams[iteration].outputContLabels) { @@ -542,27 +491,9 @@ void VertexerTraits::computeVertices(const int iteration) vertices.clear(); polls.clear(); } + #ifdef VTX_DEBUG - TFile* dbg_file = TFile::Open("artefacts_tf.root", "update"); - TTree* ln_clus_lines_tree = new TTree("clusterlines", "tf"); - std::vector cl_lines_vec_pre(0); - std::vector cl_lines_vec_post(0); - ln_clus_lines_tree->Branch("cllines_pre", &cl_lines_vec_pre); - ln_clus_lines_tree->Branch("cllines_post", &cl_lines_vec_post); - for (auto rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { - cl_lines_vec_pre.clear(); - cl_lines_vec_post.clear(); - for (auto& clln : mTimeFrame->getTrackletClusters(rofId)) { - cl_lines_vec_post.push_back(clln); - } - for (auto& cl : dbg_clusLines[rofId]) { - cl_lines_vec_pre.push_back(cl); - } - ln_clus_lines_tree->Fill(); - } - dbg_file->cd(); - ln_clus_lines_tree->Write(); - dbg_file->Close(); + debugComputeVertices(iteration); #endif } @@ -625,7 +556,7 @@ void VertexerTraits::addTruthSeedingVertices() } else { mTimeFrame->getNoVertexROF()++; } - mTimeFrame->addPrimaryVertices(verts, iROF, 0); + mTimeFrame->addPrimaryVertices(verts, 0); mTimeFrame->addPrimaryVerticesLabels(polls); } LOGP(info, "Found {}/{} ROFs with {} vertices -> ={:.2f}", vertices.size(), mTimeFrame->getNrof(), nVerts, (float)nVerts / (float)vertices.size()); @@ -634,6 +565,7 @@ void VertexerTraits::addTruthSeedingVertices() void VertexerTraits::setNThreads(int n, std::shared_ptr& arena) { #if defined(VTX_DEBUG) + LOGP(info, "Vertexer with debug output forcing single thread"); mTaskArena = std::make_shared(1); #else if (arena == nullptr) { @@ -645,3 +577,257 @@ void VertexerTraits::setNThreads(int n, std::shared_ptr& arena) } #endif } + +void VertexerTraits::debugComputeTracklets(int iteration) +{ + auto stream = new utils::TreeStreamRedirector("artefacts_tf.root", "recreate"); + LOGP(info, "writing debug output for computeTracklets"); + for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { + const auto& strk0 = mTimeFrame->getFoundTracklets(rofId, 0); + std::vector trk0(strk0.begin(), strk0.end()); + const auto& strk1 = mTimeFrame->getFoundTracklets(rofId, 1); + std::vector trk1(strk1.begin(), strk1.end()); + (*stream) << "tracklets" + << "Tracklets0=" << trk0 + << "Tracklets1=" << trk1 + << "iteration=" << iteration + << "\n"; + } + stream->Close(); + delete stream; +} + +void VertexerTraits::debugComputeTrackletMatching(int iteration) +{ + auto stream = new utils::TreeStreamRedirector("artefacts_tf.root", "update"); + LOGP(info, "writing debug output for computeTrackletMatching"); + for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { + (*stream) << "lines" + << "Lines=" << toSTDVector(mTimeFrame->getLines(rofId)) + << "NTrackletCluster01=" << mTimeFrame->getNTrackletsCluster(rofId, 0) + << "NTrackletCluster12=" << mTimeFrame->getNTrackletsCluster(rofId, 1) + << "iteration=" << iteration + << "\n"; + } + + if (mTimeFrame->hasMCinformation()) { + LOGP(info, "\tdumping also MC information"); + const auto dc = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); + const auto irs = dc->getEventRecords(); + int64_t roFrameBiasInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameBiasInBC; + int64_t roFrameLengthInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameLengthInBC; + o2::steer::MCKinematicsReader mcReader(dc); + + std::map eve2BcInROF, bcInRofNEve; + for (int iSrc{0}; iSrc < mcReader.getNSources(); ++iSrc) { + auto eveId2colId = dc->getCollisionIndicesForSource(iSrc); + for (int iEve{0}; iEve < mcReader.getNEvents(iSrc); ++iEve) { + const auto& ir = irs[eveId2colId[iEve]]; + if (!ir.isDummy()) { // do we need this, is this for diffractive events? + const auto& eve = mcReader.getMCEventHeader(iSrc, iEve); + const int bcInROF = ((ir - raw::HBFUtils::Instance().getFirstSampledTFIR()).toLong() - roFrameBiasInBC) % roFrameLengthInBC; + eve2BcInROF[iEve] = bcInROF; + ++bcInRofNEve[bcInROF]; + } + } + } + + std::unordered_map bcROFNTracklets01, bcROFNTracklets12; + std::vector> tracklet01BC, tracklet12BC; + for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { + { // 0-1 + const auto& tracklet01 = mTimeFrame->getFoundTracklets(rofId, 0); + const auto& lbls01 = mTimeFrame->getLabelsFoundTracklets(rofId, 0); + auto& trkls01 = tracklet01BC.emplace_back(); + for (int iTrklt{0}; iTrklt < (int)tracklet01.size(); ++iTrklt) { + const auto& tracklet = tracklet01[iTrklt]; + const auto& lbl = lbls01[iTrklt]; + if (lbl.isCorrect()) { + ++bcROFNTracklets01[eve2BcInROF[lbl.getEventID()]]; + trkls01.push_back(eve2BcInROF[lbl.getEventID()]); + } else { + trkls01.push_back(-1); + } + } + } + { // 1-2 computed on the fly! + const auto& tracklet12 = mTimeFrame->getFoundTracklets(rofId, 1); + auto& trkls12 = tracklet12BC.emplace_back(); + for (int iTrklt{0}; iTrklt < (int)tracklet12.size(); ++iTrklt) { + const auto& tracklet = tracklet12[iTrklt]; + o2::MCCompLabel label; + + int sortedId1{mTimeFrame->getSortedIndex(tracklet.rof[0], 1, tracklet.firstClusterIndex)}; + int sortedId2{mTimeFrame->getSortedIndex(tracklet.rof[1], 2, tracklet.secondClusterIndex)}; + for (const auto& lab1 : mTimeFrame->getClusterLabels(1, mTimeFrame->getClusters()[1][sortedId1].clusterId)) { + for (const auto& lab2 : mTimeFrame->getClusterLabels(2, mTimeFrame->getClusters()[2][sortedId2].clusterId)) { + if (lab1 == lab2 && lab1.isValid()) { + label = lab1; + break; + } + } + if (label.isValid()) { + break; + } + } + + if (label.isCorrect()) { + ++bcROFNTracklets12[eve2BcInROF[label.getEventID()]]; + trkls12.push_back(eve2BcInROF[label.getEventID()]); + } else { + trkls12.push_back(-1); + } + } + } + } + LOGP(info, "\tdumping ntracklets/RofBC ({})", bcInRofNEve.size()); + for (const auto& [bcInRof, neve] : bcInRofNEve) { + (*stream) << "ntracklets" + << "bcInROF=" << bcInRof + << "ntrkl01=" << bcROFNTracklets01[bcInRof] + << "ntrkl12=" << bcROFNTracklets12[bcInRof] + << "neve=" << neve + << "iteration=" << iteration + << "\n"; + } + + std::unordered_map bcROFNLines; + for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { + const auto& lines = mTimeFrame->getLines(rofId); + const auto& lbls = mTimeFrame->getLinesLabel(rofId); + for (int iLine{0}; iLine < (int)lines.size(); ++iLine) { + const auto& line = lines[iLine]; + const auto& lbl = lbls[iLine]; + if (lbl.isCorrect()) { + ++bcROFNLines[eve2BcInROF[lbl.getEventID()]]; + } + } + } + + LOGP(info, "\tdumping nlines/RofBC"); + for (const auto& [bcInRof, neve] : bcInRofNEve) { + (*stream) << "nlines" + << "bcInROF=" << bcInRof + << "nline=" << bcROFNLines[bcInRof] + << "neve=" << neve + << "iteration=" << iteration + << "\n"; + } + } + stream->Close(); + delete stream; +} + +void VertexerTraits::debugComputeVertices(int iteration) +{ + auto stream = new utils::TreeStreamRedirector("artefacts_tf.root", "update"); + LOGP(info, "writing debug output for computeVertices"); + for (auto rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { + (*stream) << "clusterlines" + << "clines_post=" << toSTDVector(mTimeFrame->getTrackletClusters(rofId)) + << "iteration=" << iteration + << "\n"; + } + + if (mTimeFrame->hasMCinformation()) { + LOGP(info, "\tdumping also MC information"); + const auto dc = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root"); + const auto irs = dc->getEventRecords(); + int64_t roFrameBiasInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameBiasInBC; + int64_t roFrameLengthInBC = o2::itsmft::DPLAlpideParam::Instance().roFrameLengthInBC; + o2::steer::MCKinematicsReader mcReader(dc); + + std::map eve2BcInROF, bcInRofNEve; + for (int iSrc{0}; iSrc < mcReader.getNSources(); ++iSrc) { + auto eveId2colId = dc->getCollisionIndicesForSource(iSrc); + for (int iEve{0}; iEve < mcReader.getNEvents(iSrc); ++iEve) { + const auto& ir = irs[eveId2colId[iEve]]; + if (!ir.isDummy()) { // do we need this, is this for diffractive events? + const auto& eve = mcReader.getMCEventHeader(iSrc, iEve); + const int bcInROF = ((ir - raw::HBFUtils::Instance().getFirstSampledTFIR()).toLong() - roFrameBiasInBC) % roFrameLengthInBC; + eve2BcInROF[iEve] = bcInROF; + ++bcInRofNEve[bcInROF]; + } + } + } + + std::unordered_map bcROFNVtx; + std::unordered_map bcROFNPur; + std::unordered_map uniqueVertices; + for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { + const auto& pvs = mTimeFrame->getPrimaryVertices(rofId); + const auto& lblspv = mTimeFrame->getPrimaryVerticesMCRecInfo(rofId); + for (int i{0}; i < (int)pvs.size(); ++i) { + const auto& pv = pvs[i]; + const auto& [lbl, pur] = lblspv[i]; + if (lbl.isCorrect()) { + ++uniqueVertices[lbl]; + ++bcROFNVtx[eve2BcInROF[lbl.getEventID()]]; + bcROFNPur[eve2BcInROF[lbl.getEventID()]] += pur; + } + } + } + + std::unordered_map bcROFNUVtx, bcROFNCVtx; + for (const auto& [k, _] : eve2BcInROF) { + bcROFNUVtx[k] = bcROFNCVtx[k] = 0; + } + + for (const auto& [lbl, c] : uniqueVertices) { + if (c <= 1) { + ++bcROFNUVtx[eve2BcInROF[lbl.getEventID()]]; + } else { + ++bcROFNCVtx[eve2BcInROF[lbl.getEventID()]]; + } + } + + LOGP(info, "\tdumping nvtx/RofBC"); + for (const auto& [bcInRof, neve] : bcInRofNEve) { + (*stream) << "nvtx" + << "bcInROF=" << bcInRof + << "nvtx=" << bcROFNVtx[bcInRof] // all vertices + << "nuvtx=" << bcROFNUVtx[bcInRof] // unique vertices + << "ncvtx=" << bcROFNCVtx[bcInRof] // cloned vertices + << "npur=" << bcROFNPur[bcInRof] + << "neve=" << neve + << "iteration=" << iteration + << "\n"; + } + + // check dist of clones + std::unordered_map> cVtx; + for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) { + const auto& pvs = mTimeFrame->getPrimaryVertices(rofId); + const auto& lblspv = mTimeFrame->getPrimaryVerticesMCRecInfo(rofId); + for (int i{0}; i < (int)pvs.size(); ++i) { + const auto& pv = pvs[i]; + const auto& [lbl, pur] = lblspv[i]; + if (lbl.isCorrect() && uniqueVertices.contains(lbl) && uniqueVertices[lbl] > 1) { + if (!cVtx.contains(lbl)) { + cVtx[lbl] = std::vector(); + } + cVtx[lbl].push_back(pv); + } + } + } + + for (auto& [_, vertices] : cVtx) { + std::sort(vertices.begin(), vertices.end(), [](const Vertex& a, const Vertex& b) { return a.getNContributors() > b.getNContributors(); }); + for (int i{0}; i < (int)vertices.size(); ++i) { + const auto vtx = vertices[i]; + (*stream) << "cvtx" + << "vertex=" << vtx + << "i=" << i + << "dx=" << vertices[0].getX() - vtx.getX() + << "dy=" << vertices[0].getY() - vtx.getY() + << "dz=" << vertices[0].getZ() - vtx.getZ() + << "drof=" << vertices[0].getTimeStamp().getTimeStamp() - vtx.getTimeStamp().getTimeStamp() + << "dnc=" << vertices[0].getNContributors() - vtx.getNContributors() + << "iteration=" << iteration + << "\n"; + } + } + } + stream->Close(); + delete stream; +} From 02b6dc2d9938ae3c857570cb7d39d554ab200536 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 23 Jul 2025 14:43:00 +0200 Subject: [PATCH 177/315] Fix alignment so that jemalloc / address sanitizer do no complain This apparently fixes the issues with std::pmr in DataDistribution. --- DataFormats/Headers/include/Headers/Stack.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DataFormats/Headers/include/Headers/Stack.h b/DataFormats/Headers/include/Headers/Stack.h index 40987c483e1b8..0958b639ef451 100644 --- a/DataFormats/Headers/include/Headers/Stack.h +++ b/DataFormats/Headers/include/Headers/Stack.h @@ -38,7 +38,7 @@ struct Stack { struct freeobj { freeobj(memory_resource* mr) : resource(mr) {} memory_resource* resource{nullptr}; - void operator()(std::byte* ptr) { resource->deallocate(ptr, 0, 0); } + void operator()(std::byte* ptr) { resource->deallocate(ptr, 0, alignof(std::max_align_t)); } }; public: From 76f5dc4b283c38c66535ca63ba9eb3c63d4309e2 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 8 Apr 2025 09:18:26 +0200 Subject: [PATCH 178/315] [MFT] read track covariances from AO2Ds The "EXMFTTRACKCOV" table needs to be added to the aodSpawnerCallback() in order to load the MFT tracks covariances from the AO2Ds. --- Framework/Core/src/AODReaderHelpers.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Framework/Core/src/AODReaderHelpers.cxx b/Framework/Core/src/AODReaderHelpers.cxx index ba68cbf15a6e9..2587b8e4ca03a 100644 --- a/Framework/Core/src/AODReaderHelpers.cxx +++ b/Framework/Core/src/AODReaderHelpers.cxx @@ -188,6 +188,8 @@ AlgorithmSpec AODReaderHelpers::aodSpawnerCallback(std::vector& reque } else if (version == 1U) { outputs.adopt(Output{origin, description, version}, make_spawn>(input, pc)); } + } else if (description == header::DataDescription{"EXMFTTRACKCOV"}) { + outputs.adopt(Output{origin, description, version}, make_spawn>(input, pc)); } else if (description == header::DataDescription{"EXFWDTRACK"}) { outputs.adopt(Output{origin, description, version}, make_spawn>(input, pc)); } else if (description == header::DataDescription{"EXFWDTRACKCOV"}) { From b733857a1191e88a43dd9a5e0ab5515bfc347c57 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 23 Jul 2025 14:35:12 +0200 Subject: [PATCH 179/315] ITS: GPU: fix perVtx + upc iteration + atomic level update Signed-off-by: Felix Schlepper --- Detectors/ITSMFT/ITS/tracking/CMakeLists.txt | 2 +- .../GPU/ITStrackingGPU/TimeFrameGPU.h | 7 +- .../ITS/tracking/GPU/ITStrackingGPU/Utils.h | 6 + .../ITS/tracking/GPU/cuda/TimeFrameGPU.cu | 138 +++++++++--------- .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 27 ++-- .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 92 +++++------- .../ITS/tracking/GPU/hip/CMakeLists.txt | 3 +- .../tracking/include/ITStracking/TimeFrame.h | 6 +- .../include/ITStracking/TrackingInterface.h | 1 - .../ITSMFT/ITS/tracking/src/TimeFrame.cxx | 1 - Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 11 +- .../ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 3 +- .../ITS/tracking/src/TrackingInterface.cxx | 6 +- .../ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 1 - 14 files changed, 139 insertions(+), 165 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt index f9565307d35f6..291ddffbf9475 100644 --- a/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/CMakeLists.txt @@ -9,7 +9,6 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -#add_compile_options(-O0 -g -fPIC -fno-omit-frame-pointer) o2_add_library(ITStracking TARGETVARNAME targetName SOURCES src/ClusterLines.cxx @@ -37,6 +36,7 @@ o2_add_library(ITStracking PRIVATE_LINK_LIBRARIES O2::Steer TBB::tbb) +# target_compile_options(${targetName} PRIVATE -O0 -g -fPIC -fno-omit-frame-pointer) o2_add_library(ITSTrackingInterface TARGETVARNAME targetName diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h index 8b3e9bddd18d6..0ad08fd88ccf5 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h @@ -23,11 +23,6 @@ namespace o2::its::gpu { -class DefaultGPUAllocator : public ExternalAllocator -{ - void* allocate(size_t size) override; -}; - template class TimeFrameGPU : public TimeFrame { @@ -84,7 +79,7 @@ class TimeFrameGPU : public TimeFrame return mGpuStreams[stream]; } auto& getStreams() { return mGpuStreams; } - void wipe(const int); + virtual void wipe() final; /// interface int getNClustersInRofSpan(const int, const int, const int) const; diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h index 454e39e04a661..802973d5f4000 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h @@ -21,6 +21,12 @@ #include "GPUCommonDef.h" #include "GPUCommonHelpers.h" +#ifndef __HIPCC__ +#define THRUST_NAMESPACE thrust::cuda +#else +#define THRUST_NAMESPACE thrust::hip +#endif + namespace o2::its { diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu index d5ea573a2f0e8..f6d9157b0da68 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu @@ -21,8 +21,6 @@ #include "ITStrackingGPU/TracerGPU.h" #include -#include -#include #include #include @@ -31,14 +29,7 @@ #include "GPUCommonLogger.h" #include "GPUCommonHelpers.h" -namespace o2 -{ -namespace its -{ -using constants::GB; -using constants::MB; - -namespace gpu +namespace o2::its::gpu { #ifdef ITS_MEASURE_GPU_TIME @@ -96,14 +87,19 @@ class GPUTimer std::vector mStarts, mStops; std::vector mStreams; }; + +#define GPULog(...) LOGP(info, __VA_ARGS__) #else // ITS_MEASURE_GPU_TIME not defined class GPUTimer { public: - GPUTimer(Stream&, const std::string&) {} - GPUTimer(Streams&, const std::string&) {} - GPUTimer(Streams&, const std::string&, int, int = 0) {} + template + GPUTimer(Args&&...) + { + } }; + +#define GPULog(...) #endif template @@ -121,7 +117,7 @@ void TimeFrameGPU::allocMemAsync(void** ptr, size_t size, Stream& strea if (extAllocator) { *ptr = this->mAllocator->allocate(size); } else { - LOGP(debug, "Calling default CUDA allocator"); + GPULog("Calling default CUDA allocator"); GPUChkErrS(cudaMallocAsync(reinterpret_cast(ptr), size, stream.get())); } } @@ -137,10 +133,10 @@ void TimeFrameGPU::loadIndexTableUtils(const int iteration) { GPUTimer timer(mGpuStreams[0], "loading indextable utils"); if (!iteration) { - LOGP(debug, "gpu-allocation: allocating IndexTableUtils buffer, for {} MB.", sizeof(IndexTableUtils) / MB); + GPULog("gpu-allocation: allocating IndexTableUtils buffer, for {:.2f} MB.", sizeof(IndexTableUtils) / constants::MB); allocMemAsync(reinterpret_cast(&mIndexTableUtilsDevice), sizeof(IndexTableUtils), mGpuStreams[0], this->getExtAllocator()); } - LOGP(debug, "gpu-transfer: loading IndexTableUtils object, for {} MB.", sizeof(IndexTableUtils) / MB); + GPULog("gpu-transfer: loading IndexTableUtils object, for {:.2f} MB.", sizeof(IndexTableUtils) / constants::MB); GPUChkErrS(cudaMemcpyAsync(mIndexTableUtilsDevice, &(this->mIndexTableUtils), sizeof(IndexTableUtils), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } @@ -149,11 +145,11 @@ void TimeFrameGPU::loadUnsortedClustersDevice(const int iteration) { if (!iteration) { GPUTimer timer(mGpuStreams[0], "loading unsorted clusters"); - for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { - LOGP(debug, "gpu-transfer: loading {} unsorted clusters on layer {}, for {} MB.", this->mUnsortedClusters[iLayer].size(), iLayer, this->mUnsortedClusters[iLayer].size() * sizeof(Cluster) / MB); - allocMemAsync(reinterpret_cast(&mUnsortedClustersDevice[iLayer]), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), mGpuStreams[0], this->getExtAllocator()); + for (int iLayer{0}; iLayer < nLayers; ++iLayer) { + GPULog("gpu-transfer: loading {} unsorted clusters on layer {}, for {:.2f} MB.", this->mUnsortedClusters[iLayer].size(), iLayer, this->mUnsortedClusters[iLayer].size() * sizeof(Cluster) / constants::MB); + allocMemAsync(reinterpret_cast(&mUnsortedClustersDevice[iLayer]), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), mGpuStreams[iLayer], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mUnsortedClusters[iLayer].data(), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mUnsortedClustersDevice[iLayer], this->mUnsortedClusters[iLayer].data(), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpyAsync(mUnsortedClustersDevice[iLayer], this->mUnsortedClusters[iLayer].data(), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } allocMemAsync(reinterpret_cast(&mUnsortedClustersDeviceArray), nLayers * sizeof(Cluster*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mUnsortedClustersDevice.data(), nLayers * sizeof(Cluster*), cudaHostRegisterPortable)); @@ -167,7 +163,7 @@ void TimeFrameGPU::loadClustersDevice(const int iteration) if (!iteration) { GPUTimer timer(mGpuStreams[0], "loading sorted clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { - LOGP(debug, "gpu-transfer: loading {} clusters on layer {}, for {} MB.", this->mClusters[iLayer].size(), iLayer, this->mClusters[iLayer].size() * sizeof(Cluster) / MB); + GPULog("gpu-transfer: loading {} clusters on layer {}, for {:.2f} MB.", this->mClusters[iLayer].size(), iLayer, this->mClusters[iLayer].size() * sizeof(Cluster) / constants::MB); allocMemAsync(reinterpret_cast(&mClustersDevice[iLayer]), this->mClusters[iLayer].size() * sizeof(Cluster), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mClusters[iLayer].data(), this->mClusters[iLayer].size() * sizeof(Cluster), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mClustersDevice[iLayer], this->mClusters[iLayer].data(), this->mClusters[iLayer].size() * sizeof(Cluster), cudaMemcpyHostToDevice, mGpuStreams[0].get())); @@ -184,7 +180,7 @@ void TimeFrameGPU::loadClustersIndexTables(const int iteration) if (!iteration) { GPUTimer timer(mGpuStreams[0], "loading sorted clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { - LOGP(debug, "gpu-transfer: loading clusters indextable for layer {} with {} elements, for {} MB.", iLayer, this->mIndexTables[iLayer].size(), this->mIndexTables[iLayer].size() * sizeof(int) / MB); + GPULog("gpu-transfer: loading clusters indextable for layer {} with {} elements, for {:.2f} MB.", iLayer, this->mIndexTables[iLayer].size(), this->mIndexTables[iLayer].size() * sizeof(int) / constants::MB); allocMemAsync(reinterpret_cast(&mClustersIndexTablesDevice[iLayer]), this->mIndexTables[iLayer].size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mClustersIndexTablesDevice[iLayer], this->mIndexTables[iLayer].data(), this->mIndexTables[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } @@ -199,7 +195,7 @@ void TimeFrameGPU::createUsedClustersDevice(const int iteration) if (!iteration) { GPUTimer timer(mGpuStreams[0], "creating used clusters flags"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { - LOGP(debug, "gpu-transfer: creating {} used clusters flags on layer {}, for {} MB.", this->mUsedClusters[iLayer].size(), iLayer, this->mUsedClusters[iLayer].size() * sizeof(unsigned char) / MB); + GPULog("gpu-transfer: creating {} used clusters flags on layer {}, for {:.2f} MB.", this->mUsedClusters[iLayer].size(), iLayer, this->mUsedClusters[iLayer].size() * sizeof(unsigned char) / constants::MB); allocMemAsync(reinterpret_cast(&mUsedClustersDevice[iLayer]), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemsetAsync(mUsedClustersDevice[iLayer], 0, this->mUsedClusters[iLayer].size() * sizeof(unsigned char), mGpuStreams[0].get())); } @@ -213,7 +209,7 @@ void TimeFrameGPU::loadUsedClustersDevice() { GPUTimer timer(mGpuStreams[0], "loading used clusters flags"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { - LOGP(debug, "gpu-transfer: loading {} used clusters flags on layer {}, for {} MB.", this->mUsedClusters[iLayer].size(), iLayer, this->mClusters[iLayer].size() * sizeof(unsigned char) / MB); + GPULog("gpu-transfer: loading {} used clusters flags on layer {}, for {:.2f} MB.", this->mUsedClusters[iLayer].size(), iLayer, this->mClusters[iLayer].size() * sizeof(unsigned char) / constants::MB); GPUChkErrS(cudaMemcpyAsync(mUsedClustersDevice[iLayer], this->mUsedClusters[iLayer].data(), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } } @@ -224,7 +220,7 @@ void TimeFrameGPU::loadROframeClustersDevice(const int iteration) if (!iteration) { GPUTimer timer(mGpuStreams[0], "loading ROframe clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { - LOGP(debug, "gpu-transfer: loading {} ROframe clusters info on layer {}, for {} MB.", this->mROFramesClusters[iLayer].size(), iLayer, this->mROFramesClusters[iLayer].size() * sizeof(int) / MB); + GPULog("gpu-transfer: loading {} ROframe clusters info on layer {}, for {:.2f} MB.", this->mROFramesClusters[iLayer].size(), iLayer, this->mROFramesClusters[iLayer].size() * sizeof(int) / constants::MB); allocMemAsync(reinterpret_cast(&mROFramesClustersDevice[iLayer]), this->mROFramesClusters[iLayer].size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mROFramesClustersDevice[iLayer], this->mROFramesClusters[iLayer].data(), this->mROFramesClusters[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } @@ -239,7 +235,7 @@ void TimeFrameGPU::loadTrackingFrameInfoDevice(const int iteration) GPUTimer timer(mGpuStreams[0], "loading trackingframeinfo"); if (!iteration) { for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { - LOGP(debug, "gpu-transfer: loading {} tfinfo on layer {}, for {} MB.", this->mTrackingFrameInfo[iLayer].size(), iLayer, this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo) / MB); + GPULog("gpu-transfer: loading {} tfinfo on layer {}, for {:.2f} MB.", this->mTrackingFrameInfo[iLayer].size(), iLayer, this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo) / constants::MB); allocMemAsync(reinterpret_cast(&mTrackingFrameInfoDevice[iLayer]), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mTrackingFrameInfo[iLayer].data(), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackingFrameInfoDevice[iLayer], this->mTrackingFrameInfo[iLayer].data(), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), cudaMemcpyHostToDevice, mGpuStreams[0].get())); @@ -253,10 +249,12 @@ void TimeFrameGPU::loadTrackingFrameInfoDevice(const int iteration) template void TimeFrameGPU::loadMultiplicityCutMask(const int iteration) { - if (!iteration) { + if (!iteration || iteration == 3) { // we need to re-load the swapped mult-mask in upc iteration GPUTimer timer(mGpuStreams[0], "loading multiplicity cut mask"); - LOGP(debug, "gpu-transfer: loading multiplicity cut mask with {} elements, for {} MB.", this->mMultiplicityCutMask.size(), this->mMultiplicityCutMask.size() * sizeof(bool) / MB); - allocMemAsync(reinterpret_cast(&mMultMaskDevice), this->mMultiplicityCutMask.size() * sizeof(uint8_t), mGpuStreams[0], this->getExtAllocator()); + GPULog("gpu-transfer: iteration {} loading multiplicity cut mask with {} elements, for {:.2f} MB.", iteration, this->mMultiplicityCutMask.size(), this->mMultiplicityCutMask.size() * sizeof(bool) / constants::MB); + if (!iteration) { // only allocate on first call + allocMemAsync(reinterpret_cast(&mMultMaskDevice), this->mMultiplicityCutMask.size() * sizeof(uint8_t), mGpuStreams[0], this->getExtAllocator()); + } GPUChkErrS(cudaMemcpyAsync(mMultMaskDevice, this->mMultiplicityCutMask.data(), this->mMultiplicityCutMask.size() * sizeof(uint8_t), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } } @@ -266,10 +264,10 @@ void TimeFrameGPU::loadVertices(const int iteration) { if (!iteration) { GPUTimer timer(mGpuStreams[0], "loading seeding vertices"); - LOGP(debug, "gpu-transfer: loading {} ROframes vertices, for {} MB.", this->mROFramesPV.size(), this->mROFramesPV.size() * sizeof(int) / MB); + GPULog("gpu-transfer: loading {} ROframes vertices, for {:.2f} MB.", this->mROFramesPV.size(), this->mROFramesPV.size() * sizeof(int) / constants::MB); allocMemAsync(reinterpret_cast(&mROFramesPVDevice), this->mROFramesPV.size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mROFramesPVDevice, this->mROFramesPV.data(), this->mROFramesPV.size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); - LOGP(debug, "gpu-transfer: loading {} seeding vertices, for {} MB.", this->mPrimaryVertices.size(), this->mPrimaryVertices.size() * sizeof(Vertex) / MB); + GPULog("gpu-transfer: loading {} seeding vertices, for {:.2f} MB.", this->mPrimaryVertices.size(), this->mPrimaryVertices.size() * sizeof(Vertex) / constants::MB); allocMemAsync(reinterpret_cast(&mPrimaryVerticesDevice), this->mPrimaryVertices.size() * sizeof(Vertex), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mPrimaryVerticesDevice, this->mPrimaryVertices.data(), this->mPrimaryVertices.size() * sizeof(Vertex), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } @@ -278,13 +276,14 @@ void TimeFrameGPU::loadVertices(const int iteration) template void TimeFrameGPU::createTrackletsLUTDevice(const int iteration) { - GPUTimer timer(mGpuStreams, "creating tracklets LUTs", nLayers - 1); + GPUTimer timer(mGpuStreams[0], "creating tracklets LUTs"); for (auto iLayer{0}; iLayer < nLayers - 1; ++iLayer) { + const int ncls = this->mClusters[iLayer].size() + 1; if (!iteration) { - LOGP(debug, "gpu-transfer: creating tracklets LUT for {} elements on layer {}, for {} MB.", this->mClusters[iLayer].size() + 1, iLayer, (this->mClusters[iLayer].size() + 1) * sizeof(int) / MB); - allocMemAsync(reinterpret_cast(&mTrackletsLUTDevice[iLayer]), (this->mClusters[iLayer].size() + 1) * sizeof(int), mGpuStreams[iLayer], this->getExtAllocator()); + GPULog("gpu-transfer: creating tracklets LUT for {} elements on layer {}, for {:.2f} MB.", ncls, iLayer, ncls * sizeof(int) / constants::MB); + allocMemAsync(reinterpret_cast(&mTrackletsLUTDevice[iLayer]), ncls * sizeof(int), mGpuStreams[iLayer], this->getExtAllocator()); } - GPUChkErrS(cudaMemsetAsync(mTrackletsLUTDevice[iLayer], 0, (this->mClusters[iLayer].size() + 1) * sizeof(int), mGpuStreams[iLayer].get())); + GPUChkErrS(cudaMemsetAsync(mTrackletsLUTDevice[iLayer], 0, ncls * sizeof(int), mGpuStreams[iLayer].get())); } if (!iteration) { allocMemAsync(reinterpret_cast(&mTrackletsLUTDeviceArray), (nLayers - 1) * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); @@ -295,11 +294,11 @@ void TimeFrameGPU::createTrackletsLUTDevice(const int iteration) template void TimeFrameGPU::createTrackletsBuffers() { - GPUTimer timer(mGpuStreams, "creating cells buffers", nLayers - 1); - for (auto iLayer{0}; iLayer < nLayers - 1; ++iLayer) { + GPUTimer timer(mGpuStreams[0], "creating tracklet buffers"); + for (int iLayer{0}; iLayer < nLayers - 1; ++iLayer) { mNTracklets[iLayer] = 0; - GPUChkErrS(cudaMemcpyAsync(&mNTracklets[iLayer], mTrackletsLUTDevice[iLayer] + this->mClusters[iLayer].size(), sizeof(int), cudaMemcpyDeviceToHost)); - LOGP(debug, "gpu-transfer: creating tracklets buffer for {} elements on layer {}, for {} MB.", mNTracklets[iLayer], iLayer, mNTracklets[iLayer] * sizeof(Tracklet) / MB); + GPUChkErrS(cudaMemcpyAsync(&mNTracklets[iLayer], mTrackletsLUTDevice[iLayer] + this->mClusters[iLayer].size(), sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[iLayer].get())); + GPULog("gpu-transfer: creating tracklets buffer for {} elements on layer {}, for {:.2f} MB.", mNTracklets[iLayer], iLayer, mNTracklets[iLayer] * sizeof(Tracklet) / constants::MB); allocMemAsync(reinterpret_cast(&mTrackletsDevice[iLayer]), mNTracklets[iLayer] * sizeof(Tracklet), mGpuStreams[iLayer], this->getExtAllocator()); } allocMemAsync(reinterpret_cast(&mTrackletsDeviceArray), (nLayers - 1) * sizeof(Tracklet*), mGpuStreams[0], this->getExtAllocator()); @@ -312,7 +311,7 @@ void TimeFrameGPU::loadTrackletsDevice() { GPUTimer timer(mGpuStreams, "loading tracklets", nLayers - 1); for (auto iLayer{0}; iLayer < nLayers - 1; ++iLayer) { - LOGP(debug, "gpu-transfer: loading {} tracklets on layer {}, for {} MB.", this->mTracklets[iLayer].size(), iLayer, this->mTracklets[iLayer].size() * sizeof(Tracklet) / MB); + GPULog("gpu-transfer: loading {} tracklets on layer {}, for {:.2f} MB.", this->mTracklets[iLayer].size(), iLayer, this->mTracklets[iLayer].size() * sizeof(Tracklet) / constants::MB); GPUChkErrS(cudaHostRegister(this->mTracklets[iLayer].data(), this->mTracklets[iLayer].size() * sizeof(Tracklet), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackletsDevice[iLayer], this->mTracklets[iLayer].data(), this->mTracklets[iLayer].size() * sizeof(Tracklet), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } @@ -323,12 +322,12 @@ void TimeFrameGPU::loadTrackletsLUTDevice() { GPUTimer timer(mGpuStreams, "loading tracklets", nLayers - 2); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { - LOGP(debug, "gpu-transfer: loading tracklets LUT for {} elements on layer {}, for {} MB", this->mTrackletsLookupTable[iLayer].size(), iLayer + 1, this->mTrackletsLookupTable[iLayer].size() * sizeof(int) / MB); + GPULog("gpu-transfer: loading tracklets LUT for {} elements on layer {}, for {:.2f} MB", this->mTrackletsLookupTable[iLayer].size(), iLayer + 1, this->mTrackletsLookupTable[iLayer].size() * sizeof(int) / constants::MB); GPUChkErrS(cudaHostRegister(this->mTrackletsLookupTable[iLayer].data(), this->mTrackletsLookupTable[iLayer].size() * sizeof(int), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDevice[iLayer + 1], this->mTrackletsLookupTable[iLayer].data(), this->mTrackletsLookupTable[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } GPUChkErrS(cudaHostRegister(mTrackletsLUTDevice.data(), (nLayers - 1) * sizeof(int*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDeviceArray, mTrackletsLUTDevice.data(), (nLayers - 1) * sizeof(int*), cudaMemcpyHostToDevice)); + GPUChkErrS(cudaMemcpyAsync(mTrackletsLUTDeviceArray, mTrackletsLUTDevice.data(), (nLayers - 1) * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } template @@ -340,7 +339,7 @@ void TimeFrameGPU::createNeighboursIndexTablesDevice() GPUChkErrS(cudaHostRegister(mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mCellsDeviceArray, mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { - LOGP(debug, "gpu-transfer: loading neighbours LUT for {} elements on layer {}, for {} MB.", mNCells[iLayer], iLayer, mNCells[iLayer] * sizeof(CellSeed) / MB); + GPULog("gpu-transfer: loading neighbours LUT for {} elements on layer {}, for {:.2f} MB.", mNCells[iLayer], iLayer, mNCells[iLayer] * sizeof(CellSeed) / constants::MB); allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (mNCells[iLayer] + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (mNCells[iLayer] + 1) * sizeof(int), mGpuStreams[0].get())); if (iLayer < nLayers - 3) { @@ -353,7 +352,7 @@ template void TimeFrameGPU::createNeighboursLUTDevice(const int layer, const unsigned int nCells) { GPUTimer timer(mGpuStreams[0], "reserving neighboursLUT"); - LOGP(debug, "gpu-allocation: reserving neighbours LUT for {} elements on layer {} , for {} MB.", nCells + 1, layer, (nCells + 1) * sizeof(int) / MB); + GPULog("gpu-allocation: reserving neighbours LUT for {} elements on layer {} , for {:.2f} MB.", nCells + 1, layer, (nCells + 1) * sizeof(int) / constants::MB); allocMemAsync(reinterpret_cast(&mNeighboursLUTDevice[layer]), (nCells + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); // We need one element more to move exc -> inc GPUChkErrS(cudaMemsetAsync(mNeighboursLUTDevice[layer], 0, (nCells + 1) * sizeof(int), mGpuStreams[0].get())); } @@ -363,7 +362,7 @@ void TimeFrameGPU::loadCellsDevice() { GPUTimer timer(mGpuStreams, "loading cell seeds", nLayers - 2); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { - LOGP(debug, "gpu-transfer: loading {} cell seeds on layer {}, for {} MB.", this->mCells[iLayer].size(), iLayer, this->mCells[iLayer].size() * sizeof(CellSeed) / MB); + GPULog("gpu-transfer: loading {} cell seeds on layer {}, for {:.2f} MB.", this->mCells[iLayer].size(), iLayer, this->mCells[iLayer].size() * sizeof(CellSeed) / constants::MB); allocMemAsync(reinterpret_cast(&mCellsDevice[iLayer]), this->mCells[iLayer].size() * sizeof(CellSeed), mGpuStreams[iLayer], this->getExtAllocator()); allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[iLayer], this->getExtAllocator()); // accessory for the neigh. finding. GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[iLayer].get())); @@ -378,7 +377,7 @@ void TimeFrameGPU::createCellsLUTDevice() { GPUTimer timer(mGpuStreams, "creating cells LUTs", nLayers - 2); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { - LOGP(debug, "gpu-transfer: creating cell LUT for {} elements on layer {}, for {} MB.", mNTracklets[iLayer] + 1, iLayer, (mNTracklets[iLayer] + 1) * sizeof(int) / MB); + GPULog("gpu-transfer: creating cell LUT for {} elements on layer {}, for {:.2f} MB.", mNTracklets[iLayer] + 1, iLayer, (mNTracklets[iLayer] + 1) * sizeof(int) / constants::MB); allocMemAsync(reinterpret_cast(&mCellsLUTDevice[iLayer]), (mNTracklets[iLayer] + 1) * sizeof(int), mGpuStreams[iLayer], this->getExtAllocator()); GPUChkErrS(cudaMemsetAsync(mCellsLUTDevice[iLayer], 0, (mNTracklets[iLayer] + 1) * sizeof(int), mGpuStreams[iLayer].get())); } @@ -391,9 +390,9 @@ void TimeFrameGPU::createCellsBuffers(const int layer) { GPUTimer timer(mGpuStreams[0], "creating cells buffers"); mNCells[layer] = 0; - GPUChkErrS(cudaMemcpyAsync(&mNCells[layer], mCellsLUTDevice[layer] + mNTracklets[layer], sizeof(int), cudaMemcpyDeviceToHost)); - LOGP(debug, "gpu-transfer: creating cell buffer for {} elements on layer {}, for {} MB.", mNCells[layer], layer, mNCells[layer] * sizeof(CellSeed) / MB); - allocMemAsync(reinterpret_cast(&mCellsDevice[layer]), mNCells[layer] * sizeof(CellSeed), mGpuStreams[0], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(&mNCells[layer], mCellsLUTDevice[layer] + mNTracklets[layer], sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[layer].get())); + GPULog("gpu-transfer: creating cell buffer for {} elements on layer {}, for {:.2f} MB.", mNCells[layer], layer, mNCells[layer] * sizeof(CellSeed) / constants::MB); + allocMemAsync(reinterpret_cast(&mCellsDevice[layer]), mNCells[layer] * sizeof(CellSeed), mGpuStreams[layer], this->getExtAllocator()); } template @@ -401,7 +400,7 @@ void TimeFrameGPU::loadCellsLUTDevice() { GPUTimer timer(mGpuStreams, "loading cells LUTs", nLayers - 3); for (auto iLayer{0}; iLayer < nLayers - 3; ++iLayer) { - LOGP(debug, "gpu-transfer: loading cell LUT for {} elements on layer {}, for {} MB.", this->mCellsLookupTable[iLayer].size(), iLayer, this->mCellsLookupTable[iLayer].size() * sizeof(int) / MB); + GPULog("gpu-transfer: loading cell LUT for {} elements on layer {}, for {:.2f} MB.", this->mCellsLookupTable[iLayer].size(), iLayer, this->mCellsLookupTable[iLayer].size() * sizeof(int) / constants::MB); GPUChkErrS(cudaHostRegister(this->mCellsLookupTable[iLayer].data(), this->mCellsLookupTable[iLayer].size() * sizeof(int), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mCellsLUTDevice[iLayer + 1], this->mCellsLookupTable[iLayer].data(), this->mCellsLookupTable[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } @@ -411,7 +410,7 @@ template void TimeFrameGPU::loadRoadsDevice() { GPUTimer timer(mGpuStreams[0], "loading roads device"); - LOGP(debug, "gpu-transfer: loading {} roads, for {} MB.", this->mRoads.size(), this->mRoads.size() * sizeof(Road) / MB); + GPULog("gpu-transfer: loading {} roads, for {:.2f} MB.", this->mRoads.size(), this->mRoads.size() * sizeof(Road) / constants::MB); allocMemAsync(reinterpret_cast(&mRoadsDevice), this->mRoads.size() * sizeof(Road), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mRoads.data(), this->mRoads.size() * sizeof(Road), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mRoadsDevice, this->mRoads.data(), this->mRoads.size() * sizeof(Road), cudaMemcpyHostToDevice, mGpuStreams[0].get())); @@ -421,7 +420,7 @@ template void TimeFrameGPU::loadTrackSeedsDevice(bounded_vector& seeds) { GPUTimer timer(mGpuStreams[0], "loading track seeds"); - LOGP(debug, "gpu-transfer: loading {} track seeds, for {} MB.", seeds.size(), seeds.size() * sizeof(CellSeed) / MB); + GPULog("gpu-transfer: loading {} track seeds, for {:.2f} MB.", seeds.size(), seeds.size() * sizeof(CellSeed) / constants::MB); allocMemAsync(reinterpret_cast(&mTrackSeedsDevice), seeds.size() * sizeof(CellSeed), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(seeds.data(), seeds.size() * sizeof(CellSeed), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackSeedsDevice, seeds.data(), seeds.size() * sizeof(CellSeed), cudaMemcpyHostToDevice, mGpuStreams[0].get())); @@ -431,10 +430,10 @@ template void TimeFrameGPU::createNeighboursDevice(const unsigned int layer, const unsigned int nNeighbours) { GPUTimer timer(mGpuStreams[0], "reserving neighbours"); - LOGP(debug, "gpu-allocation: reserving {} neighbours (pairs), for {} MB.", nNeighbours, nNeighbours * sizeof(gpuPair) / MB); + GPULog("gpu-allocation: reserving {} neighbours (pairs), for {:.2f} MB.", nNeighbours, nNeighbours * sizeof(gpuPair) / constants::MB); allocMemAsync(reinterpret_cast(&mNeighbourPairsDevice[layer]), nNeighbours * sizeof(gpuPair), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, nNeighbours * sizeof(gpuPair), mGpuStreams[0].get())); - LOGP(debug, "gpu-allocation: reserving {} neighbours, for {} MB.", nNeighbours, nNeighbours * sizeof(gpuPair) / MB); + GPULog("gpu-allocation: reserving {} neighbours, for {:.2f} MB.", nNeighbours, nNeighbours * sizeof(gpuPair) / constants::MB); allocMemAsync(reinterpret_cast(&mNeighboursDevice[layer]), nNeighbours * sizeof(int), mGpuStreams[0], this->getExtAllocator()); } @@ -444,10 +443,10 @@ void TimeFrameGPU::createNeighboursDevice(const unsigned int layer, std GPUTimer timer(mGpuStreams[0], "reserving neighbours"); this->mCellsNeighbours[layer].clear(); this->mCellsNeighbours[layer].resize(neighbours.size()); - LOGP(debug, "gpu-allocation: reserving {} neighbours (pairs), for {} MB.", neighbours.size(), neighbours.size() * sizeof(gpuPair) / MB); + GPULog("gpu-allocation: reserving {} neighbours (pairs), for {:.2f} MB.", neighbours.size(), neighbours.size() * sizeof(gpuPair) / constants::MB); allocMemAsync(reinterpret_cast(&mNeighbourPairsDevice[layer]), neighbours.size() * sizeof(gpuPair), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, neighbours.size() * sizeof(gpuPair), mGpuStreams[0].get())); - LOGP(debug, "gpu-allocation: reserving {} neighbours, for {} MB.", neighbours.size(), neighbours.size() * sizeof(gpuPair) / MB); + GPULog("gpu-allocation: reserving {} neighbours, for {:.2f} MB.", neighbours.size(), neighbours.size() * sizeof(gpuPair) / constants::MB); allocMemAsync(reinterpret_cast(&mNeighboursDevice[layer]), neighbours.size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); } @@ -464,7 +463,7 @@ void TimeFrameGPU::createTrackITSExtDevice(bounded_vector& se { GPUTimer timer(mGpuStreams[0], "reserving tracks"); mTrackITSExt = bounded_vector(seeds.size(), {}, this->getMemoryPool().get()); - LOGP(debug, "gpu-allocation: reserving {} tracks, for {} MB.", seeds.size(), seeds.size() * sizeof(o2::its::TrackITSExt) / MB); + GPULog("gpu-allocation: reserving {} tracks, for {:.2f} MB.", seeds.size(), seeds.size() * sizeof(o2::its::TrackITSExt) / constants::MB); allocMemAsync(reinterpret_cast(&mTrackITSExtDevice), seeds.size() * sizeof(o2::its::TrackITSExt), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaMemsetAsync(mTrackITSExtDevice, 0, seeds.size() * sizeof(o2::its::TrackITSExt), mGpuStreams[0].get())); GPUChkErrS(cudaHostRegister(mTrackITSExt.data(), seeds.size() * sizeof(o2::its::TrackITSExt), cudaHostRegisterPortable)); @@ -475,7 +474,7 @@ void TimeFrameGPU::downloadCellsDevice() { GPUTimer timer(mGpuStreams, "downloading cells", nLayers - 2); for (int iLayer{0}; iLayer < nLayers - 2; ++iLayer) { - LOGP(debug, "gpu-transfer: downloading {} cells on layer: {}, for {} MB.", mNCells[iLayer], iLayer, mNCells[iLayer] * sizeof(CellSeed) / MB); + GPULog("gpu-transfer: downloading {} cells on layer: {}, for {:.2f} MB.", mNCells[iLayer], iLayer, mNCells[iLayer] * sizeof(CellSeed) / constants::MB); this->mCells[iLayer].resize(mNCells[iLayer]); GPUChkErrS(cudaMemcpyAsync(this->mCells[iLayer].data(), this->mCellsDevice[iLayer], mNCells[iLayer] * sizeof(CellSeed), cudaMemcpyDeviceToHost, mGpuStreams[iLayer].get())); } @@ -486,7 +485,7 @@ void TimeFrameGPU::downloadCellsLUTDevice() { GPUTimer timer(mGpuStreams, "downloading cell luts", nLayers - 3); for (auto iLayer{0}; iLayer < nLayers - 3; ++iLayer) { - LOGP(debug, "gpu-transfer: downloading cells lut on layer {} for {} elements", iLayer, (mNTracklets[iLayer + 1] + 1)); + GPULog("gpu-transfer: downloading cells lut on layer {} for {} elements", iLayer, (mNTracklets[iLayer + 1] + 1)); this->mCellsLookupTable[iLayer].resize(mNTracklets[iLayer + 1] + 1); GPUChkErrS(cudaMemcpyAsync(this->mCellsLookupTable[iLayer].data(), mCellsLUTDevice[iLayer + 1], (mNTracklets[iLayer + 1] + 1) * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[iLayer].get())); } @@ -496,7 +495,7 @@ template void TimeFrameGPU::downloadCellsNeighboursDevice(std::vector>>& neighbours, const int layer) { GPUTimer timer(mGpuStreams[0], fmt::format("downloading neighbours from layer {}", layer)); - LOGP(debug, "gpu-transfer: downloading {} neighbours, for {} MB.", neighbours[layer].size(), neighbours[layer].size() * sizeof(std::pair) / MB); + GPULog("gpu-transfer: downloading {} neighbours, for {:.2f} MB.", neighbours[layer].size(), neighbours[layer].size() * sizeof(std::pair) / constants::MB); // TODO: something less dangerous than assuming the same memory layout of std::pair and gpuPair... or not? :) GPUChkErrS(cudaMemcpyAsync(neighbours[layer].data(), mNeighbourPairsDevice[layer], neighbours[layer].size() * sizeof(gpuPair), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); } @@ -505,7 +504,7 @@ template void TimeFrameGPU::downloadNeighboursLUTDevice(bounded_vector& lut, const int layer) { GPUTimer timer(mGpuStreams[0], fmt::format("downloading neighbours LUT from layer {}", layer)); - LOGP(debug, "gpu-transfer: downloading neighbours LUT for {} elements on layer {}, for {} MB.", lut.size(), layer, lut.size() * sizeof(int) / MB); + GPULog("gpu-transfer: downloading neighbours LUT for {} elements on layer {}, for {:.2f} MB.", lut.size(), layer, lut.size() * sizeof(int) / constants::MB); GPUChkErrS(cudaMemcpyAsync(lut.data(), mNeighboursLUTDevice[layer], lut.size() * sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); } @@ -513,7 +512,7 @@ template void TimeFrameGPU::downloadTrackITSExtDevice(bounded_vector& seeds) { GPUTimer timer(mGpuStreams[0], "downloading tracks"); - LOGP(debug, "gpu-transfer: downloading {} tracks, for {} MB.", mTrackITSExt.size(), mTrackITSExt.size() * sizeof(o2::its::TrackITSExt) / MB); + GPULog("gpu-transfer: downloading {} tracks, for {:.2f} MB.", mTrackITSExt.size(), mTrackITSExt.size() * sizeof(o2::its::TrackITSExt) / constants::MB); GPUChkErrS(cudaMemcpyAsync(mTrackITSExt.data(), mTrackITSExtDevice, seeds.size() * sizeof(o2::its::TrackITSExt), cudaMemcpyDeviceToHost, mGpuStreams[0].get())); GPUChkErrS(cudaHostUnregister(mTrackITSExt.data())); GPUChkErrS(cudaHostUnregister(seeds.data())); @@ -523,7 +522,7 @@ template void TimeFrameGPU::unregisterRest() { GPUTimer timer(mGpuStreams[0], "unregistering rest of the host memory"); - LOGP(debug, "unregistering rest of the host memory..."); + GPULog("unregistering rest of the host memory..."); GPUChkErrS(cudaHostUnregister(mCellsDevice.data())); GPUChkErrS(cudaHostUnregister(mTrackletsDevice.data())); } @@ -531,6 +530,8 @@ void TimeFrameGPU::unregisterRest() template void TimeFrameGPU::unregisterHostMemory(const int maxLayers) { + GPUTimer timer(mGpuStreams[0], "unregistering host memory"); + GPULog("unregistering host memory"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { GPUChkErrS(cudaHostUnregister(this->mUnsortedClusters[iLayer].data())); GPUChkErrS(cudaHostUnregister(this->mClusters[iLayer].data())); @@ -552,7 +553,12 @@ void TimeFrameGPU::initialise(const int iteration, o2::its::TimeFrame::initialise(iteration, trkParam, maxLayers); } +template +void TimeFrameGPU::wipe() +{ + unregisterHostMemory(0); + o2::its::TimeFrame::wipe(); +} + template class TimeFrameGPU<7>; -} // namespace gpu -} // namespace its -} // namespace o2 +} // namespace o2::its::gpu diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index 1b1c4af682dc5..a8061e872c029 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -18,10 +18,10 @@ #include "ITStrackingGPU/TrackerTraitsGPU.h" #include "ITStrackingGPU/TrackingKernels.h" #include "ITStracking/TrackingConfigParam.h" +#include "ITStracking/Constants.h" namespace o2::its { -constexpr int UnusedIndex{-1}; template void TrackerTraitsGPU::initialiseTimeFrame(const int iteration) @@ -48,10 +48,8 @@ void TrackerTraitsGPU::adoptTimeFrame(TimeFrame* tf) template void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int iROFslice, int iVertex) { - auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); + const auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); - const Vertex diamondVert({this->mTrkParams[iteration].Diamond[0], this->mTrkParams[iteration].Diamond[1], this->mTrkParams[iteration].Diamond[2]}, {25.e-6f, 0.f, 0.f, 25.e-6f, 0.f, 36.f}, 1, 1.f); - gsl::span diamondSpan(&diamondVert, 1); int startROF{this->mTrkParams[iteration].nROFsPerIterations > 0 ? iROFslice * this->mTrkParams[iteration].nROFsPerIterations : 0}; int endROF{o2::gpu::CAMath::Min(this->mTrkParams[iteration].nROFsPerIterations > 0 ? (iROFslice + 1) * this->mTrkParams[iteration].nROFsPerIterations + this->mTrkParams[iteration].DeltaROF : mTimeFrameGPU->getNrof(), mTimeFrameGPU->getNrof())}; @@ -128,6 +126,7 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) for (int iLayer = 0; iLayer < this->mTrkParams[iteration].CellsPerRoad(); ++iLayer) { if (!mTimeFrameGPU->getNTracklets()[iLayer + 1] || !mTimeFrameGPU->getNTracklets()[iLayer]) { + mTimeFrameGPU->getNCells()[iLayer] = 0; continue; } const int currentLayerTrackletsNum{static_cast(mTimeFrameGPU->getNTracklets()[iLayer])}; @@ -173,9 +172,10 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) mTimeFrameGPU->createNeighboursIndexTablesDevice(); const auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); for (int iLayer{0}; iLayer < this->mTrkParams[iteration].CellsPerRoad() - 1; ++iLayer) { + const int currentLayerCellsNum{static_cast(mTimeFrameGPU->getNCells()[iLayer])}; const int nextLayerCellsNum{static_cast(mTimeFrameGPU->getNCells()[iLayer + 1])}; - - if (!nextLayerCellsNum) { + if (!nextLayerCellsNum || !currentLayerCellsNum) { + mTimeFrameGPU->getNNeighbours()[iLayer] = 0; continue; } @@ -188,7 +188,7 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) this->mTrkParams[0].MaxChi2ClusterAttachment, this->mBz, iLayer, - mTimeFrameGPU->getNCells()[iLayer], + currentLayerCellsNum, nextLayerCellsNum, 1e2, conf.nBlocks, @@ -204,7 +204,7 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) this->mTrkParams[0].MaxChi2ClusterAttachment, this->mBz, iLayer, - mTimeFrameGPU->getNCells()[iLayer], + currentLayerCellsNum, nextLayerCellsNum, 1e2, conf.nBlocks, @@ -251,8 +251,8 @@ void TrackerTraitsGPU::findRoads(const int iteration) conf.nThreads); } // fixme: I don't want to move tracks back and forth, but I need a way to use a thrust::allocator that is aware of our managed memory. - if (!trackSeeds.size()) { - LOGP(info, "No track seeds found, skipping track finding"); + if (trackSeeds.empty()) { + LOGP(debug, "No track seeds found, skipping track finding"); continue; } mTimeFrameGPU->createTrackITSExtDevice(trackSeeds); @@ -283,7 +283,7 @@ void TrackerTraitsGPU::findRoads(const int iteration) int nShared = 0; bool isFirstShared{false}; for (int iLayer{0}; iLayer < this->mTrkParams[0].NLayers; ++iLayer) { - if (track.getClusterIndex(iLayer) == UnusedIndex) { + if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { continue; } nShared += int(mTimeFrameGPU->isClusterUsed(iLayer, track.getClusterIndex(iLayer))); @@ -296,7 +296,7 @@ void TrackerTraitsGPU::findRoads(const int iteration) std::array rofs{INT_MAX, INT_MAX, INT_MAX}; for (int iLayer{0}; iLayer < this->mTrkParams[0].NLayers; ++iLayer) { - if (track.getClusterIndex(iLayer) == UnusedIndex) { + if (track.getClusterIndex(iLayer) == constants::UnusedIndex) { continue; } mTimeFrameGPU->markUsedCluster(iLayer, track.getClusterIndex(iLayer)); @@ -320,9 +320,6 @@ void TrackerTraitsGPU::findRoads(const int iteration) } mTimeFrameGPU->loadUsedClustersDevice(); } - if (iteration == this->mTrkParams.size() - 1) { - mTimeFrameGPU->unregisterHostMemory(0); - } }; template diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 38c59d520aa76..fb75764da2e36 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -36,15 +36,6 @@ #include "ITStrackingGPU/TrackingKernels.h" #include "ITStrackingGPU/Utils.h" -#ifndef __HIPCC__ -#define THRUST_NAMESPACE thrust::cuda -#else -#define THRUST_NAMESPACE thrust::hip -#endif - -#define GPU_BLOCKS GPUCA_DETERMINISTIC_CODE(1, 99999) -#define GPU_THREADS GPUCA_DETERMINISTIC_CODE(1, 99999) - // O2 track model #include "ReconstructionDataFormats/Track.h" #include "DetectorsBase/Propagator.h" @@ -112,7 +103,6 @@ GPUd() const int4 getBinsRect(const Cluster& currentCluster, const int layerInde if (zRangeMax < -utils.getLayerZ(layerIndex) || zRangeMin > utils.getLayerZ(layerIndex) || zRangeMin > zRangeMax) { - return getEmptyBinsRect(); } @@ -398,22 +388,20 @@ GPUg() void computeLayerCellNeighboursKernel( } if constexpr (initRun) { atomicAdd(neighboursLUT + iNextCell, 1); - foundNeighbours++; neighboursIndexTable[iCurrentCellIndex]++; } else { cellNeighbours[neighboursIndexTable[iCurrentCellIndex] + foundNeighbours] = {iCurrentCellIndex, iNextCell}; foundNeighbours++; - // FIXME: this is prone to race conditions: check on level is not atomic const int currentCellLevel{currentCellSeed.getLevel()}; if (currentCellLevel >= nextCellSeed.getLevel()) { - cellSeedArray[layerIndex + 1][iNextCell].setLevel(currentCellLevel + 1); + atomicMax(cellSeedArray[layerIndex + 1][iNextCell].getLevelPtr(), currentCellLevel + 1); } } } } } -template +template GPUg() void computeLayerCellsKernel( const Cluster** sortedClusters, const Cluster** unsortedClusters, @@ -530,8 +518,14 @@ GPUg() void computeLayerTrackletsMultiROFKernel( for (unsigned int iROF{blockIdx.x}; iROF < endROF - startROF; iROF += gridDim.x) { const short rof0 = iROF + startROF; auto primaryVertices = getPrimaryVertices(rof0, rofPV, totalROFs, multMask, vertices); + if (primaryVertices.empty()) { + continue; + } const auto startVtx{vertexId >= 0 ? vertexId : 0}; const auto endVtx{vertexId >= 0 ? o2::gpu::CAMath::Min(vertexId + 1, static_cast(primaryVertices.size())) : static_cast(primaryVertices.size())}; + if ((endVtx - startVtx) <= 0) { + continue; + } const short minROF = o2::gpu::CAMath::Max(startROF, static_cast(rof0 - deltaROF)); const short maxROF = o2::gpu::CAMath::Min(endROF - 1, static_cast(rof0 + deltaROF)); auto clustersCurrentLayer = getClustersOnLayer(rof0, totalROFs, layerIndex, ROFClusters, clusters); @@ -541,7 +535,7 @@ GPUg() void computeLayerTrackletsMultiROFKernel( for (int currentClusterIndex = threadIdx.x; currentClusterIndex < clustersCurrentLayer.size(); currentClusterIndex += blockDim.x) { unsigned int storedTracklets{0}; - auto currentCluster{clustersCurrentLayer[currentClusterIndex]}; + const auto& currentCluster{clustersCurrentLayer[currentClusterIndex]}; const int currentSortedIndex{ROFClusters[layerIndex][rof0] + currentClusterIndex}; if (usedClusters[layerIndex][currentCluster.clusterId]) { continue; @@ -550,14 +544,15 @@ GPUg() void computeLayerTrackletsMultiROFKernel( const float inverseR0{1.f / currentCluster.radius}; for (int iV{startVtx}; iV < endVtx; ++iV) { auto& primaryVertex{primaryVertices[iV]}; - if (primaryVertex.isFlagSet(2) && iteration != 3) { + if ((primaryVertex.isFlagSet(Vertex::Flags::UPCMode) && iteration != 3) || (iteration == 3 && !primaryVertex.isFlagSet(Vertex::Flags::UPCMode))) { continue; } + const float resolution = o2::gpu::CAMath::Sqrt(math_utils::Sq(resolutionPV) / primaryVertex.getNContributors() + math_utils::Sq(positionResolution)); const float tanLambda{(currentCluster.zCoordinate - primaryVertex.getZ()) * inverseR0}; const float zAtRmin{tanLambda * (minR - currentCluster.radius) + currentCluster.zCoordinate}; const float zAtRmax{tanLambda * (maxR - currentCluster.radius) + currentCluster.zCoordinate}; - const float sqInverseDeltaZ0{1.f / (math_utils::Sq(currentCluster.zCoordinate - primaryVertex.getZ()) + 2.e-8f)}; /// protecting from overflows adding the detector resolution + const float sqInverseDeltaZ0{1.f / (math_utils::Sq(currentCluster.zCoordinate - primaryVertex.getZ()) + constants::Tolerance)}; /// protecting from overflows adding the detector resolution const float sigmaZ{o2::gpu::CAMath::Sqrt(math_utils::Sq(resolution) * math_utils::Sq(tanLambda) * ((math_utils::Sq(inverseR0) + sqInverseDeltaZ0) * math_utils::Sq(meanDeltaR) + 1.f) + math_utils::Sq(meanDeltaR * MSAngle))}; const int4 selectedBinsRect{getBinsRect(currentCluster, layerIndex + 1, *utils, zAtRmin, zAtRmax, sigmaZ * NSigmaCut, phiCut)}; if (selectedBinsRect.x == 0 && selectedBinsRect.y == 0 && selectedBinsRect.z == 0 && selectedBinsRect.w == 0) { @@ -579,8 +574,8 @@ GPUg() void computeLayerTrackletsMultiROFKernel( int iPhiBin = (selectedBinsRect.y + iPhiCount) % phiBins; const int firstBinIndex{utils->getBinIndex(selectedBinsRect.x, iPhiBin)}; const int maxBinIndex{firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1}; - const int firstRowClusterIndex = indexTables[layerIndex + 1][(rof1 - startROF) * tableSize + firstBinIndex]; - const int maxRowClusterIndex = indexTables[layerIndex + 1][(rof1 - startROF) * tableSize + maxBinIndex]; + const int firstRowClusterIndex = indexTables[layerIndex + 1][(rof1)*tableSize + firstBinIndex]; + const int maxRowClusterIndex = indexTables[layerIndex + 1][(rof1)*tableSize + maxBinIndex]; for (int nextClusterIndex{firstRowClusterIndex}; nextClusterIndex < maxRowClusterIndex; ++nextClusterIndex) { if (nextClusterIndex >= clustersNextLayer.size()) { break; @@ -591,13 +586,13 @@ GPUg() void computeLayerTrackletsMultiROFKernel( } const float deltaPhi{o2::gpu::CAMath::Abs(currentCluster.phi - nextCluster.phi)}; const float deltaZ{o2::gpu::CAMath::Abs(tanLambda * (nextCluster.radius - currentCluster.radius) + currentCluster.zCoordinate - nextCluster.zCoordinate)}; - const int nextSortedIndex{ROFClusters[layerIndex + 1][rof1] + nextClusterIndex}; if (deltaZ / sigmaZ < NSigmaCut && (deltaPhi < phiCut || o2::gpu::CAMath::Abs(deltaPhi - o2::constants::math::TwoPI) < phiCut)) { if constexpr (initRun) { trackletsLUT[layerIndex][currentSortedIndex]++; // we need l0 as well for usual exclusive sums. } else { const float phi{o2::gpu::CAMath::ATan2(currentCluster.yCoordinate - nextCluster.yCoordinate, currentCluster.xCoordinate - nextCluster.xCoordinate)}; const float tanL{(currentCluster.zCoordinate - nextCluster.zCoordinate) / (currentCluster.radius - nextCluster.radius)}; + const int nextSortedIndex{ROFClusters[layerIndex + 1][rof1] + nextClusterIndex}; new (tracklets[layerIndex] + trackletsLUT[layerIndex][currentSortedIndex] + storedTracklets) Tracklet{currentSortedIndex, nextSortedIndex, tanL, phi, rof0, rof1}; } ++storedTracklets; @@ -841,11 +836,9 @@ GPUhi() void cubExclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stre { void* d_temp_storage = nullptr; size_t temp_storage_bytes = 0; - GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, - in_out, num_items, stream)); + GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); GPUChkErrS(cudaMalloc(&d_temp_storage, temp_storage_bytes)); - GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, - in_out, num_items, stream)); + GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); GPUChkErrS(cudaFree(d_temp_storage)); } @@ -860,11 +853,9 @@ GPUhi() void cubInclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stre { void* d_temp_storage = nullptr; size_t temp_storage_bytes = 0; - GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_out, - in_out, num_items, stream)); + GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); GPUChkErrS(cudaMalloc(&d_temp_storage, temp_storage_bytes)); - GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_out, - in_out, num_items, stream)); + GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); GPUChkErrS(cudaFree(d_temp_storage)); } @@ -907,10 +898,7 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, gpu::Streams& streams) { for (int iLayer = 0; iLayer < nLayers - 1; ++iLayer) { - gpu::computeLayerTrackletsMultiROFKernel<<>>( + gpu::computeLayerTrackletsMultiROFKernel<<>>( utils, multMask, iLayer, @@ -976,10 +964,7 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, gpu::Streams& streams) { for (int iLayer = 0; iLayer < nLayers - 1; ++iLayer) { - gpu::computeLayerTrackletsMultiROFKernel<<>>( + gpu::computeLayerTrackletsMultiROFKernel<<>>( utils, multMask, iLayer, @@ -1013,10 +998,10 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, nTracklets[iLayer] = unique_end - tracklets_ptr; if (iLayer > 0) { GPUChkErrS(cudaMemsetAsync(trackletsLUTsHost[iLayer], 0, nClusters[iLayer] * sizeof(int), streams[iLayer].get())); - gpu::compileTrackletsLookupTableKernel<<>>(spanTracklets[iLayer], trackletsLUTsHost[iLayer], nTracklets[iLayer]); + gpu::compileTrackletsLookupTableKernel<<>>( + spanTracklets[iLayer], + trackletsLUTsHost[iLayer], + nTracklets[iLayer]); gpu::cubExclusiveScanInPlace(trackletsLUTsHost[iLayer], nClusters[iLayer] + 1, streams[iLayer].get()); } } @@ -1040,8 +1025,7 @@ void countCellsHandler( const int nBlocks, const int nThreads) { - gpu::computeLayerCellsKernel<<>>( + gpu::computeLayerCellsKernel<<>>( sortedClusters, // const Cluster** unsortedClusters, // const Cluster** tfInfo, // const TrackingFrameInfo** @@ -1076,8 +1060,7 @@ void computeCellsHandler( const int nBlocks, const int nThreads) { - gpu::computeLayerCellsKernel<<>>( + gpu::computeLayerCellsKernel<<>>( sortedClusters, // const Cluster** unsortedClusters, // const Cluster** tfInfo, // const TrackingFrameInfo** @@ -1107,8 +1090,7 @@ unsigned int countCellNeighboursHandler(CellSeed** cellsLayersDevice, const int nBlocks, const int nThreads) { - gpu::computeLayerCellNeighboursKernel<<>>( + gpu::computeLayerCellNeighboursKernel<<>>( cellsLayersDevice, neighboursLUT, neighboursIndexTable, @@ -1142,8 +1124,7 @@ void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, const int nThreads) { - gpu::computeLayerCellNeighboursKernel<<>>( + gpu::computeLayerCellNeighboursKernel<<>>( cellsLayersDevice, neighboursLUT, neighboursIndexTable, @@ -1198,8 +1179,7 @@ void processNeighboursHandler(const int startLayer, thrust::device_vector> foundSeedsTable(nCells[startLayer] + 1, 0, allocInt); // Shortcut: device_vector skips central memory management, we are relying on the contingency. // TODO: fix this. - gpu::processNeighboursKernel<<>>( + gpu::processNeighboursKernel<<>>( startLayer, startLevel, allCellSeeds, @@ -1221,8 +1201,7 @@ void processNeighboursHandler(const int startLayer, thrust::device_vector> updatedCellId(foundSeedsTable.back(), 0, allocInt); thrust::device_vector> updatedCellSeed(foundSeedsTable.back(), allocCellSeed); - gpu::processNeighboursKernel<<>>( + gpu::processNeighboursKernel<<>>( startLayer, startLevel, allCellSeeds, @@ -1255,8 +1234,7 @@ void processNeighboursHandler(const int startLayer, foundSeedsTable.resize(lastCellSeedSize + 1); thrust::fill(foundSeedsTable.begin(), foundSeedsTable.end(), 0); - gpu::processNeighboursKernel<<>>( + gpu::processNeighboursKernel<<>>( iLayer, --level, allCellSeeds, @@ -1282,8 +1260,7 @@ void processNeighboursHandler(const int startLayer, updatedCellSeed.resize(foundSeeds); thrust::fill(updatedCellSeed.begin(), updatedCellSeed.end(), CellSeed()); - gpu::processNeighboursKernel<<>>( + gpu::processNeighboursKernel<<>>( iLayer, level, allCellSeeds, @@ -1326,8 +1303,7 @@ void trackSeedHandler(CellSeed* trackSeeds, const int nThreads) { thrust::device_vector minPts(minPtsHost); - gpu::fitTrackSeedsKernel<<>>( + gpu::fitTrackSeedsKernel<<>>( trackSeeds, // CellSeed* foundTrackingFrameInfo, // TrackingFrameInfo** tracks, // TrackITSExt* diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/hip/CMakeLists.txt b/Detectors/ITSMFT/ITS/tracking/GPU/hip/CMakeLists.txt index cc43b6845a714..e8e475f2232c8 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/hip/CMakeLists.txt +++ b/Detectors/ITSMFT/ITS/tracking/GPU/hip/CMakeLists.txt @@ -12,6 +12,7 @@ if(HIP_ENABLED) message(STATUS "Building ITS HIP tracker") set(CMAKE_HIP_FLAGS "${CMAKE_HIP_FLAGS} -fgpu-rdc") + # set(CMAKE_HIP_FLAGS "${CMAKE_HIP_FLAGS} -O0 -g -ggdb -fno-inline -fno-omit-frame-pointer -D__HIP_ENABLE_DEVICE_ASSERT__") o2_add_hipified_library(ITStrackingHIP SOURCES ../cuda/ClusterLinesGPU.cu ../cuda/TimeFrameGPU.cu @@ -28,4 +29,4 @@ if(HIP_ENABLED) hip::host PRIVATE_LINK_LIBRARIES O2::GPUTrackingHIPExternalProvider TARGETVARNAME targetName) -endif() \ No newline at end of file +endif() diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h index 3f0d291d5e51d..5e08e6c48e03a 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h @@ -308,7 +308,7 @@ struct TimeFrame { const o2::base::PropagatorImpl* mPropagatorDevice = nullptr; // Needed only for GPU - void wipe(); + virtual void wipe(); private: void prepareClusters(const TrackingParameters& trkParam, const int maxLayers = nLayers); @@ -531,8 +531,8 @@ inline gsl::span TimeFrame::getIndexTable(int rofId, int layer) if (rofId < 0 || rofId >= mNrof) { return {}; } - return {&mIndexTables[layer][rofId * (mIndexTableUtils.getNphiBins() * mIndexTableUtils.getNzBins() + 1)], - static_cast::size_type>(mIndexTableUtils.getNphiBins() * mIndexTableUtils.getNzBins() + 1)}; + const int tableSize = mIndexTableUtils.getNphiBins() * mIndexTableUtils.getNzBins() + 1; + return {&mIndexTables[layer][rofId * tableSize], static_cast::size_type>(tableSize)}; } template diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h index bf9cb79169566..f123a2a9a1d80 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingInterface.h @@ -61,7 +61,6 @@ class ITSTrackingInterface void initialise(); void run(framework::ProcessingContext& pc); void printSummary() const; - void end(); virtual void updateTimeDependentParams(framework::ProcessingContext& pc); virtual void finaliseCCDB(framework::ConcreteDataMatcher& matcher, void* obj); diff --git a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx index 2e9ce23719f90..a59c51949b9f9 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx @@ -583,7 +583,6 @@ void TimeFrame::printSliceInfo(const int startROF, const int sliceSize) template void TimeFrame::setMemoryPool(std::shared_ptr& pool) { - wipe(); mMemoryPool = pool; auto initVector = [&](bounded_vector& vec) { diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index ba722c410f95c..938356050262d 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -65,7 +65,6 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) (double)mTimeFrame->getArtefactsMemory() / GB, (double)mTrkParams[iteration].MaxMemory / GB); LOGP(error, "Exception: {}", err.what()); if (mTrkParams[iteration].DropTFUponFailure) { - mTimeFrame->wipe(); mMemoryPool->print(); ++mNumberOfDroppedTFs; error("...Dropping Timeframe..."); @@ -144,17 +143,17 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) error("Uncaught exception, all bets are off..."); } - if (mTrkParams[0].PrintMemory) { - mTimeFrame->printArtefactsMemory(); - mMemoryPool->print(); - } - if (mTimeFrame->hasMCinformation()) { computeTracksMClabels(); } rectifyClusterIndices(); ++mTimeFrameCounter; mTotalTime += total; + + if (mTrkParams[0].PrintMemory) { + mTimeFrame->printArtefactsMemory(); + mMemoryPool->print(); + } } void Tracker::computeRoadsMClabels() diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index 136ebc647cc38..b46e7a68875e6 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -107,9 +107,10 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF for (int iV = startVtx; iV < endVtx; ++iV) { const auto& pv = primaryVertices[iV]; - if (pv.isFlagSet(Vertex::Flags::UPCMode) && iteration != 3) { + if ((pv.isFlagSet(Vertex::Flags::UPCMode) && iteration != 3) || (iteration == 3 && !pv.isFlagSet(Vertex::Flags::UPCMode))) { continue; } + const float resolution = o2::gpu::CAMath::Sqrt(math_utils::Sq(mTimeFrame->getPositionResolution(iLayer)) + math_utils::Sq(mTrkParams[iteration].PVres) / float(pv.getNContributors())); const float tanLambda = (currentCluster.zCoordinate - pv.getZ()) * inverseR0; const float zAtRmin = tanLambda * (mTimeFrame->getMinR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate; diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx index 00a69a37cb51a..3b05a7655d68c 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingInterface.cxx @@ -310,6 +310,7 @@ void ITSTrackingInterface::run(framework::ProcessingContext& pc) LOGP(info, "ITSTracker pushed {} vertex purities", allVerticesPurities.size()); } } + mTimeFrame->wipe(); } void ITSTrackingInterface::updateTimeDependentParams(framework::ProcessingContext& pc) @@ -381,11 +382,6 @@ void ITSTrackingInterface::printSummary() const mTracker->printSummary(); } -void ITSTrackingInterface::end() -{ - mTimeFrame->wipe(); -} - void ITSTrackingInterface::setTraitsFromProvider(VertexerTraits* vertexerTraits, TrackerTraits7* trackerTraits, TimeFrame7* frame) diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index c825ec39d3499..be7750964b3e7 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -75,7 +75,6 @@ void TrackerDPL::endOfStream(EndOfStreamContext& ec) void TrackerDPL::end() { - mITSTrackingInterface.end(); mITSTrackingInterface.printSummary(); LOGF(info, "ITS CA-Tracker total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } From 723aeb36ed3efac043632e8b9c8195d455402513 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 24 Jul 2025 13:34:14 +0200 Subject: [PATCH 180/315] ITSMFT: FST opt. rerun clusterizer Signed-off-by: Felix Schlepper --- prodtests/full-system-test/dpl-workflow.sh | 23 ++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 55186dbff9c84..044c382e45070 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -108,9 +108,6 @@ EVE_OPT=" --jsons-folder $EDJSONS_DIR" [[ "0$DISABLE_ROOT_OUTPUT" == "00" ]] && DISABLE_ROOT_OUTPUT= -has_detectors_gpu TPC ITS && GPU_INPUT+=",its-clusters" -has_detectors_gpu TPC ITS && GPU_OUTPUT+=",its-tracks" - if [[ $CTFINPUT != 1 ]]; then GPU_OUTPUT+=",tpc-triggers" fi @@ -421,6 +418,17 @@ if [[ -n ${WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS} ]] || [[ -n ${WORKFLOW_D has_detector TOF && has_detector_from_global_reader TOF && add_W o2-tof-reco-workflow "$DISABLE_MC --input-type digits --output-type NONE $HBFINI_OPTIONS" fi +if [[ ${ITSMFT_RECO_RERUN_CLUSTERIZER:-0} == 1 && ${DISABLE_DIGIT_CLUSTER_INPUT:-} =~ "--digits-from-upstream" ]]; then + echo "Cannot set both ITSMFT_RECO_RERUN_CLUSTERIZER and DISABLE_DIGIT_CLUSTER_INPUT at the same time" + echo "DISABLE_DIGIT_CLUSTER_INPUT will be removed once used in O2DPG" + exit 1 +fi +if [[ ${ITSMFT_RECO_RERUN_CLUSTERIZER:-0} == 1 ]]; then + has_detector_reco MFT && ARGS_EXTRA_PROCESS_o2_ctf_reader_workflow+=' --mft-digits ' + ( has_detector_reco ITS || has_detector_gpu ITS ) && ARGS_EXTRA_PROCESS_o2_ctf_reader_workflow+=' --its-digits ' + DISABLE_DIGIT_CLUSTER_INPUT="--digits-from-upstream" +fi + if [[ -n $INPUT_DETECTOR_LIST ]]; then if [[ $CTFINPUT == 1 ]]; then GPU_INPUT=compressed-clusters-ctf @@ -490,7 +498,6 @@ if [[ -n $INPUT_DETECTOR_LIST ]]; then elif [[ $DIGITINPUT == 1 ]]; then [[ $NTIMEFRAMES != 1 ]] && { echo "Digit input works only with NTIMEFRAMES=1" 1>&2; exit 1; } DISABLE_DIGIT_ROOT_INPUT= - DISABLE_DIGIT_CLUSTER_INPUT= TOF_INPUT=digits GPU_INPUT=zsonthefly has_detector TPC && add_W o2-tpc-reco-workflow "--input-type digits --output-type zsraw,disable-writer $DISABLE_MC --pipeline $(get_N tpc-zsEncoder TPC RAW 1 TPCRAWDEC)" @@ -543,11 +550,15 @@ if [[ $CTFINPUT == 0 && $DIGITINPUT == 0 ]]; then has_detector EMC && ! has_detector_from_global_reader EMC && ! has_detector_flp_processing EMC && add_W o2-emcal-reco-workflow "--input-type raw --output-type cells ${RAW_EMC_SUBSPEC:-} $EMCRAW2C_CONFIG $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N EMCALRawToCellConverterSpec EMC REST 1 EMCREC)" fi +has_detector_gpu ITS && GPU_INPUT+=",its-clusters" +has_detector_gpu ITS && GPU_OUTPUT+=",its-tracks" + # --------------------------------------------------------------------------------------------------------------------- # Common reconstruction workflows +(has_detector_reco ITS && ! has_detector_gpu ITS) && ! has_detector_from_global_reader ITS && add_W o2-its-reco-workflow "--trackerCA $ITS_CONFIG $DISABLE_MC ${DISABLE_DIGIT_CLUSTER_INPUT:-} $DISABLE_ROOT_OUTPUT --pipeline $(get_N its-tracker ITS REST 1 ITSTRK),$(get_N its-clusterer ITS REST 1 ITSCL)" "$ITS_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR" +[[ ${DISABLE_DIGIT_CLUSTER_INPUT:-} =~ "--digits-from-upstream" ]] && has_detector_gpu ITS && ! has_detector_from_global_reader ITS && add_W o2-its-reco-workflow "--disable-tracking ${DISABLE_DIGIT_CLUSTER_INPUT:-} $DISABLE_MC $DISABLE_ROOT_OUTPUT --pipeline $(get_N its-clusterer ITS REST 1 ITSCL)" "$ITS_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR" (has_detector_reco TPC || has_detector_ctf TPC) && ! has_detector_from_global_reader TPC && add_W o2-gpu-reco-workflow "--gpu-reconstruction \"$GPU_CONFIG_SELF\" --input-type=$GPU_INPUT $DISABLE_MC --output-type $GPU_OUTPUT $TPC_CORR_OPT --pipeline gpu-reconstruction:${N_TPCTRK:-1},gpu-reconstruction-prepare:${N_TPCTRK:-1} $GPU_CONFIG" "GPU_global.deviceType=$GPUTYPE;GPU_proc.debugLevel=0;$GPU_CONFIG_KEY;$TRACKTUNETPCINNER;$TPC_CORR_KEY" (has_detector_reco TOF || has_detector_ctf TOF) && ! has_detector_from_global_reader TOF && add_W o2-tof-reco-workflow "$TOF_CONFIG --input-type $TOF_INPUT --output-type $TOF_OUTPUT $DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N tof-compressed-decoder TOF RAW 1),$(get_N TOFClusterer TOF REST 1)" -(has_detector_reco ITS && ! has_detector_gpu ITS) && ! has_detector_from_global_reader ITS && add_W o2-its-reco-workflow "--trackerCA $ITS_CONFIG $DISABLE_MC $DISABLE_DIGIT_CLUSTER_INPUT $DISABLE_ROOT_OUTPUT --pipeline $(get_N its-tracker ITS REST 1 ITSTRK),$(get_N its-clusterer ITS REST 1 ITSCL)" "$ITS_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR" has_detector_reco FT0 && ! has_detector_from_global_reader FT0 && add_W o2-ft0-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N ft0-reconstructor FT0 REST 1)" has_detector_reco TRD && ! has_detector_from_global_reader TRD && add_W o2-trd-tracklet-transformer "--disable-irframe-reader $DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $TRD_FILTER_CONFIG --pipeline $(get_N TRDTRACKLETTRANSFORMER TRD REST 1 TRDTRKTRANS)" has_detectors_reco ITS TPC && ! has_detector_from_global_reader_tracks ITS-TPC && has_detector_matching ITSTPC && add_W o2-tpcits-match-workflow "$DISABLE_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC $SEND_ITSTPC_DTGL $TPC_CORR_OPT --nthreads $ITSTPC_THREADS --pipeline $(get_N itstpc-track-matcher MATCH REST $ITSTPC_THREADS TPCITS)" "$ITSTPC_CONFIG_KEY;$INTERACTION_TAG_CONFIG_KEY;$ITSMFT_STROBES;$ITSEXTRAERR;$TPC_CORR_KEY" @@ -559,7 +570,7 @@ has_detectors TPC && [[ -z "$DISABLE_ROOT_OUTPUT" && "${SKIP_TPC_CLUSTERSTRACKS_ # Reconstruction workflows normally active only in async mode ($LIST_OF_ASYNC_RECO_STEPS), but can be forced via $WORKFLOW_EXTRA_PROCESSING_STEPS has_detector MID && ! has_detector_from_global_reader MID && has_processing_step MID_RECO && add_W o2-mid-reco-workflow "$DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N MIDClusterizer MID REST 1),$(get_N MIDTracker MID REST 1)" has_detector MCH && ! has_detector_from_global_reader MCH && has_processing_step MCH_RECO && add_W o2-mch-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC --pipeline $(get_N mch-track-finder MCH REST 1 MCHTRK),$(get_N mch-cluster-finder MCH REST 1 MCHCL),$(get_N mch-cluster-transformer MCH REST 1)" "$MCH_CONFIG_KEY" -has_detector MFT && ! has_detector_from_global_reader MFT && has_processing_step MFT_RECO && add_W o2-mft-reco-workflow "$DISABLE_DIGIT_CLUSTER_INPUT $DISABLE_MC $DISABLE_ROOT_OUTPUT $MFT_CONFIG --pipeline $(get_N mft-tracker MFT REST 1 MFTTRK)" "$MFT_CONFIG_KEY;$ITSMFT_STROBES" +has_detector MFT && ! has_detector_from_global_reader MFT && has_processing_step MFT_RECO && add_W o2-mft-reco-workflow "$DISABLE_MC ${DISABLE_DIGIT_CLUSTER_INPUT:-} $DISABLE_ROOT_OUTPUT $MFT_CONFIG --pipeline $(get_N mft-tracker MFT REST 1 MFTTRK)" "$MFT_CONFIG_KEY;$ITSMFT_STROBES" has_detector FDD && ! has_detector_from_global_reader FDD && has_processing_step FDD_RECO && add_W o2-fdd-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" has_detector FV0 && ! has_detector_from_global_reader FV0 && has_processing_step FV0_RECO && add_W o2-fv0-reco-workflow "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" has_detector ZDC && ! has_detector_from_global_reader ZDC && has_processing_step ZDC_RECO && add_W o2-zdc-digits-reco "$DISABLE_DIGIT_ROOT_INPUT $DISABLE_ROOT_OUTPUT $DISABLE_MC" From 84dd75dff552f74be128232ffefda1cb574e85a3 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sat, 26 Jul 2025 10:41:31 +0200 Subject: [PATCH 181/315] Fix coding rule violation --- Framework/Core/src/StepTHn.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/StepTHn.cxx b/Framework/Core/src/StepTHn.cxx index 4b2e81f02e1a2..bb0109db2c97f 100644 --- a/Framework/Core/src/StepTHn.cxx +++ b/Framework/Core/src/StepTHn.cxx @@ -327,8 +327,9 @@ void StepTHn::createTarget(Int_t step, Bool_t sparse) } THnBase* target = mTarget[step]; - if (mSumw2[step]) + if (mSumw2[step]) { target->Sumw2(); + } Int_t* binIdx = new Int_t[mNVars]; Int_t* nBins = new Int_t[mNVars]; From 6f47846208dc46772280cc26449a20703b9f720c Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Mon, 28 Jul 2025 09:56:00 +0200 Subject: [PATCH 182/315] Add Lambda1405 to TDatabasePdg and O2MCApplication (#14506) * Add Lambda1405 to TDatabasePdg and O2MCApplication * Please consider the following formatting changes --------- Co-authored-by: Francesco Mazzaschi Co-authored-by: ALICE Action Bot --- .../SimulationDataFormat/O2DatabasePDG.h | 9 ++++ Steer/src/O2MCApplication.cxx | 41 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/DataFormats/simulation/include/SimulationDataFormat/O2DatabasePDG.h b/DataFormats/simulation/include/SimulationDataFormat/O2DatabasePDG.h index ec8e6db889167..23dc30119aa7a 100644 --- a/DataFormats/simulation/include/SimulationDataFormat/O2DatabasePDG.h +++ b/DataFormats/simulation/include/SimulationDataFormat/O2DatabasePDG.h @@ -470,6 +470,15 @@ inline void O2DatabasePDG::addALICEParticles(TDatabasePDG* db) 0.185, 0, "Resonance", ionCode); } + // Lambda(1405)0 + ionCode = 102132; + if (!db->GetParticle(ionCode)) { + db->AddParticle("Lambda_1405_0", "Lambda_1405_0", 1.405, kFALSE, 0.05, 0, "Resonance", ionCode); + } + if (!db->GetParticle(-ionCode)) { + db->AddParticle("AntiLambda_1405_0", "AntiLambda_1405_0", 1.405, kFALSE, 0.05, 0, "Resonance", -ionCode); + } + // Lambda(1520)0 ionCode = 102134; if (!db->GetParticle(ionCode)) { diff --git a/Steer/src/O2MCApplication.cxx b/Steer/src/O2MCApplication.cxx index e44758241b8d2..77b49ec9e2906 100644 --- a/Steer/src/O2MCApplication.cxx +++ b/Steer/src/O2MCApplication.cxx @@ -383,6 +383,10 @@ void addSpecialParticles() // f1(1420) (PDG: width = 54 MeV) Spin/Parity might not be correct TVirtualMC::GetMC()->DefineParticle(20333, "f1_1420", kPTNeutron, 1.42640, 0.0, 1e-24, "Hadron", 0.05490, 3, 1, 0, 0, 0, 0, 0, 1, kTRUE); + // lambda1405 (PDG: width = 50 MeV) + TVirtualMC::GetMC()->DefineParticle(102132, "Lambda1405", kPTNeutron, 1.405, 0.0, 1.316e-23, "Hadron", 0.050, 0, 1, 0, 0, 0, 0, 0, 2, kTRUE); + TVirtualMC::GetMC()->DefineParticle(-102132, "AntiLambda1405", kPTNeutron, 1.405, 0.0, 1.316e-23, "Hadron", 0.050, 0, 1, 0, 0, 0, 0, 0, 2, kTRUE); + // Glueball hunting family // Their life times are not known, so we set them to 1e-24 // f0(1370) (PDG: width = 200-500 MeV) Spin/Parity might not be correct @@ -1380,6 +1384,43 @@ void addSpecialParticles() TVirtualMC::GetMC()->SetDecayMode(20223, bratio2, mode); // f1(1285) TVirtualMC::GetMC()->SetDecayMode(20333, bratio2, mode); // f1(1420) + // Define the decay modes for the Lambda(1405) + for (Int_t kz = 0; kz < 6; kz++) { + bratio[kz] = 0.; + mode[kz][0] = 0; + mode[kz][1] = 0; + mode[kz][2] = 0; + } + // 33.3 % sigma-pi+, sigma+pi-, sigma0pi0 + bratio[0] = 33.3; + mode[0][0] = 3112; // Sigma- + mode[0][1] = 211; // negative pion + bratio[1] = 33.3; + mode[1][0] = 3222; // Sigma+ + mode[1][1] = -211; // positive pion + bratio[2] = 33.3; + mode[2][0] = 3212; // Sigma0 + mode[2][1] = 111; // neutral pion + TVirtualMC::GetMC()->SetDecayMode(102132, bratio, mode); // Lambda(1405) + // Define the decay modes for the Anti-Lambda(1405) + for (Int_t kz = 0; kz < 6; kz++) { + abratio[kz] = 0.; + amode[kz][0] = 0; + amode[kz][1] = 0; + amode[kz][2] = 0; + } + // 33.3 % sigma-pi-, sigma-pi+, sigma0pi0 + abratio[0] = 33.3; + amode[0][0] = -3112; // AntiSigma- + amode[0][1] = -211; // positive pion + abratio[1] = 33.3; + amode[1][0] = -3222; // AntiSigma+ + amode[1][1] = 211; // negative pion + abratio[2] = 33.3; + amode[2][0] = -3212; // Sigma0 + amode[2][1] = 111; // negative pion + TVirtualMC::GetMC()->SetDecayMode(-102132, abratio, amode); // Anti-Lambda(1405) + // Lambda1520/Lambda1520bar TVirtualMC::GetMC()->DefineParticle(102134, "Lambda1520", kPTNeutron, 1.5195, 0.0, 4.22e-23, "Hadron", 0.0156, 3, -1, 0, 0, 0, 0, 0, 1, kTRUE); From 69f673745dc009e30b4143b774d81c45b791a2af Mon Sep 17 00:00:00 2001 From: Christian Sonnabend Date: Mon, 28 Jul 2025 16:01:55 +0200 Subject: [PATCH 183/315] NN clusterizer: Bug-fixes and adding deterministic mode (#14530) * Adding first version of kernel timers * Removing GPU_CONFIG_KEY from dpl-workflow.sh to set my own values * Bug fixes * undoing changes in dpl-workflow.sh * Furhter fixes and beautifications * Please consider the following formatting changes * Removing unused timers * Moving Stop() of classification timer * Adding force method to fill input like it is done on GPU * Removing unnecessary static asserts * Adding deterministic mode (unfortunately that did not make it deterministic on GPU -> general problem with ONNX) * Please consider the following formatting changes * Adjusting for comment * Adding deterministic mode * Please consider the following formatting changes --------- Co-authored-by: ALICE Action Bot --- Common/ML/include/ML/OrtInterface.h | 2 +- Common/ML/src/OrtInterface.cxx | 5 ++ GPU/GPUTracking/Definitions/GPUSettingsList.h | 3 ++ .../Global/GPUChainTrackingClusterizer.cxx | 53 ++++++++++++++----- .../TPCClusterFinder/GPUTPCNNClusterizer.h | 1 + .../GPUTPCNNClusterizerHost.cxx | 4 +- .../GPUTPCNNClusterizerHost.h | 4 +- .../GPUTPCNNClusterizerKernels.cxx | 26 ++++----- .../GPUTPCNNClusterizerKernels.h | 6 --- 9 files changed, 65 insertions(+), 39 deletions(-) diff --git a/Common/ML/include/ML/OrtInterface.h b/Common/ML/include/ML/OrtInterface.h index 0c498e33d2e2c..04a5e0ba5c9fc 100644 --- a/Common/ML/include/ML/OrtInterface.h +++ b/Common/ML/include/ML/OrtInterface.h @@ -116,7 +116,7 @@ class OrtModel int32_t mInputsTotal = 0, mOutputsTotal = 0; // Total number of inputs and outputs // Environment settings - bool mInitialized = false; + bool mInitialized = false, mDeterministicMode = false; std::string mModelPath, mEnvName = "", mDeviceType = "CPU", mThreadAffinity = ""; // device options should be cpu, rocm, migraphx, cuda int32_t mIntraOpNumThreads = 1, mInterOpNumThreads = 1, mDeviceId = -1, mEnableProfiling = 0, mLoggingLevel = 0, mAllocateDeviceMemory = 0, mEnableOptimizations = 0; diff --git a/Common/ML/src/OrtInterface.cxx b/Common/ML/src/OrtInterface.cxx index 1cd9913efb6aa..58d80eb9c0bf0 100644 --- a/Common/ML/src/OrtInterface.cxx +++ b/Common/ML/src/OrtInterface.cxx @@ -68,6 +68,7 @@ void OrtModel::initOptions(std::unordered_map optionsM mEnableProfiling = (optionsMap.contains("enable-profiling") ? std::stoi(optionsMap["enable-profiling"]) : 0); mEnableOptimizations = (optionsMap.contains("enable-optimizations") ? std::stoi(optionsMap["enable-optimizations"]) : 0); mEnvName = (optionsMap.contains("onnx-environment-name") ? optionsMap["onnx-environment-name"] : "onnx_model_inference"); + mDeterministicMode = (optionsMap.contains("deterministic-compute") ? std::stoi(optionsMap["deterministic-compute"]) : 0); if (mDeviceType == "CPU") { (mPImplOrt->sessionOptions).SetIntraOpNumThreads(mIntraOpNumThreads); @@ -99,6 +100,10 @@ void OrtModel::initOptions(std::unordered_map optionsM (mPImplOrt->sessionOptions).DisableProfiling(); } + if (mDeterministicMode > 0) { + (mPImplOrt->sessionOptions).AddConfigEntry("session_options.use_deterministic_compute", "1"); + } + (mPImplOrt->sessionOptions).SetGraphOptimizationLevel(GraphOptimizationLevel(mEnableOptimizations)); (mPImplOrt->sessionOptions).SetLogSeverityLevel(OrtLoggingLevel(mLoggingLevel)); diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index 51a0add7dbeea..65697b7f7c08b 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -256,6 +256,7 @@ AddOption(nnInferenceOutputDType, std::string, "FP32", "", 0, "(std::string) Spe AddOption(nnInferenceIntraOpNumThreads, int, 1, "", 0, "Number of threads used to evaluate one neural network (ONNX: SetIntraOpNumThreads). 0 = auto-detect, can lead to problems on SLURM systems.") AddOption(nnInferenceInterOpNumThreads, int, 1, "", 0, "Number of threads used to evaluate one neural network (ONNX: SetInterOpNumThreads). 0 = auto-detect, can lead to problems on SLURM systems.") AddOption(nnInferenceEnableOrtOptimization, unsigned int, 99, "", 0, "Enables graph optimizations in ONNX Runtime. Can be [0, 1, 2, 99] -> see https://github.com/microsoft/onnxruntime/blob/3f71d637a83dc3540753a8bb06740f67e926dc13/include/onnxruntime/core/session/onnxruntime_c_api.h#L347") +AddOption(nnInferenceUseDeterministicCompute, int, 0, "", 0, "Enables deterministic compute in ONNX Runtime were possible. Can be [0, 1] -> see https://github.com/microsoft/onnxruntime/blob/3b97d79b3c12dbf93aa0d563f345714596dc8ab6/onnxruntime/core/framework/session_options.h#L208") AddOption(nnInferenceOrtProfiling, int, 0, "", 0, "Enables profiling of model execution in ONNX Runtime") AddOption(nnInferenceOrtProfilingPath, std::string, ".", "", 0, "If nnInferenceOrtProfiling is set, the path to store the profiling data") AddOption(nnInferenceVerbosity, int, 1, "", 0, "0: No messages; 1: Warnings; 2: Warnings + major debugs; >3: All debugs") @@ -275,6 +276,8 @@ AddOption(nnClassThreshold, float, 0.5, "", 0, "The cutoff at which clusters wil AddOption(nnRegressionPath, std::string, "network_reg.onnx", "", 0, "The regression network path") AddOption(nnSigmoidTrafoClassThreshold, int, 1, "", 0, "If true (default), then the classification threshold is transformed by an inverse sigmoid function. This depends on how the network was trained (with a sigmoid as acitvation function in the last layer or not).") AddOption(nnEvalMode, std::string, "c1:r1", "", 0, "Concatention of modes, e.g. c1:r1 (classification class 1, regression class 1)") +AddOption(nnClusterizerUseClassification, int, 1, "", 0, "If 1, the classification output of the network is used to select clusters, else only the regression output is used and no clusters are rejected by classification") +AddOption(nnClusterizerForceGpuInputFill, int, 0, "", 0, "Forces to use the fillInputNNGPU function") // CCDB AddOption(nnLoadFromCCDB, int, 0, "", 0, "If 1 networks are fetched from ccdb, else locally") AddOption(nnLocalFolder, std::string, ".", "", 0, "Local folder in which the networks will be fetched") diff --git a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx index 13455efe6cb47..07b332db1fc12 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx @@ -641,13 +641,30 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) const GPUSettingsProcessingNNclusterizer& nn_settings = GetProcessingSettings().nn; GPUTPCNNClusterizerHost nnApplications[GetProcessingSettings().nTPCClustererLanes]; + // Maximum of 4 lanes supported + HighResTimer* nnTimers[12]; + if (GetProcessingSettings().nn.applyNNclusterizer && GetProcessingSettings().debugLevel >= 1) { + nnTimers[0] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 0); + nnTimers[1] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 1); + nnTimers[2] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 2); + nnTimers[3] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 3); + nnTimers[4] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 4); + nnTimers[5] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 5); + nnTimers[6] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 6); + nnTimers[7] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 7); + nnTimers[8] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 8); + nnTimers[9] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 9); + nnTimers[10] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 10); + nnTimers[11] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 11); + } + if (GetProcessingSettings().nn.applyNNclusterizer) { int32_t deviceId = -1; int32_t numLanes = GetProcessingSettings().nTPCClustererLanes; int32_t maxThreads = mRec->getNKernelHostThreads(true); // bool recreateMemoryAllocator = false; mRec->runParallelOuterLoop(doGPU, numLanes, [&](uint32_t lane) { - nnApplications[lane].init(nn_settings); + nnApplications[lane].init(nn_settings, GetProcessingSettings().deterministicGPUReconstruction); if (nnApplications[lane].mModelsUsed[0]) { SetONNXGPUStream(*(nnApplications[lane].mModelClass).getSessionOptions(), lane, &deviceId); (nnApplications[lane].mModelClass).setDeviceId(deviceId); @@ -993,9 +1010,9 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) size_t iSize = CAMath::Min((uint)clustererNNShadow.mNnClusterizerBatchedMode, (uint)(clusterer.mPmemory->counters.nClusters - batchStart)); // Filling the data - if (mRec->IsGPU()) { + if (mRec->IsGPU() || GetProcessingSettings().nn.nnClusterizerForceGpuInputFill) { // Fills element by element of each input matrix -> better parallelizability, but worse on CPU due to unnecessary computations - runKernel({GetGrid(iSize * clustererNNShadow.mNnClusterizerElementSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, batchStart); + runKernel({GetGrid(iSize * clustererNNShadow.mNnClusterizerRowTimeSizeFull, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, batchStart); } else { // Fills the whole input matrix at once -> better performance on CPU, but worse parallelizability runKernel({GetGrid(iSize, lane), krnlRunRangeNone}, iSector, clustererNNShadow.mNnInferenceInputDType, propagateMCLabels, batchStart); @@ -1006,20 +1023,25 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } // NN evaluations - if (clustererNNShadow.mNnInferenceInputDType == 0) { - if (clustererNNShadow.mNnInferenceOutputDType == 0) { - (nnApplication.mModelClass).inference(clustererNNShadow.mInputData_16, iSize, clustererNNShadow.mModelProbabilities_16); - } else if (clustererNNShadow.mNnInferenceOutputDType == 1) { - (nnApplication.mModelClass).inference(clustererNNShadow.mInputData_16, iSize, clustererNNShadow.mModelProbabilities_32); - } - } else if (clustererNNShadow.mNnInferenceInputDType == 1) { - if (clustererNNShadow.mNnInferenceOutputDType == 0) { - (nnApplication.mModelClass).inference(clustererNNShadow.mInputData_32, iSize, clustererNNShadow.mModelProbabilities_16); - } else if (clustererNNShadow.mNnInferenceOutputDType == 1) { - (nnApplication.mModelClass).inference(clustererNNShadow.mInputData_32, iSize, clustererNNShadow.mModelProbabilities_32); + if(clustererNNShadow.mNnClusterizerUseClassification) { + if(GetProcessingSettings().debugLevel >= 1 && doGPU) { nnTimers[3*lane]->Start(); } + if (clustererNNShadow.mNnInferenceInputDType == 0) { + if (clustererNNShadow.mNnInferenceOutputDType == 0) { + (nnApplication.mModelClass).inference(clustererNNShadow.mInputData_16, iSize, clustererNNShadow.mModelProbabilities_16); + } else if (clustererNNShadow.mNnInferenceOutputDType == 1) { + (nnApplication.mModelClass).inference(clustererNNShadow.mInputData_16, iSize, clustererNNShadow.mModelProbabilities_32); + } + } else if (clustererNNShadow.mNnInferenceInputDType == 1) { + if (clustererNNShadow.mNnInferenceOutputDType == 0) { + (nnApplication.mModelClass).inference(clustererNNShadow.mInputData_32, iSize, clustererNNShadow.mModelProbabilities_16); + } else if (clustererNNShadow.mNnInferenceOutputDType == 1) { + (nnApplication.mModelClass).inference(clustererNNShadow.mInputData_32, iSize, clustererNNShadow.mModelProbabilities_32); + } } + if(GetProcessingSettings().debugLevel >= 1 && doGPU) { nnTimers[3*lane]->Stop(); } } if (!clustererNNShadow.mNnClusterizerUseCfRegression) { + if(GetProcessingSettings().debugLevel >= 1 && doGPU) { nnTimers[3*lane + 1]->Start(); } if (clustererNNShadow.mNnInferenceInputDType == 0) { if (clustererNNShadow.mNnInferenceOutputDType == 0) { (nnApplication.mModelReg1).inference(clustererNNShadow.mInputData_16, iSize, clustererNNShadow.mOutputDataReg1_16); @@ -1033,7 +1055,9 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) (nnApplication.mModelReg1).inference(clustererNNShadow.mInputData_32, iSize, clustererNNShadow.mOutputDataReg1_32); } } + if(GetProcessingSettings().debugLevel >= 1 && doGPU) { nnTimers[3*lane + 1]->Stop(); } if (nnApplication.mModelClass.getNumOutputNodes()[0][1] > 1 && nnApplication.mModelReg2.isInitialized()) { + if(GetProcessingSettings().debugLevel >= 1 && doGPU) { nnTimers[3*lane + 2]->Start(); } if (clustererNNShadow.mNnInferenceInputDType == 0) { if (clustererNNShadow.mNnInferenceOutputDType == 0) { (nnApplication.mModelReg2).inference(clustererNNShadow.mInputData_16, iSize, clustererNNShadow.mOutputDataReg2_16); @@ -1047,6 +1071,7 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) (nnApplication.mModelReg2).inference(clustererNNShadow.mInputData_32, iSize, clustererNNShadow.mOutputDataReg2_32); } } + if(GetProcessingSettings().debugLevel >= 1 && doGPU) { nnTimers[3*lane + 2]->Stop(); } } } diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h index 7c22d8123fdec..69972c8a0651c 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizer.h @@ -43,6 +43,7 @@ class GPUTPCNNClusterizer : public GPUProcessor int32_t mNnClusterizerChargeArraySize = -1; int32_t mNnClusterizerElementSize = -1; int8_t mNnClusterizerAddIndexData = 1; + int8_t mNnClusterizerUseClassification = 1; float mNnClassThreshold = 0.01; int8_t mNnSigmoidTrafoClassThreshold = 1; int8_t mNnClusterizerSetDeconvolutionFlags = 1; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx index fd56d49de7921..ad635c15b9256 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.cxx @@ -28,7 +28,7 @@ using namespace o2::gpu; -void GPUTPCNNClusterizerHost::init(const GPUSettingsProcessingNNclusterizer& settings) +void GPUTPCNNClusterizerHost::init(const GPUSettingsProcessingNNclusterizer& settings, bool useDeterministicMode) { std::string class_model_path = settings.nnClassificationPath, reg_model_path = settings.nnRegressionPath; std::vector reg_model_paths_local; @@ -54,6 +54,7 @@ void GPUTPCNNClusterizerHost::init(const GPUSettingsProcessingNNclusterizer& set {"intra-op-num-threads", std::to_string(settings.nnInferenceIntraOpNumThreads)}, {"inter-op-num-threads", std::to_string(settings.nnInferenceInterOpNumThreads)}, {"enable-optimizations", std::to_string(settings.nnInferenceEnableOrtOptimization)}, + {"deterministic-compute", std::to_string(useDeterministicMode ? 1 : settings.nnInferenceUseDeterministicCompute)}, // TODO: This unfortunately doesn't guarantee determinism (25.07.2025) {"enable-profiling", std::to_string(settings.nnInferenceOrtProfiling)}, {"profiling-output-path", settings.nnInferenceOrtProfilingPath}, {"logging-level", std::to_string(settings.nnInferenceVerbosity)}, @@ -106,6 +107,7 @@ void GPUTPCNNClusterizerHost::initClusterizer(const GPUSettingsProcessingNNclust clustererNN.mNnClusterizerBatchedMode = settings.nnClusterizerBatchedMode; clustererNN.mNnClusterizerBoundaryFillValue = settings.nnClusterizerBoundaryFillValue; clustererNN.mNnSigmoidTrafoClassThreshold = settings.nnSigmoidTrafoClassThreshold; + clustererNN.mNnClusterizerUseClassification = settings.nnClusterizerUseClassification; clustererNN.mNnClusterizerSetDeconvolutionFlags = (bool)settings.nnClusterizerSetDeconvolutionFlags; if (clustererNN.mNnSigmoidTrafoClassThreshold) { clustererNN.mNnClassThreshold = (float)std::log(settings.nnClassThreshold / (1.f - settings.nnClassThreshold)); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h index ed3c80320b632..414c4539a33c1 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerHost.h @@ -45,9 +45,9 @@ class GPUTPCNNClusterizerHost { public: GPUTPCNNClusterizerHost() = default; - GPUTPCNNClusterizerHost(const GPUSettingsProcessingNNclusterizer& settings) { init(settings); } + GPUTPCNNClusterizerHost(const GPUSettingsProcessingNNclusterizer& settings, bool useDeterministicMode = false) { init(settings, useDeterministicMode); } - void init(const GPUSettingsProcessingNNclusterizer&); + void init(const GPUSettingsProcessingNNclusterizer&, bool = false); void initClusterizer(const GPUSettingsProcessingNNclusterizer&, GPUTPCNNClusterizer&); void createBoundary(GPUTPCNNClusterizer&); void createIndexLookup(GPUTPCNNClusterizer&); diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx index 4cd0c094398df..dd33a72f79389 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.cxx @@ -117,18 +117,14 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread(pad) / GPUTPCGeometry::NPads(row); - if (dtype == 0) { - clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)sector_norm; - clustererNN.mInputData_16[write_idx + 1] = (OrtDataType::Float16_t)row_norm; - clustererNN.mInputData_16[write_idx + 2] = (OrtDataType::Float16_t)pad_norm; + clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)(static_cast(sector) / o2::tpc::constants::MAXSECTOR); + clustererNN.mInputData_16[write_idx + 1] = (OrtDataType::Float16_t)(static_cast(row) / o2::tpc::constants::MAXGLOBALPADROW); + clustererNN.mInputData_16[write_idx + 2] = (OrtDataType::Float16_t)(static_cast(pad) / GPUTPCGeometry::NPads(row)); } else { - clustererNN.mInputData_32[write_idx] = sector_norm; - clustererNN.mInputData_32[write_idx + 1] = row_norm; - clustererNN.mInputData_32[write_idx + 2] = pad_norm; + clustererNN.mInputData_32[write_idx] = static_cast(sector) / o2::tpc::constants::MAXSECTOR; + clustererNN.mInputData_32[write_idx + 1] = static_cast(row) / o2::tpc::constants::MAXGLOBALPADROW; + clustererNN.mInputData_32[write_idx + 2] = static_cast(pad) / GPUTPCGeometry::NPads(row); } } @@ -178,8 +174,8 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread(sector) / o2::tpc::constants::MAXSECTOR, + static_cast(row) / o2::tpc::constants::MAXGLOBALPADROW, static_cast(pad) / GPUTPCGeometry::NPads(row)}; if (dtype == 0) { @@ -335,11 +331,11 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread= 1)) { + if (clustererNN.mOutputDataClass[full_glo_idx] == 1 || (clustererNN.mNnClusterizerUseClassification <= 0)) { ClusterAccumulator pc; @@ -451,7 +447,7 @@ GPUdii() void GPUTPCNNClusterizerKernels::Thread 0) { + if ((clustererNN.mOutputDataClass[full_glo_idx] > 0) || (clustererNN.mNnClusterizerUseClassification <= 0)) { ClusterAccumulator pc; diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h index 5659c61894c85..7469754594124 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCNNClusterizerKernels.h @@ -38,12 +38,6 @@ class GPUTPCNNClusterizerKernels : public GPUKernelTemplate { public: // Must all have same number of threads, since they use a common SCRATCH_PAD_WORK_GROUP_SIZE below - static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_fillInputNNCPU) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); - static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_fillInputNNGPU) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); - static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_determineClass1Labels) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); - static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_determineClass2Labels) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); - static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_publishClass1Regression) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); - static_assert(GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_publishClass2Regression) == GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer)); static constexpr size_t SCRATCH_PAD_WORK_GROUP_SIZE = GPUCA_GET_THREAD_COUNT(GPUCA_LB_GPUTPCNNClusterizerKernels_runCfClusterizer); struct GPUSharedMemory { // Regular cluster finder From 99071164afd16c430b42aba76a2f5a4d8f149455 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Tue, 29 Jul 2025 11:35:02 +0200 Subject: [PATCH 184/315] Make max Xiu for pre-propagation settable (#14544) * Change name of prepropagation config variable * Makes max xiu to be propagated settable from command line --- .../AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h | 2 +- Detectors/AOD/src/AODProducerWorkflowSpec.cxx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h index 1e3a4cf970d3b..62b99e98f990d 100644 --- a/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h +++ b/Detectors/AOD/include/AODProducerWorkflow/AODProducerWorkflowSpec.h @@ -246,7 +246,7 @@ class AODProducerWorkflowDPL : public Task std::mt19937 mGenerator{}; ///< random generator for trackQA sampling o2::base::Propagator::MatCorrType mMatCorr{o2::base::Propagator::MatCorrType::USEMatCorrLUT}; o2::dataformats::MeanVertexObject mVtx; - float mMinPropR{o2::constants::geom::XTPCInnerRef + 0.1f}; + float mMaxPropXiu{5.0f}; // max X_IU for which track is to be propagated if mPropTracks is true. (other option: o2::constants::geom::XTPCInnerRef + 0.1f) std::unordered_set mGIDUsedBySVtx; std::unordered_set mGIDUsedByStr; diff --git a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx index 7d9b6c7902360..8247eb3d870c0 100644 --- a/Detectors/AOD/src/AODProducerWorkflowSpec.cxx +++ b/Detectors/AOD/src/AODProducerWorkflowSpec.cxx @@ -540,7 +540,7 @@ void AODProducerWorkflowDPL::fillTrackTablesPerCollision(int collisionID, } const auto& trOrig = data.getTrackParam(trackIndex); bool isProp = false; - if (mPropTracks && trOrig.getX() < mMinPropR && + if (mPropTracks && trOrig.getX() < mMaxPropXiu && mGIDUsedBySVtx.find(trackIndex) == mGIDUsedBySVtx.end() && mGIDUsedByStr.find(trackIndex) == mGIDUsedByStr.end()) { // Do not propagate track assoc. to V0s and str. tracking auto trackPar(trOrig); @@ -1688,6 +1688,7 @@ void AODProducerWorkflowDPL::init(InitContext& ic) mEMCselectLeading = ic.options().get("emc-select-leading"); mThinTracks = ic.options().get("thin-tracks"); mPropTracks = ic.options().get("propagate-tracks"); + mMaxPropXiu = ic.options().get("propagate-tracks-max-xiu"); mPropMuons = ic.options().get("propagate-muons"); if (auto s = ic.options().get("with-streamers"); !s.empty()) { mStreamerFlags.set(s); @@ -3299,6 +3300,7 @@ DataProcessorSpec getAODProducerWorkflowSpec(GID::mask_t src, bool enableSV, boo ConfigParamSpec{"ctpreadout-create", VariantType::Int, 0, {"Create CTP digits from detector readout and CTP inputs. !=1 -- off, 1 -- on"}}, ConfigParamSpec{"emc-select-leading", VariantType::Bool, false, {"Flag to select if only the leading contributing particle for an EMCal cell should be stored"}}, ConfigParamSpec{"propagate-tracks", VariantType::Bool, false, {"Propagate tracks (not used for secondary vertices) to IP"}}, + ConfigParamSpec{"propagate-tracks-max-xiu", VariantType::Float, 5.0f, {"Propagate tracks to IP if X_IU smaller than this value (and if propagate tracks enabled)"}}, ConfigParamSpec{"hepmc-update", VariantType::String, "always", {"When to update HepMC Aux tables: always - force update, never - never update, all - if all keys are present, any - when any key is present (not valid yet)"}}, ConfigParamSpec{"propagate-muons", VariantType::Bool, false, {"Propagate muons to IP"}}, ConfigParamSpec{"thin-tracks", VariantType::Bool, false, {"Produce thinned track tables"}}, From 0975a957c93bf14147c03fe622f3e548cfeb8744 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 29 Jul 2025 13:06:27 +0200 Subject: [PATCH 185/315] DataFormats: Add V0Type (#14547) * DataFormats: Add V0Type * Update DecayNBodyIndex.h --- .../ReconstructionDataFormats/DecayNBodyIndex.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/DecayNBodyIndex.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/DecayNBodyIndex.h index 31a4b8ebc44b3..5a5a8a9e64cca 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/DecayNBodyIndex.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/DecayNBodyIndex.h @@ -55,14 +55,19 @@ class DecayNBodyIndex class V0Index : public DecayNBodyIndex<2> { public: + enum V0Type : uint8_t { + kStandaloneV0 = 0, + kPhotonOnly, + kCollinear, + }; using DecayNBodyIndex<2>::DecayNBodyIndex; V0Index(int v, GIndex p, GIndex n) : DecayNBodyIndex<2>(v, {p, n}) {} - bool isStandaloneV0() const { return testBit(0); } - bool isPhotonOnly() const { return testBit(1); } - bool isCollinear() const { return testBit(2); } - void setStandaloneV0() { setBit(0); } - void setPhotonOnly() { setBit(1); } - void setCollinear() { setBit(2); } + bool isStandaloneV0() const { return testBit(kStandaloneV0); } + bool isPhotonOnly() const { return testBit(kPhotonOnly); } + bool isCollinear() const { return testBit(kCollinear); } + void setStandaloneV0() { setBit(kStandaloneV0); } + void setPhotonOnly() { setBit(kPhotonOnly); } + void setCollinear() { setBit(kCollinear); } ClassDefNV(V0Index, 1); }; From 30e53d06741031c33016419c9a5dd66bfc238d6f Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 18 Jul 2025 17:30:33 +0200 Subject: [PATCH 186/315] Account for TPC clusters non-monotonous sorting --- .../GlobalTrackingStudy/TrackMCStudyTypes.h | 18 +++++- .../study/src/TrackMCStudy.cxx | 30 ++++++--- .../study/src/TrackMCStudyTypes.cxx | 62 +++++++++++++++++++ .../study/src/TrackingStudy.cxx | 18 +++--- 4 files changed, 111 insertions(+), 17 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyTypes.h b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyTypes.h index 47fed477f98bd..66ae23d91eaaa 100644 --- a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyTypes.h +++ b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackMCStudyTypes.h @@ -69,6 +69,10 @@ struct MCTrackInfo { void setBit(int bit) { flags |= BitMask & (0x1 << bit); } void resetBit(int bit) { flags &= ~(BitMask & (0x1 << bit)); } + o2::track::TrackPar getTrackParTPC(float b, float x = 90) const; + float getTrackParTPCPar(int i, float b, float x = 90) const; + float getTrackParTPCPhiSec(float b, float x = 90) const; + ClassDefNV(MCTrackInfo, 7); }; @@ -80,6 +84,7 @@ struct RecTrack { FakeTOF = 0x1 << 3, FakeITSTPC = 0x1 << 4, FakeITSTPCTRD = 0x1 << 5, + HASACSides = 0x1 << 6, FakeGLO = 0x1 << 7 }; o2::track::TrackParCov track{}; @@ -87,12 +92,15 @@ struct RecTrack { o2::dataformats::TimeStampWithError ts{}; o2::MCEventLabel pvLabel{}; short pvID = -1; + uint8_t nClTPCShared = 0; uint8_t flags = 0; uint8_t nClITS = 0; uint8_t nClTPC = 0; uint8_t pattITS = 0; int8_t lowestPadRow = -1; int8_t padFromEdge = -1; + uint8_t rowMaxTPC = 0; + uint8_t rowCountTPC = 0; bool isFakeGLO() const { return flags & FakeGLO; } bool isFakeITS() const { return flags & FakeITS; } @@ -100,8 +108,9 @@ struct RecTrack { bool isFakeTRD() const { return flags & FakeTRD; } bool isFakeTOF() const { return flags & FakeTOF; } bool isFakeITSTPC() const { return flags & FakeITSTPC; } + bool hasACSides() const { return flags & HASACSides; } - ClassDefNV(RecTrack, 2); + ClassDefNV(RecTrack, 3); }; struct TrackPairInfo { @@ -151,6 +160,13 @@ struct TrackFamily { // set of tracks related to the same MC label const RecTrack& getTrackWithTPC() const { return entTPC < 0 ? dummyRecTrack : recTracks[entTPC]; } const RecTrack& getTrackWithITSTPC() const { return entITSTPC < 0 ? dummyRecTrack : recTracks[entITSTPC]; } const RecTrack& getTrackWithITSFound() const { return entITSFound < 0 ? dummyRecTrack : recTracks[entITSFound]; } + const RecTrack& getLongestTPCTrack() const + { + int n = getLongestTPCTrackEntry(); + return n < 0 ? dummyRecTrack : recTracks[n]; + } + int getLongestTPCTrackEntry() const; + int getNTPCClones() const; static RecTrack dummyRecTrack; // ClassDefNV(TrackFamily, 1); diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx index fa8cadf3a115c..9f4b79ab47b72 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudy.cxx @@ -280,20 +280,33 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData) return patt; }; - auto getLowestPadrow = [&recoData](const o2::tpc::TrackTPC& trc, RecTrack& tref) { + auto fillTPCClusterInfo = [&recoData](const o2::tpc::TrackTPC& trc, RecTrack& tref) { if (recoData.inputsTPCclusters) { - uint8_t clSect = 0, clRow = 0; + uint8_t clSect = 0, clRow = 0, lowestR = -1; uint32_t clIdx = 0; const auto clRefs = recoData.getTPCTracksClusterRefs(); const auto tpcClusAcc = recoData.getTPCClusters(); - trc.getClusterReference(clRefs, trc.getNClusterReferences() - 1, clSect, clRow, clIdx); + const auto shMap = recoData.clusterShMapTPC; + for (int ic = 0; ic < trc.getNClusterReferences(); ic++) { // outside -> inside ordering, but on the sector boundaries backward jumps are possible + trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx); + if (clRow < lowestR) { + tref.rowCountTPC++; + lowestR = clRow; + } + unsigned int absoluteIndex = tpcClusAcc.clusterOffset[clSect][clRow] + clIdx; + if (shMap[absoluteIndex] & o2::gpu::GPUTPCGMMergedTrackHit::flagShared) { + tref.nClTPCShared++; + } + } + tref.lowestPadRow = lowestR; const auto& clus = tpcClusAcc.clusters[clSect][clRow][clIdx]; int padFromEdge = int(clus.getPad()), npads = o2::gpu::GPUTPCGeometry::NPads(clRow); if (padFromEdge > npads / 2) { padFromEdge = npads - 1 - padFromEdge; } tref.padFromEdge = uint8_t(padFromEdge); - tref.lowestPadRow = clRow; + trc.getClusterReference(clRefs, 0, clSect, clRow, clIdx); + tref.rowMaxTPC = clRow; } }; @@ -557,7 +570,10 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData) if (msk[DetID::TPC]) { const auto& trtpc = recoData.getTPCTrack(gidSet[GTrackID::TPC]); tref.nClTPC = trtpc.getNClusters(); - getLowestPadrow(trtpc, tref); + if (trtpc.hasBothSidesClusters()) { + tref.flags |= RecTrack::HASACSides; + } + fillTPCClusterInfo(trtpc, tref); flagTPCClusters(trtpc, entry.first); if (trackFam.entTPC < 0) { trackFam.entTPC = tcnt; @@ -748,8 +764,8 @@ void TrackMCStudy::fillMCClusterInfo(const o2::globaltracking::RecoContainer& re const auto& params = o2::trackstudy::TrackMCStudyConfig::Instance(); ClResTPC clRes{}; - for (uint8_t sector = 0; sector < 36; sector++) { - for (uint8_t row = 0; row < 152; row++) { + for (uint8_t row = 0; row < 152; row++) { // we need to go in increasing row, so this should be the outer loop + for (uint8_t sector = 0; sector < 36; sector++) { unsigned int offs = TPCClusterIdxStruct.clusterOffset[sector][row]; for (unsigned int icl0 = 0; icl0 < TPCClusterIdxStruct.nClusters[sector][row]; icl0++) { const auto labels = TPCClMClab->getLabels(icl0 + offs); diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudyTypes.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudyTypes.cxx index 204e0c741a675..b6236b7bf0e73 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudyTypes.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackMCStudyTypes.cxx @@ -77,4 +77,66 @@ int MCTrackInfo::getHighestITSLayer() const return -1; } +o2::track::TrackPar MCTrackInfo::getTrackParTPC(float b, float x) const +{ + o2::track::TrackPar t(track); + int ntri = 0; + while (ntri < 2) { + int sector0 = o2::math_utils::angle2Sector(t.getAlpha()); + if (!t.propagateParamTo(x, b)) { + t.invalidate(); + break; + } + int sector = o2::math_utils::angle2Sector(t.getPhiPos()); + float alpha = o2::math_utils::sector2Angle(sector); + if (!t.rotateParam(alpha)) { + t.invalidate(); + break; + } + if (sector != sector0) { + ntri++; + continue; + } + break; + } + // printf("%s ->\n%s <-\n",track.asString().c_str(), t.asString().c_str()); + return t; +} + +float MCTrackInfo::getTrackParTPCPar(int i, float b, float x) const +{ + auto t = getTrackParTPC(b, x); + return t.isValid() ? t.getParam(i) : -999.; +} + +float MCTrackInfo::getTrackParTPCPhiSec(float b, float x) const +{ + auto t = getTrackParTPC(b, x); + return t.isValid() ? std::atan2(t.getY(), t.getX()) : -999.; +} + +int TrackFamily::getLongestTPCTrackEntry() const +{ + int n = -1, ncl = 0; + int ntr = recTracks.size(); + for (int i = 0; i < ntr; i++) { + if (recTracks[i].nClTPC > ncl) { + ncl = recTracks[i].nClTPC; + n = i; + } + } + return n; +} + +int TrackFamily::getNTPCClones() const +{ + int n = 0; + for (auto& t : recTracks) { + if (t.nClTPC > 0) { + n++; + } + } + return n; +} + } // namespace o2::trackstudy diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx index 97721a30b0ab8..44dbf5f1e1458 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx @@ -274,25 +274,25 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) const auto clRefs = recoData.getTPCTracksClusterRefs(); const auto tpcClusAcc = recoData.getTPCClusters(); const auto shMap = recoData.clusterShMapTPC; + if (recoData.inputsTPCclusters) { - uint8_t clSect = 0, clRow = 0, clRowP = -1; + uint8_t clSect = 0, clRow = 0, lowestR = -1; uint32_t clIdx = 0; - for (int ic = 0; ic < trc.getNClusterReferences(); ic++) { + for (int ic = 0; ic < trc.getNClusterReferences(); ic++) { // outside -> inside ordering, but on the sector boundaries backward jumps are possible trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx); - if (clRow != clRowP) { + if (clRow < lowestR) { trExt.rowCountTPC++; - clRowP = clRow; + lowestR = clRow; } unsigned int absoluteIndex = tpcClusAcc.clusterOffset[clSect][clRow] + clIdx; if (shMap[absoluteIndex] & o2::gpu::GPUTPCGMMergedTrackHit::flagShared) { trExt.nClTPCShared++; } } - trc.getClusterReference(clRefs, trc.getNClusterReferences() - 1, clSect, clRow, clIdx); - trExt.rowMinTPC = clRow; + trExt.rowMinTPC = lowestR; const auto& clus = tpcClusAcc.clusters[clSect][clRow][clIdx]; trExt.padFromEdge = uint8_t(clus.getPad()); - int npads = o2::gpu::GPUTPCGeometry::NPads(clRow); + int npads = o2::gpu::GPUTPCGeometry::NPads(lowestR); if (trExt.padFromEdge > npads / 2) { trExt.padFromEdge = npads - 1 - trExt.padFromEdge; } @@ -314,9 +314,9 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) uint8_t clSect0 = 0, clRow0 = 0, clSect1 = 0, clRow1 = 0; uint32_t clIdx0 = 0, clIdx1 = 0; int ic1Start = 0; - for (int ic0 = 0; ic0 < trc0.getNClusterReferences(); ic0++) { // outside -> inside + for (int ic0 = 0; ic0 < trc0.getNClusterReferences(); ic0++) { // outside -> inside, but on the sector boundaries backward jumps are possible trc0.getClusterReference(clRefs, ic0, clSect0, clRow0, clIdx0); - for (int ic1 = ic1Start; ic1 < trc1.getNClusterReferences(); ic1++) { // outside -> inside + for (int ic1 = ic1Start; ic1 < trc1.getNClusterReferences(); ic1++) { // outside -> inside, but on the sector boundaries backward jumps are possible trc1.getClusterReference(clRefs, ic1, clSect1, clRow1, clIdx1); if (clRow1 > clRow0) { ic1Start = ic1 + 1; From 7fa67851725829b5e473f103bc44482b61afe7be Mon Sep 17 00:00:00 2001 From: Vikas Singhal Date: Wed, 30 Jul 2025 08:24:32 +0200 Subject: [PATCH 187/315] GPU: GPUd --> GPUdii Force Inline, Code did not break --- GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx index 87486292eb034..f224e860839df 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMTrackParam.cxx @@ -1095,7 +1095,7 @@ GPUd() bool GPUTPCGMTrackParam::CheckNumericalQuality(float overrideCovYY) const return ok; } -GPUd() void GPUTPCGMTrackParam::RefitTrack(GPUTPCGMMergedTrack& GPUrestrict() track, int32_t iTrk, GPUTPCGMMerger* GPUrestrict() merger, int32_t attempt) // TODO: Inline me, once __forceinline__ is fixed by HIP +GPUdii() void GPUTPCGMTrackParam::RefitTrack(GPUTPCGMMergedTrack& GPUrestrict() track, int32_t iTrk, GPUTPCGMMerger* GPUrestrict() merger, int32_t attempt) // VS: GPUd changed to GPUdii. No change in output and no performance penalty. { if (!track.OK()) { return; From d55013b2ec4f6043963ed8f9e40ff7a1d6dc5a46 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 30 Jul 2025 16:29:03 +0200 Subject: [PATCH 188/315] Add hash method to the TrackParam Hash is calculated by combining the precision-truncated (a la AOD) x, alpha + 5 parameters, so the hash depends on the X where it is evaluated. --- .../TrackParametrization.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h index f240e34861eeb..9c3079208b2f5 100644 --- a/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h +++ b/DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackParametrization.h @@ -248,6 +248,8 @@ class TrackParametrization #ifndef GPUCA_ALIGPUCODE std::string asString() const; std::string asStringHexadecimal(); + size_t hash() const { return hash(getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt()); } + static size_t hash(float x, float alp, float y, float z, float snp, float tgl, float q2pt); #endif GPUd() void updateParam(value_t delta, int i); @@ -752,6 +754,21 @@ GPUdi() void TrackParametrization::updateParams(const value_t* delta) } } +#ifndef GPUCA_ALIGPUCODE +template +size_t TrackParametrization::hash(float x, float alp, float y, float z, float snp, float tgl, float q2pt) +{ + size_t h = std::hash{}(o2::math_utils::detail::truncateFloatFraction(x, 0xFFFFFFF0)); + h ^= std::hash{}(o2::math_utils::detail::truncateFloatFraction(alp, 0xFFFFFFF0)) << 1; + h ^= std::hash{}(o2::math_utils::detail::truncateFloatFraction(y, 0xFFFFFFF0)) << 1; + h ^= std::hash{}(o2::math_utils::detail::truncateFloatFraction(z, 0xFFFFFFF0)) << 1; + h ^= std::hash{}(o2::math_utils::detail::truncateFloatFraction(snp, 0xFFFFFF00)) << 1; + h ^= std::hash{}(o2::math_utils::detail::truncateFloatFraction(tgl, 0xFFFFFF00)) << 1; + h ^= std::hash{}(o2::math_utils::detail::truncateFloatFraction(q2pt, 0xFFFFFC00)) << 1; + return h; +} +#endif + } // namespace track } // namespace o2 From de1a1d68f0bd4d62b7b84ddaef5b0931f5546edd Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 30 Jul 2025 16:29:32 +0200 Subject: [PATCH 189/315] Add track hash to TrackStudy output --- .../study/include/GlobalTrackingStudy/TrackInfoExt.h | 4 ++-- Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackInfoExt.h b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackInfoExt.h index 2eed64df3bfca..e33a0def63842 100644 --- a/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackInfoExt.h +++ b/Detectors/GlobalTrackingWorkflow/study/include/GlobalTrackingStudy/TrackInfoExt.h @@ -53,7 +53,7 @@ struct TrackInfoExt { uint8_t padFromEdge = -1; uint8_t rowMaxTPC = 0; uint8_t rowCountTPC = 0; - + size_t hashIU = 0; void setTPCA() { setBit(int(TPCA)); } void setTPCC() { setBit(int(TPCC)); } void setTPCAC() { setBit(int(TPCC)); } @@ -74,7 +74,7 @@ struct TrackInfoExt { void resetBit(int bit) { flags &= ~(kBitMask & (0x1 << bit)); } bool isBitSet(int bit) const { return flags & (kBitMask & (0x1 << bit)); } - ClassDefNV(TrackInfoExt, 7); + ClassDefNV(TrackInfoExt, 8); }; } // namespace dataformats diff --git a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx index 44dbf5f1e1458..d9ea9fe4516e1 100644 --- a/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx +++ b/Detectors/GlobalTrackingWorkflow/study/src/TrackingStudy.cxx @@ -479,6 +479,7 @@ void TrackingStudySpec::process(o2::globaltracking::RecoContainer& recoData) auto& trcExt = trcExtVec.emplace_back(); recoData.getTrackTime(vid, trcExt.ttime, trcExt.ttimeE); trcExt.track = trc; + trcExt.hashIU = trc.hash(); trcExt.dca = dca; trcExt.gid = vid; trcExt.xmin = xmin; From fd6d4eb302df34cb4d97ac8bb2ea74874b439958 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 31 Jul 2025 10:47:37 +0200 Subject: [PATCH 190/315] dpl-workflow: simple serialization mitigation seems not to work on MI100 in async, have to use full serialization workaround --- prodtests/full-system-test/dpl-workflow.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prodtests/full-system-test/dpl-workflow.sh b/prodtests/full-system-test/dpl-workflow.sh index 044c382e45070..e4cd6d3c74cec 100755 --- a/prodtests/full-system-test/dpl-workflow.sh +++ b/prodtests/full-system-test/dpl-workflow.sh @@ -272,7 +272,8 @@ if [[ $GPUTYPE == "HIP" ]]; then GPU_CONFIG+=" --environment \"ROCR_VISIBLE_DEVICES={timeslice${TIMESLICEOFFSET}}\"" fi # serialization workaround for MI100 nodes: remove it again if the problem will be fixed in ROCm, then also remove the DISABLE_MI100_SERIALIZATION flag in the O2DPG parse script - [[ $EPNSYNCMODE == 1 || -n ${OPTIMIZED_PARALLEL_ASYNC:-} ]] && [[ ${EPN_NODE_MI100:-} == "1" ]] && [[ ${DISABLE_MI100_SERIALIZATION:-0} != 1 ]] && GPU_CONFIG_KEY+="GPU_proc.amdMI100SerializationWorkaround=1;" + [[ $EPNSYNCMODE == 1 ]] && [[ ${EPN_NODE_MI100:-} == "1" ]] && [[ ${DISABLE_MI100_SERIALIZATION:-0} != 1 ]] && GPU_CONFIG_KEY+="GPU_proc.amdMI100SerializationWorkaround=1;" + [[ -n ${OPTIMIZED_PARALLEL_ASYNC:-} ]] && [[ ${EPN_NODE_MI100:-} == "1" ]] && [[ ${DISABLE_MI100_SERIALIZATION:-0} != 1 ]] && GPU_CONFIG_KEY+="GPU_proc.serializeGPU=3;" #export HSA_TOOLS_LIB=/opt/rocm/lib/librocm-debug-agent.so.2 else GPU_CONFIG_KEY+="GPU_proc.deviceNum=-2;" From c01e12034776fe51d63106c06f9f961eb94930c1 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 31 Jul 2025 22:38:58 +0200 Subject: [PATCH 191/315] ITS: if TF dropped clear tracks (#14553) --- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index 938356050262d..b0add9881d01b 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -66,6 +66,7 @@ void Tracker::clustersToTracks(const LogFunc& logger, const LogFunc& error) LOGP(error, "Exception: {}", err.what()); if (mTrkParams[iteration].DropTFUponFailure) { mMemoryPool->print(); + mTimeFrame->wipe(); ++mNumberOfDroppedTFs; error("...Dropping Timeframe..."); } else { From 5cae1bcdde3318e4d5720403c87d5af00b79f7f5 Mon Sep 17 00:00:00 2001 From: Christian Sonnabend Date: Fri, 1 Aug 2025 01:55:29 +0200 Subject: [PATCH 192/315] Bug-fix for memory allocation (#14554) --- .../Global/GPUChainTrackingClusterizer.cxx | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx index 07b332db1fc12..846df352d3a34 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx @@ -643,26 +643,28 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) // Maximum of 4 lanes supported HighResTimer* nnTimers[12]; - if (GetProcessingSettings().nn.applyNNclusterizer && GetProcessingSettings().debugLevel >= 1) { - nnTimers[0] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 0); - nnTimers[1] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 1); - nnTimers[2] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 2); - nnTimers[3] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 3); - nnTimers[4] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 4); - nnTimers[5] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 5); - nnTimers[6] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 6); - nnTimers[7] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 7); - nnTimers[8] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 8); - nnTimers[9] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 9); - nnTimers[10] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 10); - nnTimers[11] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 11); - } if (GetProcessingSettings().nn.applyNNclusterizer) { int32_t deviceId = -1; int32_t numLanes = GetProcessingSettings().nTPCClustererLanes; int32_t maxThreads = mRec->getNKernelHostThreads(true); // bool recreateMemoryAllocator = false; + + if (GetProcessingSettings().debugLevel >= 1) { + nnTimers[0] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 0); + nnTimers[1] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 1); + nnTimers[2] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 2); + nnTimers[3] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 3); + nnTimers[4] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 4); + nnTimers[5] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 5); + nnTimers[6] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 6); + nnTimers[7] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 7); + nnTimers[8] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 8); + nnTimers[9] = &getTimer("GPUTPCNNClusterizer_ONNXClassification_0_", 9); + nnTimers[10] = &getTimer("GPUTPCNNClusterizer_ONNXRegression_1_", 10); + nnTimers[11] = &getTimer("GPUTPCNNClusterizer_ONNXRegression2_2_", 11); + } + mRec->runParallelOuterLoop(doGPU, numLanes, [&](uint32_t lane) { nnApplications[lane].init(nn_settings, GetProcessingSettings().deterministicGPUReconstruction); if (nnApplications[lane].mModelsUsed[0]) { @@ -708,7 +710,7 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) LOG(info) << "(ORT) Allocated ONNX stream for lane " << lane << " and device " << deviceId; } }); - mRec->runParallelOuterLoop(doGPU, NSECTORS, [&](uint32_t sector) { + for (int32_t sector = 0; sector < NSECTORS; sector++) { GPUTPCNNClusterizer& clustererNN = processors()->tpcNNClusterer[sector]; GPUTPCNNClusterizer& clustererNNShadow = doGPU ? processorsShadow()->tpcNNClusterer[sector] : clustererNN; int32_t lane = sector % numLanes; @@ -725,7 +727,7 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) AllocateRegisteredMemory(clustererNN.mMemoryId); // nnApplications[lane].createBoundary(clustererNNShadow); // nnApplications[lane].createIndexLookup(clustererNNShadow); - }); + } if (doGPU) { WriteToConstantMemory(RecoStep::TPCClusterFinding, (char*)&processors()->tpcNNClusterer - (char*)processors(), &processorsShadow()->tpcNNClusterer, sizeof(GPUTPCNNClusterizer) * NSECTORS, mRec->NStreams() - 1, &mEvents->init); } From 1aa2c1409988e1054730c7cccdc987fbe1db7506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 15 Jul 2025 19:18:09 +0200 Subject: [PATCH 193/315] TOF Param container: move to header only --- DataFormats/Detectors/TOF/CMakeLists.txt | 1 - .../DataFormatsTOF/ParameterContainers.h | 43 +++++++++++-- .../Detectors/TOF/src/ParameterContainers.cxx | 62 ------------------- 3 files changed, 38 insertions(+), 68 deletions(-) delete mode 100644 DataFormats/Detectors/TOF/src/ParameterContainers.cxx diff --git a/DataFormats/Detectors/TOF/CMakeLists.txt b/DataFormats/Detectors/TOF/CMakeLists.txt index 03dbd9275edf9..8a55e531287e1 100644 --- a/DataFormats/Detectors/TOF/CMakeLists.txt +++ b/DataFormats/Detectors/TOF/CMakeLists.txt @@ -16,7 +16,6 @@ o2_add_library(DataFormatsTOF src/CalibLHCphaseTOF.cxx src/CalibTimeSlewingParamTOF.cxx src/CTF.cxx - src/ParameterContainers.cxx src/CalibInfoCluster.cxx src/CosmicInfo.cxx src/Diagnostic.cxx diff --git a/DataFormats/Detectors/TOF/include/DataFormatsTOF/ParameterContainers.h b/DataFormats/Detectors/TOF/include/DataFormatsTOF/ParameterContainers.h index 9029c06d503c8..c9d910d8345e5 100644 --- a/DataFormats/Detectors/TOF/include/DataFormatsTOF/ParameterContainers.h +++ b/DataFormats/Detectors/TOF/include/DataFormatsTOF/ParameterContainers.h @@ -37,7 +37,7 @@ class Parameters Parameters(std::array parNames, std::string name) : mName{name}, mPar{}, mParNames{parNames} {}; /// Default destructor - ~Parameters() = default; + virtual ~Parameters() = default; // Ensure proper cleanup in derived classes /// Setter for the parameter at position iparam /// \param iparam index in the array of the parameters @@ -183,10 +183,27 @@ class ParameterCollection : public TNamed /// @param value parameter to add to the stored information /// @param pass key to look for in the stored information e.g. pass /// @return true if found and configured false if not fully configured - bool addParameter(const std::string& pass, const std::string& parName, float value); + bool addParameter(const std::string& pass, const std::string& parName, float value) + { + const bool alreadyPresent = hasKey(pass); + if (alreadyPresent) { + LOG(debug) << "Changing parametrization corresponding to key " << pass << " from size " << mParameters[pass].size() << " to " << parName; + } else { + mParameters[pass] = std::unordered_map{}; + LOG(debug) << "Adding new parametrization corresponding to key " << pass << ": " << parName; + } + mParameters[pass][parName] = value; + return true; + } /// @return the size of the container i.e. the number of stored keys (or passes) - int getSize(const std::string& pass) const; + int getSize(const std::string& pass) const + { + if (!hasKey(pass)) { + return -1; + } + return mParameters.at(pass).size(); + } /// @brief Function to push the parameters from the sub container into the collection and store it under a given key /// @tparam ParType type of the parameter container @@ -214,10 +231,26 @@ class ParameterCollection : public TNamed /// @brief printing function for the content of the pass /// @param pass pass to print - void print(const std::string& pass) const; + void print(const std::string& pass) const + { + const auto& size = getSize(pass); + if (size < 0) { + LOG(info) << "empty pass: " << pass; + return; + } + LOG(info) << "Pass \"" << pass << "\" with size " << size; + for (const auto& [par, value] : mParameters.at(pass)) { + LOG(info) << "par name = " << par << ", value = " << value; + } + } /// @brief printing function for the full content of the container - void print() const; + void print() const + { + for (const auto& [pass, pars] : mParameters) { + print(pass); + } + } /// @brief Getter of the full map of parameters stored in the container /// @return returns the full map of parameters diff --git a/DataFormats/Detectors/TOF/src/ParameterContainers.cxx b/DataFormats/Detectors/TOF/src/ParameterContainers.cxx deleted file mode 100644 index 91f723873e9cd..0000000000000 --- a/DataFormats/Detectors/TOF/src/ParameterContainers.cxx +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file ParameterContainers.h -/// \author Francesco Noferini -/// \author Nicolò Jacazio nicolo.jacazio@cern.ch -/// @since 2022-11-08 -/// \brief Implementation of the containers for the general parameters - -#include "DataFormatsTOF/ParameterContainers.h" - -// ClassImp(o2::tof::Parameters); -using namespace o2::tof; - -bool ParameterCollection::addParameter(const std::string& pass, const std::string& parName, float value) -{ - const bool alreadyPresent = hasKey(pass); - if (alreadyPresent) { - LOG(debug) << "Changing parametrization corresponding to key " << pass << " from size " << mParameters[pass].size() << " to " << parName; - } else { - mParameters[pass] = std::unordered_map{}; - LOG(debug) << "Adding new parametrization corresponding to key " << pass << ": " << parName; - } - mParameters[pass][parName] = value; - return true; -} - -int ParameterCollection::getSize(const std::string& pass) const -{ - if (!hasKey(pass)) { - return -1; - } - return mParameters.at(pass).size(); -} - -void ParameterCollection::print() const -{ - for (const auto& [pass, pars] : mParameters) { - print(pass); - } -} - -void ParameterCollection::print(const std::string& pass) const -{ - const auto& size = getSize(pass); - if (size < 0) { - LOG(info) << "empty pass: " << pass; - return; - } - LOG(info) << "Pass \"" << pass << "\" with size " << size; - for (const auto& [par, value] : mParameters.at(pass)) { - LOG(info) << "par name = " << par << ", value = " << value; - } -} From f08023c41d023c219ac097d031398ff7e41fd742 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 31 Jul 2025 11:32:50 +0200 Subject: [PATCH 194/315] ITS: allow to Individually set kernel parameters --- .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 32 +++++++++---------- .../include/ITStracking/TrackingConfigParam.h | 29 +++++++++++++++-- Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx | 1 + .../ITS/tracking/src/TrackingConfigParam.cxx | 28 ++++++++++++++++ 4 files changed, 71 insertions(+), 19 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index a8061e872c029..82eb48a8a7663 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -80,8 +80,8 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i mTimeFrameGPU->getPositionResolutions(), this->mTrkParams[iteration].LayerRadii, mTimeFrameGPU->getMSangles(), - conf.nBlocks, - conf.nThreads, + conf.nBlocksLayerTracklets[iteration], + conf.nThreadsLayerTracklets[iteration], mTimeFrameGPU->getStreams()); mTimeFrameGPU->createTrackletsBuffers(); computeTrackletsInROFsHandler(mTimeFrameGPU->getDeviceIndexTableUtils(), @@ -113,8 +113,8 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i mTimeFrameGPU->getPositionResolutions(), this->mTrkParams[iteration].LayerRadii, mTimeFrameGPU->getMSangles(), - conf.nBlocks, - conf.nThreads, + conf.nBlocksLayerTracklets[iteration], + conf.nThreadsLayerTracklets[iteration], mTimeFrameGPU->getStreams()); } @@ -144,8 +144,8 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) this->mTrkParams[iteration].MaxChi2ClusterAttachment, this->mTrkParams[iteration].CellDeltaTanLambdaSigma, this->mTrkParams[iteration].NSigmaCut, - conf.nBlocks, - conf.nThreads); + conf.nBlocksLayerCells[iteration], + conf.nThreadsLayerCells[iteration]); mTimeFrameGPU->createCellsBuffers(iLayer); computeCellsHandler(mTimeFrameGPU->getDeviceArrayClusters(), mTimeFrameGPU->getDeviceArrayUnsortedClusters(), @@ -161,8 +161,8 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) this->mTrkParams[iteration].MaxChi2ClusterAttachment, this->mTrkParams[iteration].CellDeltaTanLambdaSigma, this->mTrkParams[iteration].NSigmaCut, - conf.nBlocks, - conf.nThreads); + conf.nBlocksLayerCells[iteration], + conf.nThreadsLayerCells[iteration]); } } @@ -191,8 +191,8 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) currentLayerCellsNum, nextLayerCellsNum, 1e2, - conf.nBlocks, - conf.nThreads); + conf.nBlocksFindNeighbours[iteration], + conf.nThreadsFindNeighbours[iteration]); mTimeFrameGPU->createNeighboursDevice(iLayer, nNeigh); @@ -207,8 +207,8 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) currentLayerCellsNum, nextLayerCellsNum, 1e2, - conf.nBlocks, - conf.nThreads); + conf.nBlocksFindNeighbours[iteration], + conf.nThreadsFindNeighbours[iteration]); nNeigh = filterCellNeighboursHandler(mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), mTimeFrameGPU->getDeviceNeighbours(iLayer), @@ -247,8 +247,8 @@ void TrackerTraitsGPU::findRoads(const int iteration) this->mTrkParams[0].MaxChi2NDF, mTimeFrameGPU->getDevicePropagator(), this->mTrkParams[0].CorrType, - conf.nBlocks, - conf.nThreads); + conf.nBlocksProcessNeighbours[iteration], + conf.nThreadsProcessNeighbours[iteration]); } // fixme: I don't want to move tracks back and forth, but I need a way to use a thrust::allocator that is aware of our managed memory. if (trackSeeds.empty()) { @@ -269,8 +269,8 @@ void TrackerTraitsGPU::findRoads(const int iteration) this->mTrkParams[0].MaxChi2NDF, // float maxChi2NDF mTimeFrameGPU->getDevicePropagator(), // const o2::base::Propagator* propagator this->mTrkParams[0].CorrType, // o2::base::PropagatorImpl::MatCorrType - conf.nBlocks, - conf.nThreads); + conf.nBlocksTracksSeeds[iteration], + conf.nThreadsTracksSeeds[iteration]); mTimeFrameGPU->downloadTrackITSExtDevice(trackSeeds); diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h index ef6f925f1c29f..5b4b1aca1dfb8 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h @@ -107,9 +107,32 @@ struct TrackerParamConfig : public o2::conf::ConfigurableParamHelper { - // GPU-specific parameters - int nBlocks = 20; - int nThreads = 256; + static constexpr int MaxIter = TrackerParamConfig::MaxIter; + + /// Set nBlocks/nThreads to summarily override all kernel launch parameters in each iteration. + /// Parameters must start with nBlocks/nThreads. + static constexpr int OverrideValue{-1}; + static constexpr char const* BlocksName = "nBlocks"; + static constexpr char const* ThreadsName = "nThreads"; + int nBlocks = OverrideValue; + int nThreads = OverrideValue; + void maybeOverride() const; + + /// Individual kernel launch parameter for each iteration + int nBlocksLayerTracklets[MaxIter] = {30, 30, 30, 30}; + int nThreadsLayerTracklets[MaxIter] = {256, 256, 256, 256}; + + int nBlocksLayerCells[MaxIter] = {30, 30, 30, 30}; + int nThreadsLayerCells[MaxIter] = {256, 256, 256, 256}; + + int nBlocksFindNeighbours[MaxIter] = {30, 30, 30, 30}; + int nThreadsFindNeighbours[MaxIter] = {256, 256, 256, 256}; + + int nBlocksProcessNeighbours[MaxIter] = {30, 30, 30, 30}; + int nThreadsProcessNeighbours[MaxIter] = {256, 256, 256, 256}; + + int nBlocksTracksSeeds[MaxIter] = {30, 30, 30, 30}; + int nThreadsTracksSeeds[MaxIter] = {256, 256, 256, 256}; O2ParamDef(ITSGpuTrackingParamConfig, "ITSGpuTrackingParam"); }; diff --git a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx index b0add9881d01b..c8bf39142e019 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx @@ -39,6 +39,7 @@ Tracker::Tracker(TrackerTraits7* traits) : mTraits(traits) /// Initialise standard configuration with 1 iteration mTrkParams.resize(1); if (traits->isGPU()) { + ITSGpuTrackingParamConfig::Instance().maybeOverride(); ITSGpuTrackingParamConfig::Instance().printKeyValues(true, true); } } diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx index b5fbedcc89339..3101c34d4ab8f 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackingConfigParam.cxx @@ -9,8 +9,36 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include + +#include "Framework/Logger.h" #include "ITStracking/TrackingConfigParam.h" O2ParamImpl(o2::its::VertexerParamConfig); O2ParamImpl(o2::its::TrackerParamConfig); O2ParamImpl(o2::its::ITSGpuTrackingParamConfig); + +namespace o2::its +{ + +void ITSGpuTrackingParamConfig::maybeOverride() const +{ + if (nBlocks == OverrideValue && nThreads == OverrideValue) { + return; + } + const auto name = getName(); + auto members = getDataMembers(); + for (auto member : *members) { + if (!member.name.ends_with(BlocksName) && !member.name.ends_with(ThreadsName)) { + if (nBlocks != OverrideValue && member.name.starts_with(BlocksName) && (member.value != nBlocks)) { + o2::conf::ConfigurableParam::setValue(name, member.name, nBlocks); + } + if (nThreads != OverrideValue && member.name.starts_with(ThreadsName) && (member.value != nThreads)) { + o2::conf::ConfigurableParam::setValue(name, member.name, nThreads); + } + } + } + LOGP(info, "Overwriting gpu threading parameters"); +} // namespace o2::its + +} // namespace o2::its From afc3e674f955961207efd3ee919ad94983953f6a Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 4 Aug 2025 16:08:45 +0200 Subject: [PATCH 195/315] ITS: Tracklet add print compatible on GPU Signed-off-by: Felix Schlepper --- .../ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h index 5741a9fc65947..e6c9db55198a3 100644 --- a/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h +++ b/Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h @@ -47,13 +47,10 @@ struct Tracklet final { GPUhdi() auto getDeltaRof() const { return rof[1] - rof[0]; } GPUhdi() auto getSpanRof(const Tracklet& o) const noexcept { return o2::gpu::CAMath::Max(getMaxRof(), o.getMaxRof()) - o2::gpu::CAMath::Min(getMinRof(), o.getMinRof()); } GPUhdi() unsigned char operator<(const Tracklet&) const; -#if !defined(GPUCA_NO_FMT) && !defined(GPUCA_GPUCODE_DEVICE) - std::string asString() const + GPUhd() void print() const { - return fmt::format("fClIdx:{} fROF:{} sClIdx:{} sROF:{} (DROF:{})", firstClusterIndex, rof[0], secondClusterIndex, rof[1], getDeltaRof()); + printf("TRKLT: fClIdx:%d fROF:%d sClIdx:%d sROF:%d (DROF:%d) tgl=%f phi=%f\n", firstClusterIndex, rof[0], secondClusterIndex, rof[1], getDeltaRof(), tanLambda, phi); } - void print() const { LOG(info) << asString(); } -#endif int firstClusterIndex{constants::UnusedIndex}; int secondClusterIndex{constants::UnusedIndex}; From 8feebaaa2e31b5f33618f11b17eedb327cdebab8 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 4 Aug 2025 16:09:38 +0200 Subject: [PATCH 196/315] ITS: format time for TF Signed-off-by: Felix Schlepper --- Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx index be7750964b3e7..201f1d064a632 100644 --- a/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx +++ b/Detectors/ITSMFT/ITS/workflow/src/TrackerSpec.cxx @@ -60,7 +60,7 @@ void TrackerDPL::run(ProcessingContext& pc) mITSTrackingInterface.updateTimeDependentParams(pc); mITSTrackingInterface.run(pc); mTimer.Stop(); - LOGP(info, "CPU Reconstruction time for this TF {} s (cpu), {} s (wall)", mTimer.CpuTime() - cput, mTimer.RealTime() - realt); + LOGP(info, "CPU Reconstruction time for this TF {:.2f} s (cpu), {:.2f} s (wall)", mTimer.CpuTime() - cput, mTimer.RealTime() - realt); } void TrackerDPL::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj) From 0a6a9624ca5066bbdfa9732e91190ee5c4151706 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 4 Aug 2025 16:10:26 +0200 Subject: [PATCH 197/315] ITS: make trackleting compatible with GPU (partial revert) Signed-off-by: Felix Schlepper --- .../ITSMFT/ITS/tracking/src/TrackerTraits.cxx | 181 ++++++++---------- 1 file changed, 84 insertions(+), 97 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx index b46e7a68875e6..2515f8287d72b 100644 --- a/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx +++ b/Detectors/ITSMFT/ITS/tracking/src/TrackerTraits.cxx @@ -73,6 +73,9 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF mTaskArena->execute([&] { auto forTracklets = [&](auto Tag, int iLayer, int pivotROF, int base, int& offset) -> int { + if (!mTimeFrame->mMultiplicityCutMask[pivotROF]) { + return 0; + } int minROF = o2::gpu::CAMath::Max(startROF, pivotROF - mTrkParams[iteration].DeltaROF); int maxROF = o2::gpu::CAMath::Min(endROF - 1, pivotROF + mTrkParams[iteration].DeltaROF); gsl::span primaryVertices = mTrkParams[iteration].UseDiamond ? diamondSpan : mTimeFrame->getPrimaryVertices(minROF, maxROF); @@ -87,103 +90,98 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF int localCount = 0; auto& tracklets = mTimeFrame->getTracklets()[iLayer]; - for (int targetROF0{minROF}; targetROF0 <= maxROF; ++targetROF0) { - if (!mTimeFrame->mMultiplicityCutMask[targetROF0]) { - continue; - } - auto layer0 = mTimeFrame->getClustersOnLayer(targetROF0, iLayer); - if (layer0.empty()) { + auto layer0 = mTimeFrame->getClustersOnLayer(pivotROF, iLayer); + if (layer0.empty()) { + return 0; + } + + const float meanDeltaR = mTrkParams[iteration].LayerRadii[iLayer + 1] - mTrkParams[iteration].LayerRadii[iLayer]; + + for (int iCluster = 0; iCluster < int(layer0.size()); ++iCluster) { + const Cluster& currentCluster = layer0[iCluster]; + const int currentSortedIndex = mTimeFrame->getSortedIndex(pivotROF, iLayer, iCluster); + if (mTimeFrame->isClusterUsed(iLayer, currentCluster.clusterId)) { continue; } - const float meanDeltaR = mTrkParams[iteration].LayerRadii[iLayer + 1] - mTrkParams[iteration].LayerRadii[iLayer]; + const float inverseR0 = 1.f / currentCluster.radius; - for (int iCluster = 0; iCluster < int(layer0.size()); ++iCluster) { - const Cluster& currentCluster = layer0[iCluster]; - const int currentSortedIndex = mTimeFrame->getSortedIndex(targetROF0, iLayer, iCluster); - if (mTimeFrame->isClusterUsed(iLayer, currentCluster.clusterId)) { + for (int iV = startVtx; iV < endVtx; ++iV) { + const auto& pv = primaryVertices[iV]; + if ((pv.isFlagSet(Vertex::Flags::UPCMode) && iteration != 3) || (iteration == 3 && !pv.isFlagSet(Vertex::Flags::UPCMode))) { continue; } - const float inverseR0 = 1.f / currentCluster.radius; - for (int iV = startVtx; iV < endVtx; ++iV) { - const auto& pv = primaryVertices[iV]; - if ((pv.isFlagSet(Vertex::Flags::UPCMode) && iteration != 3) || (iteration == 3 && !pv.isFlagSet(Vertex::Flags::UPCMode))) { - continue; - } + const float resolution = o2::gpu::CAMath::Sqrt(math_utils::Sq(mTimeFrame->getPositionResolution(iLayer)) + math_utils::Sq(mTrkParams[iteration].PVres) / float(pv.getNContributors())); + const float tanLambda = (currentCluster.zCoordinate - pv.getZ()) * inverseR0; + const float zAtRmin = tanLambda * (mTimeFrame->getMinR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate; + const float zAtRmax = tanLambda * (mTimeFrame->getMaxR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate; + const float sqInvDeltaZ0 = 1.f / (math_utils::Sq(currentCluster.zCoordinate - pv.getZ()) + constants::Tolerance); + const float sigmaZ = o2::gpu::CAMath::Sqrt( + math_utils::Sq(resolution) * math_utils::Sq(tanLambda) * ((math_utils::Sq(inverseR0) + sqInvDeltaZ0) * math_utils::Sq(meanDeltaR) + 1.f) + math_utils::Sq(meanDeltaR * mTimeFrame->getMSangle(iLayer))); - const float resolution = o2::gpu::CAMath::Sqrt(math_utils::Sq(mTimeFrame->getPositionResolution(iLayer)) + math_utils::Sq(mTrkParams[iteration].PVres) / float(pv.getNContributors())); - const float tanLambda = (currentCluster.zCoordinate - pv.getZ()) * inverseR0; - const float zAtRmin = tanLambda * (mTimeFrame->getMinR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate; - const float zAtRmax = tanLambda * (mTimeFrame->getMaxR(iLayer + 1) - currentCluster.radius) + currentCluster.zCoordinate; - const float sqInvDeltaZ0 = 1.f / (math_utils::Sq(currentCluster.zCoordinate - pv.getZ()) + constants::Tolerance); - const float sigmaZ = o2::gpu::CAMath::Sqrt( - math_utils::Sq(resolution) * math_utils::Sq(tanLambda) * ((math_utils::Sq(inverseR0) + sqInvDeltaZ0) * math_utils::Sq(meanDeltaR) + 1.f) + math_utils::Sq(meanDeltaR * mTimeFrame->getMSangle(iLayer))); + auto bins = getBinsRect(currentCluster, iLayer + 1, zAtRmin, zAtRmax, sigmaZ * mTrkParams[iteration].NSigmaCut, mTimeFrame->getPhiCut(iLayer)); + if (bins.x == 0 && bins.y == 0 && bins.z == 0 && bins.w == 0) { + continue; + } + int phiBinsNum = bins.w - bins.y + 1; + if (phiBinsNum < 0) { + phiBinsNum += mTrkParams[iteration].PhiBins; + } - auto bins = getBinsRect(currentCluster, iLayer + 1, zAtRmin, zAtRmax, sigmaZ * mTrkParams[iteration].NSigmaCut, mTimeFrame->getPhiCut(iLayer)); - if (bins.x == 0 && bins.y == 0 && bins.z == 0 && bins.w == 0) { + for (int targetROF{minROF}; targetROF <= maxROF; ++targetROF) { + if (!mTimeFrame->mMultiplicityCutMask[targetROF]) { continue; } - int phiBinsNum = bins.w - bins.y + 1; - if (phiBinsNum < 0) { - phiBinsNum += mTrkParams[iteration].PhiBins; + auto layer1 = mTimeFrame->getClustersOnLayer(targetROF, iLayer + 1); + if (layer1.empty()) { + continue; } - - for (int targetROF1{minROF}; targetROF1 <= maxROF; ++targetROF1) { - if (!mTimeFrame->mMultiplicityCutMask[targetROF1] || std::abs(targetROF0 - targetROF1) > mTrkParams[iteration].DeltaROF) { - continue; - } - auto layer1 = mTimeFrame->getClustersOnLayer(targetROF1, iLayer + 1); - if (layer1.empty()) { - continue; - } - for (int iPhi = 0; iPhi < phiBinsNum; ++iPhi) { - int iPhiBin = (bins.y + iPhi) % mTrkParams[iteration].PhiBins; - int firstBinIdx = mTimeFrame->mIndexTableUtils.getBinIndex(bins.x, iPhiBin); - int maxBinIdx = firstBinIdx + (bins.z - bins.x) + 1; - int firstRow = mTimeFrame->getIndexTable(targetROF1, iLayer + 1)[firstBinIdx]; - int lastRow = mTimeFrame->getIndexTable(targetROF1, iLayer + 1)[maxBinIdx]; - for (int iNext = firstRow; iNext < lastRow; ++iNext) { - if (iNext >= int(layer1.size())) { - break; - } - const Cluster& nextCluster = layer1[iNext]; - if (mTimeFrame->isClusterUsed(iLayer + 1, nextCluster.clusterId)) { - continue; - } - float deltaPhi = o2::gpu::GPUCommonMath::Abs(currentCluster.phi - nextCluster.phi); - float deltaZ = o2::gpu::GPUCommonMath::Abs((tanLambda * (nextCluster.radius - currentCluster.radius)) + currentCluster.zCoordinate - nextCluster.zCoordinate); + for (int iPhi = 0; iPhi < phiBinsNum; ++iPhi) { + const int iPhiBin = (bins.y + iPhi) % mTrkParams[iteration].PhiBins; + const int firstBinIdx = mTimeFrame->mIndexTableUtils.getBinIndex(bins.x, iPhiBin); + const int maxBinIdx = firstBinIdx + (bins.z - bins.x) + 1; + const int firstRow = mTimeFrame->getIndexTable(targetROF, iLayer + 1)[firstBinIdx]; + const int lastRow = mTimeFrame->getIndexTable(targetROF, iLayer + 1)[maxBinIdx]; + for (int iNext = firstRow; iNext < lastRow; ++iNext) { + if (iNext >= int(layer1.size())) { + break; + } + const Cluster& nextCluster = layer1[iNext]; + if (mTimeFrame->isClusterUsed(iLayer + 1, nextCluster.clusterId)) { + continue; + } + float deltaPhi = o2::gpu::GPUCommonMath::Abs(currentCluster.phi - nextCluster.phi); + float deltaZ = o2::gpu::GPUCommonMath::Abs((tanLambda * (nextCluster.radius - currentCluster.radius)) + currentCluster.zCoordinate - nextCluster.zCoordinate); #ifdef OPTIMISATION_OUTPUT - MCCompLabel label; - int currentId{currentCluster.clusterId}; - int nextId{nextCluster.clusterId}; - for (auto& lab1 : mTimeFrame->getClusterLabels(iLayer, currentId)) { - for (auto& lab2 : mTimeFrame->getClusterLabels(iLayer + 1, nextId)) { - if (lab1 == lab2 && lab1.isValid()) { - label = lab1; - break; - } - } - if (label.isValid()) { + MCCompLabel label; + int currentId{currentCluster.clusterId}; + int nextId{nextCluster.clusterId}; + for (auto& lab1 : mTimeFrame->getClusterLabels(iLayer, currentId)) { + for (auto& lab2 : mTimeFrame->getClusterLabels(iLayer + 1, nextId)) { + if (lab1 == lab2 && lab1.isValid()) { + label = lab1; break; } } - off << std::format("{}\t{:d}\t{}\t{}\t{}\t{}", iLayer, label.isValid(), (tanLambda * (nextCluster.radius - currentCluster.radius) + currentCluster.zCoordinate - nextCluster.zCoordinate) / sigmaZ, tanLambda, resolution, sigmaZ) << std::endl; + if (label.isValid()) { + break; + } + } + off << std::format("{}\t{:d}\t{}\t{}\t{}\t{}", iLayer, label.isValid(), (tanLambda * (nextCluster.radius - currentCluster.radius) + currentCluster.zCoordinate - nextCluster.zCoordinate) / sigmaZ, tanLambda, resolution, sigmaZ) << std::endl; #endif - if (deltaZ / sigmaZ < mTrkParams[iteration].NSigmaCut && - (deltaPhi < mTimeFrame->getPhiCut(iLayer) || - o2::gpu::GPUCommonMath::Abs(deltaPhi - o2::constants::math::TwoPI) < mTimeFrame->getPhiCut(iLayer))) { - float phi = o2::gpu::GPUCommonMath::ATan2(currentCluster.yCoordinate - nextCluster.yCoordinate, currentCluster.xCoordinate - nextCluster.xCoordinate); - float tanL = (currentCluster.zCoordinate - nextCluster.zCoordinate) / (currentCluster.radius - nextCluster.radius); - if constexpr (decltype(Tag)::value == PassMode::OnePass::value) { - tracklets.emplace_back(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF1, iLayer + 1, iNext), tanL, phi, targetROF0, targetROF1); - } else if constexpr (decltype(Tag)::value == PassMode::TwoPassCount::value) { - ++localCount; - } else if constexpr (decltype(Tag)::value == PassMode::TwoPassInsert::value) { - const int idx = base + offset++; - tracklets[idx] = Tracklet(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF1, iLayer + 1, iNext), tanL, phi, targetROF0, targetROF1); - } + if (deltaZ / sigmaZ < mTrkParams[iteration].NSigmaCut && + ((deltaPhi < mTimeFrame->getPhiCut(iLayer) || o2::gpu::GPUCommonMath::Abs(deltaPhi - o2::constants::math::TwoPI) < mTimeFrame->getPhiCut(iLayer)))) { + const float phi{o2::gpu::CAMath::ATan2(currentCluster.yCoordinate - nextCluster.yCoordinate, currentCluster.xCoordinate - nextCluster.xCoordinate)}; + const float tanL = (currentCluster.zCoordinate - nextCluster.zCoordinate) / (currentCluster.radius - nextCluster.radius); + if constexpr (decltype(Tag)::value == PassMode::OnePass::value) { + tracklets.emplace_back(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF, iLayer + 1, iNext), tanL, phi, pivotROF, targetROF); + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassCount::value) { + ++localCount; + } else if constexpr (decltype(Tag)::value == PassMode::TwoPassInsert::value) { + const int idx = base + offset++; + tracklets[idx] = Tracklet(currentSortedIndex, mTimeFrame->getSortedIndex(targetROF, iLayer + 1, iNext), tanL, phi, pivotROF, targetROF); } } } @@ -250,7 +248,10 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF /// Sort tracklets auto& trkl{mTimeFrame->getTracklets()[iLayer]}; tbb::parallel_sort(trkl.begin(), trkl.end(), [](const Tracklet& a, const Tracklet& b) -> bool { - return a.firstClusterIndex < b.firstClusterIndex || (a.firstClusterIndex == b.firstClusterIndex && a.secondClusterIndex < b.secondClusterIndex); + if (a.firstClusterIndex != b.firstClusterIndex) { + return a.firstClusterIndex < b.firstClusterIndex; + } + return a.secondClusterIndex < b.secondClusterIndex; }); /// Remove duplicates trkl.erase(std::unique(trkl.begin(), trkl.end(), [](const Tracklet& a, const Tracklet& b) -> bool { @@ -297,7 +298,7 @@ void TrackerTraits::computeLayerTracklets(const int iteration, int iROF }); } }); -} +} // namespace o2::its template void TrackerTraits::computeLayerCells(const int iteration) @@ -327,7 +328,6 @@ void TrackerTraits::computeLayerCells(const int iteration) for (int iNextTracklet{nextLayerFirstTrackletIndex}; iNextTracklet < nextLayerLastTrackletIndex; ++iNextTracklet) { const Tracklet& nextTracklet{mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet]}; const auto& nextLbl = mTimeFrame->getTrackletsLabel(iLayer + 1)[iNextTracklet]; - bool print = false; if (mTimeFrame->getTracklets()[iLayer + 1][iNextTracklet].firstClusterIndex != nextLayerClusterIndex) { break; } @@ -509,7 +509,8 @@ void TrackerTraits::findCellsNeighbours(const int iteration) const auto& trkl01 = mTimeFrame->getTracklets()[iLayer + 1][currentCellSeed.getSecondTrackletIndex()]; const auto& trkl10 = mTimeFrame->getTracklets()[iLayer + 1][nextCellSeed.getFirstTrackletIndex()]; const auto& trkl11 = mTimeFrame->getTracklets()[iLayer + 2][nextCellSeed.getSecondTrackletIndex()]; - if ((std::max({trkl00.getMaxRof(), trkl01.getMaxRof(), trkl10.getMaxRof(), trkl11.getMaxRof()}) - std::min({trkl00.getMinRof(), trkl01.getMinRof(), trkl10.getMinRof(), trkl10.getMinRof()})) > mTrkParams[0].DeltaROF) { + if ((std::max({trkl00.getMaxRof(), trkl01.getMaxRof(), trkl10.getMaxRof(), trkl11.getMaxRof()}) - + std::min({trkl00.getMinRof(), trkl01.getMinRof(), trkl10.getMinRof(), trkl11.getMinRof()})) > mTrkParams[0].DeltaROF) { continue; } } @@ -657,20 +658,6 @@ void TrackerTraits::processNeighbours(int iLayer, int iLevel, const bou CA_DEBUGGER(failed[0]++); continue; } - if (mTrkParams[0].DeltaROF) { // TODO this has to be improved for the staggering - const auto& trklNeigh = mTimeFrame->getTracklets()[iLayer - 1][neighbourCell.getFirstTrackletIndex()]; - short minRof{std::numeric_limits::max()}, maxRof{std::numeric_limits::min()}; - for (int iLayer{0}; iLayer < mTrkParams[0].NLayers; ++iLayer) { - if (const auto clsId = currentCell.getCluster(iLayer); clsId != constants::UnusedIndex) { - const short clsROF = mTimeFrame->getClusterROF(iLayer, clsId); - minRof = std::min(minRof, clsROF); - maxRof = std::max(maxRof, clsROF); - } - } - if ((std::max(trklNeigh.getMaxRof(), maxRof) - std::min(trklNeigh.getMinRof(), minRof)) > mTrkParams[0].DeltaROF) { - continue; - } - } /// Let's start the fitting procedure CellSeed seed{currentCell}; From c62aef2ea85d3e24b42e1eff827d440cb2702132 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 4 Aug 2025 16:11:21 +0200 Subject: [PATCH 198/315] ITS: GPU: fix deltaROF tracking Signed-off-by: Felix Schlepper --- .../GPU/ITStrackingGPU/TrackingKernels.h | 6 ++ .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 6 ++ .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 102 +++++++++++++----- 3 files changed, 88 insertions(+), 26 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h index a058f7e5fab0c..b0fb443513fef 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h @@ -131,6 +131,7 @@ void countCellsHandler(const Cluster** sortedClusters, CellSeed* cells, int** cellsLUTsDeviceArray, int* cellsLUTsHost, + const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -148,6 +149,7 @@ void computeCellsHandler(const Cluster** sortedClusters, CellSeed* cells, int** cellsLUTsDeviceArray, int* cellsLUTsHost, + const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -160,6 +162,8 @@ unsigned int countCellNeighboursHandler(CellSeed** cellsLayersDevice, int** cellsLUTs, gpuPair* cellNeighbours, int* neighboursIndexTable, + const Tracklet** tracklets, + const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, @@ -174,6 +178,8 @@ void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, int** cellsLUTs, gpuPair* cellNeighbours, int* neighboursIndexTable, + const Tracklet** tracklets, + const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index 82eb48a8a7663..eaa6080761fec 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -140,6 +140,7 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) nullptr, mTimeFrameGPU->getDeviceArrayCellsLUT(), mTimeFrameGPU->getDeviceCellLUTs()[iLayer], + this->mTrkParams[iteration].DeltaROF, this->mBz, this->mTrkParams[iteration].MaxChi2ClusterAttachment, this->mTrkParams[iteration].CellDeltaTanLambdaSigma, @@ -157,6 +158,7 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) mTimeFrameGPU->getDeviceCells()[iLayer], mTimeFrameGPU->getDeviceArrayCellsLUT(), mTimeFrameGPU->getDeviceCellLUTs()[iLayer], + this->mTrkParams[iteration].DeltaROF, this->mBz, this->mTrkParams[iteration].MaxChi2ClusterAttachment, this->mTrkParams[iteration].CellDeltaTanLambdaSigma, @@ -185,6 +187,8 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) mTimeFrameGPU->getDeviceArrayCellsLUT(), mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), mTimeFrameGPU->getDeviceNeighboursIndexTables(iLayer), + (const Tracklet**)mTimeFrameGPU->getDeviceArrayTracklets(), + this->mTrkParams[0].DeltaROF, this->mTrkParams[0].MaxChi2ClusterAttachment, this->mBz, iLayer, @@ -201,6 +205,8 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) mTimeFrameGPU->getDeviceArrayCellsLUT(), mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), mTimeFrameGPU->getDeviceNeighboursIndexTables(iLayer), + (const Tracklet**)mTimeFrameGPU->getDeviceArrayTracklets(), + this->mTrkParams[0].DeltaROF, this->mTrkParams[0].MaxChi2ClusterAttachment, this->mBz, iLayer, diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index fb75764da2e36..02be19b1e3a08 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -201,7 +201,13 @@ GPUd() o2::track::TrackParCov buildTrackSeed(const Cluster& cluster1, } struct sort_tracklets { - GPUhd() bool operator()(const Tracklet& a, const Tracklet& b) { return a.firstClusterIndex < b.firstClusterIndex || (a.firstClusterIndex == b.firstClusterIndex && a.secondClusterIndex < b.secondClusterIndex); } + GPUhd() bool operator()(const Tracklet& a, const Tracklet& b) + { + if (a.firstClusterIndex != b.firstClusterIndex) { + return a.firstClusterIndex < b.firstClusterIndex; + } + return a.secondClusterIndex < b.secondClusterIndex; + } }; struct equal_tracklets { @@ -263,23 +269,34 @@ struct compare_track_chi2 { } }; -GPUd() gpuSpan getPrimaryVertices(const int rof, - const int* roframesPV, - const int nROF, - const uint8_t* mask, - const Vertex* vertices) +GPUdii() gpuSpan getPrimaryVertices(const int rof, + const int* roframesPV, + const int nROF, + const uint8_t* mask, + const Vertex* vertices) { const int start_pv_id = roframesPV[rof]; const int stop_rof = rof >= nROF - 1 ? nROF : rof + 1; - size_t delta = mask[rof] ? roframesPV[stop_rof] - start_pv_id : 0; // return empty span if ROF is excluded + const size_t delta = mask[rof] ? roframesPV[stop_rof] - start_pv_id : 0; // return empty span if ROF is excluded return gpuSpan(&vertices[start_pv_id], delta); }; -GPUd() gpuSpan getClustersOnLayer(const int rof, - const int totROFs, - const int layer, - const int** roframesClus, - const Cluster** clusters) +GPUdii() gpuSpan getPrimaryVertices(const int romin, + const int romax, + const int* roframesPV, + const int nROF, + const Vertex* vertices) +{ + const int start_pv_id = roframesPV[romin]; + const int stop_rof = romax >= nROF - 1 ? nROF : romax + 1; + return gpuSpan(&vertices[start_pv_id], roframesPV[stop_rof] - roframesPV[romin]); +}; + +GPUdii() gpuSpan getClustersOnLayer(const int rof, + const int totROFs, + const int layer, + const int** roframesClus, + const Cluster** clusters) { if (rof < 0 || rof >= totROFs) { return gpuSpan(); @@ -360,6 +377,8 @@ GPUg() void computeLayerCellNeighboursKernel( int* neighboursIndexTable, int** cellsLUTs, gpuPair* cellNeighbours, + const Tracklet** tracklets, + const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, @@ -377,15 +396,29 @@ GPUg() void computeLayerCellNeighboursKernel( if (nextCellSeed.getFirstTrackletIndex() != nextLayerTrackletIndex) { // Check if cells share the same tracklet break; } + + if (deltaROF) { + const auto& trkl00 = tracklets[layerIndex][currentCellSeed.getFirstTrackletIndex()]; + const auto& trkl01 = tracklets[layerIndex + 1][currentCellSeed.getSecondTrackletIndex()]; + const auto& trkl10 = tracklets[layerIndex + 1][nextCellSeed.getFirstTrackletIndex()]; + const auto& trkl11 = tracklets[layerIndex + 2][nextCellSeed.getSecondTrackletIndex()]; + if ((o2::gpu::CAMath::Max(trkl00.getMaxRof(), o2::gpu::CAMath::Max(trkl01.getMaxRof(), o2::gpu::CAMath::Max(trkl10.getMaxRof(), trkl11.getMaxRof()))) - + o2::gpu::CAMath::Min(trkl00.getMinRof(), o2::gpu::CAMath::Min(trkl01.getMinRof(), o2::gpu::CAMath::Min(trkl10.getMinRof(), trkl11.getMinRof())))) > deltaROF) { + continue; + } + } + if (!nextCellSeed.rotate(currentCellSeed.getAlpha()) || !nextCellSeed.propagateTo(currentCellSeed.getX(), bz)) { continue; } + float chi2 = currentCellSeed.getPredictedChi2(nextCellSeed); if (chi2 > maxChi2ClusterAttachment) /// TODO: switch to the chi2 wrt cluster to avoid correlation { continue; } + if constexpr (initRun) { atomicAdd(neighboursLUT + iNextCell, 1); neighboursIndexTable[iCurrentCellIndex]++; @@ -412,6 +445,7 @@ GPUg() void computeLayerCellsKernel( const int layer, CellSeed* cells, int** cellsLUTs, + const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -432,6 +466,9 @@ GPUg() void computeLayerCellsKernel( break; } const Tracklet& nextTracklet = tracklets[layer + 1][iNextTrackletIndex]; + if (deltaROF && currentTracklet.getSpanRof(nextTracklet) > deltaROF) { + continue; + } const float deltaTanLambda{o2::gpu::CAMath::Abs(currentTracklet.tanLambda - nextTracklet.tanLambda)}; if (deltaTanLambda / cellDeltaTanLambdaSigma < nSigmaCut) { @@ -515,9 +552,12 @@ GPUg() void computeLayerTrackletsMultiROFKernel( { const int phiBins{utils->getNphiBins()}; const int zBins{utils->getNzBins()}; + const int tableSize{phiBins * zBins + 1}; for (unsigned int iROF{blockIdx.x}; iROF < endROF - startROF; iROF += gridDim.x) { - const short rof0 = iROF + startROF; - auto primaryVertices = getPrimaryVertices(rof0, rofPV, totalROFs, multMask, vertices); + const short pivotROF = iROF + startROF; + const short minROF = o2::gpu::CAMath::Max(startROF, static_cast(pivotROF - deltaROF)); + const short maxROF = o2::gpu::CAMath::Min(endROF - 1, static_cast(pivotROF + deltaROF)); + auto primaryVertices = getPrimaryVertices(minROF, maxROF, rofPV, totalROFs, vertices); if (primaryVertices.empty()) { continue; } @@ -526,17 +566,17 @@ GPUg() void computeLayerTrackletsMultiROFKernel( if ((endVtx - startVtx) <= 0) { continue; } - const short minROF = o2::gpu::CAMath::Max(startROF, static_cast(rof0 - deltaROF)); - const short maxROF = o2::gpu::CAMath::Min(endROF - 1, static_cast(rof0 + deltaROF)); - auto clustersCurrentLayer = getClustersOnLayer(rof0, totalROFs, layerIndex, ROFClusters, clusters); + + auto clustersCurrentLayer = getClustersOnLayer(pivotROF, totalROFs, layerIndex, ROFClusters, clusters); if (clustersCurrentLayer.empty()) { continue; } for (int currentClusterIndex = threadIdx.x; currentClusterIndex < clustersCurrentLayer.size(); currentClusterIndex += blockDim.x) { + unsigned int storedTracklets{0}; const auto& currentCluster{clustersCurrentLayer[currentClusterIndex]}; - const int currentSortedIndex{ROFClusters[layerIndex][rof0] + currentClusterIndex}; + const int currentSortedIndex{ROFClusters[layerIndex][pivotROF] + currentClusterIndex}; if (usedClusters[layerIndex][currentCluster.clusterId]) { continue; } @@ -564,9 +604,8 @@ GPUg() void computeLayerTrackletsMultiROFKernel( phiBinsNum += phiBins; } - const int tableSize{phiBins * zBins + 1}; - for (short rof1{minROF}; rof1 <= maxROF; ++rof1) { - auto clustersNextLayer = getClustersOnLayer(rof1, totalROFs, layerIndex + 1, ROFClusters, clusters); + for (short targetROF{minROF}; targetROF <= maxROF; ++targetROF) { + auto clustersNextLayer = getClustersOnLayer(targetROF, totalROFs, layerIndex + 1, ROFClusters, clusters); if (clustersNextLayer.empty()) { continue; } @@ -574,8 +613,8 @@ GPUg() void computeLayerTrackletsMultiROFKernel( int iPhiBin = (selectedBinsRect.y + iPhiCount) % phiBins; const int firstBinIndex{utils->getBinIndex(selectedBinsRect.x, iPhiBin)}; const int maxBinIndex{firstBinIndex + selectedBinsRect.z - selectedBinsRect.x + 1}; - const int firstRowClusterIndex = indexTables[layerIndex + 1][(rof1)*tableSize + firstBinIndex]; - const int maxRowClusterIndex = indexTables[layerIndex + 1][(rof1)*tableSize + maxBinIndex]; + const int firstRowClusterIndex = indexTables[layerIndex + 1][(targetROF)*tableSize + firstBinIndex]; + const int maxRowClusterIndex = indexTables[layerIndex + 1][(targetROF)*tableSize + maxBinIndex]; for (int nextClusterIndex{firstRowClusterIndex}; nextClusterIndex < maxRowClusterIndex; ++nextClusterIndex) { if (nextClusterIndex >= clustersNextLayer.size()) { break; @@ -592,8 +631,8 @@ GPUg() void computeLayerTrackletsMultiROFKernel( } else { const float phi{o2::gpu::CAMath::ATan2(currentCluster.yCoordinate - nextCluster.yCoordinate, currentCluster.xCoordinate - nextCluster.xCoordinate)}; const float tanL{(currentCluster.zCoordinate - nextCluster.zCoordinate) / (currentCluster.radius - nextCluster.radius)}; - const int nextSortedIndex{ROFClusters[layerIndex + 1][rof1] + nextClusterIndex}; - new (tracklets[layerIndex] + trackletsLUT[layerIndex][currentSortedIndex] + storedTracklets) Tracklet{currentSortedIndex, nextSortedIndex, tanL, phi, rof0, rof1}; + const int nextSortedIndex{ROFClusters[layerIndex + 1][targetROF] + nextClusterIndex}; + new (tracklets[layerIndex] + trackletsLUT[layerIndex][currentSortedIndex] + storedTracklets) Tracklet{currentSortedIndex, nextSortedIndex, tanL, phi, pivotROF, targetROF}; } ++storedTracklets; } @@ -1018,6 +1057,7 @@ void countCellsHandler( CellSeed* cells, int** cellsLUTsArrayDevice, int* cellsLUTsHost, + const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -1035,6 +1075,7 @@ void countCellsHandler( layer, // const int cells, // CellSeed* cellsLUTsArrayDevice, // int** + deltaROF, // const int bz, // const float maxChi2ClusterAttachment, // const float cellDeltaTanLambdaSigma, // const float @@ -1053,6 +1094,7 @@ void computeCellsHandler( CellSeed* cells, int** cellsLUTsArrayDevice, int* cellsLUTsHost, + const int deltaROF, const float bz, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, @@ -1070,6 +1112,7 @@ void computeCellsHandler( layer, // const int cells, // CellSeed* cellsLUTsArrayDevice, // int** + deltaROF, // const int bz, // const float maxChi2ClusterAttachment, // const float cellDeltaTanLambdaSigma, // const float @@ -1081,6 +1124,8 @@ unsigned int countCellNeighboursHandler(CellSeed** cellsLayersDevice, int** cellsLUTs, gpuPair* cellNeighbours, int* neighboursIndexTable, + const Tracklet** tracklets, + const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, @@ -1096,12 +1141,13 @@ unsigned int countCellNeighboursHandler(CellSeed** cellsLayersDevice, neighboursIndexTable, cellsLUTs, cellNeighbours, + tracklets, + deltaROF, maxChi2ClusterAttachment, bz, layerIndex, nCells, maxCellNeighbours); - gpu::cubInclusiveScanInPlace(neighboursLUT, nCellsNext); gpu::cubExclusiveScanInPlace(neighboursIndexTable, nCells + 1); unsigned int nNeighbours; @@ -1114,6 +1160,8 @@ void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, int** cellsLUTs, gpuPair* cellNeighbours, int* neighboursIndexTable, + const Tracklet** tracklets, + const int deltaROF, const float maxChi2ClusterAttachment, const float bz, const int layerIndex, @@ -1130,6 +1178,8 @@ void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, neighboursIndexTable, cellsLUTs, cellNeighbours, + tracklets, + deltaROF, maxChi2ClusterAttachment, bz, layerIndex, From 0e237624c33f47edd65930a27f6f7131fb827744 Mon Sep 17 00:00:00 2001 From: jmyrcha Date: Tue, 5 Aug 2025 09:01:12 +0200 Subject: [PATCH 199/315] added socket communication (#14529) * added socket communication * fixed timeout problem * changed Location parameter to reference * clang --------- Co-authored-by: Julian Myrcha --- .../DataConverter/CMakeLists.txt | 2 + .../Location.h | 70 +++++++ .../VisualisationEventJSONSerializer.h | 2 +- .../VisualisationEventOpenGLSerializer.h | 2 +- .../VisualisationEventROOTSerializer.h | 2 +- .../VisualisationEventSerializer.h | 3 +- .../DataConverter/src/Location.cxx | 182 ++++++++++++++++++ .../src/VisualisationEventJSONSerializer.cxx | 3 +- .../VisualisationEventOpenGLSerializer.cxx | 52 ++--- .../src/VisualisationEventROOTSerializer.cxx | 3 +- .../DataConverter/src/converter.cxx | 104 +++++++--- .../include/EveWorkflow/EveWorkflowHelper.h | 2 +- .../include/EveWorkflow/FileProducer.h | 5 +- .../include/EveWorkflow/O2DPLDisplay.h | 42 +++- .../Workflow/src/AO2DConverter.cxx | 4 +- .../Workflow/src/EveWorkflowHelper.cxx | 148 +++++++++----- .../Workflow/src/FileProducer.cxx | 14 +- .../Workflow/src/O2DPLDisplay.cxx | 17 +- 18 files changed, 536 insertions(+), 121 deletions(-) create mode 100644 EventVisualisation/DataConverter/include/EventVisualisationDataConverter/Location.h create mode 100644 EventVisualisation/DataConverter/src/Location.cxx diff --git a/EventVisualisation/DataConverter/CMakeLists.txt b/EventVisualisation/DataConverter/CMakeLists.txt index 778a3b6182aaf..b0198000c3dbe 100644 --- a/EventVisualisation/DataConverter/CMakeLists.txt +++ b/EventVisualisation/DataConverter/CMakeLists.txt @@ -18,6 +18,7 @@ o2_add_library(EventVisualisationDataConverter src/VisualisationEventJSONSerializer.cxx src/VisualisationEventROOTSerializer.cxx src/VisualisationEventOpenGLSerializer.cxx + src/Location.cxx PUBLIC_LINK_LIBRARIES RapidJSON::RapidJSON O2::ReconstructionDataFormats O2::DataFormatsParameters @@ -33,6 +34,7 @@ o2_add_executable(eve-convert src/VisualisationTrack.cxx src/VisualisationCluster.cxx src/VisualisationCalo.cxx + src/Location.cxx PUBLIC_LINK_LIBRARIES O2::EventVisualisationView RapidJSON::RapidJSON diff --git a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/Location.h b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/Location.h new file mode 100644 index 0000000000000..72ebc36b1dd31 --- /dev/null +++ b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/Location.h @@ -0,0 +1,70 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file Location.h +/// \author Julian Myrcha +/// + +#ifndef O2EVE_LOCATION_H +#define O2EVE_LOCATION_H + +#include +#include +#include + +namespace o2::event_visualisation +{ +struct LocationParams { + std::string fileName; + int port = -1; + int timeout = 100; + std::string host = "localhost"; + bool toFile = true; + bool toSocket = true; +}; +class Location +{ + std::ofstream* mOut; + int mClientSocket; + bool mToFile; + bool mToSocket; + std::string mFileName; + int mPort; + int mTimeout; + std::string mHostName; + + public: + explicit Location(const LocationParams& params) + { + this->mFileName = params.fileName; + this->mToFile = !params.fileName.empty() && params.toFile; + this->mToSocket = params.port != -1 && params.toSocket; + this->mOut = nullptr; + this->mPort = params.port; + this->mHostName = params.host; + this->mClientSocket = -1; + this->mTimeout = params.timeout; + } + ~Location() + { + close(); + } + void open(); + void close(); + void write(char* buf, std::streamsize size); + [[nodiscard]] std::string fileName() const { return this->mFileName; } + [[nodiscard]] std::string hostName() const { return this->mHostName; } + [[nodiscard]] int port() const { return this->mPort; } +}; +} // namespace o2::event_visualisation + +#endif // O2EVE_LOCATION_H diff --git a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventJSONSerializer.h b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventJSONSerializer.h index c08009215d9fe..8f4b0d2bd8375 100644 --- a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventJSONSerializer.h +++ b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventJSONSerializer.h @@ -56,7 +56,7 @@ class VisualisationEventJSONSerializer : public VisualisationEventSerializer public: bool fromFile(VisualisationEvent& event, std::string fileName) override; - void toFile(const VisualisationEvent& event, std::string fileName) override; + void toFile(const VisualisationEvent& event, Location& location) override; ~VisualisationEventJSONSerializer() override = default; }; diff --git a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventOpenGLSerializer.h b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventOpenGLSerializer.h index 3e6d3809cb709..8af91d6964a46 100644 --- a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventOpenGLSerializer.h +++ b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventOpenGLSerializer.h @@ -38,7 +38,7 @@ class VisualisationEventOpenGLSerializer : public VisualisationEventSerializer public: const std::string serializerName() const override { return std::string("VisualisationEventOpenGLSerializer"); } bool fromFile(VisualisationEvent& event, std::string fileName) override; - void toFile(const VisualisationEvent& event, std::string fileName) override; + void toFile(const VisualisationEvent& event, Location& location) override; ~VisualisationEventOpenGLSerializer() override = default; }; diff --git a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventROOTSerializer.h b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventROOTSerializer.h index e6408fb1c6c3f..3a5cf245f4816 100644 --- a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventROOTSerializer.h +++ b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventROOTSerializer.h @@ -44,7 +44,7 @@ class VisualisationEventROOTSerializer : public VisualisationEventSerializer public: [[nodiscard]] const std::string serializerName() const override { return std::string("VisualisationEventROOTSerializer"); } bool fromFile(VisualisationEvent& event, std::string fileName) override; - void toFile(const VisualisationEvent& event, std::string fileName) override; + void toFile(const VisualisationEvent& event, Location& location) override; ~VisualisationEventROOTSerializer() override = default; }; diff --git a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventSerializer.h b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventSerializer.h index 5a6d902084ebf..80cb3c0b131a0 100644 --- a/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventSerializer.h +++ b/EventVisualisation/DataConverter/include/EventVisualisationDataConverter/VisualisationEventSerializer.h @@ -17,6 +17,7 @@ #define O2EVE_VISUALISATIONEVENTSERIALIZER_H #include "EventVisualisationDataConverter/VisualisationEvent.h" +#include "EventVisualisationDataConverter/Location.h" #include #include @@ -45,7 +46,7 @@ class VisualisationEventSerializer static o2::dataformats::GlobalTrackID deserialize(unsigned source, unsigned index, unsigned flags); static VisualisationEventSerializer* getInstance(std::string ext) { return instances[ext]; } virtual bool fromFile(VisualisationEvent& event, std::string fileName) = 0; - virtual void toFile(const VisualisationEvent& event, std::string fileName) = 0; + virtual void toFile(const VisualisationEvent& event, Location& location) = 0; virtual const std::string serializerName() const = 0; virtual ~VisualisationEventSerializer() = default; }; diff --git a/EventVisualisation/DataConverter/src/Location.cxx b/EventVisualisation/DataConverter/src/Location.cxx new file mode 100644 index 0000000000000..416412c742252 --- /dev/null +++ b/EventVisualisation/DataConverter/src/Location.cxx @@ -0,0 +1,182 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file Location.cxx +/// \author Julian Myrcha +/// + +#include "EventVisualisationDataConverter/Location.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace o2::event_visualisation +{ + +int connect_with_timeout(const int socket, const struct sockaddr* addr, socklen_t addrlen, const unsigned int timeout_ms) +{ + int connection = 0; + // Setting O_NONBLOCK + int socket_flags_before; + if ((socket_flags_before = fcntl(socket, F_GETFL, 0) < 0)) { + return -1; + } + if (fcntl(socket, F_SETFL, socket_flags_before | O_NONBLOCK) < 0) { + return -1; + } + do { + if (connect(socket, addr, addrlen) < 0) { + if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) { + connection = -1; // error + } else { // wait for complete + // deadline 'timeout' ms from now + timespec now; // NOLINT(*-pro-type-member-init) + if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) { + connection = -1; + break; + } + const timespec deadline = {.tv_sec = now.tv_sec, + .tv_nsec = now.tv_nsec + timeout_ms * 1000000l}; + do { + if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) { + connection = -1; + break; + } + // compute remaining deadline + const int ms_until_deadline = static_cast((deadline.tv_sec - now.tv_sec) * 1000l + (deadline.tv_nsec - now.tv_nsec) / 1000000l); + if (ms_until_deadline < 0) { + connection = 0; + break; + } + pollfd connectionPool[] = {{.fd = socket, .events = POLLOUT}}; + connection = poll(connectionPool, 1, ms_until_deadline); + + if (connection > 0) { // confirm the success + int error = 0; + socklen_t len = sizeof(error); + if (getsockopt(socket, SOL_SOCKET, SO_ERROR, &error, &len) == 0) { + errno = error; + } + if (error != 0) { + connection = -1; + } + } + } while (connection == -1 && errno == EINTR); // If interrupted, try again. + if (connection == 0) { + errno = ETIMEDOUT; + connection = -1; + } + } + } + } while (false); + // Restore socket state + if (fcntl(socket, F_SETFL, socket_flags_before) < 0) { + return -1; + } + return connection; +} + +void Location::open() +{ + if (this->mToFile) { + this->mOut = new std::ofstream(mFileName, std::ios::out | std::ios::binary); + } + if (this->mToSocket) { + // resolve host name + sockaddr_in serverAddress; // NOLINT(*-pro-type-member-init) + serverAddress.sin_family = AF_INET; + serverAddress.sin_port = htons(this->mPort); // Port number + + // ask once + static auto server = gethostbyname(this->mHostName.c_str()); + if (server == nullptr) { + LOGF(info, "Error no such host %s", this->mHostName.c_str()); + return; + }; + + bcopy((char*)server->h_addr, + (char*)&serverAddress.sin_addr.s_addr, + server->h_length); + + // Connect to the server + this->mClientSocket = socket(AF_INET, SOCK_STREAM, 0); + if (this->mClientSocket == -1) { + LOGF(info, "Error creating socket"); + return; + } + + if (connect_with_timeout(this->mClientSocket, (sockaddr*)&serverAddress, + sizeof(serverAddress), this->mTimeout) == -1) { + LOGF(info, "Error connecting to %s:%d", this->mHostName.c_str(), this->mPort); + ::close(this->mClientSocket); + this->mClientSocket = -1; + return; + } + try { + char buf[256] = "SEND:"; + strncpy(buf + 6, this->mFileName.c_str(), sizeof(buf) - 7); + strncpy(buf + sizeof(buf) - 6, "ALICE", 6); + auto real = send(this->mClientSocket, buf, sizeof(buf), 0); + if (real != sizeof(buf)) { + throw real; + } + } catch (...) { + ::close(this->mClientSocket); + this->mClientSocket = -1; + LOGF(info, "Error sending file name to %s:%d", this->mHostName.c_str(), this->mPort); + } + } +} + +void Location::close() +{ + if (this->mToFile && this->mOut) { + this->mOut->close(); + delete this->mOut; + this->mOut = nullptr; + } + if (this->mToSocket && this->mClientSocket != -1) { + ::close(this->mClientSocket); + this->mClientSocket = -1; + } +} + +void Location::write(char* buf, std::streamsize size) +{ + if (size == 0) { + return; + } + if (this->mToFile && this->mOut) { + this->mOut->write(buf, size); + } + if (this->mToSocket && this->mClientSocket != -1) { + LOGF(info, "Location::write() socket %s ++++++++++++++++++++++", fileName()); + try { + auto real = send(this->mClientSocket, buf, size, 0); + if (real != size) { + throw real; + } + } catch (...) { + ::close(this->mClientSocket); + this->mClientSocket = -1; + LOGF(info, "Error sending data to %s:%d", this->mHostName.c_str(), this->mPort); + } + } +} + +} // namespace o2::event_visualisation \ No newline at end of file diff --git a/EventVisualisation/DataConverter/src/VisualisationEventJSONSerializer.cxx b/EventVisualisation/DataConverter/src/VisualisationEventJSONSerializer.cxx index 612ddaf8717f4..cce3e6b4a2c58 100644 --- a/EventVisualisation/DataConverter/src/VisualisationEventJSONSerializer.cxx +++ b/EventVisualisation/DataConverter/src/VisualisationEventJSONSerializer.cxx @@ -29,8 +29,9 @@ using namespace rapidjson; namespace o2::event_visualisation { -void VisualisationEventJSONSerializer::toFile(const VisualisationEvent& event, std::string fileName) +void VisualisationEventJSONSerializer::toFile(const VisualisationEvent& event, Location& location) { + std::string fileName = location.fileName(); std::string json = toJson(event); std::ofstream out(fileName); out << json; diff --git a/EventVisualisation/DataConverter/src/VisualisationEventOpenGLSerializer.cxx b/EventVisualisation/DataConverter/src/VisualisationEventOpenGLSerializer.cxx index 4c907eeda0291..1d22a02df61af 100644 --- a/EventVisualisation/DataConverter/src/VisualisationEventOpenGLSerializer.cxx +++ b/EventVisualisation/DataConverter/src/VisualisationEventOpenGLSerializer.cxx @@ -20,6 +20,7 @@ #include #include #include +#include "EventVisualisationDataConverter/Location.h" namespace o2::event_visualisation { @@ -82,8 +83,9 @@ const auto CALT = "CALT"; // calo PID const auto FINE = "FINE"; // -void VisualisationEventOpenGLSerializer::toFile(const VisualisationEvent& event, std::string fileName) +void VisualisationEventOpenGLSerializer::toFile(const VisualisationEvent& event, Location& location) { + std::string fileName = location.fileName(); static const std::vector det_coma = { "ITS", "TPC", "TRD", "TOF", "PHS", "CPV", "EMC", "HMP", "MFT", "MCH", "MID", "ZDC", "FT0", "FV0", "FDD", "ITS-TPC", "TPC-TOF", "TPC-TRD", "MFT-MCH", "ITS-TPC-TRD", "ITS-TPC-TOF", "TPC-TRD-TOF", "MFT-MCH-MID", "ITS-TPC-TRD-TOF", "ITS-AB", "CTP", @@ -91,7 +93,9 @@ void VisualisationEventOpenGLSerializer::toFile(const VisualisationEvent& event, std::ostringstream buf; constexpr auto SIGSIZE = 512; unsigned char data[SIGSIZE]; - std::ofstream out(fileName, std::ios::out | std::ios::binary); + // std::ofstream out(fileName, std::ios::out | std::ios::binary); + + location.open(); // head --bytes 512 fileName.eve buf << "eve" << std::endl; buf << "version=1.00" << std::endl; @@ -104,7 +108,7 @@ void VisualisationEventOpenGLSerializer::toFile(const VisualisationEvent& event, memcpy((char*)&data[0], buf.str().c_str(), SIGSIZE); data[SIGSIZE - 2] = '\n'; data[SIGSIZE - 1] = 0; - out.write((char*)&data[0], SIGSIZE); // <----0 SIGN + location.write((char*)&data[0], SIGSIZE); // <----0 SIGN const auto trackNo = event.getTracksSpan().size(); int phsCount = 0; @@ -140,7 +144,7 @@ void VisualisationEventOpenGLSerializer::toFile(const VisualisationEvent& event, head[Header::emcCount] = emcCount; head[Header::primaryVertex] = event.getPrimaryVertex(); head[Header::tfCounter] = event.getTfCounter(); - out.write(static_cast(chunkHEAD), chunkSize(chunkHEAD)); // <----1 HEAD + location.write(static_cast(chunkHEAD), chunkSize(chunkHEAD)); // <----1 HEAD free(chunkHEAD); } @@ -171,15 +175,15 @@ void VisualisationEventOpenGLSerializer::toFile(const VisualisationEvent& event, celm[index] = track.getClusterCount(); index++; } - out.write(static_cast(chunkTTYP), chunkSize(chunkTTYP)); // <----2 TTYP + location.write(static_cast(chunkTTYP), chunkSize(chunkTTYP)); // <----2 TTYP free(chunkTTYP); - out.write(static_cast(chunkTELM), chunkSize(chunkTELM)); // <----3 TELM + location.write(static_cast(chunkTELM), chunkSize(chunkTELM)); // <----3 TELM free(chunkTELM); - out.write(static_cast(chunkCELM), chunkSize(chunkCELM)); // <----3 CELM + location.write(static_cast(chunkCELM), chunkSize(chunkCELM)); // <----3 CELM free(chunkCELM); - out.write(static_cast(chunkTGID), chunkSize(chunkTGID)); // <----3 GIND + location.write(static_cast(chunkTGID), chunkSize(chunkTGID)); // <----3 GIND free(chunkTGID); - out.write(static_cast(chunkTPID), chunkSize(chunkTPID)); // <----3 TPID (tracks pid) + location.write(static_cast(chunkTPID), chunkSize(chunkTPID)); // <----3 TPID (tracks pid) free(chunkTPID); } @@ -230,17 +234,17 @@ void VisualisationEventOpenGLSerializer::toFile(const VisualisationEvent& event, cxyz[cidx++] = track.getClustersSpan()[i].Z(); } } - out.write(static_cast(chunkTXYZ), chunkSize(chunkTXYZ)); // <----4 TXYZ + location.write(static_cast(chunkTXYZ), chunkSize(chunkTXYZ)); // <----4 TXYZ free(chunkTXYZ); - out.write(static_cast(chunkCXYZ), chunkSize(chunkCXYZ)); // <----4 CXYZ + location.write(static_cast(chunkCXYZ), chunkSize(chunkCXYZ)); // <----4 CXYZ free(chunkCXYZ); - out.write(static_cast(chunkTIME), chunkSize(chunkTIME)); // <----4 TIME + location.write(static_cast(chunkTIME), chunkSize(chunkTIME)); // <----4 TIME free(chunkTIME); - out.write(static_cast(chunkSXYZ), chunkSize(chunkSXYZ)); // <----4 SXYZ + location.write(static_cast(chunkSXYZ), chunkSize(chunkSXYZ)); // <----4 SXYZ free(chunkSXYZ); - out.write(static_cast(chunkCRGE), chunkSize(chunkCRGE)); // <----4 CRGE + location.write(static_cast(chunkCRGE), chunkSize(chunkCRGE)); // <----4 CRGE free(chunkCRGE); - out.write(static_cast(chunkATPE), chunkSize(chunkATPE)); // <----4 CRGE + location.write(static_cast(chunkATPE), chunkSize(chunkATPE)); // <----4 CRGE free(chunkATPE); } @@ -260,11 +264,11 @@ void VisualisationEventOpenGLSerializer::toFile(const VisualisationEvent& event, uxyz[idx++] = c.Y(); uxyz[idx++] = c.Z(); } - out.write(static_cast(chunkUGID), chunkSize(chunkUGID)); // + location.write(static_cast(chunkUGID), chunkSize(chunkUGID)); // free(chunkUGID); - out.write(static_cast(chunkUTIM), chunkSize(chunkUTIM)); // + location.write(static_cast(chunkUTIM), chunkSize(chunkUTIM)); // free(chunkUTIM); - out.write(static_cast(chunkUXYZ), chunkSize(chunkUXYZ)); // + location.write(static_cast(chunkUXYZ), chunkSize(chunkUXYZ)); // free(chunkUXYZ); } @@ -300,22 +304,22 @@ void VisualisationEventOpenGLSerializer::toFile(const VisualisationEvent& event, } } - out.write((char*)chunkCALO, chunkSize(chunkCALO)); // + location.write((char*)chunkCALO, chunkSize(chunkCALO)); // free(chunkCALO); - out.write((char*)chunkCALP, chunkSize(chunkCALP)); // + location.write((char*)chunkCALP, chunkSize(chunkCALP)); // free(chunkCALP); - out.write((char*)chunkCALG, chunkSize(chunkCALG)); // + location.write((char*)chunkCALG, chunkSize(chunkCALG)); // free(chunkCALG); - out.write((char*)chunkCALT, chunkSize(chunkCALT)); // + location.write((char*)chunkCALT, chunkSize(chunkCALT)); // free(chunkCALT); } { const auto chunkFINE = createChunk(FINE, 0); - out.write(static_cast(chunkFINE), chunkSize(chunkFINE)); // <----5 FINE + location.write(static_cast(chunkFINE), chunkSize(chunkFINE)); // <----5 FINE free(chunkFINE); } - out.close(); + location.close(); } void* VisualisationEventOpenGLSerializer::createChunk(const char* lbl, unsigned size) diff --git a/EventVisualisation/DataConverter/src/VisualisationEventROOTSerializer.cxx b/EventVisualisation/DataConverter/src/VisualisationEventROOTSerializer.cxx index 730af08b5fd61..8c1a84c1bf85e 100644 --- a/EventVisualisation/DataConverter/src/VisualisationEventROOTSerializer.cxx +++ b/EventVisualisation/DataConverter/src/VisualisationEventROOTSerializer.cxx @@ -93,8 +93,9 @@ bool VisualisationEventROOTSerializer::existUInt64(TFile& f, const char* name) return true; } -void VisualisationEventROOTSerializer::toFile(const VisualisationEvent& event, std::string fileName) +void VisualisationEventROOTSerializer::toFile(const VisualisationEvent& event, Location& location) { + std::string fileName = location.fileName(); TFile f(fileName.c_str(), "recreate"); saveInt("runNumber", event.mRunNumber); diff --git a/EventVisualisation/DataConverter/src/converter.cxx b/EventVisualisation/DataConverter/src/converter.cxx index a0820d2e6feef..7bbada4bbb5e9 100644 --- a/EventVisualisation/DataConverter/src/converter.cxx +++ b/EventVisualisation/DataConverter/src/converter.cxx @@ -16,31 +16,40 @@ #include "EventVisualisationDataConverter/VisualisationEvent.h" #include "EventVisualisationView/Initializer.h" #include "EventVisualisationView/Options.h" +#include #include #include #include #include -#include #include -#include #include #include #include #include #include +#include +#include +#include + using namespace std::chrono_literals; // source file name, destination (not existing) file name, if limit > 0 then limit EACH type of data -int singleFileConversion(const std::string& src, const std::string& dst, const int limit = -1) +int singleFileConversion(const std::string& src, o2::event_visualisation::Location& dst, const int limit = -1) { - LOGF(info, "Translate: %s -> %s", src, dst); + LOGF(info, "Translate: %s -> %s", src, dst.fileName()); o2::event_visualisation::VisualisationEvent vEvent; auto srcSerializer = o2::event_visualisation::VisualisationEventSerializer::getInstance( std::filesystem::path(src).extension()); + auto dstExtension = std::filesystem::path( + src) + .extension(); // if there is no destination, there will be no extension change + if (!dst.fileName().empty()) { + dstExtension = std::filesystem::path(dst.fileName()).extension(); + } auto dstSerializer = o2::event_visualisation::VisualisationEventSerializer::getInstance( - std::filesystem::path(dst).extension()); + dstExtension); std::chrono::time_point currentTime = std::chrono::high_resolution_clock::now(); std::chrono::time_point endTime = std::chrono::high_resolution_clock::now(); @@ -61,8 +70,9 @@ int singleFileConversion(const std::string& src, const std::string& dst, const i // reads source folder files, find missing files in destination folder and convert them // source folder (/path-to-folder/.ext1) , destination folder (/path-to-folder/.ext2) -int folderConversion(const std::string& srcFolder, const std::string& dstFolder) +int folderConversion(const std::string& srcFolder, const o2::event_visualisation::Location& dstFolderLocation) { + const std::string dstFolder = dstFolderLocation.fileName(); std::vector supported = {".json", ".root", ".eve"}; auto ext1 = srcFolder.substr(srcFolder.rfind('.')); auto ext2 = dstFolder.substr(dstFolder.rfind('.')); @@ -109,7 +119,13 @@ int folderConversion(const std::string& srcFolder, const std::string& dstFolder) auto match = e.substr(0, e.size() - ext1.size()) + ext2; if (destinationList.end() == std::find(destinationList.begin(), destinationList.end(), match)) { // LOGF(info, "translate %s ->%s", src+e, dst+match); - singleFileConversion(src + e, dst + match); + o2::event_visualisation::Location location({.fileName = dst + match, + .port = dstFolderLocation.port(), + .host = dstFolderLocation.hostName()}); + singleFileConversion(src + e, location); + ; + singleFileConversion(src + e, location); + ; } } @@ -122,6 +138,10 @@ void my_handler(int s) exit(1); } +namespace po = boost::program_options; + +using namespace std; + int main(int argc, char** argv) { struct sigaction sigIntHandler { @@ -133,25 +153,59 @@ int main(int argc, char** argv) sigaction(SIGINT, &sigIntHandler, nullptr); LOGF(info, "Welcome in O2 event conversion tool"); - if (argc == 3) { - singleFileConversion(argv[1], argv[2]); // std::quick_exit(... - return 0; - } - if (argc == 4 and std::string(argv[1]) == std::string("-l")) { - singleFileConversion(argv[2], argv[3], 3); // std::quick_exit(... - return 0; - } - if (argc == 4 and std::string(argv[1]) == std::string("-f")) { - folderConversion(argv[2], argv[3]); // std::quick_exit(... - return 0; - } - if (argc == 4 and std::string(argv[1]) == std::string("-c")) { - while (true) { - std::this_thread::sleep_for(2000ms); - folderConversion(argv[2], argv[3]); + try { + int port; + string host; + int limit; + bool folderMode; + bool continuousMode; + vector sources; + po::options_description desc("Allowed options"); + desc.add_options()("help,h", "produce help message")("port", po::value(&port)->default_value(-1), "port number")("host", po::value(&host)->default_value("localhost"), "host name")("sources", po::value(&sources), "sources")("limit,l", po::value(&limit)->default_value(-1), "limit number of elements")("folder,f", po::bool_switch(&folderMode)->default_value(false), "convert folders")("continuous,c", po::bool_switch(&continuousMode)->default_value(false), "continuous folder mode"); + + po::positional_options_description p; + p.add("sources", 2); + + po::variables_map vm; + po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); + po::notify(vm); + + if (vm.count("help")) { + cout << desc << "\n"; + return 0; + } + + if (vm.count("sources")) { + if (vm["sources"].as>().size() != 2) { + cout << "two positional parameters expected" << "\n"; + return 0; + } } - return 0; + o2::event_visualisation::LocationParams locationParams; + locationParams.fileName = sources[1]; + locationParams.port = port; + locationParams.host = host; + + o2::event_visualisation::Location location(locationParams); + + if (folderMode) { + folderConversion(sources[0], location); + } else if (continuousMode) { + while (true) { + std::this_thread::sleep_for(2000ms); + folderConversion(sources[0], location); + } + } else { + singleFileConversion(sources[0], location, limit); + return 0; + } + } + + catch (exception& e) { + cerr << "error: " << e.what() << "\n"; + return 1; + } catch (...) { + cerr << "Exception of unknown type!\n"; } - LOGF(error, "two filename required, second should point to not existent file"); return -1; // std::quick_exit(-1); } diff --git a/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h b/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h index 1043ed5c303e0..6b3ec653c5350 100644 --- a/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h +++ b/EventVisualisation/Workflow/include/EveWorkflow/EveWorkflowHelper.h @@ -183,7 +183,7 @@ class EveWorkflowHelper bool isInsideITSROF(float t); bool isInsideTimeBracket(float t); - void save(const std::string& jsonPath, const std::string& ext, int numberOfFiles); + void save(const std::string& jsonPath, const std::string& ext, int numberOfFiles, const std::string& receiverHostname, int receiverPort, int receiverTimeout, bool useOnlyFiles, bool useOnlySockets); bool mUseTimeBracket = false; bool mUseEtaBracketTPC = false; diff --git a/EventVisualisation/Workflow/include/EveWorkflow/FileProducer.h b/EventVisualisation/Workflow/include/EveWorkflow/FileProducer.h index d35ddcaa78711..e7203baceba2a 100644 --- a/EventVisualisation/Workflow/include/EveWorkflow/FileProducer.h +++ b/EventVisualisation/Workflow/include/EveWorkflow/FileProducer.h @@ -26,16 +26,15 @@ namespace event_visualisation class FileProducer { private: - size_t mFilesInFolder; std::string mPath; std::string mName; std::string mExt; public: - explicit FileProducer(const std::string& path, const std::string& ext, int filesInFolder = -1, - const std::string& name = "tracks_{timestamp}_{hostname}_{pid}{ext}"); + explicit FileProducer(const std::string& path, const std::string& ext, const std::string& name = "tracks_{timestamp}_{hostname}_{pid}{ext}"); [[nodiscard]] std::string newFileName() const; + void reduceNumberOfFiles(size_t filesInFolder) const; }; } // namespace event_visualisation diff --git a/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h b/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h index 1156d31d190ea..37d4155803e85 100644 --- a/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h +++ b/EventVisualisation/Workflow/include/EveWorkflow/O2DPLDisplay.h @@ -50,7 +50,8 @@ class TPCFastTransform; class O2DPLDisplaySpec : public o2::framework::Task { public: - static constexpr auto allowedTracks = "ITS,TPC,MFT,MCH,MID,ITS-TPC,TPC-TRD,ITS-TPC-TOF,ITS-TPC-TRD,ITS-TPC-TRD-TOF,MCH-MID,MFT-MCH,MFT-MCH-MID,PHS,EMC,HMP"; + static constexpr auto allowedTracks = + "ITS,TPC,MFT,MCH,MID,ITS-TPC,TPC-TRD,ITS-TPC-TOF,ITS-TPC-TRD,ITS-TPC-TRD-TOF,MCH-MID,MFT-MCH,MFT-MCH-MID,PHS,EMC,HMP"; static constexpr auto allowedClusters = "ITS,TPC,TRD,TOF,MFT,MCH,MID,PHS,EMC,HMP"; O2DPLDisplaySpec(bool disableWrite, bool useMC, o2::dataformats::GlobalTrackID::mask_t trkMask, @@ -60,12 +61,33 @@ class O2DPLDisplaySpec : public o2::framework::Task std::shared_ptr emcCalibLoader, const std::string& jsonPath, const std::string& ext, std::chrono::milliseconds timeInterval, - bool eveHostNameMatch) - : mDisableWrite(disableWrite), mUseMC(useMC), mTrkMask(trkMask), mClMask(clMask), mDataRequest(dataRequest), mGGCCDBRequest(gr), mEMCALCalibLoader(emcCalibLoader), mJsonPath(jsonPath), mExt(ext), mTimeInterval(timeInterval), mEveHostNameMatch(eveHostNameMatch), mRunType(o2::parameters::GRPECS::NONE) - + bool eveHostNameMatch, + const std::string& receiverHostname, + int receiverPort, + int receiverTimeout, + bool useOnlyFiles, + bool useOnlySockets) + : mDisableWrite(disableWrite), + mUseMC(useMC), + mTrkMask(trkMask), + mClMask(clMask), + mDataRequest(dataRequest), + mGGCCDBRequest(gr), + mEMCALCalibLoader(emcCalibLoader), + mJsonPath(jsonPath), + mExt(ext), + mTimeInterval(timeInterval), + mEveHostNameMatch(eveHostNameMatch), + mRunType(o2::parameters::GRPECS::NONE), + mReceiverHostname(receiverHostname), + mReceiverPort(receiverPort), + mReceiverTimeout(receiverTimeout), + mUseOnlyFiles(useOnlyFiles), + mUseOnlySockets(useOnlySockets) { this->mTimeStamp = std::chrono::high_resolution_clock::now() - timeInterval; // first run meets condition } + ~O2DPLDisplaySpec() override = default; void init(o2::framework::InitContext& ic) final; void run(o2::framework::ProcessingContext& pc) final; @@ -81,7 +103,8 @@ class O2DPLDisplaySpec : public o2::framework::Task std::string mJsonPath; // folder where files are stored std::string mExt; // extension of created files (".json" or ".root") std::chrono::milliseconds mTimeInterval; // minimal interval between files in milliseconds - bool mPrimaryVertexTriggers; // instead of drawing vertices with tracks (and maybe calorimeter triggers), draw vertices with calorimeter triggers (and maybe tracks) + bool mPrimaryVertexTriggers; + // instead of drawing vertices with tracks (and maybe calorimeter triggers), draw vertices with calorimeter triggers (and maybe tracks) int mEventCounter = 0; std::chrono::time_point mTimeStamp; @@ -94,8 +117,13 @@ class O2DPLDisplaySpec : public o2::framework::Task std::shared_ptr mEMCALCalibLoader; std::unique_ptr mEMCALCalibrator; o2::tpc::VDriftHelper mTPCVDriftHelper{}; -}; + std::string mReceiverHostname; + int mReceiverPort; + int mReceiverTimeout; + bool mUseOnlyFiles; + bool mUseOnlySockets; +}; } // namespace o2::event_visualisation -#endif +#endif \ No newline at end of file diff --git a/EventVisualisation/Workflow/src/AO2DConverter.cxx b/EventVisualisation/Workflow/src/AO2DConverter.cxx index d339b150265de..f54907c20d260 100644 --- a/EventVisualisation/Workflow/src/AO2DConverter.cxx +++ b/EventVisualisation/Workflow/src/AO2DConverter.cxx @@ -74,8 +74,8 @@ struct AO2DConverter { mHelper->mEvent.setTfCounter(mTfCounter); mHelper->mEvent.setFirstTForbit(mTfOrbit); mHelper->mEvent.setCreationTime(collision.collisionTime()); - - mHelper->save(jsonPath, ".root", -1); + const std::string hostname("localhost"); + mHelper->save(jsonPath, ".root", -1, hostname, -1, 100, true, true); mHelper->clear(); } }; diff --git a/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx b/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx index 8c795dd01c79f..2bb3c220d67a0 100644 --- a/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx +++ b/EventVisualisation/Workflow/src/EveWorkflowHelper.cxx @@ -23,6 +23,7 @@ #include "ITStracking/IOUtils.h" #include "MFTTracking/IOUtils.h" #include "DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h" +#include "DataFormatsMID/Track.h" #include "ReconstructionDataFormats/PrimaryVertex.h" #include "DetectorsBase/GRPGeomHelper.h" #include "DetectorsBase/Propagator.h" @@ -120,7 +121,8 @@ double EveWorkflowHelper::bcDiffToTFTimeMUS(const o2::InteractionRecord& ir) auto bcd = ir.differenceInBC(startIR); if (uint64_t(bcd) > o2::constants::lhc::LHCMaxBunches * 256 && BCDiffErrCount < MAXBCDiffErrCount) { - LOGP(alarm, "ATTENTION: wrong bunches diff. {} for current IR {} wrt 1st TF orbit {}", bcd, ir.asString(), startIR.asString()); + LOGP(alarm, "ATTENTION: wrong bunches diff. {} for current IR {} wrt 1st TF orbit {}", bcd, ir.asString(), + startIR.asString()); BCDiffErrCount++; } @@ -162,12 +164,14 @@ void EveWorkflowHelper::selectTracks(const CalibObjectsConst* calib, t0 *= this->mTPCBin2MUS; terr *= this->mTPCBin2MUS; } else if constexpr (isITSTrack()) { - t0 += 0.5f * this->mITSROFrameLengthMUS; // ITS time is supplied in \mus as beginning of ROF - terr *= this->mITSROFrameLengthMUS; // error is supplied as a half-ROF duration, convert to \mus - } else if constexpr (isMFTTrack()) { // Same for MFT + t0 += 0.5f * this->mITSROFrameLengthMUS; // ITS time is supplied in \mus as beginning of ROF + terr *= this->mITSROFrameLengthMUS; // error is supplied as a half-ROF duration, convert to \mus + } else if constexpr (isMFTTrack()) { + // Same for MFT t0 += 0.5f * this->mMFTROFrameLengthMUS; terr *= this->mMFTROFrameLengthMUS; - } else if constexpr (!(isMCHTrack() || isMIDTrack() || isGlobalFwdTrack())) { + } else if constexpr (!(isMCHTrack() || isMIDTrack() || + isGlobalFwdTrack())) { // for all other tracks the time is in \mus with gaussian error terr *= mPVParams->nSigmaTimeTrack; // gaussian errors must be scaled by requested n-sigma } @@ -197,7 +201,8 @@ void EveWorkflowHelper::selectTracks(const CalibObjectsConst* calib, } } }; - auto creator = [&conf, maskTrk, this, &correctTrackTime, &flagTime, &fixMFTMCHMIDLabel](auto& trk, GID gid, float time, float terr) { + auto creator = [&conf, maskTrk, this, &correctTrackTime, &flagTime, &fixMFTMCHMIDLabel](auto& trk, GID gid, + float time, float terr) { fixMFTMCHMIDLabel(gid); const auto src = gid.getSource(); @@ -234,7 +239,8 @@ void EveWorkflowHelper::selectTracks(const CalibObjectsConst* calib, bool checkTPCDCA = conf.TPCOnlyMaxDCARZ[0] > 0.f || conf.TPCOnlyMaxDCARZ[1] > 0.f; const auto trackIndex = mRecoCont->getPrimaryVertexMatchedTracks(); // Global ID's for associated tracks const auto vtxRefs = mRecoCont->getPrimaryVertexMatchedTrackRefs(); // references from vertex to these track IDs - const auto totalPrimaryVertices = vtxRefs.size() - 1; // The last entry is for unassigned tracks, ignore them + const auto totalPrimaryVertices = + vtxRefs.size() - 1; // The last entry is for unassigned tracks, ignore them for (std::size_t iv = 0; iv < totalPrimaryVertices; iv++) { const auto& pv = mRecoCont->getPrimaryVertex(iv); @@ -259,15 +265,19 @@ void EveWorkflowHelper::selectTracks(const CalibObjectsConst* calib, if (gid.getSource() == o2::dataformats::GlobalTrackID::TPC && checkTPCDCA) { const auto& tpcTr = mRecoCont->getTPCTrack(gid); o2::track::TrackPar trc{tpcTr}; - if (!tpcTr.hasBothSidesClusters()) { // need to correct track Z with this vertex time - float dz = (tpcTr.getTime0() * mTPCTimeBins2MUS - (pv.getTimeStamp().getTimeStamp() + mTPCVDrift->getTimeOffset())) * mTPCVDrift->getVDrift(); + if (!tpcTr.hasBothSidesClusters()) { + // need to correct track Z with this vertex time + float dz = (tpcTr.getTime0() * mTPCTimeBins2MUS - + (pv.getTimeStamp().getTimeStamp() + mTPCVDrift->getTimeOffset())) * + mTPCVDrift->getVDrift(); if (tpcTr.hasCSideClustersOnly()) { dz = -dz; } trc.setZ(trc.getZ() + dz); } std::array dca; - if (!prop->propagateToDCA(pvXYZ, trc, prop->getNominalBz(), 10., o2::base::PropagatorF::MatCorrType::USEMatCorrNONE, &dca) || + if (!prop->propagateToDCA(pvXYZ, trc, prop->getNominalBz(), 10., + o2::base::PropagatorF::MatCorrType::USEMatCorrNONE, &dca) || (conf.TPCOnlyMaxDCARZ[1] > 0. && std::abs(dca[1]) > conf.TPCOnlyMaxDCARZ[1]) || (conf.TPCOnlyMaxDCARZ[0] > 0. && std::abs(dca[0]) > conf.TPCOnlyMaxDCARZ[0])) { continue; @@ -303,7 +313,8 @@ void EveWorkflowHelper::selectTowers() if (conf.PVMode) { const auto trackIndex = mRecoCont->getPrimaryVertexMatchedTracks(); // Global ID's for associated tracks const auto vtxRefs = mRecoCont->getPrimaryVertexMatchedTrackRefs(); // references from vertex to these track IDs - const auto totalPrimaryVertices = vtxRefs.size() - 1; // The last entry is for unassigned tracks, ignore them + const auto totalPrimaryVertices = + vtxRefs.size() - 1; // The last entry is for unassigned tracks, ignore them for (std::size_t iv = 0; iv < totalPrimaryVertices; iv++) { const auto& vtref = vtxRefs[iv]; @@ -315,7 +326,8 @@ void EveWorkflowHelper::selectTowers() mPrimaryVertexTriggerGIDs[iv].emplace_back(GID{static_cast(i), GID::HMP}); } - const auto triggersPHOS = gsl::span(trackIndex.data() + vtref.getFirstEntryOfSource(GID::PHS), vtref.getEntriesOfSource(GID::PHS)); + const auto triggersPHOS = gsl::span(trackIndex.data() + vtref.getFirstEntryOfSource(GID::PHS), + vtref.getEntriesOfSource(GID::PHS)); for (const auto& tvid : triggersPHOS) { mTotalDataTypes[GID::PHS]++; @@ -327,7 +339,8 @@ void EveWorkflowHelper::selectTowers() } } - const auto triggersEMCAL = gsl::span(trackIndex.data() + vtref.getFirstEntryOfSource(GID::EMC), vtref.getEntriesOfSource(GID::EMC)); + const auto triggersEMCAL = gsl::span(trackIndex.data() + vtref.getFirstEntryOfSource(GID::EMC), + vtref.getEntriesOfSource(GID::EMC)); for (const auto& tvid : triggersEMCAL) { mTotalDataTypes[GID::EMC]++; @@ -416,11 +429,14 @@ void EveWorkflowHelper::draw(std::size_t primaryVertexIdx, bool sortTracks) break; case GID::TPC: { float dz = 0.f; - if (conf.PVMode) { // for TPC the nominal time (center of the bracket) is stored but in the PVMode we correct it by the PV time + if (conf.PVMode) { + // for TPC the nominal time (center of the bracket) is stored but in the PVMode we correct it by the PV time tim = pvTime; const auto& tpcTr = mRecoCont->getTPCTrack(gid); - if (!tpcTr.hasBothSidesClusters()) { // need to correct track Z with this vertex time - float dz = (tpcTr.getTime0() * mTPCTimeBins2MUS - (pvTime + mTPCVDrift->getTimeOffset())) * mTPCVDrift->getVDrift(); + if (!tpcTr.hasBothSidesClusters()) { + // need to correct track Z with this vertex time + float dz = (tpcTr.getTime0() * mTPCTimeBins2MUS - (pvTime + mTPCVDrift->getTimeOffset())) * + mTPCVDrift->getVDrift(); if (tpcTr.hasCSideClustersOnly()) { dz = -dz; } @@ -500,14 +516,25 @@ void EveWorkflowHelper::draw(std::size_t primaryVertexIdx, bool sortTracks) } } -void EveWorkflowHelper::save(const std::string& jsonPath, const std::string& ext, int numberOfFiles) +void EveWorkflowHelper::save(const std::string& jsonPath, const std::string& ext, int numberOfFiles, + const std::string& receiverHostname, int receiverPort, int receiverTimeout, bool useOnlyFiles, + bool useOnlySockets) { mEvent.setEveVersion(o2_eve_version); - FileProducer producer(jsonPath, ext, numberOfFiles); - VisualisationEventSerializer::getInstance(ext)->toFile(mEvent, producer.newFileName()); + FileProducer producer(jsonPath, ext); + producer.reduceNumberOfFiles(numberOfFiles); + Location location({.fileName = producer.newFileName(), + .port = receiverPort, + .timeout = receiverTimeout, + .host = receiverHostname, + .toFile = !useOnlySockets, + .toSocket = !useOnlyFiles}); + VisualisationEventSerializer::getInstance(ext)->toFile(mEvent, location); } -std::vector EveWorkflowHelper::getTrackPoints(const o2::track::TrackPar& trc, float minR, float maxR, float maxStep, float minZ, float maxZ) +std::vector + EveWorkflowHelper::getTrackPoints(const o2::track::TrackPar& trc, float minR, float maxR, float maxStep, float minZ, + float maxZ) { // adjust minR according to real track start from track starting point auto maxR2 = maxR * maxR; @@ -528,7 +555,8 @@ std::vector EveWorkflowHelper::getTrackPoints(const o2::track::TrackPar& tr auto tp = trc; float dxmin = std::abs(xMin - tp.getX()), dxmax = std::abs(xMax - tp.getX()); - if (dxmin > dxmax) { // start from closest end + if (dxmin > dxmax) { + // start from closest end std::swap(xMin, xMax); dx = -dx; } @@ -556,7 +584,8 @@ std::vector EveWorkflowHelper::getTrackPoints(const o2::track::TrackPar& tr return pnts; } -void EveWorkflowHelper::addTrackToEvent(const o2::track::TrackPar& tr, GID gid, float trackTime, float dz, GID::Source source, float maxStep) +void EveWorkflowHelper::addTrackToEvent(const o2::track::TrackPar& tr, GID gid, float trackTime, float dz, + GID::Source source, float maxStep) { if (source == GID::NSources) { source = (o2::dataformats::GlobalTrackID::Source)gid.getSource(); @@ -599,7 +628,8 @@ void EveWorkflowHelper::prepareITSClusters(const o2::itsmft::TopologyDictionary* } } -void EveWorkflowHelper::prepareMFTClusters(const o2::itsmft::TopologyDictionary* dict) // do we also have something as ITS...dict? +void EveWorkflowHelper::prepareMFTClusters( + const o2::itsmft::TopologyDictionary* dict) // do we also have something as ITS...dict? { const auto& MFTClusterROFRec = this->mRecoCont->getMFTClustersROFRecords(); const auto& clusMFT = this->mRecoCont->getMFTClusters(); @@ -669,7 +699,8 @@ void EveWorkflowHelper::drawEMC(GID gid) const auto& conf = EveConfParam::Instance(); for (const auto& cell : cellsForTrigger) { - if (!(cell.getType() == o2::emcal::ChannelType_t::HIGH_GAIN || cell.getType() == o2::emcal::ChannelType_t::LOW_GAIN)) { + if (!(cell.getType() == o2::emcal::ChannelType_t::HIGH_GAIN || + cell.getType() == o2::emcal::ChannelType_t::LOW_GAIN)) { // Select FEE cells (excluding LEDMON or TRU cells) continue; } @@ -738,7 +769,7 @@ void EveWorkflowHelper::drawTPCTRD(GID gid, float trackTime, GID::Source source) const auto& tpcTrdTrack = mRecoCont->getTPCTRDTrack(gid); addTrackToEvent(tpcTrdTrack, gid, trackTime, 0., source); drawTPCClusters(tpcTrdTrack.getRefGlobalTrackId(), trackTime * mMUS2TPCTimeBins); - drawTRDClusters(tpcTrdTrack); // tracktime + drawTRDClusters(tpcTrdTrack); // tracktime } void EveWorkflowHelper::drawITSTPCTRD(GID gid, float trackTime, GID::Source source) @@ -774,7 +805,7 @@ void EveWorkflowHelper::drawTPCTOF(GID gid, float trackTime) const auto& match = mRecoCont->getTPCTOFMatch(gid.getIndex()); addTrackToEvent(trTPCTOF, gid, trackTime, 0); drawTPCClusters(match.getTrackRef(), trackTime * mMUS2TPCTimeBins); - drawTOFClusters(gid); // trackTime + drawTOFClusters(gid); // trackTime } void EveWorkflowHelper::drawMFTMCH(GID gid, float trackTime) @@ -832,8 +863,9 @@ void EveWorkflowHelper::drawMCHMID(GID gid, float trackTime) void EveWorkflowHelper::drawAODBarrel(EveWorkflowHelper::AODBarrelTrack const& track, float trackTime) { - const std::array arraypar = {track.y(), track.z(), track.snp(), - track.tgl(), track.signed1Pt()}; + const std::array arraypar = { + track.y(), track.z(), track.snp(), + track.tgl(), track.signed1Pt()}; const auto tr = o2::track::TrackPar(track.x(), track.alpha(), arraypar); @@ -907,7 +939,9 @@ void EveWorkflowHelper::drawForwardTrack(GID gid, mch::TrackParam track, float s auto vTrack = mEvent.addTrack({.time = static_cast(trackTime), .charge = 0, .PID = o2::track::PID::Muon, - .startXYZ = {(float)track.getNonBendingCoor(), (float)track.getBendingCoor(), (float)track.getZ()}, + .startXYZ = { + (float)track.getNonBendingCoor(), (float)track.getBendingCoor(), + (float)track.getZ()}, .phi = (float)0, .theta = (float)0, .eta = (float)0, @@ -950,7 +984,8 @@ void EveWorkflowHelper::drawTOFClusters(GID gid) void EveWorkflowHelper::drawITSClusters(GID gid) // float trackTime { - if (gid.getSource() == GID::ITS) { // this is for for full standalone tracks + if (gid.getSource() == GID::ITS) { + // this is for for full standalone tracks const auto& trc = mRecoCont->getITSTrack(gid); auto refs = mRecoCont->getITSTracksClusterRefs(); int ncl = trc.getNumberOfClusters(); @@ -961,7 +996,8 @@ void EveWorkflowHelper::drawITSClusters(GID gid) // float trackTime float xyz[] = {glo.X(), glo.Y(), glo.Z()}; drawPoint(xyz); // trackTime; } - } else if (gid.getSource() == GID::ITSAB) { // this is for ITS tracklets from ITS-TPC afterburner + } else if (gid.getSource() == GID::ITSAB) { + // this is for ITS tracklets from ITS-TPC afterburner const auto& trc = mRecoCont->getITSABRef(gid); const auto& refs = mRecoCont->getITSABClusterRefs(); int ncl = trc.getNClusters(); @@ -990,9 +1026,12 @@ void EveWorkflowHelper::drawTPCClusters(GID gid, float trackTimeTB) const auto& clTPC = trc.getCluster(mTPCTracksClusIdx, iCl, *mTPCClusterIdxStruct, sector, row); std::array xyz; - this->mTPCFastTransform->TransformIdeal(sector, row, clTPC.getPad(), clTPC.getTime(), xyz[0], xyz[1], xyz[2], trackTimeTB); // in sector coordinate - o2::math_utils::rotateZ(xyz, o2::math_utils::sector2Angle(sector % o2::tpc::SECTORSPERSIDE)); // lab coordinate (global) - mEvent.addCluster(xyz.data()); // trackTimeTB / mMUS2TPCTimeBins + this->mTPCFastTransform->TransformIdeal(sector, row, clTPC.getPad(), clTPC.getTime(), xyz[0], xyz[1], xyz[2], + trackTimeTB); // in sector coordinate + o2::math_utils::rotateZ(xyz, o2::math_utils::sector2Angle( + sector % o2::tpc::SECTORSPERSIDE)); // lab coordinate (global) + mEvent.addCluster( + xyz.data()); // trackTimeTB / mMUS2TPCTimeBins } } @@ -1018,8 +1057,10 @@ void EveWorkflowHelper::drawTPC(GID gid, float trackTime, float dz) } addTrackToEvent(tr, gid, trackTime, dz, GID::TPC); - float clTime0 = EveConfParam::Instance().PVMode ? trackTime * mMUS2TPCTimeBins : -2e9; // in PVMode use supplied real time converted to TB, otherwise pass dummy time to use tpcTrack.getTime0 - drawTPCClusters(gid, clTime0); // trackTime + float clTime0 = EveConfParam::Instance().PVMode + ? trackTime * mMUS2TPCTimeBins + : -2e9; // in PVMode use supplied real time converted to TB, otherwise pass dummy time to use tpcTrack.getTime0 + drawTPCClusters(gid, clTime0); // trackTime } void EveWorkflowHelper::drawITS(GID gid, float trackTime) @@ -1074,7 +1115,9 @@ void EveWorkflowHelper::drawMID(GID gid, float trackTime) auto vTrack = mEvent.addTrack({.time = static_cast(trackTime), .charge = (int)0, .PID = o2::track::PID::Muon, - .startXYZ = {(float)midTrack.getPositionX(), (float)midTrack.getPositionY(), (float)midTrack.getPositionZ()}, + .startXYZ = { + (float)midTrack.getPositionX(), (float)midTrack.getPositionY(), + (float)midTrack.getPositionZ()}, .phi = (float)0, .theta = (float)0, .eta = (float)0, @@ -1149,9 +1192,12 @@ EveWorkflowHelper::EveWorkflowHelper() } o2::mch::TrackExtrap::setField(); this->mMFTGeom = o2::mft::GeometryTGeo::Instance(); - this->mMFTGeom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); + this->mMFTGeom->fillMatrixCache( + o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G)); this->mITSGeom = o2::its::GeometryTGeo::Instance(); - this->mITSGeom->fillMatrixCache(o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, o2::math_utils::TransformType::L2G)); + this->mITSGeom->fillMatrixCache( + o2::math_utils::bit2Mask(o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::T2GRot, + o2::math_utils::TransformType::L2G)); this->mEMCALGeom = o2::emcal::Geometry::GetInstance(""); this->mPHOSGeom = o2::phos::Geometry::GetInstance(""); this->mTPCFastTransform = (o2::tpc::TPCFastTransformHelperO2::instance()->create(0)); @@ -1161,10 +1207,18 @@ EveWorkflowHelper::EveWorkflowHelper() mTPCBin2MUS = elParams.ZbinWidth; const auto grp = o2::base::GRPGeomHelper::instance().getGRPECS(); const auto& alpParamsITS = o2::itsmft::DPLAlpideParam::Instance(); - mITSROFrameLengthMUS = grp->isDetContinuousReadOut(o2::detectors::DetID::ITS) ? alpParamsITS.roFrameLengthInBC * o2::constants::lhc::LHCBunchSpacingMUS : alpParamsITS.roFrameLengthTrig * 1.e-3; + mITSROFrameLengthMUS = grp->isDetContinuousReadOut(o2::detectors::DetID::ITS) + ? alpParamsITS.roFrameLengthInBC * + o2::constants::lhc::LHCBunchSpacingMUS + : alpParamsITS.roFrameLengthTrig * + 1.e-3; const auto& alpParamsMFT = o2::itsmft::DPLAlpideParam::Instance(); - mMFTROFrameLengthMUS = grp->isDetContinuousReadOut(o2::detectors::DetID::MFT) ? alpParamsMFT.roFrameLengthInBC * o2::constants::lhc::LHCBunchSpacingMUS : alpParamsMFT.roFrameLengthTrig * 1.e-3; + mMFTROFrameLengthMUS = grp->isDetContinuousReadOut(o2::detectors::DetID::MFT) + ? alpParamsMFT.roFrameLengthInBC * + o2::constants::lhc::LHCBunchSpacingMUS + : alpParamsMFT.roFrameLengthTrig * + 1.e-3; mPVParams = &o2::vertexing::PVertexerParams::Instance(); @@ -1177,7 +1231,8 @@ void EveWorkflowHelper::setTPCVDrift(const o2::tpc::VDriftCorrFact* v) { mTPCVDrift = v; if (v) { - o2::tpc::TPCFastTransformHelperO2::instance()->updateCalibration(*mTPCFastTransform.get(), 0, v->corrFact, v->refVDrift, v->getTimeOffset()); + o2::tpc::TPCFastTransformHelperO2::instance()->updateCalibration(*mTPCFastTransform.get(), 0, v->corrFact, + v->refVDrift, v->getTimeOffset()); } } @@ -1198,11 +1253,14 @@ GID::Source EveWorkflowHelper::detectorMapToGIDSource(uint8_t dm) return GID::TPCTOF; case static_cast(o2::aod::track::TPC) | static_cast(o2::aod::track::TRD): return GID::TPCTRD; - case static_cast(o2::aod::track::ITS) | static_cast(o2::aod::track::TPC) | static_cast(o2::aod::track::TRD): + case static_cast(o2::aod::track::ITS) | static_cast(o2::aod::track::TPC) | + static_cast(o2::aod::track::TRD): return GID::ITSTPCTRD; - case static_cast(o2::aod::track::ITS) | static_cast(o2::aod::track::TPC) | static_cast(o2::aod::track::TOF): + case static_cast(o2::aod::track::ITS) | static_cast(o2::aod::track::TPC) | + static_cast(o2::aod::track::TOF): return GID::ITSTPCTOF; - case static_cast(o2::aod::track::TPC) | static_cast(o2::aod::track::TRD) | static_cast(o2::aod::track::TOF): + case static_cast(o2::aod::track::TPC) | static_cast(o2::aod::track::TRD) | + static_cast(o2::aod::track::TOF): return GID::TPCTRDTOF; default: return GID::ITSTPCTRDTOF; diff --git a/EventVisualisation/Workflow/src/FileProducer.cxx b/EventVisualisation/Workflow/src/FileProducer.cxx index c50dcb8fad135..01e68240bfe6a 100644 --- a/EventVisualisation/Workflow/src/FileProducer.cxx +++ b/EventVisualisation/Workflow/src/FileProducer.cxx @@ -30,13 +30,18 @@ using std::chrono::duration_cast; using std::chrono::milliseconds; using std::chrono::system_clock; -FileProducer::FileProducer(const std::string& path, const std::string& ext, int filesInFolder, const std::string& name) +FileProducer::FileProducer(const std::string& path, const std::string& ext, const std::string& name) { - this->mFilesInFolder = filesInFolder; this->mPath = path; this->mName = name; this->mExt = ext; - o2::utils::createDirectoriesIfAbsent(path); // create folder if not exists (fails if no rights) + o2::utils::createDirectoriesIfAbsent(path); // create a folder if not exists (fails if no rights) +} + +void FileProducer::reduceNumberOfFiles(size_t filesInFolder) const +{ + const std::vector ext = {".json", ".root", ".eve"}; + DirectoryLoader::reduceNumberOfFiles(this->mPath, DirectoryLoader::load(this->mPath, "_", ext), filesInFolder); } std::string FileProducer::newFileName() const @@ -52,8 +57,5 @@ std::string FileProducer::newFileName() const fmt::arg("pid", pid), fmt::arg("timestamp", millisec_since_epoch), fmt::arg("ext", this->mExt)); - const std::vector ext = {".json", ".root", ".eve"}; - DirectoryLoader::reduceNumberOfFiles(this->mPath, DirectoryLoader::load(this->mPath, "_", ext), this->mFilesInFolder); - return this->mPath + "/" + result; } diff --git a/EventVisualisation/Workflow/src/O2DPLDisplay.cxx b/EventVisualisation/Workflow/src/O2DPLDisplay.cxx index e02e1ee20ce58..bd8ab5a664d99 100644 --- a/EventVisualisation/Workflow/src/O2DPLDisplay.cxx +++ b/EventVisualisation/Workflow/src/O2DPLDisplay.cxx @@ -60,6 +60,11 @@ void customize(std::vector& workflowOptions) { std::vector options{ {"jsons-folder", VariantType::String, "jsons", {"name of the folder to store json files"}}, + {"receiver-hostname", VariantType::String, "arcbs04.cern.ch", {"name of the host where visualisation data is transmitted (only eve format)"}}, + {"receiver-port", VariantType::Int, 8001, {"port number of the host where visualisation data is transmitted (only eve format)"}}, + {"receiver-timeout", VariantType::Int, 300, {"socket connection timeout (ms)"}}, + {"use-only-files", VariantType::Bool, false, {"do not transmit visualisation data using sockets (only eve format)"}}, + {"use-only-sockets", VariantType::Bool, false, {"do not store visualisation data using filesystem"}}, {"use-json-format", VariantType::Bool, false, {"instead of eve format (default) use json format"}}, {"use-root-format", VariantType::Bool, false, {"instead of eve format (default) use root format"}}, {"eve-hostname", VariantType::String, "", {"name of the host allowed to produce files (empty means no limit)"}}, @@ -186,7 +191,7 @@ void O2DPLDisplaySpec::run(ProcessingContext& pc) helper.mEvent.setRunType(this->mRunType); helper.mEvent.setPrimaryVertex(pv); helper.mEvent.setCreationTime(tinfo.creation); - helper.save(this->mJsonPath, this->mExt, conf.maxFiles); + helper.save(this->mJsonPath, this->mExt, conf.maxFiles, this->mReceiverHostname, this->mReceiverPort, this->mReceiverTimeout, this->mUseOnlyFiles, this->mUseOnlySockets); filesSaved++; currentTime = std::chrono::high_resolution_clock::now(); // time AFTER save this->mTimeStamp = currentTime; // next run AFTER period counted from last save @@ -302,6 +307,12 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) bool useMC = !cfgc.options().get("disable-mc"); bool disableWrite = cfgc.options().get("disable-write"); + auto receiverHostname = cfgc.options().get("receiver-hostname"); + auto receiverPort = cfgc.options().get("receiver-port"); + auto receiverTimeout = cfgc.options().get("receiver-timeout"); + auto useOnlyFiles = cfgc.options().get("use-only-files"); + auto useOnlySockets = cfgc.options().get("use-only-sockets"); + char hostname[_POSIX_HOST_NAME_MAX]; gethostname(hostname, _POSIX_HOST_NAME_MAX); bool eveHostNameMatch = eveHostName.empty() || eveHostName == hostname; @@ -398,7 +409,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) "o2-eve-export", dataRequest->inputs, {}, - AlgorithmSpec{adaptFromTask(disableWrite, useMC, srcTrk, srcCl, dataRequest, ggRequest, emcalCalibLoader, jsonFolder, ext, timeInterval, eveHostNameMatch)}}); + AlgorithmSpec{adaptFromTask(disableWrite, useMC, srcTrk, srcCl, dataRequest, ggRequest, + emcalCalibLoader, jsonFolder, ext, timeInterval, eveHostNameMatch, + receiverHostname, receiverPort, receiverTimeout, useOnlyFiles, useOnlySockets)}}); // configure dpl timer to inject correct firstTForbit: start from the 1st orbit of TF containing 1st sampled orbit o2::raw::HBFUtilsInitializer hbfIni(cfgc, specs); From 83467b3c67f9b51545b730c3fff5904419ea2806 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 18 Jun 2025 08:47:02 +0200 Subject: [PATCH 200/315] DPL: move to std::pmr where possible --- CCDB/include/CCDB/CCDBDownloader.h | 2 +- CCDB/include/CCDB/CcdbApi.h | 18 +++++------ CCDB/src/CcdbApi.cxx | 14 ++++----- CCDB/test/testCcdbApi.cxx | 4 +-- CCDB/test/testCcdbApiDownloader.cxx | 6 ++-- DataFormats/Headers/include/Headers/Stack.h | 13 ++++---- DataFormats/Headers/test/testDataHeader.cxx | 5 ++-- .../include/MemoryResources/MemoryResources.h | 25 ++++++---------- .../test/testMemoryResources.cxx | 10 +++---- .../include/CTPReconstruction/CTFCoder.h | 3 +- .../CTPReconstruction/RawDataDecoder.h | 6 ++-- .../CTP/reconstruction/src/RawDataDecoder.cxx | 8 ++--- .../include/CTPWorkflow/RawDecoderSpec.h | 2 +- .../src/emc-channel-data-producer.cxx | 4 +-- .../Clusters/clusters-sampler-workflow.cxx | 6 ++-- .../MCH/DevIO/Tracks/TrackSamplerSpec.cxx | 4 +-- .../src/ClusterTransformerSpec.cxx | 2 +- .../MUON/MCH/Tracking/src/TrackFinderSpec.cxx | 8 ++--- .../MCH/Workflow/src/ClusterFinderGEMSpec.cxx | 4 +-- .../src/ClusterFinderOriginalSpec.cxx | 8 ++--- .../workflow/src/TOFIntegrateClusterSpec.cxx | 6 ++-- .../TPC/calibration/src/IDCFactorization.cxx | 2 +- .../TPCWorkflow/TPCDistributeIDCSpec.h | 2 +- .../include/TPCWorkflow/TPCFLPIDCSpec.h | 6 ++-- .../workflow/test/test_ft_EPN_Aggregator.cxx | 2 +- Detectors/Vertexing/src/SVertexer.cxx | 2 +- Framework/CCDBSupport/src/CCDBHelpers.cxx | 2 +- .../Core/include/Framework/DataAllocator.h | 9 +++--- Framework/Core/include/Framework/DataChunk.h | 30 +++++++------------ .../Core/include/Framework/MessageContext.h | 14 ++++----- Framework/Core/src/LifetimeHelpers.cxx | 2 +- Framework/Core/test/test_DataAllocator.cxx | 2 +- Framework/Core/test/test_DataRefUtils.cxx | 1 + Framework/Core/test/test_DataRelayer.cxx | 1 + Framework/Core/test/test_FairMQ.cxx | 7 ++--- .../Core/test/test_O2DataModelHelpers.cxx | 1 + Framework/Utils/include/DPLUtils/Utils.h | 2 +- 37 files changed, 115 insertions(+), 128 deletions(-) diff --git a/CCDB/include/CCDB/CCDBDownloader.h b/CCDB/include/CCDB/CCDBDownloader.h index 6c057a537a096..3ca2e763130df 100644 --- a/CCDB/include/CCDB/CCDBDownloader.h +++ b/CCDB/include/CCDB/CCDBDownloader.h @@ -41,7 +41,7 @@ namespace o2::ccdb #if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__) struct HeaderObjectPair_t { std::multimap header; - o2::pmr::vector* object = nullptr; + std::pmr::vector* object = nullptr; int counter = 0; }; diff --git a/CCDB/include/CCDB/CcdbApi.h b/CCDB/include/CCDB/CcdbApi.h index cc8312d0bef0a..60097ff86baeb 100644 --- a/CCDB/include/CCDB/CcdbApi.h +++ b/CCDB/include/CCDB/CcdbApi.h @@ -355,7 +355,7 @@ class CcdbApi //: public DatabaseInterface #if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__ROOTCLING__) && !defined(__CLING__) typedef struct RequestContext { - o2::pmr::vector& dest; + std::pmr::vector& dest; std::string path; std::map const& metadata; long timestamp; @@ -365,7 +365,7 @@ class CcdbApi //: public DatabaseInterface std::string createdNotBefore; bool considerSnapshot; - RequestContext(o2::pmr::vector& d, + RequestContext(std::pmr::vector& d, std::map const& m, std::map& h) : dest(d), metadata(m), headers(h) {} @@ -379,7 +379,7 @@ class CcdbApi //: public DatabaseInterface void getFromSnapshot(bool createSnapshot, std::string const& path, long timestamp, std::map& headers, - std::string& snapshotpath, o2::pmr::vector& dest, int& fromSnapshot, std::string const& etag) const; + std::string& snapshotpath, std::pmr::vector& dest, int& fromSnapshot, std::string const& etag) const; void releaseNamedSemaphore(boost::interprocess::named_semaphore* sem, std::string const& path) const; boost::interprocess::named_semaphore* createNamedSemaphore(std::string const& path) const; static std::string determineSemaphoreName(std::string const& basedir, std::string const& objectpath); @@ -388,22 +388,22 @@ class CcdbApi //: public DatabaseInterface static bool removeSemaphore(std::string const& name, bool remove = false); static void removeLeakingSemaphores(std::string const& basedir, bool remove = false); - void loadFileToMemory(o2::pmr::vector& dest, const std::string& path, std::map* localHeaders = nullptr, bool fetchLocalMetaData = true) const; - void loadFileToMemory(o2::pmr::vector& dest, std::string const& path, + void loadFileToMemory(std::pmr::vector& dest, const std::string& path, std::map* localHeaders = nullptr, bool fetchLocalMetaData = true) const; + void loadFileToMemory(std::pmr::vector& dest, std::string const& path, std::map const& metadata, long timestamp, std::map* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore, bool considerSnapshot = true) const; // Loads files from alien and cvmfs into given destination. - bool loadLocalContentToMemory(o2::pmr::vector& dest, std::string& url) const; + bool loadLocalContentToMemory(std::pmr::vector& dest, std::string& url) const; // add annotated flattened headers in the end of the blob - static void appendFlatHeader(o2::pmr::vector& dest, const std::map& headers); + static void appendFlatHeader(std::pmr::vector& dest, const std::map& headers); // the failure to load the file to memory is signaled by 0 size and non-0 capacity - static bool isMemoryFileInvalid(const o2::pmr::vector& v) { return v.size() == 0 && v.capacity() > 0; } + static bool isMemoryFileInvalid(const std::pmr::vector& v) { return v.size() == 0 && v.capacity() > 0; } template - static T* extractFromMemoryBlob(o2::pmr::vector& blob) + static T* extractFromMemoryBlob(std::pmr::vector& blob) { auto obj = static_cast(interpretAsTMemFileAndExtract(blob.data(), blob.size(), typeid(T))); if constexpr (std::is_base_of::value) { diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index f187fbf57f558..056435ca9f0fe 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -843,7 +843,7 @@ bool CcdbApi::retrieveBlob(std::string const& path, std::string const& targetdir return false; } - o2::pmr::vector buff; + std::pmr::vector buff; std::map headers; // avoid creating snapshot via loadFileToMemory itself loadFileToMemory(buff, path, metadata, timestamp, &headers, "", createdNotAfter, createdNotBefore, false); @@ -1838,7 +1838,7 @@ void CcdbApi::removeLeakingSemaphores(std::string const& snapshotdir, bool remov void CcdbApi::getFromSnapshot(bool createSnapshot, std::string const& path, long timestamp, std::map& headers, - std::string& snapshotpath, o2::pmr::vector& dest, int& fromSnapshot, std::string const& etag) const + std::string& snapshotpath, std::pmr::vector& dest, int& fromSnapshot, std::string const& etag) const { if (createSnapshot) { // create named semaphore std::string logfile = mSnapshotCachePath + "/log"; @@ -1892,7 +1892,7 @@ void CcdbApi::loadFileToMemory(std::vector& dest, std::string const& path, std::map* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore, bool considerSnapshot) const { - o2::pmr::vector destP; + std::pmr::vector destP; destP.reserve(dest.size()); loadFileToMemory(destP, path, metadata, timestamp, headers, etag, createdNotAfter, createdNotBefore, considerSnapshot); dest.clear(); @@ -1902,7 +1902,7 @@ void CcdbApi::loadFileToMemory(std::vector& dest, std::string const& path, } } -void CcdbApi::loadFileToMemory(o2::pmr::vector& dest, std::string const& path, +void CcdbApi::loadFileToMemory(std::pmr::vector& dest, std::string const& path, std::map const& metadata, long timestamp, std::map* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore, bool considerSnapshot) const @@ -1920,7 +1920,7 @@ void CcdbApi::loadFileToMemory(o2::pmr::vector& dest, std::string const& p vectoredLoadFileToMemory(contexts); } -void CcdbApi::appendFlatHeader(o2::pmr::vector& dest, const std::map& headers) +void CcdbApi::appendFlatHeader(std::pmr::vector& dest, const std::map& headers) { size_t hsize = getFlatHeaderSize(headers), cnt = dest.size(); dest.resize(cnt + hsize); @@ -1985,7 +1985,7 @@ void CcdbApi::vectoredLoadFileToMemory(std::vector& requestConte } } -bool CcdbApi::loadLocalContentToMemory(o2::pmr::vector& dest, std::string& url) const +bool CcdbApi::loadLocalContentToMemory(std::pmr::vector& dest, std::string& url) const { if (url.find("alien:/", 0) != std::string::npos) { std::map localHeaders; @@ -2013,7 +2013,7 @@ bool CcdbApi::loadLocalContentToMemory(o2::pmr::vector& dest, std::string& return false; } -void CcdbApi::loadFileToMemory(o2::pmr::vector& dest, const std::string& path, std::map* localHeaders, bool fetchLocalMetaData) const +void CcdbApi::loadFileToMemory(std::pmr::vector& dest, const std::string& path, std::map* localHeaders, bool fetchLocalMetaData) const { // Read file to memory as vector. For special case of the locally cached file retriev metadata stored directly in the file constexpr size_t MaxCopySize = 0x1L << 25; diff --git a/CCDB/test/testCcdbApi.cxx b/CCDB/test/testCcdbApi.cxx index 0ba037710cf62..84119b099de3b 100644 --- a/CCDB/test/testCcdbApi.cxx +++ b/CCDB/test/testCcdbApi.cxx @@ -560,7 +560,7 @@ BOOST_AUTO_TEST_CASE(multi_host_test) api.init("http://bogus-host.cern.ch,http://ccdb-test.cern.ch:8080"); std::map metadata; std::map headers; - o2::pmr::vector dst; + std::pmr::vector dst; std::string url = "Analysis/ALICE3/Centrality"; api.loadFileToMemory(dst, url, metadata, 1645780010602, &headers, "", "", "", true); BOOST_CHECK(dst.size() != 0); @@ -572,7 +572,7 @@ BOOST_AUTO_TEST_CASE(vectored) api.init("http://ccdb-test.cern.ch:8080"); int TEST_SAMPLE_SIZE = 5; - std::vector> dests(TEST_SAMPLE_SIZE); + std::vector> dests(TEST_SAMPLE_SIZE); std::vector> metadatas(TEST_SAMPLE_SIZE); std::vector> headers(TEST_SAMPLE_SIZE); diff --git a/CCDB/test/testCcdbApiDownloader.cxx b/CCDB/test/testCcdbApiDownloader.cxx index 76686f5ee1c00..8e412dcfa7f76 100644 --- a/CCDB/test/testCcdbApiDownloader.cxx +++ b/CCDB/test/testCcdbApiDownloader.cxx @@ -116,12 +116,12 @@ size_t writeCallbackNoLambda(void* contents, size_t size, size_t nmemb, void* ch return realsize; } -std::vector prepareAsyncHandles(size_t num, std::vector*>& dests) +std::vector prepareAsyncHandles(size_t num, std::vector*>& dests) { std::vector handles; for (int i = 0; i < num; i++) { - auto dest = new o2::pmr::vector(); + auto dest = new std::pmr::vector(); dests.push_back(dest); CURL* curl_handle = curl_easy_init(); handles.push_back(curl_handle); @@ -154,7 +154,7 @@ BOOST_AUTO_TEST_CASE(asynch_schedule_test) } CCDBDownloader downloader; - std::vector*> dests; + std::vector*> dests; auto handles = prepareAsyncHandles(TRANSFERS, dests); size_t transfersLeft = 0; diff --git a/DataFormats/Headers/include/Headers/Stack.h b/DataFormats/Headers/include/Headers/Stack.h index 0958b639ef451..98fb95e602ecf 100644 --- a/DataFormats/Headers/include/Headers/Stack.h +++ b/DataFormats/Headers/include/Headers/Stack.h @@ -11,9 +11,10 @@ #ifndef O2_HEADERS_STACK_H #define O2_HEADERS_STACK_H -#include "MemoryResources/MemoryResources.h" #include "Headers/DataHeader.h" +#include + namespace o2::header { //__________________________________________________________________________________________________ @@ -32,7 +33,7 @@ namespace o2::header /// - returns a Stack ready to be shipped. struct Stack { - using memory_resource = o2::pmr::memory_resource; + using memory_resource = std::pmr::memory_resource; private: struct freeobj { @@ -42,7 +43,7 @@ struct Stack { }; public: - using allocator_type = fair::mq::pmr::polymorphic_allocator; + using allocator_type = std::pmr::polymorphic_allocator; using value_type = std::byte; using BufferType = std::unique_ptr; // this gives us proper default move semantics for free @@ -87,9 +88,9 @@ struct Stack { /// all headers must derive from BaseHeader, in addition also other stacks can be passed to ctor. template >::value, int> = 0> + !std::is_convertible>::value, int> = 0> Stack(FirstArgType&& firstHeader, Headers&&... headers) - : Stack(fair::mq::pmr::new_delete_resource(), std::forward(firstHeader), + : Stack(std::pmr::new_delete_resource(), std::forward(firstHeader), std::forward(headers)...) { } @@ -140,7 +141,7 @@ struct Stack { constexpr static size_t calculateSize() { return 0; } private: - allocator_type allocator{fair::mq::pmr::new_delete_resource()}; + allocator_type allocator{std::pmr::new_delete_resource()}; size_t bufferSize{0}; BufferType buffer{nullptr, freeobj{allocator.resource()}}; diff --git a/DataFormats/Headers/test/testDataHeader.cxx b/DataFormats/Headers/test/testDataHeader.cxx index 2403c1a6230be..23a230840fafe 100644 --- a/DataFormats/Headers/test/testDataHeader.cxx +++ b/DataFormats/Headers/test/testDataHeader.cxx @@ -314,8 +314,7 @@ BOOST_AUTO_TEST_CASE(headerStack_test) BOOST_CHECK(h3->secret == 42); // test constructing from a buffer and an additional header - using namespace fair::mq::pmr; - Stack s5(new_delete_resource(), s1.data(), Stack{}, meta); + Stack s5(std::pmr::new_delete_resource(), s1.data(), Stack{}, meta); BOOST_CHECK(s5.size() == s1.size() + sizeof(meta)); // check if we can find the header even though there was an empty stack in the middle h3 = get(s5.data()); @@ -329,7 +328,7 @@ BOOST_AUTO_TEST_CASE(headerStack_test) BOOST_CHECK(h4 == h3); // let's assume we have some stack that is missing the required DataHeader at the beginning: - Stack s6{new_delete_resource(), DataHeader{}, s1.data()}; + Stack s6{std::pmr::new_delete_resource(), DataHeader{}, s1.data()}; BOOST_CHECK(s6.size() == sizeof(DataHeader) + s1.size()); } diff --git a/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h b/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h index b52f5c715575e..66b44162b47ff 100644 --- a/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h +++ b/DataFormats/MemoryResources/include/MemoryResources/MemoryResources.h @@ -28,9 +28,6 @@ #ifndef ALICEO2_MEMORY_RESOURCES_ #define ALICEO2_MEMORY_RESOURCES_ -#include -#include -#include #include #include #include @@ -45,12 +42,8 @@ namespace o2::pmr { -using FairMQMemoryResource = fair::mq::MemoryResource; -using ChannelResource = fair::mq::ChannelResource; -using namespace fair::mq::pmr; - template -fair::mq::MessagePtr getMessage(ContainerT&& container, FairMQMemoryResource* targetResource = nullptr) +fair::mq::MessagePtr getMessage(ContainerT&& container, fair::mq::MemoryResource* targetResource = nullptr) { return fair::mq::getMessage(std::forward(container), targetResource); } @@ -60,7 +53,7 @@ fair::mq::MessagePtr getMessage(ContainerT&& container, FairMQMemoryResource* ta /// Ownership of hte message is taken. Meant to be used for transparent data adoption in containers. /// In combination with the SpectatorAllocator this is an alternative to using span, as raw memory /// (e.g. an existing buffer message) will be accessible with appropriate container. -class MessageResource : public FairMQMemoryResource +class MessageResource : public fair::mq::MemoryResource { public: @@ -82,7 +75,7 @@ class MessageResource : public FairMQMemoryResource size_t getNumberOfMessages() const noexcept override { return mMessageData ? 1 : 0; } protected: - FairMQMemoryResource* mUpstream{nullptr}; + fair::mq::MemoryResource* mUpstream{nullptr}; size_t mMessageSize{0}; void* mMessageData{nullptr}; bool initialImport{true}; @@ -113,14 +106,14 @@ class MessageResource : public FairMQMemoryResource // The NoConstructAllocator behaves like the normal pmr vector but does not call constructors / destructors template -class NoConstructAllocator : public fair::mq::pmr::polymorphic_allocator +class NoConstructAllocator : public std::pmr::polymorphic_allocator { public: - using fair::mq::pmr::polymorphic_allocator::polymorphic_allocator; + using std::pmr::polymorphic_allocator::polymorphic_allocator; using propagate_on_container_move_assignment = std::true_type; template - NoConstructAllocator(Args&&... args) : fair::mq::pmr::polymorphic_allocator(std::forward(args)...) + NoConstructAllocator(Args&&... args) : std::pmr::polymorphic_allocator(std::forward(args)...) { } @@ -145,13 +138,13 @@ class NoConstructAllocator : public fair::mq::pmr::polymorphic_allocator //__________________________________________________________________________________________________ //__________________________________________________________________________________________________ -using BytePmrAllocator = fair::mq::pmr::polymorphic_allocator; +using BytePmrAllocator = std::pmr::polymorphic_allocator; template -using vector = std::vector>; +using vector = std::vector>; //__________________________________________________________________________________________________ /// Get the allocator associated to a transport factory -inline static FairMQMemoryResource* getTransportAllocator(fair::mq::TransportFactory* factory) +inline static fair::mq::MemoryResource* getTransportAllocator(fair::mq::TransportFactory* factory) { return *factory; } diff --git a/DataFormats/MemoryResources/test/testMemoryResources.cxx b/DataFormats/MemoryResources/test/testMemoryResources.cxx index a49cd00d75255..c72ac8f6d422b 100644 --- a/DataFormats/MemoryResources/test/testMemoryResources.cxx +++ b/DataFormats/MemoryResources/test/testMemoryResources.cxx @@ -19,6 +19,7 @@ #include #include #include +#include namespace o2::pmr { @@ -60,8 +61,6 @@ BOOST_AUTO_TEST_CASE(transportallocatormap_test) BOOST_CHECK(_tmp == allocZMQ); } -using namespace fair::mq::pmr; - BOOST_AUTO_TEST_CASE(allocator_test) { size_t session{(size_t)getpid() * 1000 + 1}; @@ -76,7 +75,7 @@ BOOST_AUTO_TEST_CASE(allocator_test) testData::nconstructions = 0; { - std::vector> v(polymorphic_allocator{allocZMQ}); + std::vector> v(std::pmr::polymorphic_allocator{allocZMQ}); v.reserve(3); BOOST_CHECK(v.capacity() == 3); BOOST_CHECK(allocZMQ->getNumberOfMessages() == 1); @@ -110,7 +109,7 @@ BOOST_AUTO_TEST_CASE(getMessage_test) // test message creation on the same channel it was allocated with { - std::vector> v(polymorphic_allocator{allocZMQ}); + std::vector> v(std::pmr::polymorphic_allocator{allocZMQ}); v.emplace_back(1); v.emplace_back(2); v.emplace_back(3); @@ -125,7 +124,7 @@ BOOST_AUTO_TEST_CASE(getMessage_test) // test message creation on a different channel than it was allocated with { - std::vector> v(polymorphic_allocator{allocZMQ}); + std::vector> v(std::pmr::polymorphic_allocator{allocZMQ}); v.emplace_back(4); v.emplace_back(5); v.emplace_back(6); @@ -137,7 +136,6 @@ BOOST_AUTO_TEST_CASE(getMessage_test) BOOST_CHECK(message->GetSize() == 3 * sizeof(testData)); messageArray = static_cast(message->GetData()); BOOST_CHECK(messageArray[0] == 4 && messageArray[1] == 5 && messageArray[2] == 6); - } }; // namespace o2::pmr diff --git a/Detectors/CTP/reconstruction/include/CTPReconstruction/CTFCoder.h b/Detectors/CTP/reconstruction/include/CTPReconstruction/CTFCoder.h index 9189df5d12685..4b3d097417659 100644 --- a/Detectors/CTP/reconstruction/include/CTPReconstruction/CTFCoder.h +++ b/Detectors/CTP/reconstruction/include/CTPReconstruction/CTFCoder.h @@ -26,6 +26,7 @@ #include "CTPReconstruction/CTFHelper.h" #include "CTPReconstruction/RawDataDecoder.h" #include "DataFormatsCTP/Configuration.h" +#include class TTree; @@ -225,7 +226,7 @@ o2::ctf::CTFIOSize CTFCoder::decode(const CTF::base& ec, VTRG& data, LumiInfo& l trgclassmask = mCTPConfig.getTriggerClassMask(); } // std::cout << "trgclassmask:" << std::hex << trgclassmask << std::dec << std::endl; - o2::pmr::vector digits; + std::pmr::vector digits; o2::ctp::RawDataDecoder::shiftInputs(digitsMap, digits, mFirstTFOrbit, trgclassmask); for (auto const& dig : digits) { data.emplace_back(dig); diff --git a/Detectors/CTP/reconstruction/include/CTPReconstruction/RawDataDecoder.h b/Detectors/CTP/reconstruction/include/CTPReconstruction/RawDataDecoder.h index 53addf32c538f..3027c8aea39fc 100644 --- a/Detectors/CTP/reconstruction/include/CTPReconstruction/RawDataDecoder.h +++ b/Detectors/CTP/reconstruction/include/CTPReconstruction/RawDataDecoder.h @@ -35,7 +35,7 @@ class RawDataDecoder ~RawDataDecoder() = default; static void makeGBTWordInverse(std::vector& diglets, gbtword80_t& GBTWord, gbtword80_t& remnant, uint32_t& size_gbt, uint32_t Npld); int addCTPDigit(uint32_t linkCRU, uint32_t triggerOrbit, gbtword80_t& diglet, gbtword80_t& pldmask, std::map& digits); - int decodeRaw(o2::framework::InputRecord& inputs, std::vector& filter, o2::pmr::vector& digits, std::vector& lumiPointsHBF1); + int decodeRaw(o2::framework::InputRecord& inputs, std::vector& filter, std::pmr::vector& digits, std::vector& lumiPointsHBF1); int decodeRawFatal(o2::framework::InputRecord& inputs, std::vector& filter); int decodeRaw(o2::framework::InputRecord& inputs, std::vector& filter, std::vector& digits, std::vector& lumiPointsHBF1); void setDecodeInps(bool decodeinps) { mDecodeInps = decodeinps; } @@ -54,8 +54,8 @@ class RawDataDecoder CTPConfiguration& getCTPConfig() { return mCTPConfig; } int init(); static int shiftNew(const o2::InteractionRecord& irin, uint32_t TFOrbit, std::bitset<48>& inpmask, int64_t shift, int level, std::map& digmap); - static int shiftInputs(std::map& digitsMap, o2::pmr::vector& digits, uint32_t TFOrbit, uint64_t trgclassmask = 0xffffffffffffffff); - int checkReadoutConsistentncy(o2::pmr::vector& digits, uint64_t trgclassmask = 0xffffffffffffffff, uint64_t trigclassmaskNoTrgDets = 0xffffffffffffffff); + static int shiftInputs(std::map& digitsMap, std::pmr::vector& digits, uint32_t TFOrbit, uint64_t trgclassmask = 0xffffffffffffffff); + int checkReadoutConsistentncy(std::pmr::vector& digits, uint64_t trgclassmask = 0xffffffffffffffff, uint64_t trigclassmaskNoTrgDets = 0xffffffffffffffff); std::array getClassErrorsA() { return mClassErrorsA; } std::array getClassErrorsB() { return mClassErrorsB; } std::array getClassCountersA() { return mClassCountersA; } diff --git a/Detectors/CTP/reconstruction/src/RawDataDecoder.cxx b/Detectors/CTP/reconstruction/src/RawDataDecoder.cxx index a062a262acf62..025e63a786a48 100644 --- a/Detectors/CTP/reconstruction/src/RawDataDecoder.cxx +++ b/Detectors/CTP/reconstruction/src/RawDataDecoder.cxx @@ -128,7 +128,7 @@ int RawDataDecoder::addCTPDigit(uint32_t linkCRU, uint32_t orbit, gbtword80_t& d // Decodes one page // It is NOT assumed that CTP HBF has never more than one page. // 1 HBF/page <= 8000kB = 8*1024*8/120 = 546 GBT words = 546 IRs/page = 5.5 MHz -int RawDataDecoder::decodeRaw(o2::framework::InputRecord& inputs, std::vector& filter, o2::pmr::vector& digits, std::vector& lumiPointsHBF1) +int RawDataDecoder::decodeRaw(o2::framework::InputRecord& inputs, std::vector& filter, std::pmr::vector& digits, std::vector& lumiPointsHBF1) { int ret = 0; static int nwrites = 0; @@ -495,7 +495,7 @@ int RawDataDecoder::decodeRawFatal(o2::framework::InputRecord& inputs, std::vect // int RawDataDecoder::decodeRaw(o2::framework::InputRecord& inputs, std::vector& filter, std::vector& digits, std::vector& lumiPointsHBF1) { - o2::pmr::vector pmrdigits; + std::pmr::vector pmrdigits; int ret = decodeRaw(inputs, filter, pmrdigits, lumiPointsHBF1); for (auto const d : pmrdigits) { digits.push_back(d); @@ -532,7 +532,7 @@ int RawDataDecoder::shiftNew(const o2::InteractionRecord& irin, uint32_t TFOrbit } // -int RawDataDecoder::shiftInputs(std::map& digitsMap, o2::pmr::vector& digits, uint32_t TFOrbit, uint64_t trgclassmask) +int RawDataDecoder::shiftInputs(std::map& digitsMap, std::pmr::vector& digits, uint32_t TFOrbit, uint64_t trgclassmask) { // int nClasswoInp = 0; // counting classes without input which should never happen int lost = 0; @@ -598,7 +598,7 @@ int RawDataDecoder::shiftInputs(std::map& digit return lost; } // -int RawDataDecoder::checkReadoutConsistentncy(o2::pmr::vector& digits, uint64_t trgclassmask, uint64_t trgclassmaskNoTrgDet) +int RawDataDecoder::checkReadoutConsistentncy(std::pmr::vector& digits, uint64_t trgclassmask, uint64_t trgclassmaskNoTrgDet) { LOG(debug) << "Checking readout"; int ret = 0; diff --git a/Detectors/CTP/workflow/include/CTPWorkflow/RawDecoderSpec.h b/Detectors/CTP/workflow/include/CTPWorkflow/RawDecoderSpec.h index 3198e5c33e219..1ba01803f3b19 100644 --- a/Detectors/CTP/workflow/include/CTPWorkflow/RawDecoderSpec.h +++ b/Detectors/CTP/workflow/include/CTPWorkflow/RawDecoderSpec.h @@ -57,7 +57,7 @@ class RawDecoderSpec : public framework::Task private: // for digits bool mDoDigits = true; - o2::pmr::vector mOutputDigits; + std::pmr::vector mOutputDigits; int mMaxInputSize = 0; bool mMaxInputSizeFatal = 0; // for lumi diff --git a/Detectors/EMCAL/workflow/src/emc-channel-data-producer.cxx b/Detectors/EMCAL/workflow/src/emc-channel-data-producer.cxx index 75e2cdbd9fce3..a0141256ac29d 100644 --- a/Detectors/EMCAL/workflow/src/emc-channel-data-producer.cxx +++ b/Detectors/EMCAL/workflow/src/emc-channel-data-producer.cxx @@ -128,7 +128,7 @@ DataProcessorSpec generateData(const std::string nameRootFile, const std::string // loop over cells // ToDo: Make more realistic assumption that we dont always have the same amount of cells per event - o2::pmr::vector CellOutput; + std::pmr::vector CellOutput; for (int i = 0; i < nCellsPerEvent; ++i) { double cellID = 0; double cellE = 0; @@ -157,7 +157,7 @@ DataProcessorSpec generateData(const std::string nameRootFile, const std::string } // send output LOG(debug) << "sending " << CellOutput.size() << "cells"; - o2::pmr::vector TriggerOutput; + std::pmr::vector TriggerOutput; TriggerOutput.emplace_back(0, 0, 0, CellOutput.size()); ctx.outputs().adoptContainer(Output{o2::header::gDataOriginEMC, "CELLS", 0}, std::move(CellOutput)); diff --git a/Detectors/MUON/MCH/DevIO/Clusters/clusters-sampler-workflow.cxx b/Detectors/MUON/MCH/DevIO/Clusters/clusters-sampler-workflow.cxx index 9d98ada911df2..95c748f1cc6f1 100644 --- a/Detectors/MUON/MCH/DevIO/Clusters/clusters-sampler-workflow.cxx +++ b/Detectors/MUON/MCH/DevIO/Clusters/clusters-sampler-workflow.cxx @@ -101,7 +101,7 @@ class ClusterSamplerTask // create the output messages auto& rofs = pc.outputs().make>(OutputRef{"rofs"}); auto& clusters = pc.outputs().make>(OutputRef{"clusters"}); - std::vector>* digits(nullptr); + std::vector>* digits(nullptr); if (mDoDigits) { digits = &pc.outputs().make>(OutputRef{"digits"}); } @@ -115,8 +115,8 @@ class ClusterSamplerTask private: //_________________________________________________________________________________________________ - int readOneEvent(std::vector>& clusters, - std::vector>* digits) + int readOneEvent(std::vector>& clusters, + std::vector>* digits) { /// fill the internal buffers with the clusters and digits of the current event diff --git a/Detectors/MUON/MCH/DevIO/Tracks/TrackSamplerSpec.cxx b/Detectors/MUON/MCH/DevIO/Tracks/TrackSamplerSpec.cxx index 4a53659e2732b..27291af10e3b0 100644 --- a/Detectors/MUON/MCH/DevIO/Tracks/TrackSamplerSpec.cxx +++ b/Detectors/MUON/MCH/DevIO/Tracks/TrackSamplerSpec.cxx @@ -102,8 +102,8 @@ class TrackSamplerTask } //_________________________________________________________________________________________________ - int readOneEvent(std::vector>& tracks, - std::vector>& clusters) + int readOneEvent(std::vector>& tracks, + std::vector>& clusters) { /// fill the output messages with the tracks and attached clusters of the current event /// modify the references to the attached clusters according to their position in the global vector diff --git a/Detectors/MUON/MCH/Geometry/Transformer/src/ClusterTransformerSpec.cxx b/Detectors/MUON/MCH/Geometry/Transformer/src/ClusterTransformerSpec.cxx index f70f9574b6974..1f71af86078a8 100644 --- a/Detectors/MUON/MCH/Geometry/Transformer/src/ClusterTransformerSpec.cxx +++ b/Detectors/MUON/MCH/Geometry/Transformer/src/ClusterTransformerSpec.cxx @@ -42,7 +42,7 @@ namespace o2::mch // convert all clusters from local to global reference frames void local2global(geo::TransformationCreator transformation, gsl::span localClusters, - std::vector>& globalClusters) + std::vector>& globalClusters) { int i{0}; globalClusters.insert(globalClusters.end(), localClusters.begin(), localClusters.end()); diff --git a/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx b/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx index 6239186309dc3..c21249527cb23 100644 --- a/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx +++ b/Detectors/MUON/MCH/Tracking/src/TrackFinderSpec.cxx @@ -145,7 +145,7 @@ class TrackFinderTask auto& trackROFs = pc.outputs().make>(OutputRef{"trackrofs"}); auto& mchTracks = pc.outputs().make>(OutputRef{"tracks"}); auto& usedClusters = pc.outputs().make>(OutputRef{"trackclusters"}); - std::vector>* usedDigits(nullptr); + std::vector>* usedDigits(nullptr); if (mDigits) { usedDigits = &pc.outputs().make>(OutputRef{"trackdigits"}); } @@ -219,9 +219,9 @@ class TrackFinderTask //_________________________________________________________________________________________________ void writeTracks(const std::list& tracks, const gsl::span& digitsIn, const ROFRecord& clusterROF, uint32_t firstTForbit, - std::vector>& mchTracks, - std::vector>& usedClusters, - std::vector>* usedDigits) const + std::vector>& mchTracks, + std::vector>& usedClusters, + std::vector>* usedDigits) const { /// fill the output messages with tracks and attached clusters and digits if requested diff --git a/Detectors/MUON/MCH/Workflow/src/ClusterFinderGEMSpec.cxx b/Detectors/MUON/MCH/Workflow/src/ClusterFinderGEMSpec.cxx index 5158cc436b277..2af245d453702 100644 --- a/Detectors/MUON/MCH/Workflow/src/ClusterFinderGEMSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/ClusterFinderGEMSpec.cxx @@ -303,8 +303,8 @@ class ClusterFinderGEMTask private: //_________________________________________________________________________________________________ - void writeClusters(std::vector>& clusters, - std::vector>& usedDigits) const + void writeClusters(std::vector>& clusters, + std::vector>& usedDigits) const { /// fill the output messages with clusters and attached digits of the current event /// modify the references to the attached digits according to their position in the global vector diff --git a/Detectors/MUON/MCH/Workflow/src/ClusterFinderOriginalSpec.cxx b/Detectors/MUON/MCH/Workflow/src/ClusterFinderOriginalSpec.cxx index 8344d2837b814..b0890e3e6c7e2 100644 --- a/Detectors/MUON/MCH/Workflow/src/ClusterFinderOriginalSpec.cxx +++ b/Detectors/MUON/MCH/Workflow/src/ClusterFinderOriginalSpec.cxx @@ -144,8 +144,8 @@ class ClusterFinderOriginalTask private: //_________________________________________________________________________________________________ void writeClusters(const gsl::span& preclusterDigits, size_t firstClusterIdx, - std::vector>& clusters, - std::vector>& usedDigits) const + std::vector>& clusters, + std::vector>& usedDigits) const { /// fill the output messages with the new clusters and all the digits from the corresponding precluster /// modify the references to the attached digits according to their position in the global vector @@ -167,8 +167,8 @@ class ClusterFinderOriginalTask } //_________________________________________________________________________________________________ - void writeClusters(std::vector>& clusters, - std::vector>& usedDigits) const + void writeClusters(std::vector>& clusters, + std::vector>& usedDigits) const { /// fill the output messages with clusters and attached digits of the current event /// modify the references to the attached digits according to their position in the global vector diff --git a/Detectors/TOF/workflow/src/TOFIntegrateClusterSpec.cxx b/Detectors/TOF/workflow/src/TOFIntegrateClusterSpec.cxx index 2b647f9236611..f3e561a0c531d 100644 --- a/Detectors/TOF/workflow/src/TOFIntegrateClusterSpec.cxx +++ b/Detectors/TOF/workflow/src/TOFIntegrateClusterSpec.cxx @@ -60,8 +60,8 @@ class TOFIntegrateClusters : public Task const float sliceWidthMSinv = 1. / float(sliceWidthMS); // storage for integrated currents - o2::pmr::vector iTOFCNCl(nSlices); - o2::pmr::vector iTOFCqTot(nSlices); + std::pmr::vector iTOFCNCl(nSlices); + std::pmr::vector iTOFCqTot(nSlices); const auto clusters = pc.inputs().get>("tofcluster"); if (mTagNoise) { @@ -106,7 +106,7 @@ class TOFIntegrateClusters : public Task std::vector mCounterNeighbours; ///< buffer for noise removal (contains number of neighbouring cluster for time +-mTimeCutNoisePS) std::shared_ptr mCCDBRequest; ///< info for CCDB request - void sendOutput(ProcessingContext& pc, o2::pmr::vector iTOFCNCl, o2::pmr::vector iTOFCqTot) + void sendOutput(ProcessingContext& pc, std::pmr::vector iTOFCNCl, std::pmr::vector iTOFCqTot) { pc.outputs().adoptContainer(Output{header::gDataOriginTOF, "ITOFCN"}, std::move(iTOFCNCl)); pc.outputs().adoptContainer(Output{header::gDataOriginTOF, "ITOFCQ"}, std::move(iTOFCqTot)); diff --git a/Detectors/TPC/calibration/src/IDCFactorization.cxx b/Detectors/TPC/calibration/src/IDCFactorization.cxx index e5474016e7b98..cc60be31acb54 100644 --- a/Detectors/TPC/calibration/src/IDCFactorization.cxx +++ b/Detectors/TPC/calibration/src/IDCFactorization.cxx @@ -1241,4 +1241,4 @@ bool o2::tpc::IDCFactorization::checkReceivedIDCs() return idcsGood; } -template void o2::tpc::IDCFactorization::calcIDCOne(const o2::pmr::vector&, const int, const int, const unsigned int, const CRU, std::vector>&, const IDCZero*, const CalDet*, const bool); +template void o2::tpc::IDCFactorization::calcIDCOne(const std::pmr::vector&, const int, const int, const unsigned int, const CRU, std::vector>&, const IDCZero*, const CalDet*, const bool); diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/TPCDistributeIDCSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/TPCDistributeIDCSpec.h index 6e589cd6c4e8b..e0c1a87d939ae 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/TPCDistributeIDCSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/TPCDistributeIDCSpec.h @@ -247,7 +247,7 @@ class TPCDistributeIDCSpec : public o2::framework::Task std::vector mFilter{}; ///< filter for looping over input data std::vector mDataDescrOut{}; - void sendOutput(o2::framework::ProcessingContext& pc, const unsigned int currentOutLane, const unsigned int cru, o2::pmr::vector idcs) + void sendOutput(o2::framework::ProcessingContext& pc, const unsigned int currentOutLane, const unsigned int cru, std::pmr::vector idcs) { pc.outputs().adoptContainer(Output{gDataOriginTPC, mDataDescrOut[currentOutLane], header::DataHeader::SubSpecificationType{cru}}, std::move(idcs)); } diff --git a/Detectors/TPC/workflow/include/TPCWorkflow/TPCFLPIDCSpec.h b/Detectors/TPC/workflow/include/TPCWorkflow/TPCFLPIDCSpec.h index ec3e158590661..6f6ff249c1935 100644 --- a/Detectors/TPC/workflow/include/TPCWorkflow/TPCFLPIDCSpec.h +++ b/Detectors/TPC/workflow/include/TPCWorkflow/TPCFLPIDCSpec.h @@ -93,7 +93,7 @@ class TPCFLPIDCDevice : public o2::framework::Task ++mCountTFsForBuffer; auto const* tpcCRUHeader = o2::framework::DataRefUtils::getHeader(ref); const int cru = tpcCRUHeader->subSpecification >> 7; - auto vecIDCs = pc.inputs().get>(ref); + auto vecIDCs = pc.inputs().get>(ref); mIDCs[cru].insert(mIDCs[cru].end(), vecIDCs.begin(), vecIDCs.end()); if (mEnableSynchProc) { @@ -164,7 +164,7 @@ class TPCFLPIDCDevice : public o2::framework::Task bool mDumpIDCs{}; ///< dump IDCs to tree for debugging int mCountTFsForBuffer{0}; ///< count processed TFs to track when the output will be send std::pair, std::vector> mOneDIDCs{}; ///< 1D-IDCs which will be send to the EPNs - std::unordered_map> mIDCs{}; ///< object for averaging and grouping of the IDCs + std::unordered_map> mIDCs{}; ///< object for averaging and grouping of the IDCs std::unordered_map, std::vector>>> mBuffer1DIDCs{}; ///< buffer for 1D-IDCs. The buffered 1D-IDCs for n TFs will be send to the EPNs for synchronous reco. Zero initialized to avoid empty first TFs! CalDet* mPadFlagsMap{nullptr}; ///< status flag for each pad (i.e. if the pad is dead) IDCZero mIDCZero{}; ///< I_0(r,\phi) = _t: Used for calculating IDC1 (provided from input file or CCDB) @@ -173,7 +173,7 @@ class TPCFLPIDCDevice : public o2::framework::Task /// update the time dependent parameters if they have changed (i.e. update the pad status map) void updateTimeDependentParams(ProcessingContext& pc) { pc.inputs().get*>("tpcpadmap").get(); } - void sendOutputSync(DataAllocator& output, const o2::pmr::vector& idc, const uint32_t cru) + void sendOutputSync(DataAllocator& output, const std::pmr::vector& idc, const uint32_t cru) { const header::DataHeader::SubSpecificationType subSpec{cru << 7}; const CRU cruTmp(cru); diff --git a/Detectors/TPC/workflow/test/test_ft_EPN_Aggregator.cxx b/Detectors/TPC/workflow/test/test_ft_EPN_Aggregator.cxx index e8255f98eff6c..f8236756b27cb 100644 --- a/Detectors/TPC/workflow/test/test_ft_EPN_Aggregator.cxx +++ b/Detectors/TPC/workflow/test/test_ft_EPN_Aggregator.cxx @@ -230,7 +230,7 @@ DataProcessorSpec generateIDCsCRU(int lane, const unsigned int maxTFs, const std o2::tpc::CRU cruTmp(icru); const unsigned int nPads = o2::tpc::Mapper::PADSPERREGION[cruTmp.region()]; const int cru = (icru + tf * Mapper::NREGIONS) % o2::tpc::CRU::MaxCRU; // shuffle CRUs - o2::pmr::vector idcs; + std::pmr::vector idcs; idcs.reserve(generateIDCs ? o2::tpc::Mapper::PADSPERREGION[cruTmp.region()] : mIDCs[cru].size()); const int nIntervals = intervalsRand.size(); for (int interval = 0; interval < nIntervals; ++interval) { diff --git a/Detectors/Vertexing/src/SVertexer.cxx b/Detectors/Vertexing/src/SVertexer.cxx index 1d48bcceb0097..edaf523cddb41 100644 --- a/Detectors/Vertexing/src/SVertexer.cxx +++ b/Detectors/Vertexing/src/SVertexer.cxx @@ -216,7 +216,7 @@ void SVertexer::produceOutput(o2::framework::ProcessingContext& pc) auto& strTracksOut = pc.outputs().make>(o2f::Output{"GLO", "STRANGETRACKS", 0}); auto& strClustOut = pc.outputs().make>(o2f::Output{"GLO", "CLUSUPDATES", 0}); - o2::pmr::vector mcLabsOut; + std::pmr::vector mcLabsOut; strTracksOut.resize(mNStrangeTracks); strClustOut.resize(mNStrangeTracks); if (mStrTracker->getMCTruthOn()) { diff --git a/Framework/CCDBSupport/src/CCDBHelpers.cxx b/Framework/CCDBSupport/src/CCDBHelpers.cxx index 0db4cbb5ac71d..71b6282c80086 100644 --- a/Framework/CCDBSupport/src/CCDBHelpers.cxx +++ b/Framework/CCDBSupport/src/CCDBHelpers.cxx @@ -159,7 +159,7 @@ CCDBHelpers::ParserResult CCDBHelpers::parseRemappings(char const* str) } } -auto getOrbitResetTime(o2::pmr::vector const& v) -> Long64_t +auto getOrbitResetTime(std::pmr::vector const& v) -> Long64_t { Int_t previousErrorLevel = gErrorIgnoreLevel; gErrorIgnoreLevel = kFatal; diff --git a/Framework/Core/include/Framework/DataAllocator.h b/Framework/Core/include/Framework/DataAllocator.h index 287513ec85845..c5aa4bbffa480 100644 --- a/Framework/Core/include/Framework/DataAllocator.h +++ b/Framework/Core/include/Framework/DataAllocator.h @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -449,7 +450,7 @@ class DataAllocator } // get the memory resource associated with an output - o2::pmr::FairMQMemoryResource* getMemoryResource(const Output& spec) + std::pmr::memory_resource* getMemoryResource(const Output& spec) { auto& timingInfo = mRegistry.get(); auto& proxy = mRegistry.get(); @@ -459,10 +460,10 @@ class DataAllocator // make a stl (pmr) vector template - o2::pmr::vector makeVector(const Output& spec, Args&&... args) + std::pmr::vector makeVector(const Output& spec, Args&&... args) { - o2::pmr::FairMQMemoryResource* targetResource = getMemoryResource(spec); - return o2::pmr::vector{targetResource, std::forward(args)...}; + std::pmr::memory_resource* targetResource = getMemoryResource(spec); + return std::pmr::vector{targetResource, std::forward(args)...}; } struct CacheId { diff --git a/Framework/Core/include/Framework/DataChunk.h b/Framework/Core/include/Framework/DataChunk.h index 664092216a0ee..bbb1c44098f46 100644 --- a/Framework/Core/include/Framework/DataChunk.h +++ b/Framework/Core/include/Framework/DataChunk.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2025 CERN and copyright holders of ALICE O2. // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. // All rights not expressly granted are reserved. // @@ -8,14 +8,13 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef FRAMEWORK_DATACHUNK_H -#define FRAMEWORK_DATACHUNK_H +#ifndef O2_FRAMEWORK_DATACHUNK_H_ +#define O2_FRAMEWORK_DATACHUNK_H_ -#include "MemoryResources/MemoryResources.h" +#include +#include -namespace o2 -{ -namespace framework +namespace o2::framework { /// @class DataChunk A resizable buffer used with DPL's DataAllocator /// DataChunk derives from std::vector with polymorphic allocator and forbids copying, the underlying @@ -23,18 +22,11 @@ namespace framework /// message memory. /// Since MessageContext returns the object by reference, the forbidden copy and assignment makes sure that /// the code can not accidentally use a copy instead reference. -class DataChunk : public std::vector> +class DataChunk : public std::vector> { public: - // FIXME: want to have a general forwarding, but then the copy constructor is not deleted any more despite - // it's declared deleted - //template - //DataChunk(T&& arg, Args&&... args) : std::vector>(std::forward(args)...) - //{ - //} - // DataChunk is special and for the moment it's enough to declare the constructor with size and allocator - DataChunk(size_t size, const o2::pmr::polymorphic_allocator& allocator) : std::vector>(size, allocator) + DataChunk(size_t size, const std::pmr::polymorphic_allocator& allocator) : std::vector>(size, allocator) { } DataChunk(const DataChunk&) = delete; @@ -43,6 +35,6 @@ class DataChunk : public std::vector> DataChunk& operator=(DataChunk&&) = default; }; -} // namespace framework -} // namespace o2 -#endif // FRAMEWORK_DATACHUNK_H +} // namespace o2::framework + +#endif // O2_FRAMEWORK_DATACHUNK_H_ diff --git a/Framework/Core/include/Framework/MessageContext.h b/Framework/Core/include/Framework/MessageContext.h index 407bac0ceb00a..4b0047e3e33ad 100644 --- a/Framework/Core/include/Framework/MessageContext.h +++ b/Framework/Core/include/Framework/MessageContext.h @@ -28,11 +28,11 @@ #include #include -#include #include #include #include #include +#include #include @@ -182,7 +182,7 @@ class MessageContext // A memory resource which can force a minimum alignment, so that // the whole polymorphic allocator business is happy... - class AlignedMemoryResource : public pmr::FairMQMemoryResource + class AlignedMemoryResource : public fair::mq::MemoryResource { public: AlignedMemoryResource(fair::mq::MemoryResource* other) @@ -230,7 +230,7 @@ class MessageContext return mUpstream->deallocate(p, bytes, alignment < 64 ? 64 : alignment); } - [[nodiscard]] bool do_is_equal(const pmr::memory_resource& other) const noexcept override + [[nodiscard]] bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override { return this == &other; } @@ -240,7 +240,7 @@ class MessageContext }; /// ContainerRefObject handles a message object holding an instance of type T - /// The allocator type is required to be o2::pmr::polymorphic_allocator + /// The allocator type is required to be std::pmr::polymorphic_allocator /// can not adopt an existing message, because the polymorphic_allocator will call type constructor, /// so this works only with new messages /// FIXME: not sure if we want to have this for all container types @@ -251,7 +251,7 @@ class MessageContext using value_type = typename T::value_type; using return_type = T; using buffer_type = return_type; - static_assert(std::is_base_of, typename T::allocator_type>::value, "container must have polymorphic allocator"); + static_assert(std::is_base_of, typename T::allocator_type>::value, "container must have polymorphic allocator"); /// default contructor forbidden, object always has to control message instances ContainerRefObject() = delete; /// constructor taking header message by move and creating the paypload message @@ -263,7 +263,7 @@ class MessageContext // the memory resource takes ownership of the message mResource{mFactory ? AlignedMemoryResource(mFactory->GetMemoryResource()) : AlignedMemoryResource(nullptr)}, // create the vector with apropriate underlying memory resource for the message - mData{std::forward(args)..., pmr::polymorphic_allocator(&mResource)} + mData{std::forward(args)..., std::pmr::polymorphic_allocator(&mResource)} { // FIXME: drop this repeated check and make sure at initial setup of devices that everything is fine // introduce error policy @@ -313,7 +313,7 @@ class MessageContext /// VectorObject handles a message object holding std::vector with polymorphic_allocator /// can not adopt an existing message, because the polymorphic_allocator will call the element constructor, /// so this works only with new messages - template >>> + template >>> class VectorObject : public _BASE { public: diff --git a/Framework/Core/src/LifetimeHelpers.cxx b/Framework/Core/src/LifetimeHelpers.cxx index 21aa29c1f10e9..439e6f852123a 100644 --- a/Framework/Core/src/LifetimeHelpers.cxx +++ b/Framework/Core/src/LifetimeHelpers.cxx @@ -353,7 +353,7 @@ size_t readToMessage(void* p, size_t size, size_t nmemb, void* userdata) if (size == 0) { return 0; } - auto* buffer = (o2::pmr::vector*)userdata; + auto* buffer = (std::pmr::vector*)userdata; size_t oldSize = buffer->size(); buffer->resize(oldSize + nmemb * size); memcpy(buffer->data() + oldSize, p, nmemb * size); diff --git a/Framework/Core/test/test_DataAllocator.cxx b/Framework/Core/test/test_DataAllocator.cxx index fefb6438b98d5..739c999e868b9 100644 --- a/Framework/Core/test/test_DataAllocator.cxx +++ b/Framework/Core/test/test_DataAllocator.cxx @@ -144,7 +144,7 @@ DataProcessorSpec getSourceSpec() // make a PMR std::vector, make it large to test the auto transport buffer resize funtionality as well Output pmrOutputSpec{"TST", "PMRTESTVECTOR", 0}; - auto pmrvec = o2::pmr::vector(pc.outputs().getMemoryResource(pmrOutputSpec)); + auto pmrvec = std::pmr::vector(pc.outputs().getMemoryResource(pmrOutputSpec)); pmrvec.reserve(100); pmrvec.emplace_back(o2::test::TriviallyCopyable{1, 2, 3}); pc.outputs().adoptContainer(pmrOutputSpec, std::move(pmrvec)); diff --git a/Framework/Core/test/test_DataRefUtils.cxx b/Framework/Core/test/test_DataRefUtils.cxx index d4accde0fecf0..a0bc4dec49df6 100644 --- a/Framework/Core/test/test_DataRefUtils.cxx +++ b/Framework/Core/test/test_DataRefUtils.cxx @@ -15,6 +15,7 @@ #include #include "Framework/RootSerializationSupport.h" #include "Framework/DataRefUtils.h" +#include #include #include diff --git a/Framework/Core/test/test_DataRelayer.cxx b/Framework/Core/test/test_DataRelayer.cxx index 7d5a3ded88e16..5f6cde4078540 100644 --- a/Framework/Core/test/test_DataRelayer.cxx +++ b/Framework/Core/test/test_DataRelayer.cxx @@ -26,6 +26,7 @@ #include "Framework/WorkflowSpec.h" #include #include +#include #include #include #include diff --git a/Framework/Core/test/test_FairMQ.cxx b/Framework/Core/test/test_FairMQ.cxx index f11d98505298f..e80741c143060 100644 --- a/Framework/Core/test/test_FairMQ.cxx +++ b/Framework/Core/test/test_FairMQ.cxx @@ -27,7 +27,7 @@ using namespace o2::pmr; //__________________________________________________________________________________________________ // addDataBlock for generic (compatible) containers, that is contiguous containers using the pmr allocator template ::value, int>::type = 0> -bool addDataBlock(fair::mq::Parts& parts, o2::header::Stack&& inputStack, ContainerT&& inputData, o2::pmr::FairMQMemoryResource* targetResource = nullptr) +bool addDataBlock(fair::mq::Parts& parts, o2::header::Stack&& inputStack, ContainerT&& inputData, fair::mq::MemoryResource* targetResource = nullptr) { auto headerMessage = o2::pmr::getMessage(std::move(inputStack), targetResource); auto dataMessage = o2::pmr::getMessage(std::forward(inputData), targetResource); @@ -42,7 +42,7 @@ bool addDataBlock(fair::mq::Parts& parts, o2::header::Stack&& inputStack, Contai // addDataBlock for data already wrapped in fair::mq::MessagePtr // note: since we cannot partially specialize function templates, use SFINAE here instead template ::value, int>::type = 0> -bool addDataBlock(fair::mq::Parts& parts, o2::header::Stack&& inputStack, ContainerT&& dataMessage, o2::pmr::FairMQMemoryResource* targetResource = nullptr) +bool addDataBlock(fair::mq::Parts& parts, o2::header::Stack&& inputStack, ContainerT&& dataMessage, fair::mq::MemoryResource* targetResource = nullptr) { // make sure the payload size in DataHeader corresponds to message size using o2::header::DataHeader; @@ -174,9 +174,8 @@ TEST_CASE("addDataBlockForEach_test") int i; int j; }; - using namespace fair::mq::pmr; fair::mq::Parts message; - std::vector> vec(polymorphic_allocator{allocZMQ}); + std::vector> vec(std::pmr::polymorphic_allocator{allocZMQ}); vec.reserve(100); vec.push_back({1, 2}); vec.push_back({3, 4}); diff --git a/Framework/Core/test/test_O2DataModelHelpers.cxx b/Framework/Core/test/test_O2DataModelHelpers.cxx index c32738699c222..98a269ed3a907 100644 --- a/Framework/Core/test/test_O2DataModelHelpers.cxx +++ b/Framework/Core/test/test_O2DataModelHelpers.cxx @@ -13,6 +13,7 @@ #include "Framework/DataProcessingHeader.h" #include "Headers/DataHeader.h" #include "Headers/Stack.h" +#include "MemoryResources/MemoryResources.h" #include #include diff --git a/Framework/Utils/include/DPLUtils/Utils.h b/Framework/Utils/include/DPLUtils/Utils.h index 8786a579fdc53..93758fbfe53db 100644 --- a/Framework/Utils/include/DPLUtils/Utils.h +++ b/Framework/Utils/include/DPLUtils/Utils.h @@ -37,7 +37,7 @@ o2f::DataProcessorSpec defineBroadcaster(std::string devName, o2f::InputSpec usr size_t fixMsgSize); o2f::DataProcessorSpec defineBroadcaster(std::string devName, o2f::InputSpec usrInput, o2f::Outputs usrOutputs); -using OutputBuffer = o2::pmr::vector; +using OutputBuffer = std::pmr::vector; // Merger implementations o2f::DataProcessorSpec defineMerger(std::string devName, o2f::Inputs usrInputs, o2f::OutputSpec usrOutput, std::function const mergerFunc); From 1f482616e0341f84b3cadb23deb72efb824d173a Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 24 Jul 2025 13:37:28 +0200 Subject: [PATCH 201/315] DPL: add component for Arrow Acero Streaming Engine --- dependencies/O2Dependencies.cmake | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/dependencies/O2Dependencies.cmake b/dependencies/O2Dependencies.cmake index 0e0b1caf7d3ba..26f381a4ef79f 100644 --- a/dependencies/O2Dependencies.cmake +++ b/dependencies/O2Dependencies.cmake @@ -65,6 +65,33 @@ if(NOT TARGET ArrowDataset::arrow_dataset_shared) ) endif() +if(NOT TARGET ArrowAcero::arrow_acero_shared) + # ArrowAcero::arrow_acero_shared is linked for no reason to parquet + # so we cannot use it because we do not want to build parquet itself. + # For that reason at the moment we need to do the lookup by hand. + get_target_property(ARROW_SHARED_LOCATION Arrow::arrow_shared LOCATION) + get_filename_component(ARROW_SHARED_DIR ${ARROW_SHARED_LOCATION} DIRECTORY) + + find_library(ARROW_ACERO_SHARED arrow_acero + PATHS ${ARROW_SHARED_DIR} + NO_DEFAULT_PATH + ) + + if(ARROW_ACERO_SHARED) + message(STATUS + "Found arrow_acero_shared library at: ${ARROW_ACERO_SHARED}") + else() + message(FATAL_ERROR + "arrow_acero_shared library not found in ${ARROW_SHARED_DIR}") + endif() + + # Step 3: Create a target for ArrowAcero::arrow_acero_shared + add_library(ArrowAcero::arrow_acero_shared SHARED IMPORTED) + set_target_properties(ArrowAcero::arrow_acero_shared PROPERTIES + IMPORTED_LOCATION ${ARROW_ACERO_SHARED} + ) +endif() + if (NOT TARGET Gandiva::gandiva_shared) add_library(Gandiva::gandiva_shared ALIAS gandiva_shared) endif() From 28345fbd29d86fad3bdbb789ef474f82e3f04a2d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 7 Aug 2025 12:43:33 +0200 Subject: [PATCH 202/315] Get rid of C++ extension warning --- CCDB/include/CCDB/CcdbApi.h | 3 --- CCDB/src/CcdbApi.cxx | 20 ++++++-------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/CCDB/include/CCDB/CcdbApi.h b/CCDB/include/CCDB/CcdbApi.h index 60097ff86baeb..9dc69cd10fc84 100644 --- a/CCDB/include/CCDB/CcdbApi.h +++ b/CCDB/include/CCDB/CcdbApi.h @@ -576,9 +576,6 @@ class CcdbApi //: public DatabaseInterface // convert type_info to TClass, throw on failure static TClass* tinfo2TClass(std::type_info const& tinfo); - // split string on delimiters and return tokens as vector - std::vector splitString(const std::string& str, const char* delimiters); - typedef size_t (*CurlWriteCallback)(void*, size_t, size_t, void*); void initCurlOptionsForRetrieve(CURL* curlHandle, void* pointer, CurlWriteCallback writeCallback, bool followRedirect = true) const; diff --git a/CCDB/src/CcdbApi.cxx b/CCDB/src/CcdbApi.cxx index 056435ca9f0fe..541ef28d17ede 100644 --- a/CCDB/src/CcdbApi.cxx +++ b/CCDB/src/CcdbApi.cxx @@ -24,6 +24,7 @@ #include "Framework/DataTakingContext.h" #include #include +#include #include #include #include @@ -1665,22 +1666,13 @@ int CcdbApi::updateMetadata(std::string const& path, std::map CcdbApi::splitString(const std::string& str, const char* delimiters) -{ - std::vector tokens; - char stringForStrTok[str.length() + 1]; - strcpy(stringForStrTok, str.c_str()); - char* token = strtok(stringForStrTok, delimiters); - while (token != nullptr) { - tokens.emplace_back(token); - token = strtok(nullptr, delimiters); - } - return tokens; -} - void CcdbApi::initHostsPool(std::string hosts) { - hostsPool = splitString(hosts, ",;"); + hostsPool.clear(); + auto splitted = hosts | std::views::transform([](char c) { return (c == ';') ? ',' : c; }) | std::views::split(','); + for (auto&& part : splitted) { + hostsPool.emplace_back(part.begin(), part.end()); + } } std::string CcdbApi::getHostUrl(int hostIndex) const From 1f0e87470ba69927be19730af82d79d7cfd1d0fb Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 7 Aug 2025 15:41:11 +0200 Subject: [PATCH 203/315] DPL tests: drop unneeded includes --- Framework/Core/test/test_HTTPParser.cxx | 2 -- Framework/Core/test/test_Parallel.cxx | 2 -- Framework/Core/test/test_RegionInfoCallbackService.cxx | 7 ------- Framework/Core/test/test_Services.cxx | 2 -- Framework/Core/test/test_TimePipeline.cxx | 6 ++---- 5 files changed, 2 insertions(+), 17 deletions(-) diff --git a/Framework/Core/test/test_HTTPParser.cxx b/Framework/Core/test/test_HTTPParser.cxx index b2889f9f305e1..1b87fcf49cfd4 100644 --- a/Framework/Core/test/test_HTTPParser.cxx +++ b/Framework/Core/test/test_HTTPParser.cxx @@ -9,8 +9,6 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include - #include "../src/HTTPParser.h" #include diff --git a/Framework/Core/test/test_Parallel.cxx b/Framework/Core/test/test_Parallel.cxx index 7967f55a7b93d..35b8a52e663a1 100644 --- a/Framework/Core/test/test_Parallel.cxx +++ b/Framework/Core/test/test_Parallel.cxx @@ -17,8 +17,6 @@ #include "Framework/ParallelContext.h" #include "Framework/runDataProcessing.h" -#include - using namespace o2::framework; struct FakeCluster { diff --git a/Framework/Core/test/test_RegionInfoCallbackService.cxx b/Framework/Core/test/test_RegionInfoCallbackService.cxx index f0e7160bcfaad..178d6048545e6 100644 --- a/Framework/Core/test/test_RegionInfoCallbackService.cxx +++ b/Framework/Core/test/test_RegionInfoCallbackService.cxx @@ -8,19 +8,12 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include - -#include "Framework/InputSpec.h" #include "Framework/CallbackService.h" #include "Framework/ControlService.h" #include "Framework/DataProcessorSpec.h" -#include "Framework/ParallelContext.h" #include "Framework/runDataProcessing.h" #include "Framework/Logger.h" -#include -#include - using namespace o2::framework; using DataHeader = o2::header::DataHeader; diff --git a/Framework/Core/test/test_Services.cxx b/Framework/Core/test/test_Services.cxx index 056a3d0d9b6c4..abac9eca5e9b0 100644 --- a/Framework/Core/test/test_Services.cxx +++ b/Framework/Core/test/test_Services.cxx @@ -8,8 +8,6 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include - #include "Framework/ServiceHandle.h" #include "Framework/ServiceRegistry.h" #include "Framework/CallbackService.h" diff --git a/Framework/Core/test/test_TimePipeline.cxx b/Framework/Core/test/test_TimePipeline.cxx index 8740f2ba365cd..5ff3eeae5e6cf 100644 --- a/Framework/Core/test/test_TimePipeline.cxx +++ b/Framework/Core/test/test_TimePipeline.cxx @@ -8,13 +8,11 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/InputSpec.h" + #include "Framework/DataProcessorSpec.h" #include "Framework/ParallelContext.h" #include "Framework/runDataProcessing.h" - -#include - +#include #include using namespace o2::framework; From 87ef0fc667ebea8b6c075d87a049cc10178a1676 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 7 Aug 2025 15:41:11 +0200 Subject: [PATCH 204/315] DPL: drop more boost_test usage --- Framework/Core/CMakeLists.txt | 13 ++++++++----- Framework/Core/test/test_InfoLogger.cxx | 10 +++------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Framework/Core/CMakeLists.txt b/Framework/Core/CMakeLists.txt index d69194c83285e..f24ac6387649e 100644 --- a/Framework/Core/CMakeLists.txt +++ b/Framework/Core/CMakeLists.txt @@ -315,11 +315,14 @@ set_property(TARGET o2-test-framework-root PROPERTY RUNTIME_OUTPUT_DIRECTORY ${o add_test(NAME framework:root COMMAND o2-test-framework-root --skip-benchmarks) add_test(NAME framework:crash COMMAND sh -e -c "PATH=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}:$PATH ${CMAKE_CURRENT_LIST_DIR}/test/test_AllCrashTypes.sh") -o2_add_test(InfoLogger NAME test_Framework_test_InfoLogger - SOURCES test/test_InfoLogger.cxx - COMPONENT_NAME Framework - LABELS framework - PUBLIC_LINK_LIBRARIES O2::Framework AliceO2::InfoLogger) +add_executable(o2-test-framework-infologger + test/test_InfoLogger.cxx) +target_link_libraries(o2-test-framework-infologger PRIVATE O2::Framework) +target_link_libraries(o2-test-framework-infologger PRIVATE AliceO2::InfoLogger) +target_link_libraries(o2-test-framework-infologger PRIVATE O2::Catch2) +set_property(TARGET o2-test-framework-infologger + PROPERTY RUNTIME_OUTPUT_DIRECTORY ${outdir}) +add_test(NAME framework:infologger COMMAND o2-test-framework-infologger) o2_add_executable(dpl-null-sink SOURCES src/o2NullSink.cxx diff --git a/Framework/Core/test/test_InfoLogger.cxx b/Framework/Core/test/test_InfoLogger.cxx index 4fde33c8775d7..b3a4e794bdcd4 100644 --- a/Framework/Core/test/test_InfoLogger.cxx +++ b/Framework/Core/test/test_InfoLogger.cxx @@ -8,16 +8,12 @@ // In applying this license CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#define BOOST_TEST_MODULE Test Framework InfoLoggerTest -#define BOOST_TEST_MAIN -#define BOOST_TEST_DYN_LINK - -#include +#include #include using namespace AliceO2::InfoLogger; -BOOST_AUTO_TEST_CASE(InfoLoggerTest) +TEST_CASE("InfoLoggerTest") { // define infologger output to stdout, as we don't want to use the default infoLoggerD pipe which might not be running here @@ -27,5 +23,5 @@ BOOST_AUTO_TEST_CASE(InfoLoggerTest) InfoLogger theLog; // log a test message - BOOST_CHECK(theLog.log("This is a log message test to stdout") == 0); + CHECK(theLog.log("This is a log message test to stdout") == 0); } From 00279c7108ea07b1e5b4091297b7bbaa20665a4f Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 7 Aug 2025 15:41:11 +0200 Subject: [PATCH 205/315] DPL CCDB: move helper initialisation to a separate function --- Framework/CCDBSupport/src/CCDBHelpers.cxx | 97 ++++++++++++----------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/Framework/CCDBSupport/src/CCDBHelpers.cxx b/Framework/CCDBSupport/src/CCDBHelpers.cxx index 71b6282c80086..2d44469c641f4 100644 --- a/Framework/CCDBSupport/src/CCDBHelpers.cxx +++ b/Framework/CCDBSupport/src/CCDBHelpers.cxx @@ -20,10 +20,8 @@ #include "CCDB/CcdbApi.h" #include "CommonConstants/LHCConstants.h" #include "Framework/Signpost.h" -#include #include #include -#include O2_DECLARE_DYNAMIC_LOG(ccdb); @@ -159,6 +157,55 @@ CCDBHelpers::ParserResult CCDBHelpers::parseRemappings(char const* str) } } +void initialiseHelper(CCDBFetcherHelper& helper, ConfigParamRegistry const& options, std::vector const& outputRoutes) +{ + std::unordered_map accountedSpecs; + auto defHost = options.get("condition-backend"); + auto checkRate = options.get("condition-tf-per-query"); + auto checkMult = options.get("condition-tf-per-query-multiplier"); + helper.timeToleranceMS = options.get("condition-time-tolerance"); + helper.queryPeriodGlo = checkRate > 0 ? checkRate : std::numeric_limits::max(); + helper.queryPeriodFactor = checkMult > 0 ? checkMult : 1; + LOGP(info, "CCDB Backend at: {}, validity check for every {} TF{}", defHost, helper.queryPeriodGlo, helper.queryPeriodFactor == 1 ? std::string{} : fmt::format(", (query for high-rate objects downscaled by {})", helper.queryPeriodFactor)); + LOGP(info, "Hook to enable signposts for CCDB messages at {}", (void*)&private_o2_log_ccdb->stacktrace); + auto remapString = options.get("condition-remap"); + CCDBHelpers::ParserResult result = CCDBHelpers::parseRemappings(remapString.c_str()); + if (!result.error.empty()) { + throw runtime_error_f("Error while parsing remapping string %s", result.error.c_str()); + } + helper.remappings = result.remappings; + helper.apis[""].init(defHost); // default backend + LOGP(info, "Initialised default CCDB host {}", defHost); + // + for (auto& entry : helper.remappings) { // init api instances for every host seen in the remapping + if (helper.apis.find(entry.second) == helper.apis.end()) { + helper.apis[entry.second].init(entry.second); + LOGP(info, "Initialised custom CCDB host {}", entry.second); + } + LOGP(info, "{} is remapped to {}", entry.first, entry.second); + } + helper.createdNotBefore = std::to_string(options.get("condition-not-before")); + helper.createdNotAfter = std::to_string(options.get("condition-not-after")); + + for (auto& route : outputRoutes) { + if (route.matcher.lifetime != Lifetime::Condition) { + continue; + } + auto specStr = DataSpecUtils::describe(route.matcher); + if (accountedSpecs.find(specStr) != accountedSpecs.end()) { + continue; + } + accountedSpecs[specStr] = true; + helper.routes.push_back(route); + LOGP(info, "The following route is a condition {}", DataSpecUtils::describe(route.matcher)); + for (auto& metadata : route.matcher.metadata) { + if (metadata.type == VariantType::String) { + LOGP(info, "- {}: {}", metadata.name, metadata.defaultValue.asString()); + } + } + } +} + auto getOrbitResetTime(std::pmr::vector const& v) -> Long64_t { Int_t previousErrorLevel = gErrorIgnoreLevel; @@ -307,51 +354,7 @@ AlgorithmSpec CCDBHelpers::fetchFromCCDB() { return adaptStateful([](CallbackService& callbacks, ConfigParamRegistry const& options, DeviceSpec const& spec) { std::shared_ptr helper = std::make_shared(); - std::unordered_map accountedSpecs; - auto defHost = options.get("condition-backend"); - auto checkRate = options.get("condition-tf-per-query"); - auto checkMult = options.get("condition-tf-per-query-multiplier"); - helper->timeToleranceMS = options.get("condition-time-tolerance"); - helper->queryPeriodGlo = checkRate > 0 ? checkRate : std::numeric_limits::max(); - helper->queryPeriodFactor = checkMult > 0 ? checkMult : 1; - LOGP(info, "CCDB Backend at: {}, validity check for every {} TF{}", defHost, helper->queryPeriodGlo, helper->queryPeriodFactor == 1 ? std::string{} : fmt::format(", (query for high-rate objects downscaled by {})", helper->queryPeriodFactor)); - LOGP(info, "Hook to enable signposts for CCDB messages at {}", (void*)&private_o2_log_ccdb->stacktrace); - auto remapString = options.get("condition-remap"); - ParserResult result = CCDBHelpers::parseRemappings(remapString.c_str()); - if (!result.error.empty()) { - throw runtime_error_f("Error while parsing remapping string %s", result.error.c_str()); - } - helper->remappings = result.remappings; - helper->apis[""].init(defHost); // default backend - LOGP(info, "Initialised default CCDB host {}", defHost); - // - for (auto& entry : helper->remappings) { // init api instances for every host seen in the remapping - if (helper->apis.find(entry.second) == helper->apis.end()) { - helper->apis[entry.second].init(entry.second); - LOGP(info, "Initialised custom CCDB host {}", entry.second); - } - LOGP(info, "{} is remapped to {}", entry.first, entry.second); - } - helper->createdNotBefore = std::to_string(options.get("condition-not-before")); - helper->createdNotAfter = std::to_string(options.get("condition-not-after")); - - for (auto &route : spec.outputs) { - if (route.matcher.lifetime != Lifetime::Condition) { - continue; - } - auto specStr = DataSpecUtils::describe(route.matcher); - if (accountedSpecs.find(specStr) != accountedSpecs.end()) { - continue; - } - accountedSpecs[specStr] = true; - helper->routes.push_back(route); - LOGP(info, "The following route is a condition {}", DataSpecUtils::describe(route.matcher)); - for (auto& metadata : route.matcher.metadata) { - if (metadata.type == VariantType::String) { - LOGP(info, "- {}: {}", metadata.name, metadata.defaultValue.asString()); - } - } - } + initialiseHelper(*helper, options, spec.outputs); /// Add a callback on stop which dumps the statistics for the caching per /// path callbacks.set([helper]() { From 6209646b6e6b4161efa09179ed1b52dde5b834a0 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Mon, 30 Jun 2025 09:39:40 +0200 Subject: [PATCH 206/315] DPL Analysis: fix hash calculation for the string_views --- Framework/Core/include/Framework/ASoA.h | 385 +++++++++--------- .../Core/include/Framework/StringHelpers.h | 7 + Framework/Core/test/test_StringHelpers.cxx | 5 + 3 files changed, 204 insertions(+), 193 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index ccf2cab5e6807..9703f8eb26b9d 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -34,7 +34,6 @@ #include #include // IWYU pragma: export #include -#include namespace o2::framework { @@ -2307,7 +2306,7 @@ consteval static std::string_view namespace_prefix() { constexpr auto name = o2::framework::type_name(); const auto pos = name.rfind(std::string_view{":"}); - return name.substr(0, pos - 1); + return name.substr(0, pos + 1); } } // namespace @@ -2326,7 +2325,7 @@ consteval static std::string_view namespace_prefix() #define DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) \ struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ static constexpr const char* mLabel = _Label_; \ - static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ + static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ static_assert(!((*(mLabel + 1) == 'I' && *(mLabel + 2) == 'n' && *(mLabel + 3) == 'd' && *(mLabel + 4) == 'e' && *(mLabel + 5) == 'x')), "Index is not a valid column name"); \ using base = o2::soa::Column<_Type_, _Name_>; \ using type = _Type_; \ @@ -2362,7 +2361,7 @@ consteval static std::string_view namespace_prefix() #define DECLARE_SOA_BITMAP_COLUMN_FULL(_Name_, _Getter_, _Size_, _Label_) \ struct _Name_ : o2::soa::Column { \ static constexpr const char* mLabel = _Label_; \ - static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ + static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ static_assert(!((*(mLabel + 1) == 'I' && *(mLabel + 2) == 'n' && *(mLabel + 3) == 'd' && *(mLabel + 4) == 'e' && *(mLabel + 5) == 'x')), "Index is not a valid column name"); \ using base = o2::soa::Column; \ using type = MAKEINT(_Size_); \ @@ -2392,38 +2391,38 @@ consteval static std::string_view namespace_prefix() /// An 'expression' column. i.e. a column that can be calculated from other /// columns with gandiva based on static C++ expression. -#define DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_, _Expression_) \ - struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ - static constexpr const char* mLabel = _Label_; \ - static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ - using base = o2::soa::Column<_Type_, _Name_>; \ - using type = _Type_; \ - using column_t = _Name_; \ - using spawnable_t = std::true_type; \ - _Name_(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_() = default; \ - _Name_(_Name_ const& other) = default; \ - _Name_& operator=(_Name_ const& other) = default; \ - \ - decltype(auto) _Getter_() const \ - { \ - return *mColumnIterator; \ - } \ - \ - decltype(auto) get() const \ - { \ - return _Getter_(); \ - } \ - \ - static o2::framework::expressions::Projector Projector() \ - { \ - return _Expression_; \ - } \ - }; \ +#define DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_, _Expression_) \ + struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ + static constexpr const char* mLabel = _Label_; \ + static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ + using base = o2::soa::Column<_Type_, _Name_>; \ + using type = _Type_; \ + using column_t = _Name_; \ + using spawnable_t = std::true_type; \ + _Name_(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_() = default; \ + _Name_(_Name_ const& other) = default; \ + _Name_& operator=(_Name_ const& other) = default; \ + \ + decltype(auto) _Getter_() const \ + { \ + return *mColumnIterator; \ + } \ + \ + decltype(auto) get() const \ + { \ + return _Getter_(); \ + } \ + \ + static o2::framework::expressions::Projector Projector() \ + { \ + return _Expression_; \ + } \ + }; \ [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Expression_) \ @@ -2431,34 +2430,34 @@ consteval static std::string_view namespace_prefix() /// A configurable 'expression' column. i.e. a column that can be calculated from other /// columns with gandiva based on dynamically supplied C++ expression or a string definition. -#define DECLARE_SOA_CONFIGURABLE_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Label_) \ - struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ - static constexpr const char* mLabel = _Label_; \ - static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ - static constexpr const int32_t mHash = _Label_ ""_h; \ - using base = o2::soa::Column<_Type_, _Name_>; \ - using type = _Type_; \ - using column_t = _Name_; \ - using spawnable_t = std::true_type; \ - _Name_(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_() = default; \ - _Name_(_Name_ const& other) = default; \ - _Name_& operator=(_Name_ const& other) = default; \ - \ - decltype(auto) _Getter_() const \ - { \ - return *mColumnIterator; \ - } \ - \ - decltype(auto) get() const \ - { \ - return _Getter_(); \ - } \ - }; \ +#define DECLARE_SOA_CONFIGURABLE_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Label_) \ + struct _Name_ : o2::soa::Column<_Type_, _Name_> { \ + static constexpr const char* mLabel = _Label_; \ + static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \ + static constexpr const int32_t mHash = _Label_ ""_h; \ + using base = o2::soa::Column<_Type_, _Name_>; \ + using type = _Type_; \ + using column_t = _Name_; \ + using spawnable_t = std::true_type; \ + _Name_(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_() = default; \ + _Name_(_Name_ const& other) = default; \ + _Name_& operator=(_Name_ const& other) = default; \ + \ + decltype(auto) _Getter_() const \ + { \ + return *mColumnIterator; \ + } \ + \ + decltype(auto) get() const \ + { \ + return _Getter_(); \ + } \ + }; \ [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() } /// An index column is a column of indices to elements / of another table named @@ -2731,81 +2730,81 @@ consteval auto getIndexTargets() #define DECLARE_SOA_ARRAY_INDEX_COLUMN_CUSTOM(_Name_, _Getter_, _Label_) DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, int32_t, _Name_##s, _Label_, "") /// NORMAL -#define DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, _Label_, _Suffix_) \ - struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ - static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ - static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ - static constexpr const char* mLabel = "fIndex" _Label_ _Suffix_; \ - static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_##Id>(), std::string_view{#_Getter_ "Id"}); \ - using base = o2::soa::Column<_Type_, _Name_##Id>; \ - using type = _Type_; \ - using column_t = _Name_##Id; \ - using binding_t = _Table_; \ - static constexpr auto index_targets = getIndexTargets<_Table_>(); \ - _Name_##Id(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_##Id() = default; \ - _Name_##Id(_Name_##Id const& other) = default; \ - _Name_##Id& operator=(_Name_##Id const& other) = default; \ - type inline getId() const \ - { \ - return _Getter_##Id(); \ - } \ - \ - type _Getter_##Id() const \ - { \ - return *mColumnIterator; \ - } \ - \ - bool has_##_Getter_() const \ - { \ - return *mColumnIterator >= 0; \ - } \ - \ - template \ - auto _Getter_##_as() const \ - { \ - if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \ - o2::soa::notBoundTable(#_Table_); \ - } \ - if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ - o2::soa::accessingInvalidIndexFor(#_Getter_); \ - } \ - auto t = mBinding.get(); \ - if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ - o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \ - } \ - return t->rawIteratorAt(*mColumnIterator); \ - } \ - \ - auto _Getter_() const \ - { \ - return _Getter_##_as(); \ - } \ - \ - template \ - bool setCurrent(T* current) \ - { \ - if constexpr (o2::soa::is_binding_compatible_v()) { \ - assert(current != nullptr); \ - this->mBinding.bind(current); \ - return true; \ - } \ - return false; \ - } \ - \ - bool setCurrentRaw(o2::soa::Binding current) \ - { \ - this->mBinding = current; \ - return true; \ - } \ - binding_t const* getCurrent() const { return mBinding.get(); } \ - o2::soa::Binding getCurrentRaw() const { return mBinding; } \ - o2::soa::Binding mBinding; \ - }; \ +#define DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, _Label_, _Suffix_) \ + struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ + static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ + static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \ + static constexpr const char* mLabel = "fIndex" _Label_ _Suffix_; \ + static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_##Id>(), std::string_view{#_Getter_ "Id"}); \ + using base = o2::soa::Column<_Type_, _Name_##Id>; \ + using type = _Type_; \ + using column_t = _Name_##Id; \ + using binding_t = _Table_; \ + static constexpr auto index_targets = getIndexTargets<_Table_>(); \ + _Name_##Id(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_##Id() = default; \ + _Name_##Id(_Name_##Id const& other) = default; \ + _Name_##Id& operator=(_Name_##Id const& other) = default; \ + type inline getId() const \ + { \ + return _Getter_##Id(); \ + } \ + \ + type _Getter_##Id() const \ + { \ + return *mColumnIterator; \ + } \ + \ + bool has_##_Getter_() const \ + { \ + return *mColumnIterator >= 0; \ + } \ + \ + template \ + auto _Getter_##_as() const \ + { \ + if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \ + o2::soa::notBoundTable(#_Table_); \ + } \ + if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ + o2::soa::accessingInvalidIndexFor(#_Getter_); \ + } \ + auto t = mBinding.get(); \ + if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ + o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \ + } \ + return t->rawIteratorAt(*mColumnIterator); \ + } \ + \ + auto _Getter_() const \ + { \ + return _Getter_##_as(); \ + } \ + \ + template \ + bool setCurrent(T* current) \ + { \ + if constexpr (o2::soa::is_binding_compatible_v()) { \ + assert(current != nullptr); \ + this->mBinding.bind(current); \ + return true; \ + } \ + return false; \ + } \ + \ + bool setCurrentRaw(o2::soa::Binding current) \ + { \ + this->mBinding = current; \ + return true; \ + } \ + binding_t const* getCurrent() const { return mBinding.get(); } \ + o2::soa::Binding getCurrentRaw() const { return mBinding; } \ + o2::soa::Binding mBinding; \ + }; \ [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" #_Table_ _Suffix_, _Name_##Id::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Table_, _Suffix_) DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, #_Table_, _Suffix_) @@ -2813,60 +2812,60 @@ consteval auto getIndexTargets() #define DECLARE_SOA_INDEX_COLUMN_CUSTOM(_Name_, _Getter_, _Label_) DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, int32_t, _Name_##s, _Label_, "") /// SELF -#define DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, _IndexTarget_) \ - struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ - static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ - static constexpr const char* mLabel = "fIndex" _Label_; \ - static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_##Id>(), std::string_view{#_Getter_ "Id"}); \ - using base = o2::soa::Column<_Type_, _Name_##Id>; \ - using type = _Type_; \ - using column_t = _Name_##Id; \ - using self_index_t = std::true_type; \ - using compatible_signature = std::conditional, _IndexTarget_, void>; \ - _Name_##Id(arrow::ChunkedArray const* column) \ - : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ - { \ - } \ - \ - _Name_##Id() = default; \ - _Name_##Id(_Name_##Id const& other) = default; \ - _Name_##Id& operator=(_Name_##Id const& other) = default; \ - type inline getId() const \ - { \ - return _Getter_##Id(); \ - } \ - \ - type _Getter_##Id() const \ - { \ - return *mColumnIterator; \ - } \ - \ - bool has_##_Getter_() const \ - { \ - return *mColumnIterator >= 0; \ - } \ - \ - template \ - auto _Getter_##_as() const \ - { \ - if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ - o2::soa::accessingInvalidIndexFor(#_Getter_); \ - } \ - auto t = mBinding.get(); \ - if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ - o2::soa::dereferenceWithWrongType(#_Getter_, "self"); \ - } \ - return t->rawIteratorAt(*mColumnIterator); \ - } \ - \ - bool setCurrentRaw(o2::soa::Binding current) \ - { \ - this->mBinding = current; \ - return true; \ - } \ - o2::soa::Binding getCurrentRaw() const { return mBinding; } \ - o2::soa::Binding mBinding; \ - }; \ +#define DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, _IndexTarget_) \ + struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \ + static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \ + static constexpr const char* mLabel = "fIndex" _Label_; \ + static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_##Id>(), std::string_view{#_Getter_ "Id"}); \ + using base = o2::soa::Column<_Type_, _Name_##Id>; \ + using type = _Type_; \ + using column_t = _Name_##Id; \ + using self_index_t = std::true_type; \ + using compatible_signature = std::conditional, _IndexTarget_, void>; \ + _Name_##Id(arrow::ChunkedArray const* column) \ + : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator(column)) \ + { \ + } \ + \ + _Name_##Id() = default; \ + _Name_##Id(_Name_##Id const& other) = default; \ + _Name_##Id& operator=(_Name_##Id const& other) = default; \ + type inline getId() const \ + { \ + return _Getter_##Id(); \ + } \ + \ + type _Getter_##Id() const \ + { \ + return *mColumnIterator; \ + } \ + \ + bool has_##_Getter_() const \ + { \ + return *mColumnIterator >= 0; \ + } \ + \ + template \ + auto _Getter_##_as() const \ + { \ + if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \ + o2::soa::accessingInvalidIndexFor(#_Getter_); \ + } \ + auto t = mBinding.get(); \ + if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \ + o2::soa::dereferenceWithWrongType(#_Getter_, "self"); \ + } \ + return t->rawIteratorAt(*mColumnIterator); \ + } \ + \ + bool setCurrentRaw(o2::soa::Binding current) \ + { \ + this->mBinding = current; \ + return true; \ + } \ + o2::soa::Binding getCurrentRaw() const { return mBinding; } \ + o2::soa::Binding mBinding; \ + }; \ [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" _Label_, _Name_##Id::hash, o2::framework::expressions::selectArrowType<_Type_>() } #define DECLARE_SOA_SELF_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, void) diff --git a/Framework/Core/include/Framework/StringHelpers.h b/Framework/Core/include/Framework/StringHelpers.h index e450764576c29..8a2d892062f70 100644 --- a/Framework/Core/include/Framework/StringHelpers.h +++ b/Framework/Core/include/Framework/StringHelpers.h @@ -85,6 +85,13 @@ consteval uint32_t crc32(Ts... Vs) return crc; } +template + requires(std::same_as && ...) +consteval uint32_t compile_time_hash(Ts... Vs) +{ + return crc32(Vs...) ^ 0xFFFFFFFF; +} + consteval uint32_t compile_time_hash(char const* str) { return crc32(str, static_cast(__builtin_strlen(str)) - 1) ^ 0xFFFFFFFF; diff --git a/Framework/Core/test/test_StringHelpers.cxx b/Framework/Core/test/test_StringHelpers.cxx index 44f3fffd4efee..96abe20b814a9 100644 --- a/Framework/Core/test/test_StringHelpers.cxx +++ b/Framework/Core/test/test_StringHelpers.cxx @@ -12,6 +12,9 @@ #include #include "Framework/StringHelpers.h" +static constexpr std::string_view part1 = "o2::aod::track::"; +static constexpr std::string_view part2 = "pt"; + TEST_CASE("StringHelpersHash") { std::string s{"test-string"}; @@ -19,6 +22,8 @@ TEST_CASE("StringHelpersHash") REQUIRE(runtime_hash(s.c_str()) == compile_time_hash("test-string")); REQUIRE(runtime_hash(cs) == compile_time_hash("test-string")); REQUIRE(runtime_hash(s.c_str()) == runtime_hash(cs)); + + REQUIRE(compile_time_hash(part1, part2) == "o2::aod::track::pt"_h); } template From 7129f4565628b8f9c6cbcdf2df43acd9d5a48272 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Mon, 30 Jun 2025 09:40:08 +0200 Subject: [PATCH 207/315] DPL Analysis: add parsing of expressions from strings --- Framework/Core/include/Framework/BasicOps.h | 58 ++ .../include/Framework/ExpressionHelpers.h | 19 +- .../Core/include/Framework/Expressions.h | 329 +++++++---- Framework/Core/src/Expressions.cxx | 535 +++++++++++++++++- Framework/Core/test/test_Expressions.cxx | 72 ++- 5 files changed, 856 insertions(+), 157 deletions(-) diff --git a/Framework/Core/include/Framework/BasicOps.h b/Framework/Core/include/Framework/BasicOps.h index 0927b557c86bc..06880de275b9e 100644 --- a/Framework/Core/include/Framework/BasicOps.h +++ b/Framework/Core/include/Framework/BasicOps.h @@ -10,6 +10,9 @@ // or submit itself to any jurisdiction. #ifndef O2_FRAMEWORK_BASICOPS_H_ #define O2_FRAMEWORK_BASICOPS_H_ +#include +#include +#include "CommonConstants/MathConstants.h" namespace o2::framework { @@ -46,6 +49,61 @@ enum BasicOp : unsigned int { BitwiseNot, Conditional // 3-ar functions }; + +static constexpr std::array mapping{ + "&&", + "||", + "+", + "-", + "/", + "*", + "&", + "|", + "^", + "<", + "<=", + ">", + ">=", + "==", + "!=", + "natan2", + "npow", + "nsqrt", + "nexp", + "nlog", + "nlog10", + "nsin", + "ncos", + "ntan", + "nasin", + "nacos", + "natan", + "nabs", + "nround", + "nbitwise_not", + "ifnode"}; + +static constexpr std::array mathConstants{ + "Almost0", + "Epsilon", + "Almost1", + "VeryBig", + "PI", + "TwoPI", + "PIHalf", + "PIThird", + "PIQuarter"}; + +static constexpr std::array mathConstantsValues{ + o2::constants::math::Almost0, + o2::constants::math::Epsilon, + o2::constants::math::Almost1, + o2::constants::math::VeryBig, + o2::constants::math::PI, + o2::constants::math::TwoPI, + o2::constants::math::PIHalf, + o2::constants::math::PIThird, + o2::constants::math::PIQuarter}; } // namespace o2::framework #endif // O2_FRAMEWORK_BASICOPS_H_ diff --git a/Framework/Core/include/Framework/ExpressionHelpers.h b/Framework/Core/include/Framework/ExpressionHelpers.h index f881abf7b0e6c..cd2ccd743c5d6 100644 --- a/Framework/Core/include/Framework/ExpressionHelpers.h +++ b/Framework/Core/include/Framework/ExpressionHelpers.h @@ -25,17 +25,26 @@ struct DatumSpec { size_t hash = 0; atype::type type = atype::NA; - explicit DatumSpec(size_t index, atype::type type_) : datum{index}, type{type_} {} - explicit DatumSpec(LiteralNode::var_t literal, atype::type type_) : datum{literal}, type{type_} {} - explicit DatumSpec(std::string binding, size_t hash_, atype::type type_) : datum{binding}, hash{hash_}, type{type_} {} + explicit constexpr DatumSpec(size_t index, atype::type type_) : datum{index}, type{type_} {} + explicit constexpr DatumSpec(LiteralNode::var_t literal, atype::type type_) : datum{literal}, type{type_} {} + explicit constexpr DatumSpec(std::string binding, size_t hash_, atype::type type_) : datum{binding}, hash{hash_}, type{type_} {} DatumSpec() = default; DatumSpec(DatumSpec const&) = default; DatumSpec(DatumSpec&&) = default; DatumSpec& operator=(DatumSpec const&) = default; DatumSpec& operator=(DatumSpec&&) = default; -}; -bool operator==(DatumSpec const& lhs, DatumSpec const& rhs); + bool operator==(DatumSpec const& rhs) const + { + bool eqValue = this->datum == rhs.datum; + bool eqHash = true; + if (this->datum.index() == 3 && eqValue) { + eqHash = this->hash == rhs.hash; + } + bool eqType = this->type == rhs.type; + return eqValue && eqHash && eqType; + } +}; std::ostream& operator<<(std::ostream& os, DatumSpec const& spec); diff --git a/Framework/Core/include/Framework/Expressions.h b/Framework/Core/include/Framework/Expressions.h index 4163a73f83983..6568f5d58c421 100644 --- a/Framework/Core/include/Framework/Expressions.h +++ b/Framework/Core/include/Framework/Expressions.h @@ -110,13 +110,16 @@ std::string upcastTo(atype::type f); /// An expression tree node corresponding to a literal value struct LiteralNode { + LiteralNode() + : value{-1}, + type{atype::INT32} + { + } template LiteralNode(T v) : value{v}, type{selectArrowType()} { } - LiteralNode(LiteralNode const& other) = default; - using var_t = LiteralValue::stored_type; var_t value; atype::type type = atype::NA; @@ -124,9 +127,16 @@ struct LiteralNode { /// An expression tree node corresponding to a column binding struct BindingNode { + constexpr BindingNode() + : name{nullptr}, + hash{0}, + type{atype::FLOAT} + { + } BindingNode(BindingNode const&) = default; BindingNode(BindingNode&&) = delete; constexpr BindingNode(const char* name_, uint32_t hash_, atype::type type_) : name{name_}, hash{hash_}, type{type_} {} + constexpr BindingNode(uint32_t hash_, atype::type type_) : name{nullptr}, hash{hash_}, type{type_} {} const char* name; uint32_t hash; atype::type type; @@ -134,8 +144,8 @@ struct BindingNode { /// An expression tree node corresponding to binary or unary operation struct OpNode { + OpNode() : op{BasicOp::Abs} {} OpNode(BasicOp op_) : op{op_} {} - OpNode(OpNode const& other) = default; BasicOp op; }; @@ -155,8 +165,6 @@ struct PlaceholderNode : LiteralNode { retrieve = [](InitContext& context, char const* name) { return LiteralNode::var_t{static_cast(context.options().get(name))}; }; } - PlaceholderNode(PlaceholderNode const& other) = default; - void reset(InitContext& context) { value = retrieve(context, name.data()); @@ -180,8 +188,6 @@ struct ParameterNode : LiteralNode { { } - ParameterNode(ParameterNode const&) = default; - template void reset(T value_, int index_ = -1) { @@ -221,7 +227,7 @@ struct Node { { } - Node(Node&& n) : self{std::forward(n.self)}, left{std::forward>(n.left)}, right{std::forward>(n.right)}, condition{std::forward>(n.condition)} + Node(Node&& n) : self{std::forward(n.self)}, left{std::forward>(n.left)}, right{std::forward>(n.right)}, condition{std::forward>(n.condition)}, binding{std::forward(n.binding)} { } @@ -229,6 +235,11 @@ struct Node { { } + Node(BindingNode const& n, std::string binding_) : self{n}, left{nullptr}, right{nullptr}, condition{nullptr}, binding{binding_} + { + get(self).name = binding.c_str(); + } + Node(ParameterNode&& p) : self{std::forward(p)}, left{nullptr}, right{nullptr}, condition{nullptr} { } @@ -239,12 +250,24 @@ struct Node { right{std::make_unique(std::forward(else_))}, condition{std::make_unique(std::forward(condition_))} {} + Node(ConditionalNode op, Node&& then_, std::unique_ptr&& else_, Node&& condition_) + : self{op}, + left{std::make_unique(std::forward(then_))}, + right{std::forward>(else_)}, + condition{std::make_unique(std::forward(condition_))} {} + Node(OpNode op, Node&& l, Node&& r) : self{op}, left{std::make_unique(std::forward(l))}, right{std::make_unique(std::forward(r))}, condition{nullptr} {} + Node(OpNode op, std::unique_ptr&& l, Node&& r) + : self{op}, + left{std::forward>(l)}, + right{std::make_unique(std::forward(r))}, + condition{nullptr} {} + Node(OpNode op, Node&& l) : self{op}, left{std::make_unique(std::forward(l))}, @@ -264,6 +287,10 @@ struct Node { if (other.condition != nullptr) { condition = std::make_unique(*other.condition); } + binding = other.binding; + if (!binding.empty()) { + get(self).name = binding.c_str(); + } } /// variant with possible nodes @@ -274,6 +301,9 @@ struct Node { std::unique_ptr left = nullptr; std::unique_ptr right = nullptr; std::unique_ptr condition = nullptr; + + /// buffer for dynamic binding + std::string binding; }; /// helper struct used to parse trees @@ -315,54 +345,58 @@ void walk(Node* head, L&& pred) } } +/// helper concepts +template +concept arithmetic = std::is_arithmetic_v; + /// overloaded operators to build the tree from an expression -#define BINARY_OP_NODES(_operator_, _operation_) \ - inline Node operator _operator_(Node&& left, Node&& right) \ - { \ - return Node{OpNode{BasicOp::_operation_}, std::forward(left), std::forward(right)}; \ - } \ - template \ - inline Node operator _operator_(Node&& left, T right) requires(std::is_arithmetic_v>) \ - { \ - return Node{OpNode{BasicOp::_operation_}, std::forward(left), LiteralNode{right}}; \ - } \ - template \ - inline Node operator _operator_(T left, Node&& right) requires(std::is_arithmetic_v>) \ - { \ - return Node{OpNode{BasicOp::_operation_}, LiteralNode{left}, std::forward(right)}; \ - } \ - template \ - inline Node operator _operator_(Node&& left, Configurable const& right) \ - { \ - return Node{OpNode{BasicOp::_operation_}, std::forward(left), PlaceholderNode{right}}; \ - } \ - template \ - inline Node operator _operator_(Configurable const& left, Node&& right) \ - { \ - return Node{OpNode{BasicOp::_operation_}, PlaceholderNode{left}, std::forward(right)}; \ - } \ - inline Node operator _operator_(BindingNode const& left, BindingNode const& right) \ - { \ - return Node{OpNode{BasicOp::_operation_}, left, right}; \ - } \ - inline Node operator _operator_(BindingNode const& left, Node&& right) \ - { \ - return Node{OpNode{BasicOp::_operation_}, left, std::forward(right)}; \ - } \ - inline Node operator _operator_(Node&& left, BindingNode const& right) \ - { \ - return Node{OpNode{BasicOp::_operation_}, std::forward(left), right}; \ - } \ - template \ - inline Node operator _operator_(Configurable const& left, BindingNode const& right) \ - { \ - return Node{OpNode{BasicOp::_operation_}, PlaceholderNode{left}, right}; \ - } \ - template \ - inline Node operator _operator_(BindingNode const& left, Configurable const& right) \ - { \ - return Node{OpNode{BasicOp::_operation_}, left, PlaceholderNode{right}}; \ +#define BINARY_OP_NODES(_operator_, _operation_) \ + inline Node operator _operator_(Node&& left, Node&& right) \ + { \ + return Node{OpNode{BasicOp::_operation_}, std::forward(left), std::forward(right)}; \ + } \ + template \ + inline Node operator _operator_(Node&& left, T right) \ + { \ + return Node{OpNode{BasicOp::_operation_}, std::forward(left), LiteralNode{right}}; \ + } \ + template \ + inline Node operator _operator_(T left, Node&& right) \ + { \ + return Node{OpNode{BasicOp::_operation_}, LiteralNode{left}, std::forward(right)}; \ + } \ + template \ + inline Node operator _operator_(Node&& left, Configurable const& right) \ + { \ + return Node{OpNode{BasicOp::_operation_}, std::forward(left), PlaceholderNode{right}}; \ + } \ + template \ + inline Node operator _operator_(Configurable const& left, Node&& right) \ + { \ + return Node{OpNode{BasicOp::_operation_}, PlaceholderNode{left}, std::forward(right)}; \ + } \ + inline Node operator _operator_(BindingNode const& left, BindingNode const& right) \ + { \ + return Node{OpNode{BasicOp::_operation_}, left, right}; \ + } \ + inline Node operator _operator_(BindingNode const& left, Node&& right) \ + { \ + return Node{OpNode{BasicOp::_operation_}, left, std::forward(right)}; \ + } \ + inline Node operator _operator_(Node&& left, BindingNode const& right) \ + { \ + return Node{OpNode{BasicOp::_operation_}, std::forward(left), right}; \ + } \ + template \ + inline Node operator _operator_(Configurable const& left, BindingNode const& right) \ + { \ + return Node{OpNode{BasicOp::_operation_}, PlaceholderNode{left}, right}; \ + } \ + template \ + inline Node operator _operator_(BindingNode const& left, Configurable const& right) \ + { \ + return Node{OpNode{BasicOp::_operation_}, left, PlaceholderNode{right}}; \ } BINARY_OP_NODES(&, BitwiseAnd); @@ -382,61 +416,61 @@ BINARY_OP_NODES(&&, LogicalAnd); BINARY_OP_NODES(||, LogicalOr); /// functions -template -inline Node npow(Node&& left, T right) requires(std::is_arithmetic_v) +template +inline Node npow(Node&& left, T right) { return Node{OpNode{BasicOp::Power}, std::forward(left), LiteralNode{right}}; } -#define BINARY_FUNC_NODES(_func_, _node_) \ - template \ - inline Node _node_(L left, R right) requires(std::is_arithmetic_v && std::is_arithmetic_v) \ - { \ - return Node{OpNode{BasicOp::_func_}, LiteralNode{left}, LiteralNode{right}}; \ - } \ - \ - inline Node _node_(Node&& left, Node&& right) \ - { \ - return Node{OpNode{BasicOp::_func_}, std::forward(left), std::forward(right)}; \ - } \ - \ - inline Node _node_(Node&& left, BindingNode const& right) \ - { \ - return Node{OpNode{BasicOp::_func_}, std::forward(left), right}; \ - } \ - \ - inline Node _node_(BindingNode const& left, BindingNode const& right) \ - { \ - return Node{OpNode{BasicOp::_func_}, left, right}; \ - } \ - \ - inline Node _node_(BindingNode const& left, Node&& right) \ - { \ - return Node{OpNode{BasicOp::_func_}, left, std::forward(right)}; \ - } \ - \ - template \ - inline Node _node_(Node&& left, Configurable const& right) \ - { \ - return Node{OpNode{BasicOp::_func_}, std::forward(left), PlaceholderNode{right}}; \ - } \ - \ - template \ - inline Node _node_(Configurable const& left, Node&& right) \ - { \ - return Node{OpNode{BasicOp::_func_}, PlaceholderNode{left}, std::forward(right)}; \ - } \ - \ - template \ - inline Node _node_(BindingNode const& left, Configurable const& right) \ - { \ - return Node{OpNode{BasicOp::_func_}, left, PlaceholderNode{right}}; \ - } \ - \ - template \ - inline Node _node_(Configurable const& left, BindingNode const& right) \ - { \ - return Node{OpNode{BasicOp::_func_}, PlaceholderNode{left}, right}; \ +#define BINARY_FUNC_NODES(_func_, _node_) \ + template \ + inline Node _node_(L left, R right) \ + { \ + return Node{OpNode{BasicOp::_func_}, LiteralNode{left}, LiteralNode{right}}; \ + } \ + \ + inline Node _node_(Node&& left, Node&& right) \ + { \ + return Node{OpNode{BasicOp::_func_}, std::forward(left), std::forward(right)}; \ + } \ + \ + inline Node _node_(Node&& left, BindingNode const& right) \ + { \ + return Node{OpNode{BasicOp::_func_}, std::forward(left), right}; \ + } \ + \ + inline Node _node_(BindingNode const& left, BindingNode const& right) \ + { \ + return Node{OpNode{BasicOp::_func_}, left, right}; \ + } \ + \ + inline Node _node_(BindingNode const& left, Node&& right) \ + { \ + return Node{OpNode{BasicOp::_func_}, left, std::forward(right)}; \ + } \ + \ + template \ + inline Node _node_(Node&& left, Configurable const& right) \ + { \ + return Node{OpNode{BasicOp::_func_}, std::forward(left), PlaceholderNode{right}}; \ + } \ + \ + template \ + inline Node _node_(Configurable const& left, Node&& right) \ + { \ + return Node{OpNode{BasicOp::_func_}, PlaceholderNode{left}, std::forward(right)}; \ + } \ + \ + template \ + inline Node _node_(BindingNode const& left, Configurable const& right) \ + { \ + return Node{OpNode{BasicOp::_func_}, left, PlaceholderNode{right}}; \ + } \ + \ + template \ + inline Node _node_(Configurable const& left, BindingNode const& right) \ + { \ + return Node{OpNode{BasicOp::_func_}, PlaceholderNode{left}, right}; \ } BINARY_FUNC_NODES(Atan2, natan2); @@ -469,20 +503,20 @@ inline Node ifnode(Node&& condition_, Node&& then_, Node&& else_) return Node{ConditionalNode{}, std::forward(then_), std::forward(else_), std::forward(condition_)}; } -template -inline Node ifnode(Node&& condition_, Node&& then_, L else_) requires(std::is_arithmetic_v) +template +inline Node ifnode(Node&& condition_, Node&& then_, L else_) { return Node{ConditionalNode{}, std::forward(then_), LiteralNode{else_}, std::forward(condition_)}; } -template -inline Node ifnode(Node&& condition_, L then_, Node&& else_) requires(std::is_arithmetic_v) +template +inline Node ifnode(Node&& condition_, L then_, Node&& else_) { return Node{ConditionalNode{}, LiteralNode{then_}, std::forward(else_), std::forward(condition_)}; } -template -inline Node ifnode(Node&& condition_, L1 then_, L2 else_) requires(std::is_arithmetic_v&& std::is_arithmetic_v) +template +inline Node ifnode(Node&& condition_, L1 then_, L2 else_) { return Node{ConditionalNode{}, LiteralNode{then_}, LiteralNode{else_}, std::forward(condition_)}; } @@ -644,6 +678,79 @@ std::shared_ptr createProjectors(framework::pack, std: } void updateFilterInfo(ExpressionInfo& info, std::shared_ptr& table); + +/* + * The formal grammar for framework expressions. + * Operations are in the order of increasing priority. + * Identifier includes namespaces, e.g. o2::aod::track::pt. + * + * top ::= primary + * + * primary ::= tier1 ('||' tier1)* + * tier1 ::= tier2 ('&&' tier2)* + * tier2 ::= tier3 ('|' tier3)* + * tier3 ::= tier4 ('^' tier4)* + * tier4 ::= tier5 ('&' tier5)* + * tier5 ::= tier6 (('=='|'!=') tier6)* + * tier6 ::= tier7 (('<'|'>'|'<='|'>=') tier7)* + * tier7 ::= tier8 (('+'|'-') tier8)* + * tier8 ::= base (('*'|'/') base)* + * + * base ::= identifier + * | number + * | function_call + * | '(' primary ')' + * + * number ::= -?[0-9]+(\.[0-9]*)?([uf])? + * identifier ::= [a-zA-Z][a-zA-Z0-9_]* ('::' [a-zA-Z][a-zA-Z0-9_]*)* + * function_call ::= identifier '(' (primary (',' primary)*)? ')' + */ + +/// String parsing +enum Token : int { + EoL = -1, + Identifier = -2, + IntegerNumber = -3, + FloatNumber = -4, + BinaryOp = -5, + Unexpected = -100 +}; + +struct Tokenizer { + std::string source; + std::string::iterator current; + std::string IdentifierStr; + std::string BinaryOpStr; + std::string StrValue; + std::string TokenStr; + std::variant IntegerValue; + std::variant FloatValue; + char LastChar; + int currentToken = Token::Unexpected; + + Tokenizer(std::string const& input = ""); + void reset(std::string const& input); + [[maybe_unused]] int nextToken(); + void pop(); + char peek(); +}; + +struct Parser { + static Node parse(std::string const& input); + static std::unique_ptr parsePrimary(Tokenizer& tk); + static std::unique_ptr parseTier1(Tokenizer& tk); + static std::unique_ptr parseTier2(Tokenizer& tk); + static std::unique_ptr parseTier3(Tokenizer& tk); + static std::unique_ptr parseTier4(Tokenizer& tk); + static std::unique_ptr parseTier5(Tokenizer& tk); + static std::unique_ptr parseTier6(Tokenizer& tk); + static std::unique_ptr parseTier7(Tokenizer& tk); + static std::unique_ptr parseTier8(Tokenizer& tk); + static std::unique_ptr parseBase(Tokenizer& tk); + + static OpNode opFromToken(std::string const& token); +}; + } // namespace o2::framework::expressions #endif // O2_FRAMEWORK_EXPRESSIONS_H_ diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index 94649f8639a0a..3e52d49dfa4bb 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -31,7 +31,7 @@ void unknownParameterUsed(const char* name) /// a map between BasicOp and gandiva node definitions /// note that logical 'and' and 'or' are created separately -static const std::array basicOperationsMap = { +static constexpr std::array basicOperationsMap = { "and", "or", "add", @@ -175,11 +175,6 @@ std::string upcastTo(atype::type f) } } -bool operator==(DatumSpec const& lhs, DatumSpec const& rhs) -{ - return (lhs.datum == rhs.datum) && (lhs.type == rhs.type); -} - std::ostream& operator<<(std::ostream& os, DatumSpec const& spec) { std::visit( @@ -332,7 +327,7 @@ Operations createOperations(Filter const& expression) std::vector resultTypes; resultTypes.resize(OperationSpecs.size()); - auto inferResultType = [&resultTypes](DatumSpec& left, DatumSpec& right) { + auto inferResultType = [&resultTypes](BasicOp op, DatumSpec& left, DatumSpec& right) { // if the left datum is monostate (error) if (left.datum.index() == 0) { throw runtime_error("Malformed operation spec: empty left datum"); @@ -365,11 +360,15 @@ Operations createOperations(Filter const& expression) return (t == atype::UINT8) || (t == atype::INT8) || (t == atype::UINT16) || (t == atype::INT16) || (t == atype::UINT32) || (t == atype::INT32) || (t == atype::UINT64) || (t == atype::INT64); }; + auto isBitwiseOp = [](auto o) { + return ((o == BasicOp::BitwiseAnd) || (o == BasicOp::BitwiseNot) || (o == BasicOp::BitwiseOr) || (o == BasicOp::BitwiseXor)); + }; + if (isIntType(t1)) { - if (t2 == atype::FLOAT) { + if (t2 == atype::FLOAT && !isBitwiseOp(op)) { return atype::FLOAT; } - if (t2 == atype::DOUBLE) { + if (t2 == atype::DOUBLE && !isBitwiseOp(op)) { return atype::DOUBLE; } if (isIntType(t2)) { @@ -380,7 +379,7 @@ Operations createOperations(Filter const& expression) } } if (t1 == atype::FLOAT) { - if (isIntType(t2)) { + if (isIntType(t2) && !isBitwiseOp(op)) { return atype::FLOAT; } if (t2 == atype::DOUBLE) { @@ -390,11 +389,19 @@ Operations createOperations(Filter const& expression) if (t1 == atype::DOUBLE) { return atype::DOUBLE; } + + if (isIntType(t1) && isBitwiseOp(op)) { + return t1; + } + if (isIntType(t2) && isBitwiseOp(op)) { + return t2; + } + throw runtime_error_f("Invalid combination of argument types %s and %s", stringType(t1), stringType(t2)); }; for (auto it = OperationSpecs.rbegin(); it != OperationSpecs.rend(); ++it) { - auto type = inferResultType(it->left, it->right); + auto type = inferResultType(it->op, it->left, it->right); if (it->type == atype::NA) { it->type = type; } @@ -609,30 +616,34 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, throw runtime_error("Malformed DatumSpec"); }; + auto insertUpcastNode = [](gandiva::NodePtr node, atype::type t0, atype::type t) { + if (t != t0) { + auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t0), {node}, concreteArrowType(t0)); + node = upcast; + } + return node; + }; + + auto insertEqualizeUpcastNode = [](gandiva::NodePtr& node1, gandiva::NodePtr& node2, atype::type t1, atype::type t2) { + if (t2 > t1) { + auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t2), {node1}, concreteArrowType(t2)); + node1 = upcast; + } else if (t1 > t2) { + auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t1), {node2}, concreteArrowType(t1)); + node2 = upcast; + } + }; + + auto isBitwiseOp = [](auto o) { + return ((o == BasicOp::BitwiseAnd) || (o == BasicOp::BitwiseNot) || (o == BasicOp::BitwiseOr) || (o == BasicOp::BitwiseXor)); + }; + gandiva::NodePtr tree = nullptr; for (auto it = opSpecs.rbegin(); it != opSpecs.rend(); ++it) { auto leftNode = datumNode(it->left); auto rightNode = datumNode(it->right); auto condNode = datumNode(it->condition); - auto insertUpcastNode = [](gandiva::NodePtr node, atype::type t0, atype::type t) { - if (t != t0) { - auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t0), {node}, concreteArrowType(t0)); - node = upcast; - } - return node; - }; - - auto insertEqualizeUpcastNode = [](gandiva::NodePtr& node1, gandiva::NodePtr& node2, atype::type t1, atype::type t2) { - if (t2 > t1) { - auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t2), {node1}, concreteArrowType(t2)); - node1 = upcast; - } else if (t1 > t2) { - auto upcast = gandiva::TreeExprBuilder::MakeFunction(upcastTo(t1), {node2}, concreteArrowType(t1)); - node2 = upcast; - } - }; - gandiva::NodePtr temp_node; switch (it->op) { @@ -647,7 +658,7 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, break; default: if (it->op < BasicOp::Sqrt) { - if (it->type != atype::BOOL) { + if (it->type != atype::BOOL && !isBitwiseOp(it->op)) { leftNode = insertUpcastNode(leftNode, it->type, it->left.type); rightNode = insertUpcastNode(rightNode, it->type, it->right.type); } else if (it->op == BasicOp::Equal || it->op == BasicOp::NotEqual) { @@ -655,7 +666,9 @@ gandiva::NodePtr createExpressionTree(Operations const& opSpecs, } temp_node = gandiva::TreeExprBuilder::MakeFunction(basicOperationsMap[it->op], {leftNode, rightNode}, concreteArrowType(it->type)); } else { - leftNode = insertUpcastNode(leftNode, it->type, it->left.type); + if (!isBitwiseOp(it->op)) { + leftNode = insertUpcastNode(leftNode, it->type, it->left.type); + } temp_node = gandiva::TreeExprBuilder::MakeFunction(basicOperationsMap[it->op], {leftNode}, concreteArrowType(it->type)); } break; @@ -722,4 +735,464 @@ void updateFilterInfo(ExpressionInfo& info, std::shared_ptr& table } } +/// String parsing +Tokenizer::Tokenizer(std::string const& input) + : source{input}, + IdentifierStr{""}, + StrValue{""}, + IntegerValue{0}, + FloatValue{0.f} +{ + LastChar = ' '; + if (!source.empty()) { + source.erase(std::remove_if(source.begin(), source.end(), ::isspace), source.end()); + } + current = source.begin(); +} + +void Tokenizer::reset(std::string const& input) +{ + LastChar = ' '; + IdentifierStr = ""; + StrValue = ""; + IntegerValue = 0; + FloatValue = 0.f; + source = input; + if (!source.empty()) { + source.erase(std::remove_if(source.begin(), source.end(), ::isspace), source.end()); + } + current = source.begin(); + currentToken = Token::Unexpected; +} + +int Tokenizer::nextToken() +{ + // skip initial space + if (isspace(LastChar)) { + pop(); + } + // logical or bitwise OR + if (LastChar == '|') { + BinaryOpStr = LastChar; + if (peek() == '|') { + pop(); + BinaryOpStr += LastChar; + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } else { + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } + } + // logical or bitwise AND + if (LastChar == '&') { + BinaryOpStr = LastChar; + if (peek() == '&') { + pop(); + BinaryOpStr += LastChar; + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } else { + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } + } + // less than or less or equal than + if (LastChar == '<') { + BinaryOpStr = LastChar; + if (peek() == '=') { + pop(); + BinaryOpStr += LastChar; + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } else { + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } + } + // greater than or greater or equal than + if (LastChar == '>') { + BinaryOpStr = LastChar; + if (peek() == '=') { + pop(); + BinaryOpStr += LastChar; + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } else { + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } + } + // equal or error + if (LastChar == '=') { + BinaryOpStr = LastChar; + if (peek() == '=') { + pop(); + BinaryOpStr += LastChar; + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } else { + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::Unexpected; + return currentToken; + } + } + // not equal or error + if (LastChar == '!') { + BinaryOpStr = LastChar; + if (peek() == '=') { + pop(); + BinaryOpStr += LastChar; + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } else { + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } + } + // unambiguous single-character binary operations: addition, multiplication, subtraction, division, bitwise XOR + if (LastChar == '+' || LastChar == '*' || (LastChar == '-' && (currentToken != Token::BinaryOp && currentToken != '(' && currentToken != Token::Unexpected)) || LastChar == '/' || LastChar == '^') { + BinaryOpStr = LastChar; + pop(); + TokenStr = BinaryOpStr; + currentToken = Token::BinaryOp; + return currentToken; + } + // identifier: column, function, constant + if (isalpha(LastChar)) { + // identifier + IdentifierStr = LastChar; + pop(); + while (isalnum(LastChar) || (LastChar == '_') || (LastChar == ':')) { + IdentifierStr += LastChar; + pop(); + } + TokenStr = IdentifierStr; + currentToken = Token::Identifier; + return currentToken; + } + // number: integer, unsigned integer or float + if (isdigit(LastChar) || LastChar == '.' || (LastChar == '-' && isdigit(peek()))) { + // number + StrValue = ""; + bool isFloat = false; + bool isUnsigned = false; + do { + StrValue += LastChar; + pop(); + } while (isdigit(LastChar) || LastChar == '.'); + if (LastChar == 'f') { + isFloat = true; + pop(); + } + if (LastChar == 'u') { + isUnsigned = true; + pop(); + } + if (std::find(StrValue.begin(), StrValue.end(), '.') == StrValue.end() && !isFloat) { + if (!isUnsigned) { + IntegerValue = atoi(StrValue.c_str()); + } else { + IntegerValue = static_cast(atoi(StrValue.c_str())); + } + TokenStr = StrValue; + currentToken = Token::IntegerNumber; + return currentToken; + } + if (isFloat) { + FloatValue = strtof(StrValue.c_str(), nullptr); + } else { + FloatValue = strtod(StrValue.c_str(), nullptr); + } + TokenStr = StrValue; + currentToken = Token::FloatNumber; + return currentToken; + } + // end-of-line + if (LastChar == '\0') { + TokenStr = LastChar; + currentToken = Token::EoL; + return currentToken; + } + // generic character + currentToken = LastChar; + TokenStr = LastChar; + pop(); + return currentToken; +} + +void Tokenizer::pop() +{ + if (current != source.end()) { + LastChar = *current; + ++current; + } else { + LastChar = '\0'; + } +} + +char Tokenizer::peek() +{ + if (current != source.end()) { + return *current; + } else { + return '\0'; + } +} + +Node Parser::parse(std::string const& input) +{ + auto tk = Tokenizer(input); + tk.nextToken(); + auto node = parsePrimary(tk); + if (tk.currentToken != Token::EoL) { + throw runtime_error_f("Unexpected token after expression: %s", tk.TokenStr.c_str()); + } + return *node.get(); +} + +std::unique_ptr Parser::parsePrimary(Tokenizer& tk) +{ + auto root = parseTier1(tk); + while (tk.TokenStr == "||") { + auto opnode = std::make_unique(OpNode{BasicOp::LogicalOr}, std::move(root), LiteralNode{-1}); + root.swap(opnode); + tk.nextToken(); + root->right = parseTier1(tk); + } + return root; +} + +std::unique_ptr Parser::parseTier1(Tokenizer& tk) +{ + auto root = parseTier2(tk); + while (tk.TokenStr == "&&") { + auto opnode = std::make_unique(OpNode{BasicOp::LogicalAnd}, std::move(root), LiteralNode{-1}); + root.swap(opnode); + tk.nextToken(); + root->right = parseTier2(tk); + } + return root; +} + +std::unique_ptr Parser::parseTier2(Tokenizer& tk) +{ + auto root = parseTier3(tk); + while (tk.TokenStr == "|") { + auto opnode = std::make_unique(OpNode{BasicOp::BitwiseOr}, std::move(root), LiteralNode{-1}); + root.swap(opnode); + tk.nextToken(); + root->right = parseTier3(tk); + } + return root; +} + +std::unique_ptr Parser::parseTier3(Tokenizer& tk) +{ + auto root = parseTier4(tk); + while (tk.TokenStr == "^") { + auto opnode = std::make_unique(OpNode{BasicOp::BitwiseXor}, std::move(root), LiteralNode{-1}); + root.swap(opnode); + tk.nextToken(); + root->right = parseTier4(tk); + } + return root; +} + +std::unique_ptr Parser::parseTier4(Tokenizer& tk) +{ + auto root = parseTier5(tk); + while (tk.TokenStr == "&") { + auto opnode = std::make_unique(OpNode{BasicOp::BitwiseAnd}, std::move(root), LiteralNode{-1}); + root.swap(opnode); + tk.nextToken(); + root->right = parseTier5(tk); + } + return root; +} + +std::unique_ptr Parser::parseTier5(Tokenizer& tk) +{ + auto root = parseTier6(tk); + while (tk.TokenStr == "==" || tk.TokenStr == "!=") { + auto opnode = std::make_unique(opFromToken(tk.TokenStr), std::move(root), LiteralNode{-1}); + root.swap(opnode); + tk.nextToken(); + root->right = parseTier6(tk); + } + return root; +} + +std::unique_ptr Parser::parseTier6(Tokenizer& tk) +{ + auto root = parseTier7(tk); + while (tk.TokenStr == "<" || tk.TokenStr == "<=" || tk.TokenStr == "=>" || tk.TokenStr == ">") { + auto opnode = std::make_unique(opFromToken(tk.TokenStr), std::move(root), LiteralNode{-1}); + root.swap(opnode); + tk.nextToken(); + root->right = parseTier7(tk); + } + return root; +} + +std::unique_ptr Parser::parseTier7(Tokenizer& tk) +{ + auto root = parseTier8(tk); + while (tk.TokenStr == "+" || tk.TokenStr == "-") { + auto opnode = std::make_unique(opFromToken(tk.TokenStr), std::move(root), LiteralNode{-1}); + root.swap(opnode); + tk.nextToken(); + root->right = parseTier8(tk); + } + return root; +} + +std::unique_ptr Parser::parseTier8(Tokenizer& tk) +{ + auto root = parseBase(tk); + while (tk.TokenStr == "*" || tk.TokenStr == "/") { + auto opnode = std::make_unique(opFromToken(tk.TokenStr), std::move(root), LiteralNode{-1}); + root.swap(opnode); + tk.nextToken(); + root->right = parseBase(tk); + } + return root; +} + +std::unique_ptr Parser::parseBase(Tokenizer& tk) +{ + // parentheses + if (tk.currentToken == '(') { + tk.nextToken(); + auto node = parsePrimary(tk); + if (tk.currentToken != ')') { + throw runtime_error_f("Expected \")\" got %s", tk.TokenStr.c_str()); + } + tk.nextToken(); + return node; + } + + // identifier or function call + if (tk.currentToken == Token::Identifier) { + std::string id = tk.IdentifierStr; + tk.nextToken(); + if (tk.currentToken != '(') { // binding node or a constant + std::string binding = id; + auto posc = std::find(mathConstants.begin(), mathConstants.end(), id); + if (posc != mathConstants.end()) { // constant + return std::make_unique(LiteralNode{mathConstantsValues[std::distance(mathConstants.begin(), posc)]}); + } + // binding node + auto pos = binding.rfind(':'); + binding.erase(0, pos + 1); + binding[0] = std::toupper(binding[0]); + binding.insert(binding.begin(), 'f'); + return std::make_unique(BindingNode{runtime_hash(id.c_str()), atype::FLOAT}, binding); + } + + // function call + if (id == "ifnode") { // conditional, 3 args + auto node = std::make_unique(ConditionalNode{}, LiteralNode{-1}, LiteralNode{-1}, LiteralNode{-1}); + int args = 0; + while (tk.currentToken != ')') { + do { + tk.nextToken(); + if (args == 0) { + node->condition = parsePrimary(tk); + } else if (args == 1) { + node->left = parsePrimary(tk); + } else if (args == 2) { + node->right = parsePrimary(tk); + } else { + throw runtime_error_f("Extra argument in a conditional: %s", tk.TokenStr.c_str()); + } + ++args; + } while (tk.currentToken == ','); + } + tk.nextToken(); + return node; + } else { // normal function + auto node = std::make_unique(opFromToken(id), LiteralNode{-1}, LiteralNode{-1}); + int args = 0; + while (tk.currentToken != ')') { + do { + tk.nextToken(); + if (args == 0) { + node->left = parsePrimary(tk); + } else if (args == 1) { + node->right = parsePrimary(tk); + } else { + throw runtime_error_f("Extra argument in a function call: %s", tk.TokenStr.c_str()); + } + ++args; + } while (tk.currentToken == ','); + } + if (args == 1) { + node->right = nullptr; + } + tk.nextToken(); + return node; + } + } + + // number + if (tk.currentToken == Token::FloatNumber) { + tk.nextToken(); + switch (tk.FloatValue.index()) { + case 0: + return std::make_unique(LiteralNode{get<0>(tk.FloatValue)}); + case 1: + return std::make_unique(LiteralNode{get<1>(tk.FloatValue)}); + } + } + if (tk.currentToken == Token::IntegerNumber) { + tk.nextToken(); + switch (tk.IntegerValue.index()) { + case 0: + return std::make_unique(LiteralNode{get<0>(tk.IntegerValue)}); + case 1: + return std::make_unique(LiteralNode{get<1>(tk.IntegerValue)}); + case 2: + return std::make_unique(LiteralNode{get<2>(tk.IntegerValue)}); + case 3: + return std::make_unique(LiteralNode{get<3>(tk.IntegerValue)}); + } + } + + // error + throw runtime_error_f("Unexpected token %s in operand", tk.TokenStr.c_str()); +} + +OpNode Parser::opFromToken(std::string const& token) +{ + auto locate = std::find(mapping.begin(), mapping.end(), token); + if (locate == mapping.end()) { + throw runtime_error_f("No operation \"%s\" defined", token.c_str()); + } + return OpNode{static_cast(std::distance(mapping.begin(), locate))}; +} + } // namespace o2::framework::expressions diff --git a/Framework/Core/test/test_Expressions.cxx b/Framework/Core/test/test_Expressions.cxx index e8cf43e03e11d..eef0375f46086 100644 --- a/Framework/Core/test/test_Expressions.cxx +++ b/Framework/Core/test/test_Expressions.cxx @@ -14,6 +14,7 @@ #include "Framework/AnalysisDataModel.h" #include #include +#include using namespace o2::framework; using namespace o2::framework::expressions; @@ -127,7 +128,7 @@ TEST_CASE("TestTreeParsing") REQUIRE(ptfilter.node->left->self.index() == 1); REQUIRE(ptfilter.node->right->self.index() == 3); auto ptfilterspecs = createOperations(ptfilter); - REQUIRE(ptfilterspecs[0].left == (DatumSpec{std::string{"fPt"}, typeid(o2::aod::track::Pt).hash_code(), atype::FLOAT})); + REQUIRE(ptfilterspecs[0].left == (DatumSpec{std::string{"fPt"}, "o2::aod::track::pt"_h, atype::FLOAT})); REQUIRE(ptfilterspecs[0].right == (DatumSpec{LiteralNode::var_t{0.5f}, atype::FLOAT})); REQUIRE(ptfilterspecs[0].result == (DatumSpec{0u, atype::BOOL})); @@ -143,7 +144,7 @@ TEST_CASE("TestTreeParsing") REQUIRE(ptfilter2.node->right->self.index() == 3); REQUIRE(std::get(ptfilter2.node->right->self).name == "prefix.pTCut"); auto ptfilterspecs2 = createOperations(ptfilter2); - REQUIRE(ptfilterspecs2[0].left == (DatumSpec{std::string{"fPt"}, typeid(o2::aod::track::Pt).hash_code(), atype::FLOAT})); + REQUIRE(ptfilterspecs2[0].left == (DatumSpec{std::string{"fPt"}, "o2::aod::track::pt"_h, atype::FLOAT})); REQUIRE(ptfilterspecs2[0].right == (DatumSpec{LiteralNode::var_t{1.0f}, atype::FLOAT})); REQUIRE(ptfilterspecs2[0].result == (DatumSpec{0u, atype::BOOL})); @@ -161,12 +162,12 @@ TEST_CASE("TestGandivaTreeCreation") { Projector pze = o2::aod::track::Pze::Projector(); auto pzspecs = createOperations(pze); - REQUIRE(pzspecs[0].left == (DatumSpec{std::string{"fTgl"}, typeid(o2::aod::track::Tgl).hash_code(), atype::FLOAT})); + REQUIRE(pzspecs[0].left == (DatumSpec{std::string{"fTgl"}, "o2::aod::track::tgl"_h, atype::FLOAT})); REQUIRE(pzspecs[0].right == (DatumSpec{1u, atype::FLOAT})); REQUIRE(pzspecs[0].result == (DatumSpec{0u, atype::FLOAT})); REQUIRE(pzspecs[1].left == (DatumSpec{LiteralNode::var_t{1.f}, atype::FLOAT})); - REQUIRE(pzspecs[1].right == (DatumSpec{std::string{"fSigned1Pt"}, typeid(o2::aod::track::Signed1Pt).hash_code(), atype::FLOAT})); + REQUIRE(pzspecs[1].right == (DatumSpec{std::string{"fSigned1Pt"}, "o2::aod::track::signed1Pt"_h, atype::FLOAT})); REQUIRE(pzspecs[1].result == (DatumSpec{1u, atype::FLOAT})); auto infield1 = o2::aod::track::Signed1Pt::asArrowField(); auto infield2 = o2::aod::track::Tgl::asArrowField(); @@ -200,7 +201,7 @@ TEST_CASE("TestGandivaTreeCreation") REQUIRE(bwf[0].right == (DatumSpec{LiteralNode::var_t{0u}, atype::UINT32})); REQUIRE(bwf[0].result == (DatumSpec{0u, atype::BOOL})); - REQUIRE(bwf[1].left == (DatumSpec{std::string{"fFlags"}, typeid(o2::aod::track::Flags).hash_code(), atype::UINT32})); + REQUIRE(bwf[1].left == (DatumSpec{std::string{"fFlags"}, "o2::aod::track::flags"_h, atype::UINT32})); REQUIRE(bwf[1].right == (DatumSpec{LiteralNode::var_t{static_cast(o2::aod::track::TPCrefit)}, atype::UINT32})); REQUIRE(bwf[1].result == (DatumSpec{1u, atype::UINT32})); @@ -220,7 +221,7 @@ TEST_CASE("TestGandivaTreeCreation") REQUIRE(rf[0].right == (DatumSpec{LiteralNode::var_t{0.1f}, atype::FLOAT})); REQUIRE(rf[0].result == (DatumSpec{0u, atype::BOOL})); - REQUIRE(rf[1].left == (DatumSpec{std::string{"fPt"}, typeid(o2::aod::track::Pt).hash_code(), atype::FLOAT})); + REQUIRE(rf[1].left == (DatumSpec{std::string{"fPt"}, "o2::aod::track::pt"_h, atype::FLOAT})); REQUIRE(rf[1].right == (DatumSpec{})); REQUIRE(rf[1].result == (DatumSpec{1u, atype::FLOAT})); @@ -249,15 +250,15 @@ TEST_CASE("TestConditionalExpressions") REQUIRE(cfspecs[1].condition == (DatumSpec{5u, atype::BOOL})); REQUIRE(cfspecs[1].result == (DatumSpec{2u, atype::BOOL})); - REQUIRE(cfspecs[2].left == (DatumSpec{std::string{"fPt"}, typeid(o2::aod::track::Pt).hash_code(), atype::FLOAT})); + REQUIRE(cfspecs[2].left == (DatumSpec{std::string{"fPt"}, "o2::aod::track::pt"_h, atype::FLOAT})); REQUIRE(cfspecs[2].right == (DatumSpec{LiteralNode::var_t{1.0f}, atype::FLOAT})); REQUIRE(cfspecs[2].result == (DatumSpec{5u, atype::BOOL})); - REQUIRE(cfspecs[3].left == (DatumSpec{std::string{"fPhi"}, typeid(o2::aod::track::Phi).hash_code(), atype::FLOAT})); + REQUIRE(cfspecs[3].left == (DatumSpec{std::string{"fPhi"}, "o2::aod::track::phi"_h, atype::FLOAT})); REQUIRE(cfspecs[3].right == (DatumSpec{LiteralNode::var_t{(float)(M_PI / 2.)}, atype::FLOAT})); REQUIRE(cfspecs[3].result == (DatumSpec{4u, atype::BOOL})); - REQUIRE(cfspecs[4].left == (DatumSpec{std::string{"fPhi"}, typeid(o2::aod::track::Phi).hash_code(), atype::FLOAT})); + REQUIRE(cfspecs[4].left == (DatumSpec{std::string{"fPhi"}, "o2::aod::track::phi"_h, atype::FLOAT})); REQUIRE(cfspecs[4].right == (DatumSpec{LiteralNode::var_t{(float)(M_PI / 2.)}, atype::FLOAT})); REQUIRE(cfspecs[4].result == (DatumSpec{3u, atype::BOOL})); @@ -265,7 +266,7 @@ TEST_CASE("TestConditionalExpressions") REQUIRE(cfspecs[5].right == (DatumSpec{LiteralNode::var_t{1.0f}, atype::FLOAT})); REQUIRE(cfspecs[5].result == (DatumSpec{1u, atype::BOOL})); - REQUIRE(cfspecs[6].left == (DatumSpec{std::string{"fEta"}, typeid(o2::aod::track::Eta).hash_code(), atype::FLOAT})); + REQUIRE(cfspecs[6].left == (DatumSpec{std::string{"fEta"}, "o2::aod::track::eta"_h, atype::FLOAT})); REQUIRE(cfspecs[6].right == (DatumSpec{})); REQUIRE(cfspecs[6].result == (DatumSpec{6u, atype::FLOAT})); @@ -324,3 +325,54 @@ TEST_CASE("TestBinnedExpressions") auto tree2 = createExpressionTree(p2specs, schema2); REQUIRE(tree2->ToString() == "if (bool less_than((float) fPhi, (const float) 0 raw(0))) { (const float) -1 raw(bf800000) } else { if (bool less_than((float) fPhi, (const float) 1.5708 raw(3fc90fdb))) { float add(float add(float multiply(float multiply((const float) 1 raw(3f800000), (float) fX), (float) fX), float multiply(float multiply((const float) 2 raw(40000000), (float) fY), (float) fY)), float multiply(float multiply((const float) 3 raw(40400000), (float) fZ), (float) fZ)) } else { if (bool less_than((float) fPhi, (const float) 3.14159 raw(40490fdb))) { float add(float add(float multiply(float multiply((const float) 1.1 raw(3f8ccccd), (float) fX), (float) fX), float multiply(float multiply((const float) 2.1 raw(40066666), (float) fY), (float) fY)), float multiply(float multiply((const float) 3.1 raw(40466666), (float) fZ), (float) fZ)) } else { if (bool less_than((float) fPhi, (const float) 4.71239 raw(4096cbe4))) { float add(float add(float multiply(float multiply((const float) 1.2 raw(3f99999a), (float) fX), (float) fX), float multiply(float multiply((const float) 2.2 raw(400ccccd), (float) fY), (float) fY)), float multiply(float multiply((const float) 3.2 raw(404ccccd), (float) fZ), (float) fZ)) } else { if (bool less_than((float) fPhi, (const float) 6.28319 raw(40c90fdb))) { float add(float add(float multiply(float multiply((const float) 1.3 raw(3fa66666), (float) fX), (float) fX), float multiply(float multiply((const float) 2.3 raw(40133333), (float) fY), (float) fY)), float multiply(float multiply((const float) 3.3 raw(40533333), (float) fZ), (float) fZ)) } else { (const float) -1 raw(bf800000) } } } } }"); } + +void printTokens(Tokenizer& t) +{ + int token; + while ((token = t.nextToken()) && (token != Token::EoL)) { + std::cout << t.TokenStr << " "; + }; + std::cout << std::endl; +} + +TEST_CASE("TestStringExpressionsParsing") +{ + Filter f = (o2::aod::track::flags & 1u) != 0u && (o2::aod::track::pt <= 10.f); + std::string input = "(o2::aod::track::flags & 1u) != 0u && (o2::aod::track::pt <= 10.f)"; + + auto t1 = createOperations(f); + Filter ff = Parser::parse(input); + auto t2 = createOperations(ff); + + auto schema = std::make_shared(std::vector{o2::aod::track::Flags::asArrowField(), o2::aod::track::Pt::asArrowField()}); + auto tree1 = createExpressionTree(t1, schema); + auto tree2 = createExpressionTree(t2, schema); + + REQUIRE(tree1->ToString() == tree2->ToString()); + + Projector p = -1.f * nlog(ntan(o2::constants::math::PIQuarter - 0.5f * natan(o2::aod::fwdtrack::tgl))); + input = "-1.f * nlog(ntan(PIQuarter - 0.5f * natan(o2::aod::fwdtrack::tgl)))"; + + auto tp1 = createOperations(p); + Projector pp = Parser::parse(input); + auto tp2 = createOperations(pp); + + schema = std::make_shared(std::vector{o2::aod::fwdtrack::Tgl::asArrowField()}); + auto treep1 = createExpressionTree(tp1, schema); + auto treep2 = createExpressionTree(tp2, schema); + + REQUIRE(treep1->ToString() == treep2->ToString()); + + Filter f2 = o2::aod::track::signed1Pt > 0.f && ifnode(nabs(o2::aod::track::eta) < 1.0f, nabs(o2::aod::track::x) > 2.0f, nabs(o2::aod::track::y) > 3.0f); + input = "o2::aod::track::signed1Pt > 0.f && ifnode(nabs(o2::aod::track::eta) < 1.0f, nabs(o2::aod::track::x) > 2.0f, nabs(o2::aod::track::y) > 3.0f)"; + + auto tf1 = createOperations(f2); + Filter ff2 = Parser::parse(input); + auto tf2 = createOperations(ff2); + + schema = std::make_shared(std::vector{o2::aod::track::Eta::asArrowField(), o2::aod::track::Signed1Pt::asArrowField(), o2::aod::track::X::asArrowField(), o2::aod::track::Y::asArrowField()}); + auto treef1 = createExpressionTree(tf1, schema); + auto treef2 = createExpressionTree(tf2, schema); + + REQUIRE(treef1->ToString() == treef2->ToString()); +} From 81851e7f759202cb3f4d585b1b8e81d2d4c5ea86 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Mon, 30 Jun 2025 10:21:14 +0200 Subject: [PATCH 208/315] move unnecessary statics to .cxx --- Framework/Core/include/Framework/BasicOps.h | 58 -------------------- Framework/Core/src/Expressions.cxx | 61 ++++++++++++++++++++- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/Framework/Core/include/Framework/BasicOps.h b/Framework/Core/include/Framework/BasicOps.h index 06880de275b9e..0927b557c86bc 100644 --- a/Framework/Core/include/Framework/BasicOps.h +++ b/Framework/Core/include/Framework/BasicOps.h @@ -10,9 +10,6 @@ // or submit itself to any jurisdiction. #ifndef O2_FRAMEWORK_BASICOPS_H_ #define O2_FRAMEWORK_BASICOPS_H_ -#include -#include -#include "CommonConstants/MathConstants.h" namespace o2::framework { @@ -49,61 +46,6 @@ enum BasicOp : unsigned int { BitwiseNot, Conditional // 3-ar functions }; - -static constexpr std::array mapping{ - "&&", - "||", - "+", - "-", - "/", - "*", - "&", - "|", - "^", - "<", - "<=", - ">", - ">=", - "==", - "!=", - "natan2", - "npow", - "nsqrt", - "nexp", - "nlog", - "nlog10", - "nsin", - "ncos", - "ntan", - "nasin", - "nacos", - "natan", - "nabs", - "nround", - "nbitwise_not", - "ifnode"}; - -static constexpr std::array mathConstants{ - "Almost0", - "Epsilon", - "Almost1", - "VeryBig", - "PI", - "TwoPI", - "PIHalf", - "PIThird", - "PIQuarter"}; - -static constexpr std::array mathConstantsValues{ - o2::constants::math::Almost0, - o2::constants::math::Epsilon, - o2::constants::math::Almost1, - o2::constants::math::VeryBig, - o2::constants::math::PI, - o2::constants::math::TwoPI, - o2::constants::math::PIHalf, - o2::constants::math::PIThird, - o2::constants::math::PIQuarter}; } // namespace o2::framework #endif // O2_FRAMEWORK_BASICOPS_H_ diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index 3e52d49dfa4bb..cc6d9f99fb25d 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -19,6 +19,7 @@ #include #include #include +#include "CommonConstants/MathConstants.h" using namespace o2::framework; @@ -29,9 +30,67 @@ void unknownParameterUsed(const char* name) runtime_error_f("Unknown parameter used in expression: %s", name); } +/// a map between BasicOp and tokens in string expressions +constexpr std::array mapping{ + "&&", + "||", + "+", + "-", + "/", + "*", + "&", + "|", + "^", + "<", + "<=", + ">", + ">=", + "==", + "!=", + "natan2", + "npow", + "nsqrt", + "nexp", + "nlog", + "nlog10", + "nsin", + "ncos", + "ntan", + "nasin", + "nacos", + "natan", + "nabs", + "nround", + "nbitwise_not", + "ifnode"}; + +/// math constants to recognize in string expressions +constexpr std::array mathConstants{ + "Almost0", + "Epsilon", + "Almost1", + "VeryBig", + "PI", + "TwoPI", + "PIHalf", + "PIThird", + "PIQuarter"}; + +/// values of math constants to substiture +constexpr std::array mathConstantsValues{ + o2::constants::math::Almost0, + o2::constants::math::Epsilon, + o2::constants::math::Almost1, + o2::constants::math::VeryBig, + o2::constants::math::PI, + o2::constants::math::TwoPI, + o2::constants::math::PIHalf, + o2::constants::math::PIThird, + o2::constants::math::PIQuarter}; + /// a map between BasicOp and gandiva node definitions /// note that logical 'and' and 'or' are created separately -static constexpr std::array basicOperationsMap = { +constexpr std::array basicOperationsMap = { "and", "or", "add", From 59033a58b4b6fb06ae2f018fa179e55aca654152 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Mon, 30 Jun 2025 13:25:01 +0200 Subject: [PATCH 209/315] Allow filters to be set in init(); Add ability to set a filter from string directly --- Framework/Core/include/Framework/AnalysisTask.h | 9 +++++---- Framework/Core/include/Framework/Expressions.h | 14 ++++++++++++++ Framework/Core/src/Expressions.cxx | 9 +++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 892948582b3cc..b3378543e6ebb 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -574,6 +574,11 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args) callbacks.set(eoscb); + /// call the task's init() function first as it may manipulate the task's elements + if constexpr (requires { task->init(ic); }) { + task->init(ic); + } + /// update configurables in filters and partitions homogeneous_apply_refs( [&ic](auto& element) -> bool { return analysis_task_parsers::updatePlaceholders(ic, element); }, @@ -584,10 +589,6 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args) }, *task.get()); - if constexpr (requires { task->init(ic); }) { - task->init(ic); - } - /// parse process functions to enable requested grouping caches - note that at this state process configurables have their final values if constexpr (requires { &T::process; }) { AnalysisDataProcessorBuilder::cacheFromArgs(&T::process, true, bindingsKeys, bindingsKeysUnsorted); diff --git a/Framework/Core/include/Framework/Expressions.h b/Framework/Core/include/Framework/Expressions.h index 6568f5d58c421..ed8d4ef24f402 100644 --- a/Framework/Core/include/Framework/Expressions.h +++ b/Framework/Core/include/Framework/Expressions.h @@ -610,15 +610,29 @@ struct Filter { (void)designateSubtrees(node.get()); } + Filter(std::string const& input_) : input{input_} {} + Filter& operator=(Filter&& other) noexcept { node = std::move(other.node); + input = std::move(other.input); + return *this; + } + + Filter& operator=(std::string const& input_) + { + input = input_; + if (node != nullptr) { + node = nullptr; + } return *this; } std::unique_ptr node = nullptr; + std::string input; size_t designateSubtrees(Node* node, size_t index = 0); + void parse(); }; template diff --git a/Framework/Core/src/Expressions.cxx b/Framework/Core/src/Expressions.cxx index cc6d9f99fb25d..1d4dec734ff21 100644 --- a/Framework/Core/src/Expressions.cxx +++ b/Framework/Core/src/Expressions.cxx @@ -152,6 +152,12 @@ size_t Filter::designateSubtrees(Node* node, size_t index) return index; } +void Filter::parse() +{ + node = std::make_unique(Parser::parse(input)); + (void)designateSubtrees(node.get()); +} + template constexpr inline auto makeDatum(T const&) { @@ -252,6 +258,9 @@ std::ostream& operator<<(std::ostream& os, DatumSpec const& spec) void updatePlaceholders(Filter& filter, InitContext& context) { + if (filter.node == nullptr && !filter.input.empty()) { + filter.parse(); + } expressions::walk(filter.node.get(), [&](Node* node) { if (node->self.index() == 3) { std::get_if<3>(&node->self)->reset(context); From db916c26a15ef5b604c3d69423d32f124806dcf1 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Fri, 8 Aug 2025 11:38:49 +0200 Subject: [PATCH 210/315] DPL Analysis: add support for BinaryView columns The idea is to be able to have BinaryViews on top of the CCDB object blobs which are already cached in shared memory, so that we can have a table with rows of the kind: (timestamp, blob-requested-ccdb-object-2, blob-requested-ccdb-object-2) which then can be joined to the timestamps to provide access to the associated CCDB Object. --- Framework/Core/include/Framework/ASoA.h | 21 +++++++---- Framework/Core/include/Framework/ArrowTypes.h | 5 +++ .../Core/include/Framework/TableBuilder.h | 33 ++++++++++++++++- Framework/Core/test/test_TableBuilder.cxx | 35 ++++++++++++++++++- 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 9703f8eb26b9d..8af9878703d18 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -23,11 +23,12 @@ #include "Framework/ArrowTableSlicingCache.h" // IWYU pragma: export #include "Framework/SliceCache.h" // IWYU pragma: export #include "Framework/VariantHelpers.h" // IWYU pragma: export -#include // IWYU pragma: export -#include // IWYU pragma: export -#include // IWYU pragma: export -#include // IWYU pragma: export -#include // IWYU pragma: export +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export #include #include #include @@ -578,7 +579,15 @@ class ColumnIterator : ChunkingPolicy } decltype(auto) operator*() const - requires((!std::same_as>) && !std::same_as, arrow::ListArray>) + requires((!std::same_as>) && std::same_as, arrow::BinaryViewArray>) + { + checkSkipChunk(); + auto array = std::static_pointer_cast(mColumn->chunk(mCurrentChunk)); + return array->GetView(*mCurrentPos - mFirstIndex); + } + + decltype(auto) operator*() const + requires((!std::same_as>) && !std::same_as, arrow::ListArray> && !std::same_as, arrow::BinaryViewArray>) { checkSkipChunk(); return *(mCurrent + (*mCurrentPos >> SCALE_FACTOR)); diff --git a/Framework/Core/include/Framework/ArrowTypes.h b/Framework/Core/include/Framework/ArrowTypes.h index 69946b6f35a50..6fd70113fede7 100644 --- a/Framework/Core/include/Framework/ArrowTypes.h +++ b/Framework/Core/include/Framework/ArrowTypes.h @@ -12,6 +12,7 @@ #ifndef O2_FRAMEWORK_ARROWTYPES_H #define O2_FRAMEWORK_ARROWTYPES_H #include "arrow/type_fwd.h" +#include namespace o2::soa { @@ -62,6 +63,10 @@ template <> struct arrow_array_for { using type = arrow::DoubleArray; }; +template <> +struct arrow_array_for> { + using type = arrow::BinaryViewArray; +}; template struct arrow_array_for { using type = arrow::FixedSizeListArray; diff --git a/Framework/Core/include/Framework/TableBuilder.h b/Framework/Core/include/Framework/TableBuilder.h index eb56791acfd3c..74395a2680077 100644 --- a/Framework/Core/include/Framework/TableBuilder.h +++ b/Framework/Core/include/Framework/TableBuilder.h @@ -98,6 +98,7 @@ O2_ARROW_STL_CONVERSION(long unsigned, UInt64Type) O2_ARROW_STL_CONVERSION(float, FloatType) O2_ARROW_STL_CONVERSION(double, DoubleType) O2_ARROW_STL_CONVERSION(std::string, StringType) +O2_ARROW_STL_CONVERSION(std::span, BinaryViewType) } // namespace detail void addLabelToSchema(std::shared_ptr& schema, const char* label); @@ -274,6 +275,29 @@ struct BuilderMaker { } }; +template <> +struct BuilderMaker> { + using FillType = std::span; + using STLValueType = std::span; + using ArrowType = typename detail::ConversionTraits>::ArrowType; + using BuilderType = typename arrow::TypeTraits::BuilderType; + + static std::unique_ptr make(arrow::MemoryPool* pool) + { + return std::make_unique(pool); + } + + static std::shared_ptr make_datatype() + { + return arrow::TypeTraits::type_singleton(); + } + + static arrow::Status append(BuilderType& builder, std::span value) + { + return builder.Append((char*)value.data(), (int64_t)value.size()); + } +}; + template struct BuilderMaker> { using FillType = std::pair; @@ -422,6 +446,13 @@ struct DirectInsertion { return builder->Append(value); } + template + requires std::same_as, T> + arrow::Status append(BUILDER& builder, T value) + { + return builder->Append((char*)value.data(), (int64_t)value.size()); + } + template arrow::Status flush(BUILDER&) { @@ -569,7 +600,7 @@ template using IndexedHoldersTuple = decltype(makeHolderTypes()); template -concept ShouldNotDeconstruct = std::is_bounded_array_v || std::is_arithmetic_v || framework::is_base_of_template_v; +concept ShouldNotDeconstruct = std::is_bounded_array_v || std::is_arithmetic_v || framework::is_base_of_template_v || std::same_as, T>; /// Helper class which creates a lambda suitable for building /// an arrow table from a tuple. This can be used, for example diff --git a/Framework/Core/test/test_TableBuilder.cxx b/Framework/Core/test/test_TableBuilder.cxx index 00cbbbc59b725..02bc8fbe67833 100644 --- a/Framework/Core/test/test_TableBuilder.cxx +++ b/Framework/Core/test/test_TableBuilder.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2019-2025 CERN and copyright holders of ALICE O2. // See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. // All rights not expressly granted are reserved. // @@ -19,6 +19,8 @@ #include #include +#include + using namespace o2::framework; // We use a different namespace to avoid clashes with the @@ -27,10 +29,12 @@ namespace test2 { DECLARE_SOA_COLUMN_FULL(X, x, uint64_t, "x"); DECLARE_SOA_COLUMN_FULL(Y, y, uint64_t, "y"); +DECLARE_SOA_COLUMN_FULL(Blob, blob, std::span, "blob"); DECLARE_SOA_COLUMN_FULL(Pos, pos, int[4], "pos"); } // namespace test2 using TestTable = o2::soa::InPlaceTable<0, test2::X, test2::Y>; +using SpanTable = o2::soa::InPlaceTable<0, test2::Blob>; using ArrayTable = o2::soa::InPlaceTable<0, test2::Pos>; TEST_CASE("TestTableBuilder") @@ -189,6 +193,35 @@ TEST_CASE("TestTableBuilderMore") REQUIRE(table->schema()->field(3)->type()->id() == arrow::boolean()->id()); } +TEST_CASE("TestSpan") +{ + TableBuilder builder; + std::vector buffer{10, std::byte{'c'}}; + std::vector buffer1{10, std::byte{'a'}}; + + auto rowWriter = builder.persist>({"blob"}); + rowWriter(0, std::span(buffer)); + rowWriter(0, std::span(buffer.data() + 1, 9)); + rowWriter(0, std::span(buffer1.data(), 3)); + rowWriter(0, std::span(buffer1.data(), 1)); + auto table = builder.finalize(); + + REQUIRE(table->num_columns() == 1); + REQUIRE(table->num_rows() == 4); + REQUIRE(table->schema()->field(0)->name() == "blob"); + REQUIRE(table->schema()->field(0)->type()->id() == arrow::binary_view()->id()); + + auto readBack = SpanTable{table}; + auto row = readBack.begin(); + REQUIRE(row.blob() == "cccccccccc"); + ++row; + REQUIRE(row.blob() == "ccccccccc"); + ++row; + REQUIRE(row.blob() == "aaa"); + ++row; + REQUIRE(row.blob() == "a"); +} + TEST_CASE("TestSoAIntegration") { TableBuilder builder; From f2b0957773011be7cd8d4feb68fb9cae45e0e05d Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 6 Aug 2025 14:20:09 +0200 Subject: [PATCH 211/315] ITS: GPU: put trackleting properly on different streams Signed-off-by: Felix Schlepper --- .../GPU/ITStrackingGPU/TimeFrameGPU.h | 9 +- .../ITS/tracking/GPU/ITStrackingGPU/Utils.h | 25 ++++-- .../ITS/tracking/GPU/cuda/TimeFrameGPU.cu | 82 ++++++++++++------- .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 1 + .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 10 ++- 5 files changed, 80 insertions(+), 47 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h index 0ad08fd88ccf5..4656dd1d14846 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h @@ -79,6 +79,7 @@ class TimeFrameGPU : public TimeFrame return mGpuStreams[stream]; } auto& getStreams() { return mGpuStreams; } + void syncStreams(); virtual void wipe() final; /// interface @@ -108,7 +109,7 @@ class TimeFrameGPU : public TimeFrame std::vector getClusterSizes(); const unsigned char** getDeviceArrayUsedClusters() const { return mUsedClustersDeviceArray; } const int** getDeviceROframeClusters() const { return mROFrameClustersDeviceArray; } - Tracklet** getDeviceArrayTracklets() { return mTrackletsDeviceArray; } + Tracklet** getDeviceArrayTracklets() { return mTrackletsDevice.data(); } int** getDeviceArrayTrackletsLUT() const { return mTrackletsLUTDeviceArray; } int** getDeviceArrayCellsLUT() const { return mCellsLUTDeviceArray; } int** getDeviceArrayNeighboursCellLUT() const { return mNeighboursCellLUTDeviceArray; } @@ -140,7 +141,8 @@ class TimeFrameGPU : public TimeFrame int getNumberOfNeighbours() const final; private: - void allocMemAsync(void**, size_t, Stream&, bool); // Abstract owned and unowned memory allocations + void allocMemAsync(void**, size_t, Stream&, bool); // Abstract owned and unowned memory allocations on specific stream + void allocMem(void**, size_t, bool); // Abstract owned and unowned memory allocations on default stream bool mHostRegistered = false; TimeFrameGPUParameters mGpuParams; @@ -167,7 +169,6 @@ class TimeFrameGPU : public TimeFrame const unsigned char** mUsedClustersDeviceArray; const int** mROFrameClustersDeviceArray; std::array mTrackletsDevice; - Tracklet** mTrackletsDeviceArray; std::array mTrackletsLUTDevice; std::array mCellsLUTDevice; std::array mNeighboursLUTDevice; @@ -195,8 +196,6 @@ class TimeFrameGPU : public TimeFrame // State Streams mGpuStreams; - size_t mAvailMemGB; - bool mFirstInit = true; // Temporary buffer for storing output tracks from GPU tracking bounded_vector mTrackITSExt; diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h index 802973d5f4000..9d25bd22484fe 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h @@ -94,16 +94,21 @@ class Stream public: #if defined(__HIPCC__) using Handle = hipStream_t; - static constexpr Handle Default = 0; + static constexpr Handle DefaultStream = 0; + // static constexpr unsigned int DefaultFlag = hipStreamNonBlocking; TODO replace once ready + static constexpr unsigned int DefaultFlag = 0; #elif defined(__CUDACC__) using Handle = cudaStream_t; - static constexpr Handle Default = 0; + static constexpr Handle DefaultStream = 0; + // static constexpr unsigned int DefaultFlag = cudaStreamNonBlocking; TODO replace once ready + static constexpr unsigned int DefaultFlag = 0; #else using Handle = void*; - static constexpr Handle Default = nullptr; + static constexpr Handle DefaultStream = nullptr; + static constexpr unsigned int DefaultFlag = 0; #endif - Stream(unsigned int flags = 0) + Stream(unsigned int flags = DefaultFlag) { #if defined(__HIPCC__) GPUChkErrS(hipStreamCreateWithFlags(&mHandle, flags)); @@ -115,7 +120,7 @@ class Stream Stream(Handle h) : mHandle(h) {} ~Stream() { - if (mHandle != Default) { + if (mHandle != DefaultStream) { #if defined(__HIPCC__) GPUChkErrS(hipStreamDestroy(mHandle)); #elif defined(__CUDACC__) @@ -124,7 +129,7 @@ class Stream } } - operator bool() const { return mHandle != Default; } + operator bool() const { return mHandle != DefaultStream; } const Handle& get() { return mHandle; } void sync() const { @@ -136,7 +141,7 @@ class Stream } private: - Handle mHandle{Default}; + Handle mHandle{DefaultStream}; }; static_assert(sizeof(Stream) == sizeof(void*), "Stream type must match pointer type!"); @@ -150,6 +155,12 @@ class Streams void clear() { mStreams.clear(); } auto& operator[](size_t i) { return mStreams[i % mStreams.size()]; } void push_back(const Stream& stream) { mStreams.push_back(stream); } + void sync() + { + for (auto& s : mStreams) { + s.sync(); + } + } private: std::vector mStreams; diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu index f6d9157b0da68..dafd218c1e811 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu @@ -122,6 +122,17 @@ void TimeFrameGPU::allocMemAsync(void** ptr, size_t size, Stream& strea } } +template +void TimeFrameGPU::allocMem(void** ptr, size_t size, bool extAllocator) +{ + if (extAllocator) { + *ptr = this->mAllocator->allocate(size); + } else { + GPULog("Calling default CUDA allocator"); + GPUChkErrS(cudaMalloc(reinterpret_cast(ptr), size)); + } +} + template void TimeFrameGPU::setDevicePropagator(const o2::base::PropagatorImpl* propagator) { @@ -134,10 +145,10 @@ void TimeFrameGPU::loadIndexTableUtils(const int iteration) GPUTimer timer(mGpuStreams[0], "loading indextable utils"); if (!iteration) { GPULog("gpu-allocation: allocating IndexTableUtils buffer, for {:.2f} MB.", sizeof(IndexTableUtils) / constants::MB); - allocMemAsync(reinterpret_cast(&mIndexTableUtilsDevice), sizeof(IndexTableUtils), mGpuStreams[0], this->getExtAllocator()); + allocMem(reinterpret_cast(&mIndexTableUtilsDevice), sizeof(IndexTableUtils), this->getExtAllocator()); } GPULog("gpu-transfer: loading IndexTableUtils object, for {:.2f} MB.", sizeof(IndexTableUtils) / constants::MB); - GPUChkErrS(cudaMemcpyAsync(mIndexTableUtilsDevice, &(this->mIndexTableUtils), sizeof(IndexTableUtils), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpy(mIndexTableUtilsDevice, &(this->mIndexTableUtils), sizeof(IndexTableUtils), cudaMemcpyHostToDevice)); } template @@ -151,9 +162,10 @@ void TimeFrameGPU::loadUnsortedClustersDevice(const int iteration) GPUChkErrS(cudaHostRegister(this->mUnsortedClusters[iLayer].data(), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mUnsortedClustersDevice[iLayer], this->mUnsortedClusters[iLayer].data(), this->mUnsortedClusters[iLayer].size() * sizeof(Cluster), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } - allocMemAsync(reinterpret_cast(&mUnsortedClustersDeviceArray), nLayers * sizeof(Cluster*), mGpuStreams[0], this->getExtAllocator()); + mGpuStreams.sync(); + allocMem(reinterpret_cast(&mUnsortedClustersDeviceArray), nLayers * sizeof(Cluster*), this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mUnsortedClustersDevice.data(), nLayers * sizeof(Cluster*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mUnsortedClustersDeviceArray, mUnsortedClustersDevice.data(), nLayers * sizeof(Cluster*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpy(mUnsortedClustersDeviceArray, mUnsortedClustersDevice.data(), nLayers * sizeof(Cluster*), cudaMemcpyHostToDevice)); } } @@ -164,13 +176,14 @@ void TimeFrameGPU::loadClustersDevice(const int iteration) GPUTimer timer(mGpuStreams[0], "loading sorted clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { GPULog("gpu-transfer: loading {} clusters on layer {}, for {:.2f} MB.", this->mClusters[iLayer].size(), iLayer, this->mClusters[iLayer].size() * sizeof(Cluster) / constants::MB); - allocMemAsync(reinterpret_cast(&mClustersDevice[iLayer]), this->mClusters[iLayer].size() * sizeof(Cluster), mGpuStreams[0], this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mClustersDevice[iLayer]), this->mClusters[iLayer].size() * sizeof(Cluster), mGpuStreams[iLayer], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mClusters[iLayer].data(), this->mClusters[iLayer].size() * sizeof(Cluster), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mClustersDevice[iLayer], this->mClusters[iLayer].data(), this->mClusters[iLayer].size() * sizeof(Cluster), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpyAsync(mClustersDevice[iLayer], this->mClusters[iLayer].data(), this->mClusters[iLayer].size() * sizeof(Cluster), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } - allocMemAsync(reinterpret_cast(&mClustersDeviceArray), nLayers * sizeof(Cluster*), mGpuStreams[0], this->getExtAllocator()); + mGpuStreams.sync(); + allocMem(reinterpret_cast(&mClustersDeviceArray), nLayers * sizeof(Cluster*), this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mClustersDevice.data(), nLayers * sizeof(Cluster*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mClustersDeviceArray, mClustersDevice.data(), nLayers * sizeof(Cluster*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpy(mClustersDeviceArray, mClustersDevice.data(), nLayers * sizeof(Cluster*), cudaMemcpyHostToDevice)); } } @@ -181,11 +194,12 @@ void TimeFrameGPU::loadClustersIndexTables(const int iteration) GPUTimer timer(mGpuStreams[0], "loading sorted clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { GPULog("gpu-transfer: loading clusters indextable for layer {} with {} elements, for {:.2f} MB.", iLayer, this->mIndexTables[iLayer].size(), this->mIndexTables[iLayer].size() * sizeof(int) / constants::MB); - allocMemAsync(reinterpret_cast(&mClustersIndexTablesDevice[iLayer]), this->mIndexTables[iLayer].size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mClustersIndexTablesDevice[iLayer], this->mIndexTables[iLayer].data(), this->mIndexTables[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + allocMemAsync(reinterpret_cast(&mClustersIndexTablesDevice[iLayer]), this->mIndexTables[iLayer].size() * sizeof(int), mGpuStreams[iLayer], this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mClustersIndexTablesDevice[iLayer], this->mIndexTables[iLayer].data(), this->mIndexTables[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } - allocMemAsync(reinterpret_cast(&mClustersIndexTablesDeviceArray), nLayers * sizeof(int), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mClustersIndexTablesDeviceArray, mClustersIndexTablesDevice.data(), nLayers * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + mGpuStreams.sync(); + allocMem(reinterpret_cast(&mClustersIndexTablesDeviceArray), nLayers * sizeof(int), this->getExtAllocator()); + GPUChkErrS(cudaMemcpyAsync(mClustersIndexTablesDeviceArray, mClustersIndexTablesDevice.data(), nLayers * sizeof(int*), cudaMemcpyHostToDevice)); } } @@ -196,10 +210,11 @@ void TimeFrameGPU::createUsedClustersDevice(const int iteration) GPUTimer timer(mGpuStreams[0], "creating used clusters flags"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { GPULog("gpu-transfer: creating {} used clusters flags on layer {}, for {:.2f} MB.", this->mUsedClusters[iLayer].size(), iLayer, this->mUsedClusters[iLayer].size() * sizeof(unsigned char) / constants::MB); - allocMemAsync(reinterpret_cast(&mUsedClustersDevice[iLayer]), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mUsedClustersDevice[iLayer], 0, this->mUsedClusters[iLayer].size() * sizeof(unsigned char), mGpuStreams[0].get())); + allocMemAsync(reinterpret_cast(&mUsedClustersDevice[iLayer]), this->mUsedClusters[iLayer].size() * sizeof(unsigned char), mGpuStreams[iLayer], this->getExtAllocator()); + GPUChkErrS(cudaMemsetAsync(mUsedClustersDevice[iLayer], 0, this->mUsedClusters[iLayer].size() * sizeof(unsigned char), mGpuStreams[iLayer].get())); } - allocMemAsync(reinterpret_cast(&mUsedClustersDeviceArray), nLayers * sizeof(unsigned char*), mGpuStreams[0], this->getExtAllocator()); + mGpuStreams.sync(); + allocMem(reinterpret_cast(&mUsedClustersDeviceArray), nLayers * sizeof(unsigned char*), this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mUsedClustersDeviceArray, mUsedClustersDevice.data(), nLayers * sizeof(unsigned char*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } } @@ -221,11 +236,12 @@ void TimeFrameGPU::loadROframeClustersDevice(const int iteration) GPUTimer timer(mGpuStreams[0], "loading ROframe clusters"); for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { GPULog("gpu-transfer: loading {} ROframe clusters info on layer {}, for {:.2f} MB.", this->mROFramesClusters[iLayer].size(), iLayer, this->mROFramesClusters[iLayer].size() * sizeof(int) / constants::MB); - allocMemAsync(reinterpret_cast(&mROFramesClustersDevice[iLayer]), this->mROFramesClusters[iLayer].size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mROFramesClustersDevice[iLayer]), this->mROFramesClusters[iLayer].size() * sizeof(int), mGpuStreams[iLayer], this->getExtAllocator()); GPUChkErrS(cudaMemcpyAsync(mROFramesClustersDevice[iLayer], this->mROFramesClusters[iLayer].data(), this->mROFramesClusters[iLayer].size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } - allocMemAsync(reinterpret_cast(&mROFrameClustersDeviceArray), nLayers * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mROFrameClustersDeviceArray, mROFramesClustersDevice.data(), nLayers * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + mGpuStreams.sync(); + allocMem(reinterpret_cast(&mROFrameClustersDeviceArray), nLayers * sizeof(int*), this->getExtAllocator()); + GPUChkErrS(cudaMemcpy(mROFrameClustersDeviceArray, mROFramesClustersDevice.data(), nLayers * sizeof(int*), cudaMemcpyHostToDevice)); } } @@ -236,10 +252,11 @@ void TimeFrameGPU::loadTrackingFrameInfoDevice(const int iteration) if (!iteration) { for (auto iLayer{0}; iLayer < nLayers; ++iLayer) { GPULog("gpu-transfer: loading {} tfinfo on layer {}, for {:.2f} MB.", this->mTrackingFrameInfo[iLayer].size(), iLayer, this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo) / constants::MB); - allocMemAsync(reinterpret_cast(&mTrackingFrameInfoDevice[iLayer]), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), mGpuStreams[0], this->getExtAllocator()); + allocMemAsync(reinterpret_cast(&mTrackingFrameInfoDevice[iLayer]), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), mGpuStreams[iLayer], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(this->mTrackingFrameInfo[iLayer].data(), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mTrackingFrameInfoDevice[iLayer], this->mTrackingFrameInfo[iLayer].data(), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpyAsync(mTrackingFrameInfoDevice[iLayer], this->mTrackingFrameInfo[iLayer].data(), this->mTrackingFrameInfo[iLayer].size() * sizeof(TrackingFrameInfo), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } + mGpuStreams.sync(); allocMemAsync(reinterpret_cast(&mTrackingFrameInfoDeviceArray), nLayers * sizeof(TrackingFrameInfo*), mGpuStreams[0], this->getExtAllocator()); GPUChkErrS(cudaHostRegister(mTrackingFrameInfoDevice.data(), nLayers * sizeof(TrackingFrameInfo*), cudaHostRegisterPortable)); GPUChkErrS(cudaMemcpyAsync(mTrackingFrameInfoDeviceArray, mTrackingFrameInfoDevice.data(), nLayers * sizeof(TrackingFrameInfo*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); @@ -253,9 +270,9 @@ void TimeFrameGPU::loadMultiplicityCutMask(const int iteration) GPUTimer timer(mGpuStreams[0], "loading multiplicity cut mask"); GPULog("gpu-transfer: iteration {} loading multiplicity cut mask with {} elements, for {:.2f} MB.", iteration, this->mMultiplicityCutMask.size(), this->mMultiplicityCutMask.size() * sizeof(bool) / constants::MB); if (!iteration) { // only allocate on first call - allocMemAsync(reinterpret_cast(&mMultMaskDevice), this->mMultiplicityCutMask.size() * sizeof(uint8_t), mGpuStreams[0], this->getExtAllocator()); + allocMem(reinterpret_cast(&mMultMaskDevice), this->mMultiplicityCutMask.size() * sizeof(uint8_t), this->getExtAllocator()); } - GPUChkErrS(cudaMemcpyAsync(mMultMaskDevice, this->mMultiplicityCutMask.data(), this->mMultiplicityCutMask.size() * sizeof(uint8_t), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + GPUChkErrS(cudaMemcpy(mMultMaskDevice, this->mMultiplicityCutMask.data(), this->mMultiplicityCutMask.size() * sizeof(uint8_t), cudaMemcpyHostToDevice)); } } @@ -265,11 +282,11 @@ void TimeFrameGPU::loadVertices(const int iteration) if (!iteration) { GPUTimer timer(mGpuStreams[0], "loading seeding vertices"); GPULog("gpu-transfer: loading {} ROframes vertices, for {:.2f} MB.", this->mROFramesPV.size(), this->mROFramesPV.size() * sizeof(int) / constants::MB); - allocMemAsync(reinterpret_cast(&mROFramesPVDevice), this->mROFramesPV.size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mROFramesPVDevice, this->mROFramesPV.data(), this->mROFramesPV.size() * sizeof(int), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + allocMem(reinterpret_cast(&mROFramesPVDevice), this->mROFramesPV.size() * sizeof(int), this->getExtAllocator()); + GPUChkErrS(cudaMemcpy(mROFramesPVDevice, this->mROFramesPV.data(), this->mROFramesPV.size() * sizeof(int), cudaMemcpyHostToDevice)); GPULog("gpu-transfer: loading {} seeding vertices, for {:.2f} MB.", this->mPrimaryVertices.size(), this->mPrimaryVertices.size() * sizeof(Vertex) / constants::MB); - allocMemAsync(reinterpret_cast(&mPrimaryVerticesDevice), this->mPrimaryVertices.size() * sizeof(Vertex), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mPrimaryVerticesDevice, this->mPrimaryVertices.data(), this->mPrimaryVertices.size() * sizeof(Vertex), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + allocMem(reinterpret_cast(&mPrimaryVerticesDevice), this->mPrimaryVertices.size() * sizeof(Vertex), this->getExtAllocator()); + GPUChkErrS(cudaMemcpy(mPrimaryVerticesDevice, this->mPrimaryVertices.data(), this->mPrimaryVertices.size() * sizeof(Vertex), cudaMemcpyHostToDevice)); } } @@ -294,16 +311,13 @@ void TimeFrameGPU::createTrackletsLUTDevice(const int iteration) template void TimeFrameGPU::createTrackletsBuffers() { - GPUTimer timer(mGpuStreams[0], "creating tracklet buffers"); for (int iLayer{0}; iLayer < nLayers - 1; ++iLayer) { + GPUTimer timer(mGpuStreams[iLayer], "creating tracklet buffers"); mNTracklets[iLayer] = 0; GPUChkErrS(cudaMemcpyAsync(&mNTracklets[iLayer], mTrackletsLUTDevice[iLayer] + this->mClusters[iLayer].size(), sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[iLayer].get())); GPULog("gpu-transfer: creating tracklets buffer for {} elements on layer {}, for {:.2f} MB.", mNTracklets[iLayer], iLayer, mNTracklets[iLayer] * sizeof(Tracklet) / constants::MB); allocMemAsync(reinterpret_cast(&mTrackletsDevice[iLayer]), mNTracklets[iLayer] * sizeof(Tracklet), mGpuStreams[iLayer], this->getExtAllocator()); } - allocMemAsync(reinterpret_cast(&mTrackletsDeviceArray), (nLayers - 1) * sizeof(Tracklet*), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaHostRegister(mTrackletsDevice.data(), (nLayers - 1) * sizeof(Tracklet*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mTrackletsDeviceArray, mTrackletsDevice.data(), (nLayers - 1) * sizeof(Tracklet*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } template @@ -524,7 +538,7 @@ void TimeFrameGPU::unregisterRest() GPUTimer timer(mGpuStreams[0], "unregistering rest of the host memory"); GPULog("unregistering rest of the host memory..."); GPUChkErrS(cudaHostUnregister(mCellsDevice.data())); - GPUChkErrS(cudaHostUnregister(mTrackletsDevice.data())); + // GPUChkErrS(cudaHostUnregister(mTrackletsDevice.data())); } template @@ -553,6 +567,12 @@ void TimeFrameGPU::initialise(const int iteration, o2::its::TimeFrame::initialise(iteration, trkParam, maxLayers); } +template +void TimeFrameGPU::syncStreams() +{ + mGpuStreams.sync(); +} + template void TimeFrameGPU::wipe() { diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index eaa6080761fec..9a6fe4e050519 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -116,6 +116,7 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i conf.nBlocksLayerTracklets[iteration], conf.nThreadsLayerTracklets[iteration], mTimeFrameGPU->getStreams()); + mTimeFrameGPU->syncStreams(); // TODO evaluate if this can be removed } template diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 02be19b1e3a08..6e678118686ab 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -876,9 +876,9 @@ GPUhi() void cubExclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stre void* d_temp_storage = nullptr; size_t temp_storage_bytes = 0; GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); - GPUChkErrS(cudaMalloc(&d_temp_storage, temp_storage_bytes)); + GPUChkErrS(cudaMallocAsync(&d_temp_storage, temp_storage_bytes, stream)); GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); - GPUChkErrS(cudaFree(d_temp_storage)); + GPUChkErrS(cudaFreeAsync(d_temp_storage, stream)); } template @@ -893,9 +893,9 @@ GPUhi() void cubInclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stre void* d_temp_storage = nullptr; size_t temp_storage_bytes = 0; GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); - GPUChkErrS(cudaMalloc(&d_temp_storage, temp_storage_bytes)); + GPUChkErrS(cudaMallocAsync(&d_temp_storage, temp_storage_bytes, stream)); GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); - GPUChkErrS(cudaFree(d_temp_storage)); + GPUChkErrS(cudaFreeAsync(d_temp_storage, stream)); } template @@ -1030,6 +1030,8 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, resolutions[iLayer], radii[iLayer + 1] - radii[iLayer], mulScatAng[iLayer]); + /// Internal thrust allocation serialize this part to a degree + /// TODO switch to cub equivelent and do all work on one stream thrust::device_ptr tracklets_ptr(spanTracklets[iLayer]); auto nosync_policy = THRUST_NAMESPACE::par_nosync.on(streams[iLayer].get()); thrust::sort(nosync_policy, tracklets_ptr, tracklets_ptr + nTracklets[iLayer], gpu::sort_tracklets()); From 2498a68ad1982a2dec814390a64d0b4b1a4a9bdf Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 6 Aug 2025 15:33:05 +0200 Subject: [PATCH 212/315] ITS: GPU: put cell finding on different streams Signed-off-by: Felix Schlepper --- .../GPU/ITStrackingGPU/TimeFrameGPU.h | 6 +--- .../GPU/ITStrackingGPU/TrackingKernels.h | 11 ++++++-- .../ITS/tracking/GPU/cuda/TimeFrameGPU.cu | 8 +++++- .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 28 ++++++++++++++----- .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 12 ++++---- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h index 4656dd1d14846..afe31b14a4a0a 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h @@ -73,12 +73,8 @@ class TimeFrameGPU : public TimeFrame void downloadCellsDevice(); void downloadCellsLUTDevice(); void unregisterRest(); - template - auto& getStream(const size_t stream) - { - return mGpuStreams[stream]; - } auto& getStreams() { return mGpuStreams; } + void syncStream(const size_t stream); void syncStreams(); virtual void wipe() final; diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h index b0fb443513fef..567aa07f42f7c 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h @@ -25,7 +25,10 @@ namespace gpu #ifdef GPUCA_GPUCODE // GPUg() global kernels must only when compiled by GPU compiler -GPUdi() int4 getEmptyBinsRect() { return int4{0, 0, 0, 0}; } +GPUdi() int4 getEmptyBinsRect() +{ + return int4{0, 0, 0, 0}; +} GPUd() bool fitTrack(TrackITSExt& track, int start, @@ -137,7 +140,8 @@ void countCellsHandler(const Cluster** sortedClusters, const float cellDeltaTanLambdaSigma, const float nSigmaCut, const int nBlocks, - const int nThreads); + const int nThreads, + gpu::Streams& streams); void computeCellsHandler(const Cluster** sortedClusters, const Cluster** unsortedClusters, @@ -155,7 +159,8 @@ void computeCellsHandler(const Cluster** sortedClusters, const float cellDeltaTanLambdaSigma, const float nSigmaCut, const int nBlocks, - const int nThreads); + const int nThreads, + gpu::Streams& streams); unsigned int countCellNeighboursHandler(CellSeed** cellsLayersDevice, int* neighboursLUTs, diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu index dafd218c1e811..da91373611a2d 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu @@ -402,7 +402,7 @@ void TimeFrameGPU::createCellsLUTDevice() template void TimeFrameGPU::createCellsBuffers(const int layer) { - GPUTimer timer(mGpuStreams[0], "creating cells buffers"); + GPUTimer timer(mGpuStreams[layer], "creating cells buffers"); mNCells[layer] = 0; GPUChkErrS(cudaMemcpyAsync(&mNCells[layer], mCellsLUTDevice[layer] + mNTracklets[layer], sizeof(int), cudaMemcpyDeviceToHost, mGpuStreams[layer].get())); GPULog("gpu-transfer: creating cell buffer for {} elements on layer {}, for {:.2f} MB.", mNCells[layer], layer, mNCells[layer] * sizeof(CellSeed) / constants::MB); @@ -567,6 +567,12 @@ void TimeFrameGPU::initialise(const int iteration, o2::its::TimeFrame::initialise(iteration, trkParam, maxLayers); } +template +void TimeFrameGPU::syncStream(const size_t stream) +{ + mGpuStreams[stream].sync(); +} + template void TimeFrameGPU::syncStreams() { diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index 9a6fe4e050519..2ae4f0aa91819 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -116,7 +116,6 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i conf.nBlocksLayerTracklets[iteration], conf.nThreadsLayerTracklets[iteration], mTimeFrameGPU->getStreams()); - mTimeFrameGPU->syncStreams(); // TODO evaluate if this can be removed } template @@ -125,18 +124,30 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) mTimeFrameGPU->createCellsLUTDevice(); auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); + std::vector isTrackletStreamSynched(this->mTrkParams[iteration].TrackletsPerRoad()); + auto syncOnce = [&](const int iLayer) { + if (!isTrackletStreamSynched[iLayer]) { + mTimeFrameGPU->syncStream(iLayer); + isTrackletStreamSynched[iLayer] = true; + } + }; + for (int iLayer = 0; iLayer < this->mTrkParams[iteration].CellsPerRoad(); ++iLayer) { - if (!mTimeFrameGPU->getNTracklets()[iLayer + 1] || !mTimeFrameGPU->getNTracklets()[iLayer]) { + // need to ensure that trackleting on layers iLayer and iLayer + 1 are done (only once) + syncOnce(iLayer); + syncOnce(iLayer + 1); + // if there are no tracklets skip entirely + const int currentLayerTrackletsNum{static_cast(mTimeFrameGPU->getNTracklets()[iLayer])}; + if (!currentLayerTrackletsNum || !mTimeFrameGPU->getNTracklets()[iLayer + 1]) { mTimeFrameGPU->getNCells()[iLayer] = 0; continue; } - const int currentLayerTrackletsNum{static_cast(mTimeFrameGPU->getNTracklets()[iLayer])}; countCellsHandler(mTimeFrameGPU->getDeviceArrayClusters(), mTimeFrameGPU->getDeviceArrayUnsortedClusters(), mTimeFrameGPU->getDeviceArrayTrackingFrameInfo(), mTimeFrameGPU->getDeviceArrayTracklets(), mTimeFrameGPU->getDeviceArrayTrackletsLUT(), - mTimeFrameGPU->getNTracklets()[iLayer], + currentLayerTrackletsNum, iLayer, nullptr, mTimeFrameGPU->getDeviceArrayCellsLUT(), @@ -147,14 +158,15 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) this->mTrkParams[iteration].CellDeltaTanLambdaSigma, this->mTrkParams[iteration].NSigmaCut, conf.nBlocksLayerCells[iteration], - conf.nThreadsLayerCells[iteration]); + conf.nThreadsLayerCells[iteration], + mTimeFrameGPU->getStreams()); mTimeFrameGPU->createCellsBuffers(iLayer); computeCellsHandler(mTimeFrameGPU->getDeviceArrayClusters(), mTimeFrameGPU->getDeviceArrayUnsortedClusters(), mTimeFrameGPU->getDeviceArrayTrackingFrameInfo(), mTimeFrameGPU->getDeviceArrayTracklets(), mTimeFrameGPU->getDeviceArrayTrackletsLUT(), - mTimeFrameGPU->getNTracklets()[iLayer], + currentLayerTrackletsNum, iLayer, mTimeFrameGPU->getDeviceCells()[iLayer], mTimeFrameGPU->getDeviceArrayCellsLUT(), @@ -165,8 +177,10 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) this->mTrkParams[iteration].CellDeltaTanLambdaSigma, this->mTrkParams[iteration].NSigmaCut, conf.nBlocksLayerCells[iteration], - conf.nThreadsLayerCells[iteration]); + conf.nThreadsLayerCells[iteration], + mTimeFrameGPU->getStreams()); } + mTimeFrameGPU->syncStreams(); // TODO evaluate if this can be removed } template diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 6e678118686ab..d4dcda067b26f 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -1065,9 +1065,10 @@ void countCellsHandler( const float cellDeltaTanLambdaSigma, const float nSigmaCut, const int nBlocks, - const int nThreads) + const int nThreads, + gpu::Streams& streams) { - gpu::computeLayerCellsKernel<<>>( + gpu::computeLayerCellsKernel<<>>( sortedClusters, // const Cluster** unsortedClusters, // const Cluster** tfInfo, // const TrackingFrameInfo** @@ -1082,7 +1083,7 @@ void countCellsHandler( maxChi2ClusterAttachment, // const float cellDeltaTanLambdaSigma, // const float nSigmaCut); // const float - gpu::cubExclusiveScanInPlace(cellsLUTsHost, nTracklets + 1); + gpu::cubExclusiveScanInPlace(cellsLUTsHost, nTracklets + 1, streams[layer].get()); } void computeCellsHandler( @@ -1102,9 +1103,10 @@ void computeCellsHandler( const float cellDeltaTanLambdaSigma, const float nSigmaCut, const int nBlocks, - const int nThreads) + const int nThreads, + gpu::Streams& streams) { - gpu::computeLayerCellsKernel<<>>( + gpu::computeLayerCellsKernel<<>>( sortedClusters, // const Cluster** unsortedClusters, // const Cluster** tfInfo, // const TrackingFrameInfo** From 853e48dd3895a78b2e81aef21968bf16f8fb1ac4 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 6 Aug 2025 16:28:15 +0200 Subject: [PATCH 213/315] ITS: GPU: put cell neighbour finding on different streams Signed-off-by: Felix Schlepper --- .../GPU/ITStrackingGPU/TimeFrameGPU.h | 12 ++-- .../GPU/ITStrackingGPU/TrackingKernels.h | 35 +++++----- .../ITS/tracking/GPU/cuda/TimeFrameGPU.cu | 59 ++++------------- .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 66 +++++++++++-------- .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 58 ++++++++-------- 5 files changed, 101 insertions(+), 129 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h index afe31b14a4a0a..5c10b01412b4e 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TimeFrameGPU.h @@ -62,17 +62,15 @@ class TimeFrameGPU : public TimeFrame void createCellsDevice(); void createCellsLUTDevice(); void createNeighboursIndexTablesDevice(); - void createNeighboursDevice(const unsigned int layer, const unsigned int nNeighbours); - void createNeighboursDevice(const unsigned int layer, std::vector>& neighbours); + void createNeighboursDevice(const unsigned int layer); void createNeighboursLUTDevice(const int, const unsigned int); - void createNeighboursDeviceArray(); void createTrackITSExtDevice(bounded_vector&); void downloadTrackITSExtDevice(bounded_vector&); void downloadCellsNeighboursDevice(std::vector>>&, const int); void downloadNeighboursLUTDevice(bounded_vector&, const int); void downloadCellsDevice(); void downloadCellsLUTDevice(); - void unregisterRest(); + auto& getStream(const size_t stream) { return mGpuStreams[stream]; } auto& getStreams() { return mGpuStreams; } void syncStream(const size_t stream); void syncStreams(); @@ -96,7 +94,7 @@ class TimeFrameGPU : public TimeFrame gpuPair* getDeviceNeighbourPairs(const int layer) { return mNeighbourPairsDevice[layer]; } std::array& getDeviceNeighboursAll() { return mNeighboursDevice; } int* getDeviceNeighbours(const int layer) { return mNeighboursDevice[layer]; } - int** getDeviceNeighboursArray() { return mNeighboursDeviceArray; } + int** getDeviceNeighboursArray() { return mNeighboursDevice.data(); } TrackingFrameInfo* getDeviceTrackingFrameInfo(const int); const TrackingFrameInfo** getDeviceArrayTrackingFrameInfo() const { return mTrackingFrameInfoDeviceArray; } const Cluster** getDeviceArrayClusters() const { return mClustersDeviceArray; } @@ -109,7 +107,7 @@ class TimeFrameGPU : public TimeFrame int** getDeviceArrayTrackletsLUT() const { return mTrackletsLUTDeviceArray; } int** getDeviceArrayCellsLUT() const { return mCellsLUTDeviceArray; } int** getDeviceArrayNeighboursCellLUT() const { return mNeighboursCellLUTDeviceArray; } - CellSeed** getDeviceArrayCells() const { return mCellsDeviceArray; } + CellSeed** getDeviceArrayCells() { return mCellsDevice.data(); } CellSeed* getDeviceTrackSeeds() { return mTrackSeedsDevice; } o2::track::TrackParCovF** getDeviceArrayTrackSeeds() { return mCellSeedsDeviceArray; } float** getDeviceArrayTrackSeedsChi2() { return mCellSeedsChi2DeviceArray; } @@ -176,7 +174,6 @@ class TimeFrameGPU : public TimeFrame std::array mCellsDevice; std::array mNeighboursIndexTablesDevice; CellSeed* mTrackSeedsDevice; - CellSeed** mCellsDeviceArray; std::array mCellSeedsDevice; o2::track::TrackParCovF** mCellSeedsDeviceArray; std::array mCellSeedsChi2Device; @@ -186,7 +183,6 @@ class TimeFrameGPU : public TimeFrame TrackITSExt* mTrackITSExtDevice; std::array*, nLayers - 2> mNeighbourPairsDevice; std::array mNeighboursDevice; - int** mNeighboursDeviceArray; std::array mTrackingFrameInfoDevice; const TrackingFrameInfo** mTrackingFrameInfoDeviceArray; diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h index 567aa07f42f7c..caa7675756db6 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h @@ -162,21 +162,22 @@ void computeCellsHandler(const Cluster** sortedClusters, const int nThreads, gpu::Streams& streams); -unsigned int countCellNeighboursHandler(CellSeed** cellsLayersDevice, - int* neighboursLUTs, - int** cellsLUTs, - gpuPair* cellNeighbours, - int* neighboursIndexTable, - const Tracklet** tracklets, - const int deltaROF, - const float maxChi2ClusterAttachment, - const float bz, - const int layerIndex, - const unsigned int nCells, - const unsigned int nCellsNext, - const int maxCellNeighbours, - const int nBlocks, - const int nThreads); +void countCellNeighboursHandler(CellSeed** cellsLayersDevice, + int* neighboursLUTs, + int** cellsLUTs, + gpuPair* cellNeighbours, + int* neighboursIndexTable, + const Tracklet** tracklets, + const int deltaROF, + const float maxChi2ClusterAttachment, + const float bz, + const int layerIndex, + const unsigned int nCells, + const unsigned int nCellsNext, + const int maxCellNeighbours, + const int nBlocks, + const int nThreads, + gpu::Stream& stream); void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, int* neighboursLUTs, @@ -192,11 +193,13 @@ void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, const unsigned int nCellsNext, const int maxCellNeighbours, const int nBlocks, - const int nThreads); + const int nThreads, + gpu::Stream& stream); int filterCellNeighboursHandler(gpuPair*, int*, unsigned int, + gpu::Stream&, o2::its::ExternalAllocator* = nullptr); template diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu index da91373611a2d..72a1f98d1b78b 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TimeFrameGPU.cu @@ -349,26 +349,20 @@ void TimeFrameGPU::createNeighboursIndexTablesDevice() { GPUTimer timer(mGpuStreams[0], "creating cells neighbours"); // Here we do also the creation of the CellsDeviceArray, as the cells buffers are populated separately in the previous steps. - allocMemAsync(reinterpret_cast(&mCellsDeviceArray), (nLayers - 2) * sizeof(CellSeed*), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaHostRegister(mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaHostRegisterPortable)); - GPUChkErrS(cudaMemcpyAsync(mCellsDeviceArray, mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); for (auto iLayer{0}; iLayer < nLayers - 2; ++iLayer) { GPULog("gpu-transfer: loading neighbours LUT for {} elements on layer {}, for {:.2f} MB.", mNCells[iLayer], iLayer, mNCells[iLayer] * sizeof(CellSeed) / constants::MB); - allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (mNCells[iLayer] + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (mNCells[iLayer] + 1) * sizeof(int), mGpuStreams[0].get())); - if (iLayer < nLayers - 3) { - mNNeighbours[iLayer] = 0; - } + allocMemAsync(reinterpret_cast(&mNeighboursIndexTablesDevice[iLayer]), (mNCells[iLayer] + 1) * sizeof(int), mGpuStreams[iLayer], this->getExtAllocator()); + GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (mNCells[iLayer] + 1) * sizeof(int), mGpuStreams[iLayer].get())); } } template void TimeFrameGPU::createNeighboursLUTDevice(const int layer, const unsigned int nCells) { - GPUTimer timer(mGpuStreams[0], "reserving neighboursLUT"); + GPUTimer timer(mGpuStreams[layer], "reserving neighboursLUT"); GPULog("gpu-allocation: reserving neighbours LUT for {} elements on layer {} , for {:.2f} MB.", nCells + 1, layer, (nCells + 1) * sizeof(int) / constants::MB); - allocMemAsync(reinterpret_cast(&mNeighboursLUTDevice[layer]), (nCells + 1) * sizeof(int), mGpuStreams[0], this->getExtAllocator()); // We need one element more to move exc -> inc - GPUChkErrS(cudaMemsetAsync(mNeighboursLUTDevice[layer], 0, (nCells + 1) * sizeof(int), mGpuStreams[0].get())); + allocMemAsync(reinterpret_cast(&mNeighboursLUTDevice[layer]), (nCells + 1) * sizeof(int), mGpuStreams[layer], this->getExtAllocator()); // We need one element more to move exc -> inc + GPUChkErrS(cudaMemsetAsync(mNeighboursLUTDevice[layer], 0, (nCells + 1) * sizeof(int), mGpuStreams[layer].get())); } template @@ -382,8 +376,6 @@ void TimeFrameGPU::loadCellsDevice() GPUChkErrS(cudaMemsetAsync(mNeighboursIndexTablesDevice[iLayer], 0, (this->mCells[iLayer].size() + 1) * sizeof(int), mGpuStreams[iLayer].get())); GPUChkErrS(cudaMemcpyAsync(mCellsDevice[iLayer], this->mCells[iLayer].data(), this->mCells[iLayer].size() * sizeof(CellSeed), cudaMemcpyHostToDevice, mGpuStreams[iLayer].get())); } - allocMemAsync(reinterpret_cast(&mCellsDeviceArray), (nLayers - 2) * sizeof(CellSeed*), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mCellsDeviceArray, mCellsDevice.data(), (nLayers - 2) * sizeof(CellSeed*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); } template @@ -441,35 +433,15 @@ void TimeFrameGPU::loadTrackSeedsDevice(bounded_vector& seeds } template -void TimeFrameGPU::createNeighboursDevice(const unsigned int layer, const unsigned int nNeighbours) +void TimeFrameGPU::createNeighboursDevice(const unsigned int layer) { - GPUTimer timer(mGpuStreams[0], "reserving neighbours"); + GPUTimer timer(mGpuStreams[layer], "reserving neighbours"); + GPUChkErrS(cudaMemcpyAsync(&(this->mNNeighbours[layer]), &(mNeighboursLUTDevice[layer][this->mNCells[layer + 1] - 1]), sizeof(unsigned int), cudaMemcpyDeviceToHost, mGpuStreams[layer].get())); GPULog("gpu-allocation: reserving {} neighbours (pairs), for {:.2f} MB.", nNeighbours, nNeighbours * sizeof(gpuPair) / constants::MB); - allocMemAsync(reinterpret_cast(&mNeighbourPairsDevice[layer]), nNeighbours * sizeof(gpuPair), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, nNeighbours * sizeof(gpuPair), mGpuStreams[0].get())); + allocMemAsync(reinterpret_cast(&mNeighbourPairsDevice[layer]), (this->mNNeighbours[layer]) * sizeof(gpuPair), mGpuStreams[layer], this->getExtAllocator()); + GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, (this->mNNeighbours[layer]) * sizeof(gpuPair), mGpuStreams[layer].get())); GPULog("gpu-allocation: reserving {} neighbours, for {:.2f} MB.", nNeighbours, nNeighbours * sizeof(gpuPair) / constants::MB); - allocMemAsync(reinterpret_cast(&mNeighboursDevice[layer]), nNeighbours * sizeof(int), mGpuStreams[0], this->getExtAllocator()); -} - -template -void TimeFrameGPU::createNeighboursDevice(const unsigned int layer, std::vector>& neighbours) -{ - GPUTimer timer(mGpuStreams[0], "reserving neighbours"); - this->mCellsNeighbours[layer].clear(); - this->mCellsNeighbours[layer].resize(neighbours.size()); - GPULog("gpu-allocation: reserving {} neighbours (pairs), for {:.2f} MB.", neighbours.size(), neighbours.size() * sizeof(gpuPair) / constants::MB); - allocMemAsync(reinterpret_cast(&mNeighbourPairsDevice[layer]), neighbours.size() * sizeof(gpuPair), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemsetAsync(mNeighbourPairsDevice[layer], -1, neighbours.size() * sizeof(gpuPair), mGpuStreams[0].get())); - GPULog("gpu-allocation: reserving {} neighbours, for {:.2f} MB.", neighbours.size(), neighbours.size() * sizeof(gpuPair) / constants::MB); - allocMemAsync(reinterpret_cast(&mNeighboursDevice[layer]), neighbours.size() * sizeof(int), mGpuStreams[0], this->getExtAllocator()); -} - -template -void TimeFrameGPU::createNeighboursDeviceArray() -{ - GPUTimer timer(mGpuStreams[0], "reserving neighbours"); - allocMemAsync(reinterpret_cast(&mNeighboursDeviceArray), (nLayers - 2) * sizeof(int*), mGpuStreams[0], this->getExtAllocator()); - GPUChkErrS(cudaMemcpyAsync(mNeighboursDeviceArray, mNeighboursDevice.data(), (nLayers - 2) * sizeof(int*), cudaMemcpyHostToDevice, mGpuStreams[0].get())); + allocMemAsync(reinterpret_cast(&mNeighboursDevice[layer]), (this->mNNeighbours[layer]) * sizeof(int), mGpuStreams[layer], this->getExtAllocator()); } template @@ -532,15 +504,6 @@ void TimeFrameGPU::downloadTrackITSExtDevice(bounded_vector& GPUChkErrS(cudaHostUnregister(seeds.data())); } -template -void TimeFrameGPU::unregisterRest() -{ - GPUTimer timer(mGpuStreams[0], "unregistering rest of the host memory"); - GPULog("unregistering rest of the host memory..."); - GPUChkErrS(cudaHostUnregister(mCellsDevice.data())); - // GPUChkErrS(cudaHostUnregister(mTrackletsDevice.data())); -} - template void TimeFrameGPU::unregisterHostMemory(const int maxLayers) { diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index 2ae4f0aa91819..0fa258f63fd23 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -180,7 +180,6 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) conf.nThreadsLayerCells[iteration], mTimeFrameGPU->getStreams()); } - mTimeFrameGPU->syncStreams(); // TODO evaluate if this can be removed } template @@ -188,7 +187,20 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) { mTimeFrameGPU->createNeighboursIndexTablesDevice(); const auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); + + std::vector isCellStreamSynched(this->mTrkParams[iteration].TrackletsPerRoad() - 1); + auto syncOnce = [&](const int iLayer) { + if (!isCellStreamSynched[iLayer]) { + mTimeFrameGPU->syncStream(iLayer); + isCellStreamSynched[iLayer] = true; + } + }; + for (int iLayer{0}; iLayer < this->mTrkParams[iteration].CellsPerRoad() - 1; ++iLayer) { + // ensure that celling is done for iLayer and iLayer+1 is done + syncOnce(iLayer); + syncOnce(iLayer + 1); + const int currentLayerCellsNum{static_cast(mTimeFrameGPU->getNCells()[iLayer])}; const int nextLayerCellsNum{static_cast(mTimeFrameGPU->getNCells()[iLayer + 1])}; if (!nextLayerCellsNum || !currentLayerCellsNum) { @@ -197,24 +209,23 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) } mTimeFrameGPU->createNeighboursLUTDevice(iLayer, nextLayerCellsNum); - unsigned int nNeigh = countCellNeighboursHandler(mTimeFrameGPU->getDeviceArrayCells(), - mTimeFrameGPU->getDeviceNeighboursLUT(iLayer), // LUT is initialised here. - mTimeFrameGPU->getDeviceArrayCellsLUT(), - mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), - mTimeFrameGPU->getDeviceNeighboursIndexTables(iLayer), - (const Tracklet**)mTimeFrameGPU->getDeviceArrayTracklets(), - this->mTrkParams[0].DeltaROF, - this->mTrkParams[0].MaxChi2ClusterAttachment, - this->mBz, - iLayer, - currentLayerCellsNum, - nextLayerCellsNum, - 1e2, - conf.nBlocksFindNeighbours[iteration], - conf.nThreadsFindNeighbours[iteration]); - - mTimeFrameGPU->createNeighboursDevice(iLayer, nNeigh); - + countCellNeighboursHandler(mTimeFrameGPU->getDeviceArrayCells(), + mTimeFrameGPU->getDeviceNeighboursLUT(iLayer), // LUT is initialised here. + mTimeFrameGPU->getDeviceArrayCellsLUT(), + mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), + mTimeFrameGPU->getDeviceNeighboursIndexTables(iLayer), + (const Tracklet**)mTimeFrameGPU->getDeviceArrayTracklets(), + this->mTrkParams[0].DeltaROF, + this->mTrkParams[0].MaxChi2ClusterAttachment, + this->mBz, + iLayer, + currentLayerCellsNum, + nextLayerCellsNum, + 1e2, + conf.nBlocksFindNeighbours[iteration], + conf.nThreadsFindNeighbours[iteration], + mTimeFrameGPU->getStream(iLayer)); + mTimeFrameGPU->createNeighboursDevice(iLayer); computeCellNeighboursHandler(mTimeFrameGPU->getDeviceArrayCells(), mTimeFrameGPU->getDeviceNeighboursLUT(iLayer), mTimeFrameGPU->getDeviceArrayCellsLUT(), @@ -229,16 +240,15 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) nextLayerCellsNum, 1e2, conf.nBlocksFindNeighbours[iteration], - conf.nThreadsFindNeighbours[iteration]); - - nNeigh = filterCellNeighboursHandler(mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), - mTimeFrameGPU->getDeviceNeighbours(iLayer), - nNeigh, - mTimeFrameGPU->getExternalAllocator()); - mTimeFrameGPU->getArrayNNeighbours()[iLayer] = nNeigh; + conf.nThreadsFindNeighbours[iteration], + mTimeFrameGPU->getStream(iLayer)); + mTimeFrameGPU->getArrayNNeighbours()[iLayer] = filterCellNeighboursHandler(mTimeFrameGPU->getDeviceNeighbourPairs(iLayer), + mTimeFrameGPU->getDeviceNeighbours(iLayer), + mTimeFrameGPU->getArrayNNeighbours()[iLayer], + mTimeFrameGPU->getStream(iLayer), + mTimeFrameGPU->getExternalAllocator()); } - mTimeFrameGPU->createNeighboursDeviceArray(); - mTimeFrameGPU->unregisterRest(); + mTimeFrameGPU->syncStreams(); // TODO evaluate if this can be removed }; template diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index d4dcda067b26f..060f150bd6f42 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -1123,23 +1123,24 @@ void computeCellsHandler( nSigmaCut); // const float } -unsigned int countCellNeighboursHandler(CellSeed** cellsLayersDevice, - int* neighboursLUT, - int** cellsLUTs, - gpuPair* cellNeighbours, - int* neighboursIndexTable, - const Tracklet** tracklets, - const int deltaROF, - const float maxChi2ClusterAttachment, - const float bz, - const int layerIndex, - const unsigned int nCells, - const unsigned int nCellsNext, - const int maxCellNeighbours, - const int nBlocks, - const int nThreads) +void countCellNeighboursHandler(CellSeed** cellsLayersDevice, + int* neighboursLUT, + int** cellsLUTs, + gpuPair* cellNeighbours, + int* neighboursIndexTable, + const Tracklet** tracklets, + const int deltaROF, + const float maxChi2ClusterAttachment, + const float bz, + const int layerIndex, + const unsigned int nCells, + const unsigned int nCellsNext, + const int maxCellNeighbours, + const int nBlocks, + const int nThreads, + gpu::Stream& stream) { - gpu::computeLayerCellNeighboursKernel<<>>( + gpu::computeLayerCellNeighboursKernel<<>>( cellsLayersDevice, neighboursLUT, neighboursIndexTable, @@ -1152,11 +1153,8 @@ unsigned int countCellNeighboursHandler(CellSeed** cellsLayersDevice, layerIndex, nCells, maxCellNeighbours); - gpu::cubInclusiveScanInPlace(neighboursLUT, nCellsNext); - gpu::cubExclusiveScanInPlace(neighboursIndexTable, nCells + 1); - unsigned int nNeighbours; - GPUChkErrS(cudaMemcpy(&nNeighbours, &neighboursLUT[nCellsNext - 1], sizeof(unsigned int), cudaMemcpyDeviceToHost)); - return nNeighbours; + gpu::cubInclusiveScanInPlace(neighboursLUT, nCellsNext, stream.get()); + gpu::cubExclusiveScanInPlace(neighboursIndexTable, nCells + 1, stream.get()); } void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, @@ -1173,10 +1171,10 @@ void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, const unsigned int nCellsNext, const int maxCellNeighbours, const int nBlocks, - const int nThreads) + const int nThreads, + gpu::Stream& stream) { - - gpu::computeLayerCellNeighboursKernel<<>>( + gpu::computeLayerCellNeighboursKernel<<>>( cellsLayersDevice, neighboursLUT, neighboursIndexTable, @@ -1189,21 +1187,23 @@ void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, layerIndex, nCells, maxCellNeighbours); - GPUChkErrS(cudaPeekAtLastError()); - GPUChkErrS(cudaDeviceSynchronize()); } int filterCellNeighboursHandler(gpuPair* cellNeighbourPairs, int* cellNeighbours, unsigned int nNeigh, + gpu::Stream& stream, o2::its::ExternalAllocator* allocator) { + /// Internal thrust allocation serialize this part to a degree + /// TODO switch to cub equivelent and do all work on one stream + auto nosync_policy = THRUST_NAMESPACE::par_nosync.on(stream.get()); thrust::device_ptr> neighVectorPairs(cellNeighbourPairs); thrust::device_ptr validNeighs(cellNeighbours); - auto updatedEnd = thrust::remove_if(neighVectorPairs, neighVectorPairs + nNeigh, gpu::is_invalid_pair()); + auto updatedEnd = thrust::remove_if(nosync_policy, neighVectorPairs, neighVectorPairs + nNeigh, gpu::is_invalid_pair()); size_t newSize = updatedEnd - neighVectorPairs; - thrust::stable_sort(neighVectorPairs, neighVectorPairs + newSize, gpu::sort_by_second()); - thrust::transform(neighVectorPairs, neighVectorPairs + newSize, validNeighs, gpu::pair_to_first()); + thrust::stable_sort(nosync_policy, neighVectorPairs, neighVectorPairs + newSize, gpu::sort_by_second()); + thrust::transform(nosync_policy, neighVectorPairs, neighVectorPairs + newSize, validNeighs, gpu::pair_to_first()); return newSize; } From 0825b22c6eb8a853eaa4094cc179e22e663a161b Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 7 Aug 2025 08:00:13 +0200 Subject: [PATCH 214/315] ITS: GPU: use external allocator for temp storage Signed-off-by: Felix Schlepper --- .../GPU/ITStrackingGPU/TrackingKernels.h | 6 +- .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 6 +- .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 67 ++++++++++++------- 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h index caa7675756db6..a7bf4c70bc5c2 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/TrackingKernels.h @@ -86,6 +86,7 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, bounded_vector& resolutions, std::vector& radii, bounded_vector& mulScatAng, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads, gpu::Streams& streams); @@ -120,6 +121,7 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, bounded_vector& resolutions, std::vector& radii, bounded_vector& mulScatAng, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads, gpu::Streams& streams); @@ -139,6 +141,7 @@ void countCellsHandler(const Cluster** sortedClusters, const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, const float nSigmaCut, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads, gpu::Streams& streams); @@ -175,6 +178,7 @@ void countCellNeighboursHandler(CellSeed** cellsLayersDevice, const unsigned int nCells, const unsigned int nCellsNext, const int maxCellNeighbours, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads, gpu::Stream& stream); @@ -213,12 +217,12 @@ void processNeighboursHandler(const int startLayer, gsl::span neighboursDeviceLUTs, const TrackingFrameInfo** foundTrackingFrameInfo, bounded_vector& seedsHost, - o2::its::ExternalAllocator*, const float bz, const float MaxChi2ClusterAttachment, const float maxChi2NDF, const o2::base::Propagator* propagator, const o2::base::PropagatorF::MatCorrType matCorrType, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads); diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index 0fa258f63fd23..e7135e55a16c8 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -80,6 +80,7 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i mTimeFrameGPU->getPositionResolutions(), this->mTrkParams[iteration].LayerRadii, mTimeFrameGPU->getMSangles(), + mTimeFrameGPU->getExternalAllocator(), conf.nBlocksLayerTracklets[iteration], conf.nThreadsLayerTracklets[iteration], mTimeFrameGPU->getStreams()); @@ -113,6 +114,7 @@ void TrackerTraitsGPU::computeLayerTracklets(const int iteration, int i mTimeFrameGPU->getPositionResolutions(), this->mTrkParams[iteration].LayerRadii, mTimeFrameGPU->getMSangles(), + mTimeFrameGPU->getExternalAllocator(), conf.nBlocksLayerTracklets[iteration], conf.nThreadsLayerTracklets[iteration], mTimeFrameGPU->getStreams()); @@ -157,6 +159,7 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) this->mTrkParams[iteration].MaxChi2ClusterAttachment, this->mTrkParams[iteration].CellDeltaTanLambdaSigma, this->mTrkParams[iteration].NSigmaCut, + mTimeFrameGPU->getExternalAllocator(), conf.nBlocksLayerCells[iteration], conf.nThreadsLayerCells[iteration], mTimeFrameGPU->getStreams()); @@ -222,6 +225,7 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) currentLayerCellsNum, nextLayerCellsNum, 1e2, + mTimeFrameGPU->getExternalAllocator(), conf.nBlocksFindNeighbours[iteration], conf.nThreadsFindNeighbours[iteration], mTimeFrameGPU->getStream(iLayer)); @@ -272,12 +276,12 @@ void TrackerTraitsGPU::findRoads(const int iteration) mTimeFrameGPU->getDeviceNeighboursLUTs(), mTimeFrameGPU->getDeviceArrayTrackingFrameInfo(), trackSeeds, - mTimeFrameGPU->getExternalAllocator(), this->mBz, this->mTrkParams[0].MaxChi2ClusterAttachment, this->mTrkParams[0].MaxChi2NDF, mTimeFrameGPU->getDevicePropagator(), this->mTrkParams[0].CorrType, + mTimeFrameGPU->getExternalAllocator(), conf.nBlocksProcessNeighbours[iteration], conf.nThreadsProcessNeighbours[iteration]); } diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index 060f150bd6f42..b8eeae12691a3 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -871,37 +871,53 @@ GPUg() void printCellSeeds(CellSeed* seed, int nCells, const unsigned int tId = } template -GPUhi() void cubExclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stream = nullptr) +GPUhi() void cubExclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stream = nullptr, ExternalAllocator* alloc = nullptr) { void* d_temp_storage = nullptr; size_t temp_storage_bytes = 0; GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); - GPUChkErrS(cudaMallocAsync(&d_temp_storage, temp_storage_bytes, stream)); + if (alloc) { + d_temp_storage = alloc->allocate(temp_storage_bytes); + } else { + GPUChkErrS(cudaMallocAsync(&d_temp_storage, temp_storage_bytes, stream)); + } GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); - GPUChkErrS(cudaFreeAsync(d_temp_storage, stream)); + if (alloc) { + alloc->deallocate(reinterpret_cast(d_temp_storage), temp_storage_bytes); + } else { + GPUChkErrS(cudaFreeAsync(d_temp_storage, stream)); + } } template -GPUhi() void cubExclusiveScanInPlace(Vector& in_out, int num_items, cudaStream_t stream = nullptr) +GPUhi() void cubExclusiveScanInPlace(Vector& in_out, int num_items, cudaStream_t stream = nullptr, ExternalAllocator* alloc = nullptr) { - cubExclusiveScanInPlace(thrust::raw_pointer_cast(in_out.data()), num_items, stream); + cubExclusiveScanInPlace(thrust::raw_pointer_cast(in_out.data()), num_items, stream, alloc); } template -GPUhi() void cubInclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stream = nullptr) +GPUhi() void cubInclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stream = nullptr, ExternalAllocator* alloc = nullptr) { void* d_temp_storage = nullptr; size_t temp_storage_bytes = 0; GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); - GPUChkErrS(cudaMallocAsync(&d_temp_storage, temp_storage_bytes, stream)); + if (alloc) { + d_temp_storage = alloc->allocate(temp_storage_bytes); + } else { + GPUChkErrS(cudaMallocAsync(&d_temp_storage, temp_storage_bytes, stream)); + } GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); - GPUChkErrS(cudaFreeAsync(d_temp_storage, stream)); + if (alloc) { + alloc->deallocate(reinterpret_cast(d_temp_storage), temp_storage_bytes); + } else { + GPUChkErrS(cudaFreeAsync(d_temp_storage, stream)); + } } template -GPUhi() void cubInclusiveScanInPlace(Vector& in_out, int num_items, cudaStream_t stream = nullptr) +GPUhi() void cubInclusiveScanInPlace(Vector& in_out, int num_items, cudaStream_t stream = nullptr, ExternalAllocator* alloc = nullptr) { - cubInclusiveScanInPlace(thrust::raw_pointer_cast(in_out.data()), num_items, stream); + cubInclusiveScanInPlace(thrust::raw_pointer_cast(in_out.data()), num_items, stream, alloc); } } // namespace gpu @@ -932,6 +948,7 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, bounded_vector& resolutions, std::vector& radii, bounded_vector& mulScatAng, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads, gpu::Streams& streams) @@ -964,7 +981,7 @@ void countTrackletsInROFsHandler(const IndexTableUtils* utils, resolutions[iLayer], radii[iLayer + 1] - radii[iLayer], mulScatAng[iLayer]); - gpu::cubExclusiveScanInPlace(trackletsLUTsHost[iLayer], nClusters[iLayer] + 1, streams[iLayer].get()); + gpu::cubExclusiveScanInPlace(trackletsLUTsHost[iLayer], nClusters[iLayer] + 1, streams[iLayer].get(), alloc); } } @@ -998,6 +1015,7 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, bounded_vector& resolutions, std::vector& radii, bounded_vector& mulScatAng, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads, gpu::Streams& streams) @@ -1043,7 +1061,7 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, spanTracklets[iLayer], trackletsLUTsHost[iLayer], nTracklets[iLayer]); - gpu::cubExclusiveScanInPlace(trackletsLUTsHost[iLayer], nClusters[iLayer] + 1, streams[iLayer].get()); + gpu::cubExclusiveScanInPlace(trackletsLUTsHost[iLayer], nClusters[iLayer] + 1, streams[iLayer].get(), alloc); } } } @@ -1064,6 +1082,7 @@ void countCellsHandler( const float maxChi2ClusterAttachment, const float cellDeltaTanLambdaSigma, const float nSigmaCut, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads, gpu::Streams& streams) @@ -1083,7 +1102,7 @@ void countCellsHandler( maxChi2ClusterAttachment, // const float cellDeltaTanLambdaSigma, // const float nSigmaCut); // const float - gpu::cubExclusiveScanInPlace(cellsLUTsHost, nTracklets + 1, streams[layer].get()); + gpu::cubExclusiveScanInPlace(cellsLUTsHost, nTracklets + 1, streams[layer].get(), alloc); } void computeCellsHandler( @@ -1136,6 +1155,7 @@ void countCellNeighboursHandler(CellSeed** cellsLayersDevice, const unsigned int nCells, const unsigned int nCellsNext, const int maxCellNeighbours, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads, gpu::Stream& stream) @@ -1153,8 +1173,8 @@ void countCellNeighboursHandler(CellSeed** cellsLayersDevice, layerIndex, nCells, maxCellNeighbours); - gpu::cubInclusiveScanInPlace(neighboursLUT, nCellsNext, stream.get()); - gpu::cubExclusiveScanInPlace(neighboursIndexTable, nCells + 1, stream.get()); + gpu::cubInclusiveScanInPlace(neighboursLUT, nCellsNext, stream.get(), alloc); + gpu::cubExclusiveScanInPlace(neighboursIndexTable, nCells + 1, stream.get(), alloc); } void computeCellNeighboursHandler(CellSeed** cellsLayersDevice, @@ -1219,19 +1239,18 @@ void processNeighboursHandler(const int startLayer, gsl::span neighboursDeviceLUTs, const TrackingFrameInfo** foundTrackingFrameInfo, bounded_vector& seedsHost, - o2::its::ExternalAllocator* allocator, const float bz, const float maxChi2ClusterAttachment, const float maxChi2NDF, const o2::base::Propagator* propagator, const o2::base::PropagatorF::MatCorrType matCorrType, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads) { - auto allocInt = gpu::TypedAllocator(allocator); - auto allocCellSeed = gpu::TypedAllocator(allocator); - thrust::device_vector> foundSeedsTable(nCells[startLayer] + 1, 0, allocInt); // Shortcut: device_vector skips central memory management, we are relying on the contingency. - // TODO: fix this. + auto allocInt = gpu::TypedAllocator(alloc); + auto allocCellSeed = gpu::TypedAllocator(alloc); + thrust::device_vector> foundSeedsTable(nCells[startLayer] + 1, 0, allocInt); gpu::processNeighboursKernel<<>>( startLayer, @@ -1251,7 +1270,7 @@ void processNeighboursHandler(const int startLayer, maxChi2ClusterAttachment, propagator, matCorrType); - gpu::cubExclusiveScanInPlace(foundSeedsTable, nCells[startLayer] + 1); + gpu::cubExclusiveScanInPlace(foundSeedsTable, nCells[startLayer] + 1, gpu::Stream::DefaultStream, alloc); thrust::device_vector> updatedCellId(foundSeedsTable.back(), 0, allocInt); thrust::device_vector> updatedCellSeed(foundSeedsTable.back(), allocCellSeed); @@ -1306,7 +1325,7 @@ void processNeighboursHandler(const int startLayer, maxChi2ClusterAttachment, propagator, matCorrType); - gpu::cubExclusiveScanInPlace(foundSeedsTable, foundSeedsTable.size()); + gpu::cubExclusiveScanInPlace(foundSeedsTable, foundSeedsTable.size(), gpu::Stream::DefaultStream, alloc); auto foundSeeds{foundSeedsTable.back()}; updatedCellId.resize(foundSeeds); @@ -1402,6 +1421,7 @@ template void countTrackletsInROFsHandler<7>(const IndexTableUtils* utils, bounded_vector& resolutions, std::vector& radii, bounded_vector& mulScatAng, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads, gpu::Streams& streams); @@ -1435,6 +1455,7 @@ template void computeTrackletsInROFsHandler<7>(const IndexTableUtils* utils, bounded_vector& resolutions, std::vector& radii, bounded_vector& mulScatAng, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads, gpu::Streams& streams); @@ -1449,12 +1470,12 @@ template void processNeighboursHandler<7>(const int startLayer, gsl::span neighboursDeviceLUTs, const TrackingFrameInfo** foundTrackingFrameInfo, bounded_vector& seedsHost, - o2::its::ExternalAllocator*, const float bz, const float maxChi2ClusterAttachment, const float maxChi2NDF, const o2::base::Propagator* propagator, const o2::base::PropagatorF::MatCorrType matCorrType, + o2::its::ExternalAllocator* alloc, const int nBlocks, const int nThreads); } // namespace o2::its From 7b7d8ff2291cb61976d5af9721057e8a53bcaf21 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 7 Aug 2025 08:06:04 +0200 Subject: [PATCH 215/315] ITS: GPU: simplify stream synchronization Signed-off-by: Felix Schlepper --- .../tracking/GPU/cuda/TrackerTraitsGPU.cxx | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx index e7135e55a16c8..bef271a1b0129 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackerTraitsGPU.cxx @@ -126,18 +126,10 @@ void TrackerTraitsGPU::computeLayerCells(const int iteration) mTimeFrameGPU->createCellsLUTDevice(); auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); - std::vector isTrackletStreamSynched(this->mTrkParams[iteration].TrackletsPerRoad()); - auto syncOnce = [&](const int iLayer) { - if (!isTrackletStreamSynched[iLayer]) { - mTimeFrameGPU->syncStream(iLayer); - isTrackletStreamSynched[iLayer] = true; - } - }; - + mTimeFrameGPU->syncStream(0); for (int iLayer = 0; iLayer < this->mTrkParams[iteration].CellsPerRoad(); ++iLayer) { - // need to ensure that trackleting on layers iLayer and iLayer + 1 are done (only once) - syncOnce(iLayer); - syncOnce(iLayer + 1); + mTimeFrameGPU->syncStream(iLayer + 1); + // if there are no tracklets skip entirely const int currentLayerTrackletsNum{static_cast(mTimeFrameGPU->getNTracklets()[iLayer])}; if (!currentLayerTrackletsNum || !mTimeFrameGPU->getNTracklets()[iLayer + 1]) { @@ -191,18 +183,10 @@ void TrackerTraitsGPU::findCellsNeighbours(const int iteration) mTimeFrameGPU->createNeighboursIndexTablesDevice(); const auto& conf = o2::its::ITSGpuTrackingParamConfig::Instance(); - std::vector isCellStreamSynched(this->mTrkParams[iteration].TrackletsPerRoad() - 1); - auto syncOnce = [&](const int iLayer) { - if (!isCellStreamSynched[iLayer]) { - mTimeFrameGPU->syncStream(iLayer); - isCellStreamSynched[iLayer] = true; - } - }; - + mTimeFrameGPU->syncStream(0); for (int iLayer{0}; iLayer < this->mTrkParams[iteration].CellsPerRoad() - 1; ++iLayer) { // ensure that celling is done for iLayer and iLayer+1 is done - syncOnce(iLayer); - syncOnce(iLayer + 1); + mTimeFrameGPU->syncStream(iLayer + 1); const int currentLayerCellsNum{static_cast(mTimeFrameGPU->getNCells()[iLayer])}; const int nextLayerCellsNum{static_cast(mTimeFrameGPU->getNCells()[iLayer + 1])}; From 80c4d143ee8d8a54aa0fdb8761a38a77814f3159 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Fri, 8 Aug 2025 12:55:50 +0200 Subject: [PATCH 216/315] ITS: GPU: resolve added TODOs Signed-off-by: Felix Schlepper --- .../ITS/tracking/GPU/ITStrackingGPU/Utils.h | 6 +- .../ITS/tracking/GPU/cuda/TrackingKernels.cu | 119 ++++++++++++------ 2 files changed, 84 insertions(+), 41 deletions(-) diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h index 9d25bd22484fe..cd860c47ebd9c 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h +++ b/Detectors/ITSMFT/ITS/tracking/GPU/ITStrackingGPU/Utils.h @@ -95,13 +95,11 @@ class Stream #if defined(__HIPCC__) using Handle = hipStream_t; static constexpr Handle DefaultStream = 0; - // static constexpr unsigned int DefaultFlag = hipStreamNonBlocking; TODO replace once ready - static constexpr unsigned int DefaultFlag = 0; + static constexpr unsigned int DefaultFlag = hipStreamNonBlocking; #elif defined(__CUDACC__) using Handle = cudaStream_t; static constexpr Handle DefaultStream = 0; - // static constexpr unsigned int DefaultFlag = cudaStreamNonBlocking; TODO replace once ready - static constexpr unsigned int DefaultFlag = 0; + static constexpr unsigned int DefaultFlag = cudaStreamNonBlocking; #else using Handle = void*; static constexpr Handle DefaultStream = nullptr; diff --git a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu index b8eeae12691a3..401d98ad63560 100644 --- a/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu +++ b/Detectors/ITSMFT/ITS/tracking/GPU/cuda/TrackingKernels.cu @@ -145,9 +145,7 @@ GPUd() bool fitTrack(TrackITSExt& track, if (matCorrType == o2::base::PropagatorF::MatCorrType::USEMatCorrNONE) { const float xx0 = (iLayer > 2) ? 1.e-2f : 5.e-3f; // Rough layer thickness - constexpr float radiationLength = 9.36f; // Radiation length of Si [cm] - constexpr float density = 2.33f; // Density of Si [g/cm^3] - if (!track.correctForMaterial(xx0, xx0 * radiationLength * density, true)) { + if (!track.correctForMaterial(xx0, xx0 * constants::Radl * constants::Rho, true)) { return false; } } @@ -728,13 +726,13 @@ GPUg() void processNeighboursKernel(const int layer, if (!seed.o2::track::TrackParCov::update(trHit.positionTrackingFrame, trHit.covarianceTrackingFrame)) { continue; } - seed.getClusters()[layer - 1] = neighbourCell.getFirstClusterIndex(); - seed.setLevel(neighbourCell.getLevel()); - seed.setFirstTrackletIndex(neighbourCell.getFirstTrackletIndex()); - seed.setSecondTrackletIndex(neighbourCell.getSecondTrackletIndex()); if constexpr (dryRun) { foundSeedsTable[iCurrentCell]++; } else { + seed.getClusters()[layer - 1] = neighbourCell.getFirstClusterIndex(); + seed.setLevel(neighbourCell.getLevel()); + seed.setFirstTrackletIndex(neighbourCell.getFirstTrackletIndex()); + seed.setSecondTrackletIndex(neighbourCell.getSecondTrackletIndex()); updatedCellsIds[foundSeedsTable[iCurrentCell] + foundSeeds] = neighbourCellId; updatedCellSeeds[foundSeedsTable[iCurrentCell] + foundSeeds] = seed; } @@ -870,25 +868,35 @@ GPUg() void printCellSeeds(CellSeed* seed, int nCells, const unsigned int tId = } } -template -GPUhi() void cubExclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stream = nullptr, ExternalAllocator* alloc = nullptr) +GPUhi() void allocateMemory(void** p, size_t bytes, cudaStream_t stream = nullptr, ExternalAllocator* alloc = nullptr) { - void* d_temp_storage = nullptr; - size_t temp_storage_bytes = 0; - GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); if (alloc) { - d_temp_storage = alloc->allocate(temp_storage_bytes); + *p = alloc->allocate(bytes); } else { - GPUChkErrS(cudaMallocAsync(&d_temp_storage, temp_storage_bytes, stream)); + GPUChkErrS(cudaMallocAsync(p, bytes, stream)); } - GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); +} + +GPUhi() void deallocateMemory(void* p, size_t bytes, cudaStream_t stream = nullptr, ExternalAllocator* alloc = nullptr) +{ if (alloc) { - alloc->deallocate(reinterpret_cast(d_temp_storage), temp_storage_bytes); + alloc->deallocate(reinterpret_cast(p), bytes); } else { - GPUChkErrS(cudaFreeAsync(d_temp_storage, stream)); + GPUChkErrS(cudaFreeAsync(p, stream)); } } +template +GPUhi() void cubExclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stream = nullptr, ExternalAllocator* alloc = nullptr) +{ + void* d_temp_storage = nullptr; + size_t temp_storage_bytes = 0; + GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); + allocateMemory(&d_temp_storage, temp_storage_bytes, stream, alloc); + GPUChkErrS(cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); + deallocateMemory(d_temp_storage, temp_storage_bytes, stream, alloc); +} + template GPUhi() void cubExclusiveScanInPlace(Vector& in_out, int num_items, cudaStream_t stream = nullptr, ExternalAllocator* alloc = nullptr) { @@ -901,21 +909,13 @@ GPUhi() void cubInclusiveScanInPlace(T* in_out, int num_items, cudaStream_t stre void* d_temp_storage = nullptr; size_t temp_storage_bytes = 0; GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); - if (alloc) { - d_temp_storage = alloc->allocate(temp_storage_bytes); - } else { - GPUChkErrS(cudaMallocAsync(&d_temp_storage, temp_storage_bytes, stream)); - } + allocateMemory(&d_temp_storage, temp_storage_bytes, stream, alloc); GPUChkErrS(cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, in_out, in_out, num_items, stream)); - if (alloc) { - alloc->deallocate(reinterpret_cast(d_temp_storage), temp_storage_bytes); - } else { - GPUChkErrS(cudaFreeAsync(d_temp_storage, stream)); - } + deallocateMemory(d_temp_storage, temp_storage_bytes, stream, alloc); } template -GPUhi() void cubInclusiveScanInPlace(Vector& in_out, int num_items, cudaStream_t stream = nullptr, ExternalAllocator* alloc = nullptr) +GPUhi() void cubInclusiveScanInPlace(Vector& in_out, int num_items, cudaStream_t stream = nullptr, o2::its::ExternalAllocator* alloc = nullptr) { cubInclusiveScanInPlace(thrust::raw_pointer_cast(in_out.data()), num_items, stream, alloc); } @@ -1048,13 +1048,30 @@ void computeTrackletsInROFsHandler(const IndexTableUtils* utils, resolutions[iLayer], radii[iLayer + 1] - radii[iLayer], mulScatAng[iLayer]); - /// Internal thrust allocation serialize this part to a degree - /// TODO switch to cub equivelent and do all work on one stream - thrust::device_ptr tracklets_ptr(spanTracklets[iLayer]); - auto nosync_policy = THRUST_NAMESPACE::par_nosync.on(streams[iLayer].get()); - thrust::sort(nosync_policy, tracklets_ptr, tracklets_ptr + nTracklets[iLayer], gpu::sort_tracklets()); - auto unique_end = thrust::unique(nosync_policy, tracklets_ptr, tracklets_ptr + nTracklets[iLayer], gpu::equal_tracklets()); - nTracklets[iLayer] = unique_end - tracklets_ptr; + if (nTracklets[iLayer]) { + Tracklet *tracklets_in = spanTracklets[iLayer], *tracklets_out{nullptr}; + size_t n = nTracklets[iLayer]; + size_t sort_temp_bytes = 0; + GPUChkErrS(cub::DeviceMergeSort::SortKeys(nullptr, sort_temp_bytes, tracklets_in, n, gpu::sort_tracklets{}, streams[iLayer].get())); + void* sort_temp_storage = nullptr; + gpu::allocateMemory(&sort_temp_storage, sort_temp_bytes, streams[iLayer].get(), alloc); + GPUChkErrS(cub::DeviceMergeSort::SortKeys(sort_temp_storage, sort_temp_bytes, tracklets_in, n, gpu::sort_tracklets{}, streams[iLayer].get())); + gpu::allocateMemory(reinterpret_cast(&tracklets_out), n * sizeof(Tracklet), streams[iLayer].get(), alloc); + size_t unique_temp_bytes = 0; + int* num_selected = nullptr; + gpu::allocateMemory(reinterpret_cast(&num_selected), sizeof(int), streams[iLayer].get(), alloc); + GPUChkErrS(cub::DeviceSelect::Unique(nullptr, unique_temp_bytes, tracklets_in, tracklets_out, num_selected, n, streams[iLayer].get())); + void* unique_temp_storage = nullptr; + gpu::allocateMemory(&unique_temp_storage, unique_temp_bytes, streams[iLayer].get(), alloc); + GPUChkErrS(cub::DeviceSelect::Unique(unique_temp_storage, unique_temp_bytes, tracklets_in, tracklets_out, num_selected, n, streams[iLayer].get())); + GPUChkErrS(cudaMemcpyAsync(tracklets_in, tracklets_out, n * sizeof(Tracklet), cudaMemcpyDeviceToDevice, streams[iLayer].get())); + GPUChkErrS(cudaMemcpyAsync(&nTracklets[iLayer], num_selected, sizeof(int), cudaMemcpyDeviceToHost, streams[iLayer].get())); + streams[iLayer].sync(); + gpu::deallocateMemory(tracklets_out, n * sizeof(Tracklet), streams[iLayer].get(), alloc); + gpu::deallocateMemory(sort_temp_storage, sort_temp_bytes, streams[iLayer].get(), alloc); + gpu::deallocateMemory(unique_temp_storage, unique_temp_bytes, streams[iLayer].get(), alloc); + gpu::deallocateMemory(num_selected, sizeof(int), streams[iLayer].get(), alloc); + } if (iLayer > 0) { GPUChkErrS(cudaMemsetAsync(trackletsLUTsHost[iLayer], 0, nClusters[iLayer] * sizeof(int), streams[iLayer].get())); gpu::compileTrackletsLookupTableKernel<<>>( @@ -1215,8 +1232,35 @@ int filterCellNeighboursHandler(gpuPair* cellNeighbourPairs, gpu::Stream& stream, o2::its::ExternalAllocator* allocator) { - /// Internal thrust allocation serialize this part to a degree - /// TODO switch to cub equivelent and do all work on one stream +#ifndef __HIPCC__ + int* d_num_selected = nullptr; + gpu::allocateMemory(reinterpret_cast(&d_num_selected), sizeof(int), stream.get(), allocator); + size_t select_bytes = 0; + GPUChkErrS(cub::DeviceSelect::If(nullptr, select_bytes, cellNeighbourPairs, static_cast*>(nullptr), d_num_selected, nNeigh, gpu::is_valid_pair(), stream.get())); + void* select_temp = nullptr; + gpu::allocateMemory(&select_temp, select_bytes, stream.get(), allocator); + gpuPair* d_temp_valid = nullptr; + gpu::allocateMemory(reinterpret_cast(&d_temp_valid), nNeigh * sizeof(gpuPair), stream.get(), allocator); + GPUChkErrS(cub::DeviceSelect::If(select_temp, select_bytes, cellNeighbourPairs, d_temp_valid, d_num_selected, nNeigh, gpu::is_valid_pair(), stream.get())); + int newSize = 0; + GPUChkErrS(cudaMemcpyAsync(&newSize, d_num_selected, sizeof(int), cudaMemcpyDeviceToHost, stream.get())); + stream.sync(); // needed to get newSize + size_t sort_bytes = 0; + GPUChkErrS(cub::DeviceMergeSort::SortPairs(nullptr, sort_bytes, d_temp_valid, d_temp_valid, newSize, gpu::sort_by_second(), stream.get())); + void* sort_temp = nullptr; + gpu::allocateMemory(&sort_temp, sort_bytes, stream.get(), allocator); + GPUChkErrS(cub::DeviceMergeSort::SortPairs(sort_temp, sort_bytes, d_temp_valid, d_temp_valid, newSize, gpu::sort_by_second(), stream.get())); + size_t transform_bytes = 0; + GPUChkErrS(cub::DeviceTransform::Transform(nullptr, transform_bytes, d_temp_valid, cellNeighbours, newSize, gpu::pair_to_first(), stream.get())); + void* transform_temp = nullptr; + gpu::allocateMemory(&transform_temp, transform_bytes, stream.get(), allocator); + GPUChkErrS(cub::DeviceTransform::Transform(transform_temp, transform_bytes, d_temp_valid, cellNeighbours, newSize, gpu::pair_to_first(), stream.get())); + gpu::deallocateMemory(transform_temp, transform_bytes, stream.get(), allocator); + gpu::deallocateMemory(d_temp_valid, newSize * sizeof(gpuPair), stream.get(), allocator); + gpu::deallocateMemory(sort_temp, sort_bytes, stream.get(), allocator); + gpu::deallocateMemory(d_num_selected, sizeof(int), stream.get(), allocator); + gpu::deallocateMemory(select_temp, select_bytes, stream.get(), allocator); +#else // FIXME using thrust here since hipcub does not yet have DeviceTransform auto nosync_policy = THRUST_NAMESPACE::par_nosync.on(stream.get()); thrust::device_ptr> neighVectorPairs(cellNeighbourPairs); thrust::device_ptr validNeighs(cellNeighbours); @@ -1224,6 +1268,7 @@ int filterCellNeighboursHandler(gpuPair* cellNeighbourPairs, size_t newSize = updatedEnd - neighVectorPairs; thrust::stable_sort(nosync_policy, neighVectorPairs, neighVectorPairs + newSize, gpu::sort_by_second()); thrust::transform(nosync_policy, neighVectorPairs, neighVectorPairs + newSize, validNeighs, gpu::pair_to_first()); +#endif return newSize; } From a4e3e1587993a315555227587d21a4b979d77177 Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 10 Aug 2025 22:08:23 +0200 Subject: [PATCH 217/315] Fix TimingInfo.timeslice vs DPH.startTime mismatch --- Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx index f4cd64377034e..2b8090af42648 100644 --- a/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx +++ b/Detectors/Raw/TFReaderDD/src/TFReaderSpec.cxx @@ -87,7 +87,8 @@ class TFReaderSpec : public o2f::Task std::map>> mRunTimeRanges; o2::utils::IRFrameSelector mIRFrameSelector; // optional IR frames selector int mConvRunTimeRangesToOrbits = -1; // not defined yet - int mTFCounter = 0; + int mSentTFCounter = 0; + int mAccTFCounter = 0; int mTFBuilderCounter = 0; int mNWaits = 0; int mTFLength = 32; @@ -159,15 +160,15 @@ void TFReaderSpec::run(o2f::ProcessingContext& ctx) } if (hd->splitPayloadIndex == 0) { // check the 1st one only auto& entry = this->mSeenOutputMap[{hd->dataDescription.str, hd->dataOrigin.str}]; - if (entry.count != this->mTFCounter) { + if (entry.count != this->mSentTFCounter) { if (verbose && hdPrev) { // report previous partition size LOGP(info, "Block:{} {}/{} with size {}", nblocks, hdPrev->dataOrigin.as(), hdPrev->dataDescription.as(), dsize); } dsizeTot += dsize; dsize = 0; - entry.count = this->mTFCounter; // acknowledge identifier seen in the data + entry.count = this->mSentTFCounter; // acknowledge identifier seen in the data LOG(debug) << "Found a part " << ip << " of " << np << " | " << hd->dataOrigin.as() << "/" << hd->dataDescription.as() - << "/" << hd->subSpecification << " part " << hd->splitPayloadIndex << " of " << hd->splitPayloadParts << " for TF " << this->mTFCounter; + << "/" << hd->subSpecification << " part " << hd->splitPayloadIndex << " of " << hd->splitPayloadParts << " for TF " << this->mSentTFCounter; nblocks++; } } @@ -219,11 +220,11 @@ void TFReaderSpec::run(o2f::ProcessingContext& ctx) const auto* hd0 = o2h::get(dataptr); const auto* dph = o2h::get(dataptr); for (auto& out : this->mSeenOutputMap) { - if (out.second.count == this->mTFCounter) { // was seen in the data + if (out.second.count == this->mSentTFCounter) { // was seen in the data continue; } LOG(debug) << "Adding dummy output for " << out.first.dataOrigin.as() << "/" << out.first.dataDescription.as() - << "/" << out.second.defSubSpec << " for TF " << this->mTFCounter; + << "/" << out.second.defSubSpec << " for TF " << this->mSentTFCounter; o2h::DataHeader outHeader(out.first.dataDescription, out.first.dataOrigin, out.second.defSubSpec, 0); outHeader.payloadSerializationMethod = o2h::gSerializationMethodNone; outHeader.firstTForbit = hd0->firstTForbit; @@ -270,7 +271,7 @@ void TFReaderSpec::run(o2f::ProcessingContext& ctx) auto tNow = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); auto tDiff = tNow - tLastTF; - if (mTFCounter && tDiff < mInput.delay_us) { + if (mSentTFCounter && tDiff < mInput.delay_us) { std::this_thread::sleep_for(std::chrono::microseconds((size_t)(mInput.delay_us - tDiff))); // respect requested delay before sending } for (auto& msgIt : *tfPtr.get()) { @@ -285,9 +286,9 @@ void TFReaderSpec::run(o2f::ProcessingContext& ctx) // however this is a small enough hack for now. ctx.services().get().fakeDispatch(); tNow = std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count(); - LOGP(info, "Sent TF {} of size {} with {} parts, {:.4f} s elapsed from previous TF., WaitSending={}", mTFCounter, dataSize, nparts, mTFCounter ? double(tNow - tLastTF) * 1e-6 : 0., mWaitSendingLast); + LOGP(info, "Sent TF {} of size {} with {} parts, {:.4f} s elapsed from previous TF., WaitSending={}", mSentTFCounter, dataSize, nparts, mSentTFCounter ? double(tNow - tLastTF) * 1e-6 : 0., mWaitSendingLast); tLastTF = tNow; - ++mTFCounter; + ++mSentTFCounter; while (mTFQueue.size() == 0 && mWaitSendingLast) { usleep(10000); @@ -300,7 +301,7 @@ void TFReaderSpec::run(o2f::ProcessingContext& ctx) } // usleep(5000); // wait 5ms for new TF to be built } - if (mTFCounter >= mInput.maxTFs || (!mTFQueue.size() && !mRunning)) { // done + if (mSentTFCounter >= mInput.maxTFs || (!mTFQueue.size() && !mRunning)) { // done stopProcessing(ctx); } } @@ -325,7 +326,7 @@ void TFReaderSpec::stopProcessing(o2f::ProcessingContext& ctx) return; } stopDone = true; - LOGP(info, "{} TFs in {} loops were sent, spent {:.2} s in {} data waiting states", mTFCounter, mFileFetcher->getNLoops(), 1e-6 * mTotalWaitTime, mNWaits); + LOGP(info, "{} TFs in {} loops were sent, spent {:.2} s in {} data waiting states", mSentTFCounter, mFileFetcher->getNLoops(), 1e-6 * mTotalWaitTime, mNWaits); mRunning = false; if (mFileFetcher) { mFileFetcher->stop(); @@ -420,7 +421,7 @@ void TFReaderSpec::TFBuilder() std::this_thread::sleep_for(sleepTime); continue; } - auto tf = reader.read(mDevice, mOutputRoutes, mInput.rawChannelConfig, mSelIDEntry, mInput.sup0xccdb, mInput.verbosity); + auto tf = reader.read(mDevice, mOutputRoutes, mInput.rawChannelConfig, mAccTFCounter, mInput.sup0xccdb, mInput.verbosity); bool acceptTF = true; if (tf) { if (mRunTimeRanges.size()) { @@ -443,21 +444,23 @@ void TFReaderSpec::TFBuilder() locID++; if (!mInput.tfIDs.empty() && acceptTF) { acceptTF = false; + while ((mInput.tfIDs[mSelIDEntry] < mTFBuilderCounter) && (mSelIDEntry + 1) < mInput.tfIDs.size()) { + mSelIDEntry++; + } + LOGP(info, "chec if mInput.tfIDs[{}]({}) == {}", mSelIDEntry, mInput.tfIDs[mSelIDEntry], mTFBuilderCounter); if (mInput.tfIDs[mSelIDEntry] == mTFBuilderCounter) { mWaitSendingLast = false; acceptTF = true; LOGP(info, "Retrieved TF#{} will be pushed as slice {} following user request", mTFBuilderCounter, mSelIDEntry); - mSelIDEntry++; } else { LOGP(info, "Retrieved TF#{} will be discared following user request", mTFBuilderCounter); } - } else { - mSelIDEntry++; } mTFBuilderCounter++; } if (mRunning && tf) { if (acceptTF) { + mAccTFCounter++; mWaitSendingLast = true; mTFQueue.push(std::move(tf)); } From 24f1796bc7d175e523c048a0c1b26b045ec48fae Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 10 Aug 2025 15:38:21 +0200 Subject: [PATCH 218/315] DPL: improve error message --- Framework/Core/src/WorkflowHelpers.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Framework/Core/src/WorkflowHelpers.cxx b/Framework/Core/src/WorkflowHelpers.cxx index 652e863f98394..b86a4f15e7306 100644 --- a/Framework/Core/src/WorkflowHelpers.cxx +++ b/Framework/Core/src/WorkflowHelpers.cxx @@ -974,7 +974,8 @@ WorkflowParsingState WorkflowHelpers::verifyWorkflow(const o2::framework::Workfl if (DataSpecUtils::validate(input) == false) { ss << "In spec " << spec.name << " input specification " << ii << " requires binding, description and origin" - " to be fully specified"; + " to be fully specified (found " + << input.binding << ":" << DataSpecUtils::describe(input) << ")"; throw std::runtime_error(ss.str()); } } From 919285695e84e3b247087b9f45c0a7da1080527c Mon Sep 17 00:00:00 2001 From: mytkom Date: Sun, 8 Sep 2024 19:30:51 +0000 Subject: [PATCH 219/315] use generic get() in row_helpers --- Framework/Core/include/Framework/ASoA.h | 2 +- .../Core/include/Framework/ASoAHelpers.h | 66 ++----------------- .../Core/include/Framework/BinningPolicy.h | 28 ++++---- 3 files changed, 19 insertions(+), 77 deletions(-) diff --git a/Framework/Core/include/Framework/ASoA.h b/Framework/Core/include/Framework/ASoA.h index 8af9878703d18..11485403e967b 100644 --- a/Framework/Core/include/Framework/ASoA.h +++ b/Framework/Core/include/Framework/ASoA.h @@ -2194,7 +2194,7 @@ typename C::type getSingleRowData(arrow::Table*, T& rowIterator, uint64_t ci = s if (globalIndex != std::numeric_limits::max() && globalIndex != *std::get<0>(rowIterator.getIndices())) { rowIterator.setCursor(globalIndex); } - return rowIterator.template getDynamicColumn(); + return static_cast(rowIterator).get(); } template diff --git a/Framework/Core/include/Framework/ASoAHelpers.h b/Framework/Core/include/Framework/ASoAHelpers.h index 5bf474e61f935..2f2d1f06fce1a 100644 --- a/Framework/Core/include/Framework/ASoAHelpers.h +++ b/Framework/Core/include/Framework/ASoAHelpers.h @@ -76,77 +76,19 @@ void dataSizeVariesBetweenColumns(); template