From dbe46033d6c0831d042b0f30d9ac1810eb0bf355 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Tue, 9 Jun 2026 21:09:34 +0200 Subject: [PATCH] GPU: Add cluster dump to CSV option in runCompressionStatistics --- .../GPUTPCClusterStatistics.cxx | 46 ++++++++++++++++++- .../DataCompression/GPUTPCClusterStatistics.h | 2 +- GPU/GPUTracking/Definitions/GPUSettingsList.h | 2 +- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx b/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx index 918b2d459a2d6..3191067570b66 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx +++ b/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.cxx @@ -19,6 +19,7 @@ #include #include #include +#include using namespace o2::gpu; @@ -106,7 +107,7 @@ void GenerateCodes(const INode* node, const HuffCode& prefix, HuffCodeMap& outCo } // anonymous namespace } // namespace o2::gpu -void GPUTPCClusterStatistics::RunStatistics(const o2::tpc::ClusterNativeAccess* clustersNative, const o2::tpc::CompressedClusters* clustersCompressed, const GPUParam& param) +void GPUTPCClusterStatistics::RunStatistics(const o2::tpc::ClusterNativeAccess* clustersNative, const o2::tpc::CompressedClusters* clustersCompressed, const GPUParam& param, bool dumpCSV) { uint32_t decodingErrors = 0; o2::tpc::ClusterNativeAccess clustersNativeDecoded; @@ -185,6 +186,49 @@ void GPUTPCClusterStatistics::RunStatistics(const o2::tpc::ClusterNativeAccess* FillStatisticCombined(mPQU, clustersCompressed->qMaxU, clustersCompressed->qTotU, clustersCompressed->nUnattachedClusters, P_MAX_QMAX); FillStatisticCombined(mProwSectorA, clustersCompressed->rowDiffA, clustersCompressed->sliceLegDiffA, clustersCompressed->nAttachedClustersReduced, GPUTPCGeometry::NROWS); mNTotalClusters += clustersCompressed->nAttachedClusters + clustersCompressed->nUnattachedClusters; + + if (dumpCSV) { + std::ofstream csv("clusters_raw.csv"); + csv << "sector,row,time,pad,flags,qtot,qmax,sigmatime,sigmapad\n"; + for (uint32_t i = 0; i < NSECTORS; i++) { + for (uint32_t j = 0; j < GPUTPCGeometry::NROWS; j++) { + for (uint32_t k = 0; k < clustersNativeDecoded.nClusters[i][j]; k++) { + const auto& cl = clustersNativeDecoded.clusters[i][j][k]; + csv << i << ',' << j << ',' << cl.getTimePacked() << ',' << cl.padPacked << ',' << (uint32_t)cl.getFlags() << ',' << cl.qTot << ',' << cl.qMax << ',' << (uint32_t)cl.sigmaTimePacked << ',' << (uint32_t)cl.sigmaPadPacked << '\n'; + } + } + } + + csv = std::ofstream("attachedCl.csv"); + csv << "qTotA,qMaxA,flagsA,sigmaPadA,sigmaTimeA\n"; + for (uint32_t i = 0; i < clustersCompressed->nAttachedClusters; i++) { + csv << clustersCompressed->qTotA[i] << ',' << clustersCompressed->qMaxA[i] << ',' << (uint32_t)clustersCompressed->flagsA[i] << ',' << (uint32_t)clustersCompressed->sigmaPadA[i] << ',' << (uint32_t)clustersCompressed->sigmaTimeA[i] << "\n"; + } + + csv = std::ofstream("attachedClred.csv"); + csv << "rodDiffA,legDiffA,padResA,timeResA\n"; + for (uint32_t i = 0; i < clustersCompressed->nAttachedClustersReduced; i++) { + csv << (uint32_t)clustersCompressed->rowDiffA[i] << ',' << (uint32_t)clustersCompressed->sliceLegDiffA[i] << ',' << clustersCompressed->padResA[i] << ',' << clustersCompressed->timeResA[i] << "\n"; + } + + csv = std::ofstream("nClU.csv"); + csv << "sliceRowCl\n"; + for (uint32_t i = 0; i < clustersCompressed->nSliceRows; i++) { + csv << clustersCompressed->nSliceRowClusters[i] << "\n"; + } + + csv = std::ofstream("trk.csv"); + csv << "qPtA,rowA,sliceA,timeA,padA,nCl\n"; + for (uint32_t i = 0; i < clustersCompressed->nTracks; i++) { + csv << (uint32_t)clustersCompressed->qPtA[i] << ',' << (uint32_t)clustersCompressed->rowA[i] << ',' << (uint32_t)clustersCompressed->sliceA[i] << ',' << clustersCompressed->timeA[i] << ',' << clustersCompressed->padA[i] << ',' << clustersCompressed->nTrackClusters[i] << "\n"; + } + + csv = std::ofstream("unattachedCl.csv"); + csv << "qTotU,qMaxU,flagsU,padDiffU,timeDiffU,sigmaPadU,sigmaTimeU\n"; + for (uint32_t i = 0; i < clustersCompressed->nUnattachedClusters; i++) { + csv << clustersCompressed->qTotU[i] << ',' << clustersCompressed->qMaxU[i] << ',' << (uint32_t)clustersCompressed->flagsU[i] << ',' << clustersCompressed->padDiffU[i] << ',' << clustersCompressed->timeDiffU[i] << ',' << (uint32_t)clustersCompressed->sigmaPadU[i] << ',' << (uint32_t)clustersCompressed->sigmaTimeU[i] << "\n"; + } + } } void GPUTPCClusterStatistics::Finish() diff --git a/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.h b/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.h index 8450c3ee59210..bdc56451ada39 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCClusterStatistics.h @@ -30,7 +30,7 @@ class GPUTPCClusterStatistics { public: static constexpr uint32_t NSECTORS = GPUTPCGeometry::NSECTORS; - void RunStatistics(const o2::tpc::ClusterNativeAccess* clustersNative, const o2::tpc::CompressedClusters* clustersCompressed, const GPUParam& param); + void RunStatistics(const o2::tpc::ClusterNativeAccess* clustersNative, const o2::tpc::CompressedClusters* clustersCompressed, const GPUParam& param, bool dumpCSV); void Finish(); protected: diff --git a/GPU/GPUTracking/Definitions/GPUSettingsList.h b/GPU/GPUTracking/Definitions/GPUSettingsList.h index eb7d67a913ceb..445317aaf483d 100644 --- a/GPU/GPUTracking/Definitions/GPUSettingsList.h +++ b/GPU/GPUTracking/Definitions/GPUSettingsList.h @@ -342,7 +342,7 @@ AddOption(serializeGPU, int8_t, 0, "", 0, "Synchronize after each kernel call (b AddOption(recoTaskTiming, bool, 0, "", 0, "Perform summary timing after whole reconstruction tasks") AddOption(deterministicGPUReconstruction, int32_t, -1, "", 0, "Make CPU and GPU debug output comparable (sort / skip concurrent parts), -1 = automatic if debugLevel >= 6 or deterministic compile flag set", def(1)) AddOption(showOutputStat, bool, false, "", 0, "Print some track output statistics") -AddOption(runCompressionStatistics, bool, false, "compressionStat", 0, "Run statistics and verification for cluster compression") +AddOption(runCompressionStatistics, int8_t, 0, "compressionStat", 0, "Run statistics and verification for cluster compression, 2 to dump clusters and entropy-reduced clusters to CSV", def(1)) AddOption(resetTimers, int8_t, 1, "", 0, "Reset timers every event") AddOption(deviceTimers, bool, true, "", 0, "Use device timers instead of host-based time measurement") AddOption(keepAllMemory, bool, false, "", 0, "Allocate all memory on both device and host, and do not reuse") diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index dc7b23a375cd3..067c4dff92810 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -789,7 +789,7 @@ int32_t GPUChainTracking::RunChainFinalize() { if (mIOPtrs.clustersNative && (GetRecoSteps() & RecoStep::TPCCompression) && GetProcessingSettings().runCompressionStatistics) { CompressedClusters c = *mIOPtrs.tpcCompressedClusters; - mCompressionStatistics->RunStatistics(mIOPtrs.clustersNative, &c, param()); + mCompressionStatistics->RunStatistics(mIOPtrs.clustersNative, &c, param(), GetProcessingSettings().runCompressionStatistics >= 2); } if (GetProcessingSettings().outputSanityCheck) {