From 9a2427e3b242727a6e5b5c5ba95365dc4e4b8732 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 11 Oct 2026 10:41:36 +0200 Subject: [PATCH 1/3] GPU: Fix uninitialized memory --- GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx index e8c98bf4b4a45..e8f7c761c1dac 100644 --- a/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx +++ b/GPU/GPUTracking/Merger/GPUTPCGMMerger.cxx @@ -640,6 +640,7 @@ GPUd() void GPUTPCGMMerger::UnpackSectorGlobal(int32_t nBlocks, int32_t nThreads SetTrackClusterT(track, iSector, sectorTr); track.Set(this, sectorTr, alpha, iSector); track.SetGlobalSectorTrackCov(); + track.SetX2(0.f); track.SetPrevNeighbour(-1); track.SetNextNeighbour(-1); track.SetNextSegmentNeighbour(-1); From 60eccfc16a8982cf47e818070bca2496bb7ae2c1 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 11 Oct 2026 10:42:34 +0200 Subject: [PATCH 2/3] GPU TPC Clusterizer: Fix endless loop when running with 1 thread --- GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx index 06709ef2d4a7e..c0c869d0dcc9b 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCClusterFinder.cxx @@ -161,6 +161,9 @@ uint32_t GPUTPCClusterFinder::getNSteps(size_t items) const } uint32_t c = 1; const size_t scanWorkgroupSize = mRec->getGPUParameters(mRec->GetRecoStepsGPU() & gpudatatypes::RecoStep::TPCClusterFinding).par_CF_SCAN_WORKGROUP_SIZE; + if (scanWorkgroupSize <= 1) { + return 1; + } size_t capacity = scanWorkgroupSize; while (items > capacity) { capacity *= scanWorkgroupSize; From e8c3b963c312e110846c77a3c5d887ebdad47319 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sun, 11 Oct 2026 13:02:25 +0200 Subject: [PATCH 3/3] GPU TPC Clusterizer: Make CPU code compatible to processing scheme as on device --- GPU/GPUTracking/Base/GPUProcessor.h | 1 + .../TPCClusterFinder/GPUTPCCFDecodeZS.cxx | 22 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/GPU/GPUTracking/Base/GPUProcessor.h b/GPU/GPUTracking/Base/GPUProcessor.h index 337ecfc61f79d..bbc156be88e06 100644 --- a/GPU/GPUTracking/Base/GPUProcessor.h +++ b/GPU/GPUTracking/Base/GPUProcessor.h @@ -51,6 +51,7 @@ class GPUProcessor GPUd() GPUconstantref() const GPUConstantMem* GetConstantMem() const; // Body in GPUConstantMem.h to avoid circular headers GPUd() GPUconstantref() const GPUParam& Param() const; // ... GPUd() void raiseError(uint32_t code, uint32_t param1 = 0, uint32_t param2 = 0, uint32_t param3 = 0) const; + GPUd() bool IsDeviceProcessor() const { return mGPUProcessorType == PROCESSOR_TYPE_DEVICE; } const GPUReconstruction& GetRec() const { return *mRec; } #ifndef __OPENCL__ diff --git a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx index e71bfea61112c..86fe293a99bfe 100644 --- a/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx +++ b/GPU/GPUTracking/TPCClusterFinder/GPUTPCCFDecodeZS.cxx @@ -48,7 +48,8 @@ GPUdii() void GPUTPCCFDecodeZS::decode(GPUTPCClusterFinder& clusterer, GPUShared #ifdef GPUCA_GPUCODE const uint32_t endpoint = clusterer.mPzsOffsets[iBlock].endpoint; #else - const uint32_t endpoint = iBlock; + const bool deviceLayout = clusterer.IsDeviceProcessor(); // Host-compiled kernel running with threading as on a device + const uint32_t endpoint = deviceLayout ? clusterer.mPzsOffsets[iBlock].endpoint : iBlock; #endif const GPUTrackingInOutZS::GPUTrackingInOutZSSector& zs = clusterer.GetConstantMem()->ioPtrs.tpcZS->sector[sector]; if (zs.count[endpoint] == 0) { @@ -74,9 +75,11 @@ GPUdii() void GPUTPCCFDecodeZS::decode(GPUTPCClusterFinder& clusterer, GPUShared { { #else - for (uint32_t i = clusterer.mMinMaxCN[endpoint].zsPtrFirst; i < clusterer.mMinMaxCN[endpoint].zsPtrLast; i++) { - const uint32_t minJ = (i == clusterer.mMinMaxCN[endpoint].zsPtrFirst) ? clusterer.mMinMaxCN[endpoint].zsPageFirst : 0; - const uint32_t maxJ = (i + 1 == clusterer.mMinMaxCN[endpoint].zsPtrLast) ? clusterer.mMinMaxCN[endpoint].zsPageLast : zs.nZSPtr[endpoint][i]; + const uint32_t iFirst = deviceLayout ? 0 : clusterer.mMinMaxCN[endpoint].zsPtrFirst; + const uint32_t iLast = deviceLayout ? 1 : clusterer.mMinMaxCN[endpoint].zsPtrLast; + for (uint32_t i = iFirst; i < iLast; i++) { + const uint32_t minJ = deviceLayout ? clusterer.mPzsOffsets[iBlock].num : ((i == iFirst) ? clusterer.mMinMaxCN[endpoint].zsPageFirst : 0); + const uint32_t maxJ = deviceLayout ? (minJ + 1) : ((i + 1 == iLast) ? clusterer.mMinMaxCN[endpoint].zsPageLast : zs.nZSPtr[endpoint][i]); for (uint32_t j = minJ; j < maxJ; j++) { #endif const uint32_t* pageSrc = (const uint32_t*)(((const uint8_t*)zs.zsPtr[endpoint][i]) + j * TPCZSHDR::TPC_ZS_PAGE_SIZE); @@ -370,7 +373,8 @@ GPUd() void GPUTPCCFDecodeZSLinkBase::Decode(int32_t nBlocks, int32_t nThreads, #ifdef GPUCA_GPUCODE const uint32_t endpoint = clusterer.mPzsOffsets[iBlock].endpoint; #else // CPU - const uint32_t endpoint = iBlock; + const bool deviceLayout = clusterer.IsDeviceProcessor(); // Host-compiled kernel running as device kernel (CPUDevice backend): GPU work distribution, one block per page + const uint32_t endpoint = deviceLayout ? clusterer.mPzsOffsets[iBlock].endpoint : iBlock; #endif const GPUTrackingInOutZS::GPUTrackingInOutZSSector& zs = clusterer.GetConstantMem()->ioPtrs.tpcZS->sector[sector]; @@ -386,9 +390,11 @@ GPUd() void GPUTPCCFDecodeZSLinkBase::Decode(int32_t nBlocks, int32_t nThreads, { { #else // CPU - for (uint32_t i = clusterer.mMinMaxCN[endpoint].zsPtrFirst; i < clusterer.mMinMaxCN[endpoint].zsPtrLast; i++) { - const uint32_t minJ = (i == clusterer.mMinMaxCN[endpoint].zsPtrFirst) ? clusterer.mMinMaxCN[endpoint].zsPageFirst : 0; - const uint32_t maxJ = (i + 1 == clusterer.mMinMaxCN[endpoint].zsPtrLast) ? clusterer.mMinMaxCN[endpoint].zsPageLast : zs.nZSPtr[endpoint][i]; + const uint32_t iFirst = deviceLayout ? 0 : clusterer.mMinMaxCN[endpoint].zsPtrFirst; + const uint32_t iLast = deviceLayout ? 1 : clusterer.mMinMaxCN[endpoint].zsPtrLast; + for (uint32_t i = iFirst; i < iLast; i++) { + const uint32_t minJ = deviceLayout ? clusterer.mPzsOffsets[iBlock].num : ((i == iFirst) ? clusterer.mMinMaxCN[endpoint].zsPageFirst : 0); + const uint32_t maxJ = deviceLayout ? (minJ + 1) : ((i + 1 == iLast) ? clusterer.mMinMaxCN[endpoint].zsPageLast : zs.nZSPtr[endpoint][i]); for (uint32_t j = minJ; j < maxJ; j++) { #endif const uint32_t* pageSrc = (const uint32_t*)(((const uint8_t*)zs.zsPtr[endpoint][i]) + j * TPCZSHDR::TPC_ZS_PAGE_SIZE);