From 33cc986ddd826bbf5a2260962dbd591ebea18aa2 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 11 Nov 2026 06:48:43 +0100 Subject: [PATCH] GPU TPC clusterizer: wait for the gather of the previous sector before clearing the maps A lane reuses its scratch memory for its next sector. At the first fragment the charge and peak maps were cleared without waiting for the gather of the previous sector, which runs on another stream, and the maps can overlap that sector's clusterByRow: on pbpb30 the peak map of sector 3 ends at row 0 of sector 0. When the gather starts late, row 0 of the previous sector is gathered as zeros: on a 20 kHz Pb-Pb time frame on Metal, the first run in a process found 0.42 % fewer sector tracks. The existing wait on the gather sat on the clusterInRow clear, after the map clears. Move it to the first map clear at fragment 0. --- .../Global/GPUChainTrackingClusterizer.cxx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx index 1aa9690453b87..7009e9f41bf18 100644 --- a/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx +++ b/GPU/GPUTracking/Global/GPUChainTrackingClusterizer.cxx @@ -1038,7 +1038,12 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) using ChargeMapType = decltype(*clustererShadow.mPchargeMap); using PeakMapType = decltype(*clustererShadow.mPpeakMap); - runKernel({GetGridAutoStep(lane, RecoStep::TPCClusterFinding)}, clustererShadow.mPchargeMap, TPCMapMemoryLayout::items(GetProcessingSettings().overrideClusterizerFragmentLen) * sizeof(ChargeMapType)); + deviceEvent* waitEvent = nullptr; + if (frag.index == 0 && transferRunning[lane] == 1) { // The gather of the previous sector of this lane may still read the scratch memory the maps are cleared in + waitEvent = &mEvents->stream[lane]; + transferRunning[lane] = 2; + } + runKernel({GetGridAutoStep(lane, RecoStep::TPCClusterFinding), krnlRunRangeNone, {nullptr, waitEvent}}, clustererShadow.mPchargeMap, TPCMapMemoryLayout::items(GetProcessingSettings().overrideClusterizerFragmentLen) * sizeof(ChargeMapType)); runKernel({GetGridAutoStep(lane, RecoStep::TPCClusterFinding)}, clustererShadow.mPpeakMap, TPCMapMemoryLayout::items(GetProcessingSettings().overrideClusterizerFragmentLen) * sizeof(PeakMapType)); if (frag.index == 0) { runKernel({GetGridAutoStep(lane, RecoStep::TPCClusterFinding)}, clustererShadow.mPpadIsNoisy, TPC_CLUSTERER_STRIDED_PAD_COUNT * sizeof(*clustererShadow.mPpadIsNoisy)); @@ -1211,12 +1216,7 @@ int32_t GPUChainTracking::RunTPCClusterizer(bool synchronizeOutput) } if (resetClusterCounters) { - deviceEvent* waitEvent = nullptr; - if (transferRunning[lane] == 1) { - waitEvent = &mEvents->stream[lane]; - transferRunning[lane] = 2; - } - runKernel({GetGridAutoStep(lane, RecoStep::TPCClusterFinding), krnlRunRangeNone, {nullptr, waitEvent}}, clustererShadow.mPclusterInRow, GPUTPCGeometry::NROWS * sizeof(*clustererShadow.mPclusterInRow)); + runKernel({GetGridAutoStep(lane, RecoStep::TPCClusterFinding)}, clustererShadow.mPclusterInRow, GPUTPCGeometry::NROWS * sizeof(*clustererShadow.mPclusterInRow)); } if (clusterer.mPmemory->counters.nPositions == 0) {