Project
Loading...
Searching...
No Matches
TrackerTraitsGPU.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
12
13#include <unistd.h>
14
15#include <algorithm>
16#include <array>
17#include <cmath>
18#include <cstdlib>
19#include <numeric>
20#include <vector>
21
28
29namespace o2::its
30{
33
34template <int NLayers>
36{
37 this->mTaskArena->execute([&] {
38 mTimeFrameGPU->initialise(this->mTrkParams[iteration], this->mTrkParams[iteration].NLayers, iteration);
39 });
40 // load iteration parameters
41 mTimeFrameGPU->loadIterationParameters(this->mTrkParams[iteration]);
42
43 if (this->mTrkParams[iteration].PassFlags[IterationStep::FirstPass]) {
44 // on default stream
45 mTimeFrameGPU->loadVertices();
46 if (this->mTrkParams[iteration].PassFlags[IterationStep::LoadPersistentTables]) {
47 mTimeFrameGPU->loadROFOverlapTable(); // this can be put in constant memory actually
48 mTimeFrameGPU->loadTrackingTopologies();
49 }
50 mTimeFrameGPU->loadROFVertexLookupTable();
51 // once the tables are in persistent memory just re-upload the vertex one
52 // mTimeFrameGPU->uploadROFVertexLookupTable();
53 mTimeFrameGPU->loadIndexTableUtils();
54 // pinned on host
55 mTimeFrameGPU->createUsedClustersDeviceArray();
56 mTimeFrameGPU->createClustersDeviceArray();
57 mTimeFrameGPU->createUnsortedClustersDeviceArray();
58 mTimeFrameGPU->createClustersIndexTablesArray();
59 mTimeFrameGPU->createTrackingFrameInfoDeviceArray();
60 mTimeFrameGPU->createROFrameClustersDeviceArray();
61 // device array
62 mTimeFrameGPU->createClusterRadiiDevice();
63 mTimeFrameGPU->uploadClusterRadii();
64 mTimeFrameGPU->createTrackletsLUTDeviceArray();
65 mTimeFrameGPU->createTrackletsBuffersArray();
66 mTimeFrameGPU->createCellsBuffersArray();
67 mTimeFrameGPU->createCellsLUTDeviceArray();
68 mTimeFrameGPU->createClusterOwnersDeviceArray();
69 }
70 if (this->mTrkParams[iteration].PassFlags[IterationStep::FirstPass] || this->mTrkParams[iteration].PassFlags[IterationStep::UseUPCMask]) {
71 mTimeFrameGPU->loadROFCutMask(iteration);
72 }
73}
74
75template <int NLayers>
77{
78 mTimeFrameGPU = static_cast<gpu::TimeFrameGPU<NLayers>*>(tf);
79 this->mTimeFrame = static_cast<TimeFrame<NLayers>*>(tf);
80}
81
82template <int NLayers>
83void TrackerTraitsGPU<NLayers>::computeLayerTracklets(const int iteration, int iVertex)
84{
85 const auto topology = mTimeFrameGPU->getDeviceTrackingTopologyView();
86 const auto hostTopology = mTimeFrameGPU->getTrackingTopologyView();
87 const bool loadFirstPassData = this->mTrkParams[iteration].PassFlags[IterationStep::FirstPass] && iVertex <= 0; // load data only on first pass and first vertex
88 for (int iLayer{0}; iLayer < this->mTrkParams[iteration].NLayers; ++iLayer) {
89 if (loadFirstPassData) {
90 mTimeFrameGPU->createUsedClustersDevice(iLayer);
91 mTimeFrameGPU->loadUnsortedClustersDevice(iLayer);
92 mTimeFrameGPU->loadROFrameClustersDevice(iLayer);
93 mTimeFrameGPU->sortClustersDevice(iLayer, this->mTrkParams[iteration]);
94 }
95 mTimeFrameGPU->recordEvent(iLayer);
96 }
97
98 for (int linkId{0}; linkId < hostTopology.nLinks; ++linkId) {
99 mTimeFrameGPU->createTrackletsLUTDevice(loadFirstPassData, linkId); // on first pass allocates, then only clears memory
100 }
101
102 // Stack allocations created from trackleting through road finding are scoped to one tracker pass.
103 // With per-primary-vertex processing, the chain is called once per vertex while initialisation is only done once.
104 mTimeFrameGPU->pushMemoryStack(iteration);
105
106 const auto nClusters = mTimeFrameGPU->getClusterSizes();
107 const bool useDiamond = this->mTrkParams[iteration].UseDiamond;
108 if (useDiamond) {
109 const Vertex diamondVert = makeDiamondVertex(this->mTrkParams[iteration]);
110 mTimeFrameGPU->createDiamondDevice(diamondVert);
111 mTimeFrameGPU->recordEvent(0);
112 }
113 const Vertex* deviceVertices = useDiamond ? mTimeFrameGPU->getDeviceDiamond() : mTimeFrameGPU->getDeviceVertices();
114 const bool seedingPass = this->mTrkParams[iteration].PassFlags[IterationStep::SeedingVertexPass];
115 bounded_vector<float> vtxPhiCuts(seedingPass ? hostTopology.nLinks : 0,
116 this->mTrkParams[iteration].VtxPhiCut,
117 this->getMemoryPool().get());
118 auto& linkPhiCuts = seedingPass ? vtxPhiCuts : mTimeFrameGPU->getLinkPhiCuts();
119
120 for (int linkId{0}; linkId < hostTopology.nLinks; ++linkId) {
121 const auto link = hostTopology.getLink(linkId);
122 mTimeFrameGPU->waitEvent(linkId, link.fromLayer);
123 mTimeFrameGPU->waitEvent(linkId, link.toLayer);
124 if (useDiamond) {
125 mTimeFrameGPU->waitEvent(linkId, 0); // links not anchored on layer 0 must still wait for the diamond upload
126 }
127 const auto key = CapacityEstimator::makeKey(SlabSite::Tracklets, iteration, iVertex + 1, linkId);
128 const auto scale = static_cast<double>(nClusters[link.fromLayer]);
129 runOnSlab(mTimeFrameGPU->getCapacityEstimator(), key, scale, [&](const int capacity) {
130 mTimeFrameGPU->createTrackletsBuffers(linkId, capacity);
131 return TrackingKernels<NLayers>::computeTrackletsInROFsHandler(mTimeFrameGPU->getDeviceIndexTableUtils(),
132 mTimeFrameGPU->getDeviceROFMaskTableView(),
133 linkId,
134 link.fromLayer,
135 link.toLayer,
136 mTimeFrameGPU->getDeviceROFOverlapTableView(),
137 mTimeFrameGPU->getDeviceROFVertexLookupTableView(),
138 iVertex,
139 deviceVertices,
140 useDiamond,
141 mTimeFrameGPU->getDeviceArrayClusters(),
142 nClusters,
143 mTimeFrameGPU->getDeviceROFrameClusters(),
144 (const uint8_t**)mTimeFrameGPU->getDeviceArrayUsedClusters(),
145 mTimeFrameGPU->getDeviceArrayClustersIndexTables(),
146 mTimeFrameGPU->getDeviceArrayTracklets(),
147 mTimeFrameGPU->getDeviceTracklets(),
148 mTimeFrameGPU->getNTracklets(),
149 capacity,
150 mTimeFrameGPU->getDeviceTrackletsLUTs(),
151 this->mTrkParams[iteration].PassFlags[IterationStep::SelectUPCVertices],
152 this->mTrkParams[iteration].NSigmaCut,
153 topology,
154 linkPhiCuts,
155 this->mTrkParams[iteration].PVres,
156 mTimeFrameGPU->getDeviceMinRs(),
157 mTimeFrameGPU->getDeviceMaxRs(),
158 mTimeFrameGPU->getPositionResolutions(),
159 this->mTrkParams[iteration].LayerRadii,
160 mTimeFrameGPU->getLinkMSAngles(),
161 mTimeFrameGPU->getFrameworkAllocator(),
162 mTimeFrameGPU->getStreams());
163 });
164 mTimeFrameGPU->recordEvent(linkId);
165 }
166}
167
168template <int NLayers>
170{
171 const auto topology = mTimeFrameGPU->getDeviceTrackingTopologyView();
172 const auto hostTopology = mTimeFrameGPU->getTrackingTopologyView();
173 for (int iLayer{0}; iLayer < this->mTrkParams[iteration].NLayers; ++iLayer) {
174 if (this->mTrkParams[iteration].PassFlags[IterationStep::FirstPass]) {
175 mTimeFrameGPU->loadUnsortedClustersDevice(iLayer); // latched: a no-op if trackleting already did it
176 mTimeFrameGPU->loadTrackingFrameInfoDevice(iLayer);
177 }
178 mTimeFrameGPU->recordEvent(iLayer);
179 }
180
181 for (int cellTopologyId{hostTopology.nCells}; cellTopologyId--;) {
182 const auto cellTopology = hostTopology.getCell(cellTopologyId);
183 const auto first = hostTopology.getLink(cellTopology.firstLink);
184 const auto second = hostTopology.getLink(cellTopology.secondLink);
185 const float cellDeltaPhiCut = this->mTrkParams[iteration].PassFlags[IterationStep::SeedingVertexPass] ? math_utils::cellDeltaPhiBound(this->mBz, this->mTrkParams[iteration].CellDeltaPhiMinPt,
186 this->mTrkParams[iteration].LayerRadii[first.fromLayer],
187 this->mTrkParams[iteration].LayerRadii[first.toLayer],
188 this->mTrkParams[iteration].LayerRadii[second.toLayer],
189 mTimeFrameGPU->getLinkMSAngle(cellTopology.firstLink))
190 : o2::constants::math::TwoPI;
191 const float cellTanLNSigma = this->mTrkParams[iteration].CellDeltaTanLambdaNSigma > 0.f
192 ? this->mTrkParams[iteration].CellDeltaTanLambdaNSigma
193 : this->mTrkParams[iteration].NSigmaCut;
194 const int currentLayerTrackletsNum{static_cast<int>(mTimeFrameGPU->getNTracklets()[cellTopology.firstLink])};
195 if (!currentLayerTrackletsNum || !mTimeFrameGPU->getNTracklets()[cellTopology.secondLink]) {
196 mTimeFrameGPU->getNCells()[cellTopologyId] = 0;
197 continue;
198 }
199
200 mTimeFrameGPU->createCellsLUTDevice(cellTopologyId);
201 mTimeFrameGPU->waitEvent(cellTopologyId, cellTopology.firstLink);
202 mTimeFrameGPU->waitEvent(cellTopologyId, cellTopology.secondLink);
203 mTimeFrameGPU->waitEvent(cellTopologyId, first.fromLayer);
204 mTimeFrameGPU->waitEvent(cellTopologyId, first.toLayer);
205 mTimeFrameGPU->waitEvent(cellTopologyId, second.toLayer);
206 const auto key = CapacityEstimator::makeKey(SlabSite::Cells, iteration, 0, cellTopologyId);
207 const auto scale = static_cast<double>(currentLayerTrackletsNum);
208 const int emitted = runOnSlab(mTimeFrameGPU->getCapacityEstimator(), key, scale, [&](const int capacity) {
209 mTimeFrameGPU->createCellsBuffers(cellTopologyId, capacity);
210 return TrackingKernels<NLayers>::computeCellsHandler(mTimeFrameGPU->getDeviceArrayClusters(),
211 mTimeFrameGPU->getDeviceArrayUnsortedClusters(),
212 mTimeFrameGPU->getDeviceArrayTrackingFrameInfo(),
213 mTimeFrameGPU->getDeviceArrayTracklets(),
214 mTimeFrameGPU->getDeviceArrayTrackletsLUT(),
215 currentLayerTrackletsNum,
216 cellTopologyId,
217 topology,
218 mTimeFrameGPU->getDeviceCells()[cellTopologyId],
219 capacity,
220 mTimeFrameGPU->getDeviceCellLUTs()[cellTopologyId],
221 this->mBz,
222 this->mTrkParams[iteration].MaxChi2ClusterAttachment,
223 this->mTrkParams[iteration].CellDeltaTanLambdaSigma,
224 cellDeltaPhiCut,
225 cellTanLNSigma,
226 mTimeFrameGPU->getDeviceLayerxX0(),
227 mTimeFrameGPU->getCapacityEstimator(),
228 iteration,
229 !this->mTrkParams[iteration].PassFlags[IterationStep::SeedingVertexPass],
230 mTimeFrameGPU->getFrameworkAllocator(),
231 mTimeFrameGPU->getStreams());
232 });
233 mTimeFrameGPU->getNCells()[cellTopologyId] = emitted;
234 mTimeFrameGPU->recordEvent(cellTopologyId);
235 }
236 mTimeFrameGPU->syncStreams(false);
237}
238
239template <int NLayers>
241{
242 const int nCells = mTimeFrameGPU->getNCells()[0];
243 if (!nCells) {
244 mTimeFrameGPU->setNLinesTotal(0);
245 return;
246 }
247 mTimeFrameGPU->createClusterOwnersDevice();
248 mTimeFrameGPU->createLinesDevice(nCells);
249 mTimeFrameGPU->resetClusterOwnersDevice();
250 mTimeFrameGPU->syncStreams(false);
251
252 TrackingKernels<NLayers>::registerClusterOwnershipHandler(mTimeFrameGPU->getDeviceCells()[0],
253 nCells,
254 mTimeFrameGPU->getDeviceArrayClusterOwners(),
255 mTimeFrameGPU->getStream(0));
256
258 mTimeFrameGPU->getDeviceCells()[0],
259 mTimeFrameGPU->getDeviceArrayClusterOwners(),
260 mTimeFrameGPU->getDeviceROFramesClusters(1),
261 mTimeFrameGPU->getNrof(1),
262 this->mTrkParams[iteration].CellLineSharedClusterCut,
263 mTimeFrameGPU->getDeviceLines(),
264 mTimeFrameGPU->getDeviceLineRof(),
265 mTimeFrameGPU->getDeviceLineClusters(),
266 mTimeFrameGPU->getDeviceLineSlots(),
267 mTimeFrameGPU->getBeamX(),
268 mTimeFrameGPU->getBeamY(),
269 this->getBz(),
270 this->mTrkParams[iteration].VtxLineCurvatureScale,
271 this->mTrkParams[iteration].VtxMaxZPositionAllowed,
272 this->mTrkParams[iteration].VtxLineMinPt,
273 mTimeFrameGPU->getDeviceLineZs(),
274 mTimeFrameGPU->getDeviceLineTimes(),
275 mTimeFrameGPU->getDeviceLineChi2(),
276 mTimeFrameGPU->getDeviceLinePt(),
277 mTimeFrameGPU->getFrameworkAllocator(),
278 mTimeFrameGPU->getStream(0));
279 const unsigned int nLines = mTimeFrameGPU->downloadLinesDevice();
280
282 mTimeFrameGPU->getNrof(1),
283 mTimeFrameGPU->getLineProjSoA(),
284 mTimeFrameGPU->getLineProjSortedSoA(),
285 mTimeFrameGPU->getDeviceLineRof(),
286 mTimeFrameGPU->getDeviceRofLineOffsets(),
287 mTimeFrameGPU->getFrameworkAllocator(),
288 mTimeFrameGPU->getStream(0));
289
290 const auto& tp = this->mTrkParams[iteration];
291 const float zWindow = 0.5f * tp.VtxClusterCut;
292 TrackingKernels<NLayers>::scanDensityHandler(static_cast<int>(nLines),
293 mTimeFrameGPU->getLineProjSortedSoA(),
294 mTimeFrameGPU->getDeviceRofLineOffsets(),
295 mTimeFrameGPU->getDeviceLineDensity(),
296 mTimeFrameGPU->getDeviceLineWin(),
297 zWindow,
298 mTimeFrameGPU->getStream(0));
299
300 const float fineZWindow = tp.VtxFineZWindow;
301 const bool doFine = fineZWindow > 0.f && fineZWindow < zWindow;
302 if (doFine) {
303 TrackingKernels<NLayers>::scanDensityHandler(static_cast<int>(nLines),
304 mTimeFrameGPU->getLineProjSortedSoA(),
305 mTimeFrameGPU->getDeviceRofLineOffsets(),
306 mTimeFrameGPU->getDeviceLineDensityFine(),
307 mTimeFrameGPU->getDeviceLineWinFine(),
308 fineZWindow,
309 mTimeFrameGPU->getStream(0));
310 }
311
313 mTimeFrameGPU->getNrof(1),
314 mTimeFrameGPU->getLineProjSortedSoA(),
315 mTimeFrameGPU->getDeviceRofLineOffsets(),
316 mTimeFrameGPU->getDeviceLineDensity(),
317 mTimeFrameGPU->getDeviceLineWin(),
318 mTimeFrameGPU->getDeviceLineIsPeak(),
319 doFine ? mTimeFrameGPU->getDeviceLineDensityFine() : nullptr,
320 doFine ? mTimeFrameGPU->getDeviceLineWinFine() : nullptr,
321 tp.VtxFineMinDensity,
322 doFine ? mTimeFrameGPU->getDeviceLineIsPeakFine() : nullptr,
323 mTimeFrameGPU->getDevicePeakScan(),
324 mTimeFrameGPU->getDevicePeakLineIdx(),
325 mTimeFrameGPU->getDevicePeakOffsets(),
326 mTimeFrameGPU->getFrameworkAllocator(),
327 mTimeFrameGPU->getStream(0));
328
329 const float goodLinePtCut = std::abs(mTimeFrameGPU->getBz()) > 0.01f ? tp.VtxGoodLinePtCut : -1.f;
330 TrackingKernels<NLayers>::fitPeaksHandler(mTimeFrameGPU->getDeviceNPeaks(),
331 mTimeFrameGPU->getDevicePeakLineIdx(),
332 mTimeFrameGPU->getDeviceLineWin(),
333 mTimeFrameGPU->getLineProjSortedSoA(),
334 mTimeFrameGPU->getDeviceLines(),
335 mTimeFrameGPU->getDeviceLineChi2(),
336 mTimeFrameGPU->getDeviceLinePt(),
337 tp.VtxGoodLineChi2Cut,
338 goodLinePtCut,
339 tp.VtxPairCut * tp.VtxPairCut,
340 tp.VtxNSigmaCut,
341 tp.VtxClusterContributorsCut,
342 mTimeFrameGPU->getBeamX(),
343 mTimeFrameGPU->getBeamY(),
344 doFine ? mTimeFrameGPU->getDeviceLineIsPeakFine() : nullptr,
345 tp.VtxFineMaxDrift,
346 mTimeFrameGPU->getDeviceVertexCands(),
347 mTimeFrameGPU->getStream(0));
348
349 const float duplicateZCut = tp.VtxDuplicateZCut > 0.f
350 ? tp.VtxDuplicateZCut
351 : std::max(4.f * tp.VtxPairCut, 0.5f * tp.VtxClusterCut);
352 TrackingKernels<NLayers>::dedupVertexCandidatesHandler(mTimeFrameGPU->getDeviceNPeaks(),
353 mTimeFrameGPU->getDevicePeakLineIdx(),
354 mTimeFrameGPU->getDevicePeakOffsets(),
355 mTimeFrameGPU->getLineProjSortedSoA(),
356 duplicateZCut,
357 tp.VtxDuplicateZScale,
358 mTimeFrameGPU->getDeviceVertexCands(),
359 mTimeFrameGPU->getStream(0));
360
361 const bool withMC = mTimeFrameGPU->hasMCinformation() && this->mTrkParams[iteration].CreateArtefactLabels;
362 mTimeFrameGPU->downloadVertexCandsDevice(); // sets nPeaks + host candidate/peak-offset mirrors
363 if (withMC) {
364 // pull back the peak windows and re-run the membership test here
365 mTimeFrameGPU->downloadPeakMembershipInputs();
366 }
367 const auto& lines = mTimeFrameGPU->getHostLines();
368 const auto& lineRof = mTimeFrameGPU->getHostLineRof();
369 const auto& lineClusters = mTimeFrameGPU->getHostLineClusters();
370 const int nRofs = mTimeFrameGPU->getNrof(1);
371 if (withMC) {
372 mTimeFrameGPU->getLineLabelFlat() = bounded_vector<o2::MCCompLabel>(nLines, o2::MCCompLabel(), mTimeFrameGPU->getMemoryPool().get());
373 }
374 auto lineLabel = [&](const int* cl) -> o2::MCCompLabel {
375 const auto l0 = mTimeFrameGPU->getClusterLabels(0, cl[0]);
376 const auto l1 = mTimeFrameGPU->getClusterLabels(1, cl[1]);
377 const auto l2 = mTimeFrameGPU->getClusterLabels(2, cl[2]);
378 for (const auto& a : l0) {
379 if (!a.isValid()) {
380 continue;
381 }
382 bool in1{false}, in2{false};
383 for (const auto& b : l1) {
384 if (b == a) {
385 in1 = true;
386 break;
387 }
388 }
389 for (const auto& c : l2) {
390 if (c == a) {
391 in2 = true;
392 break;
393 }
394 }
395 if (in1 && in2) {
396 return a;
397 }
398 }
399 return o2::MCCompLabel();
400 };
401 for (unsigned int i{0}; i < nLines; ++i) {
402 const int rof = lineRof[i];
403 if (rof < 0 || rof >= nRofs) {
404 LOGP(fatal, "ITS GPU linearizer: line {} carries out-of-range ROF {} (nRofs={}).", i, rof, nRofs);
405 }
406 const auto& l = lines[i];
407 mTimeFrameGPU->getLines(rof).emplace_back(std::array<float, 3>{l.originPoint[0], l.originPoint[1], l.originPoint[2]},
408 std::array<float, 3>{l.cosinesDirector[0], l.cosinesDirector[1], l.cosinesDirector[2]},
409 l.mTime);
410 if (withMC) {
411 const auto lbl = lineLabel(&lineClusters[3 * i]);
412 mTimeFrameGPU->getLinesLabel(rof).emplace_back(lbl);
413 mTimeFrameGPU->getLineLabelFlat()[i] = lbl; // same label, global-indexed for the vote
414 }
415 }
416 mTimeFrameGPU->setNLinesTotal(nLines);
417}
418
419template <int NLayers>
421{
422 const int nRofs = mTimeFrameGPU->getNrof(1);
423 const bool withMC = mTimeFrameGPU->hasMCinformation() && this->mTrkParams[iteration].CreateArtefactLabels;
424 const int suppressLowMultDebris = this->mTrkParams[iteration].VtxSuppressLowMultDebris;
425 const bool skipHighMultRofs = this->mTrkParams[iteration].PassFlags[IterationStep::SkipROFsAboveThreshold];
426
427 const auto& cands = mTimeFrameGPU->getHostVertexCands(); // per compacted peak slot [0, nPeaks)
428 const auto& peakOffsets = mTimeFrameGPU->getHostPeakOffsets(); // nRofs+1; per-ROF peak slices
429
430 std::vector<std::vector<Vertex>> rofVertices(nRofs);
431 std::vector<std::vector<VertexLabel>> rofLabels(nRofs);
432 const float goodSig = this->mTrkParams[iteration].VtxGoodContributorsSignificance;
433
434 for (int rofId = 0; rofId < nRofs; ++rofId) {
435 if (skipHighMultRofs &&
436 static_cast<int>(mTimeFrameGPU->getROFVertexLookupTableView().getVertices(1, rofId).getEntries()) > this->mTrkParams[iteration].VertPerRofThreshold) {
437 continue;
438 }
439 // Survivors of this ROF, sorted by contributor count desc
440 std::vector<int> accepted;
441 for (int p = peakOffsets[rofId]; p < peakOffsets[rofId + 1]; ++p) {
442 if (cands[p].keep) {
443 accepted.push_back(p);
444 }
445 }
446 std::sort(accepted.begin(), accepted.end(), [&](const int a, const int b) { return cands[a].size > cands[b].size; });
447
448 double rofLoad = 0.;
449 if (goodSig > 0.f) { // compute the number of contributors in this ROF
450 for (int p = peakOffsets[rofId]; p < peakOffsets[rofId + 1]; ++p) {
451 if (cands[p].ok && !cands[p].fine) {
452 rofLoad += cands[p].size;
453 }
454 }
455 }
456 const float debrisThreshold = goodSig > 0.f ? getDebrisThreshold(goodSig, rofLoad, suppressLowMultDebris) : 0.f;
457
458 for (const int p : accepted) {
459 const auto& c = cands[p];
460 if (!rofVertices[rofId].empty()) {
461 if (goodSig > 0.f) {
462 if (c.nGood < debrisThreshold) {
463 continue;
464 }
465 } else if (c.size < suppressLowMultDebris) {
466 continue;
467 }
468 }
469 const float pos[3] = {c.x, c.y, c.z};
470 Vertex vertex(pos, c.rms2, static_cast<ushort>(c.size), c.avgDist2);
471 vertex.setTimeStamp(c.time);
472 if (this->mTrkParams[iteration].PassFlags[IterationStep::MarkVerticesAsUPC]) {
473 vertex.setFlags(Vertex::UPCMode);
474 }
475 rofVertices[rofId].push_back(vertex);
476 if (withMC) {
477 // Re-apply here the rule the fit used: a line contributes when it is
478 // time-compatible with the peak line and within pairCut of the candidate's seed
479 const auto& memb = mTimeFrameGPU->getHostPeakMembership();
480 const auto& lines = mTimeFrameGPU->getHostLines();
481 const auto& lineLabelFlat = mTimeFrameGPU->getLineLabelFlat(); // nLines, global-indexed
482 const int nLab = static_cast<int>(lineLabelFlat.size());
483 const float pairCut2 = this->mTrkParams[iteration].VtxPairCut * this->mTrkParams[iteration].VtxPairCut;
484 const int k = memb.peakLineIdx[p];
485 const auto tk = memb.times[k];
486 const auto wk = memb.win[k];
487 std::vector<o2::MCCompLabel> labels;
488 labels.reserve(wk.hi - wk.lo);
489 for (int j = wk.lo; j < wk.hi; ++j) {
490 const auto tj = memb.times[j];
491 if (!tk.isCompatible(tj)) {
492 continue;
493 }
494 const int gi = memb.sortedToLine[j];
495 if (gi < 0 || gi >= nLab) {
496 LOGP(error, "Seeding vertexer: member line {} out of range (nLines={}), skipping label", gi, nLab);
497 continue;
498 }
499 if (o2::its::Line::getDistance2FromPoint(lines[gi], c.seed) >= pairCut2) {
500 continue;
501 }
502 labels.push_back(lineLabelFlat[gi]);
503 }
504 rofLabels[rofId].push_back(computeMainVertexLabel(labels));
505 }
506 }
507 }
508 if (!this->mTrkParams[iteration].PassFlags[IterationStep::MarkVerticesAsUPC]) { // UPC ROFs are near-empty by construction
509 pruneOverpopulatedRofs(rofVertices, rofLabels, this->mTrkParams[iteration].VtxOverpopulatedRofNSigma, suppressLowMultDebris);
510 }
511
512 for (int rofId = 0; rofId < nRofs; ++rofId) {
513 for (auto& vertex : rofVertices[rofId]) {
514 mTimeFrameGPU->addPrimaryVertex(vertex);
515 }
516 if (withMC) {
517 for (auto& label : rofLabels[rofId]) {
518 mTimeFrameGPU->addPrimaryVertexLabel(label);
519 }
520 }
521 }
522
523 auto& pvs = mTimeFrameGPU->getPrimaryVertices();
524 std::vector<size_t> indices(pvs.size());
525 std::iota(indices.begin(), indices.end(), 0);
526 std::sort(indices.begin(), indices.end(), [&pvs](const size_t i, const size_t j) {
527 const auto aLower = pvs[i].getTimeStamp().lower();
528 const auto bLower = pvs[j].getTimeStamp().lower();
529 if (aLower != bLower) {
530 return aLower < bLower;
531 }
532 return pvs[i].getNContributors() > pvs[j].getNContributors();
533 });
534 std::decay_t<decltype(pvs)> sortedVtx(pvs.get_allocator());
535 sortedVtx.reserve(pvs.size());
536 for (const size_t idx : indices) {
537 sortedVtx.push_back(pvs[idx]);
538 }
539 pvs.swap(sortedVtx);
540 if (withMC) {
541 auto& mc = mTimeFrameGPU->getPrimaryVerticesLabels();
542 std::decay_t<decltype(mc)> sortedMC(mc.get_allocator());
543 sortedMC.reserve(mc.size());
544 for (const size_t idx : indices) {
545 sortedMC.push_back(mc[idx]);
546 }
547 mc.swap(sortedMC);
548 }
549 mTimeFrameGPU->updateROFVertexLookupTable();
550
551 mTimeFrameGPU->popMemoryStack(iteration); // frees the whole seeding-pass stack frame
552}
553
554template <int NLayers>
556{
557 const auto hostTopology = mTimeFrameGPU->getTrackingTopologyView();
558 bounded_vector<int> sourceTopologies(this->getMemoryPool().get());
559 sourceTopologies.reserve(hostTopology.nCells);
560 for (int outerLayer{0}; outerLayer < NLayers; ++outerLayer) {
561 for (int targetCellTopologyId{0}; targetCellTopologyId < hostTopology.nCells; ++targetCellTopologyId) {
562 const auto targetCellTopology = hostTopology.getCell(targetCellTopologyId);
563 if (targetCellTopology.hitLayerMask.last() != outerLayer) {
564 continue;
565 }
566 const int targetCellsNum{static_cast<int>(mTimeFrameGPU->getNCells()[targetCellTopologyId])};
567 sourceTopologies.clear();
568 size_t sourceCellCount{0};
569 for (int sourceCellTopologyId{0}; sourceCellTopologyId < hostTopology.nCells; ++sourceCellTopologyId) {
570 const auto sourceCellTopology = hostTopology.getCell(sourceCellTopologyId);
571 const int sourceCellsNum{static_cast<int>(mTimeFrameGPU->getNCells()[sourceCellTopologyId])};
572 if (!sourceCellsNum || sourceCellTopology.secondLink != targetCellTopology.firstLink) {
573 continue;
574 }
575 sourceTopologies.push_back(sourceCellTopologyId);
576 sourceCellCount += sourceCellsNum;
577 }
578 if (!targetCellsNum || sourceTopologies.empty()) {
579 mTimeFrameGPU->getNNeighbours()[targetCellTopologyId] = 0;
580 mTimeFrameGPU->createNeighboursDevice(targetCellTopologyId, 0);
581 mTimeFrameGPU->recordEvent(targetCellTopologyId);
582 continue;
583 }
584 mTimeFrameGPU->createNeighboursLUTDevice(targetCellTopologyId, targetCellsNum);
585 auto& stream = mTimeFrameGPU->getStream(targetCellTopologyId);
586 int* outputCounter = mTimeFrameGPU->getDeviceNeighboursLUT(targetCellTopologyId) + targetCellsNum;
587
588 const auto key = CapacityEstimator::makeKey(SlabSite::Neighbours, iteration, 0, targetCellTopologyId);
589 const auto scale = static_cast<double>(sourceCellCount);
590 const int emitted = runOnSlab(mTimeFrameGPU->getCapacityEstimator(), key, scale, [&](const int capacity) {
591 mTimeFrameGPU->createNeighboursDevice(targetCellTopologyId, capacity);
592 resetOutputCounterHandler(outputCounter, stream);
593 for (const int sourceCellTopologyId : sourceTopologies) {
594 mTimeFrameGPU->waitEvent(targetCellTopologyId, sourceCellTopologyId);
595 TrackingKernels<NLayers>::computeCellNeighboursHandler(mTimeFrameGPU->getDeviceArrayCells(),
596 mTimeFrameGPU->getDeviceArrayCellsLUT(),
597 mTimeFrameGPU->getDeviceNeighbours(targetCellTopologyId),
598 outputCounter,
599 capacity,
600 sourceCellTopologyId,
601 targetCellTopologyId,
602 this->mTrkParams[iteration].MaxChi2ClusterAttachment,
603 this->mBz,
604 mTimeFrameGPU->getNCells()[sourceCellTopologyId],
605 mTimeFrameGPU->getFrameworkAllocator(),
606 stream);
607 }
608 return finalizeCellNeighboursHandler(mTimeFrameGPU->getDeviceNeighbours(targetCellTopologyId),
609 mTimeFrameGPU->getDeviceNeighboursLUT(targetCellTopologyId),
610 targetCellsNum,
611 capacity,
612 mTimeFrameGPU->getFrameworkAllocator(),
613 stream);
614 });
615 mTimeFrameGPU->getNNeighbours()[targetCellTopologyId] = emitted;
616 mTimeFrameGPU->recordEvent(targetCellTopologyId);
617 }
618 }
619 mTimeFrameGPU->syncStreams(false);
620}
621
622template <int NLayers>
624{
625 bounded_vector<bounded_vector<int>> firstClusters(this->mTrkParams[iteration].NLayers, bounded_vector<int>(this->getMemoryPool().get()), this->getMemoryPool().get());
626 firstClusters.resize(this->mTrkParams[iteration].NLayers);
627 const auto hostTopology = mTimeFrameGPU->getTrackingTopologyView();
628 const bool extendTop = this->mTrkParams[iteration].PassFlags[IterationStep::TrackFollowerTop];
629 const bool extendBot = this->mTrkParams[iteration].PassFlags[IterationStep::TrackFollowerBot];
630 const bool extendTracks = extendTop || extendBot;
631 for (int startLevel{this->mTrkParams[iteration].CellsPerRoad()}; startLevel >= this->mTrkParams[iteration].CellMinimumLevel(); --startLevel) {
632 // The cells that may start a road at this level, as the scale the estimator predicts from.
633 size_t startCells{0};
634 for (int startCellTopologyId{0}; startCellTopologyId < hostTopology.nCells; ++startCellTopologyId) {
635 const int startLayer = hostTopology.getCell(startCellTopologyId).hitLayerMask.last();
636 if (this->mTrkParams[iteration].StartLayerMask.has(startLayer)) {
637 startCells += mTimeFrameGPU->getNCells()[startCellTopologyId];
638 }
639 }
640 if (!startCells) {
641 continue;
642 }
643 const auto key = CapacityEstimator::makeKey(SlabSite::TrackSeeds, iteration, startLevel, 0);
644 auto& estimator = mTimeFrameGPU->getCapacityEstimator();
645 const int nSeeds = runOnSlab(estimator, key, static_cast<double>(startCells), [&](const int capacity) {
646 mTimeFrameGPU->createTrackSeedsDevice(capacity);
647 int cursor{0};
648 for (int startCellTopologyId{0}; startCellTopologyId < hostTopology.nCells; ++startCellTopologyId) {
649 const int startLayer = hostTopology.getCell(startCellTopologyId).hitLayerMask.last();
650 if (!(this->mTrkParams[iteration].StartLayerMask.has(startLayer)) || mTimeFrameGPU->getNCells()[startCellTopologyId] == 0) {
651 continue;
652 }
654 startCellTopologyId,
655 mTimeFrameGPU->getDeviceArrayCells(),
656 mTimeFrameGPU->getDeviceCells()[startCellTopologyId],
657 nullptr,
658 nullptr,
659 mTimeFrameGPU->getArrayNCells().data(),
660 (const uint8_t**)mTimeFrameGPU->getDeviceArrayUsedClusters(),
661 mTimeFrameGPU->getDeviceArrayNeighbours(),
662 mTimeFrameGPU->getDeviceArrayNeighboursCellLUT(),
663 mTimeFrameGPU->getDeviceArrayTrackingFrameInfo(),
664 mTimeFrameGPU->getDeviceTrackSeeds(),
665 capacity,
666 cursor,
667 mTimeFrameGPU->getCapacityEstimator(),
668 iteration,
669 this->mBz,
670 this->mTrkParams[iteration].MaxChi2ClusterAttachment,
671 this->mTrkParams[iteration].MaxChi2NDF,
672 this->mTrkParams[iteration].MaxHoles,
673 this->mTrkParams[iteration].getMinSeedingClusters(),
674 this->mTrkParams[iteration].HoleLayerMask,
675 this->mTrkParams[iteration].getNonSeedingLayerMask(),
676 mTimeFrameGPU->getDeviceLayerxX0(),
677 mTimeFrameGPU->getDevicePropagator(),
678 this->mTrkParams[iteration].CorrType,
679 mTimeFrameGPU->getFrameworkAllocator());
680 }
681 return cursor; }, estimator.peakCapacity(key));
682 if (!nSeeds) {
683 LOGP(debug, "No track seeds found, skipping track finding");
684 continue;
685 }
686 if (extendTracks) { // independent of the slab size, so it must not be redone on a retry
687 mTimeFrameGPU->createTrackExtensionScratchDevice(gpu::gridThreads(gpu::ResidentBlocks.fitTrackSeedsExtended),
688 this->mTrkParams[iteration].TrackFollowerMaxHypotheses);
689 }
690 const auto trackKey = CapacityEstimator::makeKey(extendTracks ? SlabSite::TracksExtended : SlabSite::Tracks,
691 iteration, startLevel, 0);
692 const int nTracks = runOnSlab(estimator, trackKey, static_cast<double>(nSeeds), [&](const int capacity) {
693 mTimeFrameGPU->createTrackITSExtDevice(capacity);
694 return TrackingKernels<NLayers>::computeTrackSeedHandler(mTimeFrameGPU->getDeviceTrackSeeds(),
695 mTimeFrameGPU->getDeviceArrayTrackingFrameInfo(),
696 mTimeFrameGPU->getDeviceArrayUnsortedClusters(),
697 mTimeFrameGPU->getDeviceIndexTableUtils(),
698 mTimeFrameGPU->getDeviceROFMaskTableView(),
699 mTimeFrameGPU->getDeviceROFOverlapTableView(),
700 mTimeFrameGPU->getDeviceArrayClusters(),
701 (const unsigned char**)mTimeFrameGPU->getDeviceArrayUsedClusters(),
702 mTimeFrameGPU->getDeviceArrayClustersIndexTables(),
703 mTimeFrameGPU->getDeviceROFrameClusters(),
704 mTimeFrameGPU->getDeviceTrackITSExt(),
705 mTimeFrameGPU->getDeviceTrackIndices(),
706 mTimeFrameGPU->getDeviceTrackSeedIndices(),
707 mTimeFrameGPU->getDeviceTrackCounter(),
708 capacity,
709 extendTracks ? mTimeFrameGPU->getDeviceActiveTrackExtensionHypotheses() : nullptr,
710 extendTracks ? mTimeFrameGPU->getDeviceNextTrackExtensionHypotheses() : nullptr,
711 mTimeFrameGPU->getDeviceLayerRadii(),
712 mTimeFrameGPU->getDeviceMinPts(),
713 mTimeFrameGPU->getDeviceLayerxX0(),
714 static_cast<unsigned int>(nSeeds),
715 this->mBz,
716 this->mTrkParams[iteration].MaxChi2ClusterAttachment,
717 this->mTrkParams[iteration].MaxChi2NDF,
718 this->mTrkParams[iteration].ReseedIfShorter,
719 this->mTrkParams[iteration].RepeatRefitOut,
720 this->mTrkParams[iteration].ShiftRefToCluster,
721 this->mTrkParams[iteration].NLayers,
722 this->mTrkParams[iteration].PhiBins,
723 this->mTrkParams[iteration].TrackFollowerMaxHypotheses,
724 extendTop,
725 extendBot,
726 this->mTrkParams[iteration].TrackFollowerNSigmaCutPhi,
727 this->mTrkParams[iteration].TrackFollowerNSigmaCutZ,
728 mTimeFrameGPU->getDevicePropagator(),
729 this->mTrkParams[iteration].CorrType,
730 mTimeFrameGPU->getFrameworkAllocator()); }, estimator.peakCapacity(trackKey));
731 mTimeFrameGPU->createTrackITSExtHost(nTracks);
732 mTimeFrameGPU->downloadTrackITSExtDevice();
733
734 auto& tracks = mTimeFrameGPU->getTrackITSExt();
735 const auto& trackIndices = mTimeFrameGPU->getTrackIndices();
736 this->acceptTracks(iteration, tracks, trackIndices, firstClusters);
737 mTimeFrameGPU->loadUsedClustersDevice();
738 }
739 this->markTracks(iteration);
740 // wipe the artefact memory
741 mTimeFrameGPU->popMemoryStack(iteration);
742};
743
744template <int NLayers>
746{
747 return mTimeFrameGPU->getNumberOfClusters();
748}
749
750template <int NLayers>
752{
753 return std::accumulate(mTimeFrameGPU->getNTracklets().begin(), mTimeFrameGPU->getNTracklets().end(), 0);
754}
755
756template <int NLayers>
758{
759 return mTimeFrameGPU->getNumberOfCells();
760}
761
762template <int NLayers>
764{
765 this->mBz = bz;
766 mTimeFrameGPU->setBz(bz);
767}
768
769template class TrackerTraitsGPU<7>;
770#ifdef ENABLE_UPGRADES
771template class TrackerTraitsGPU<11>;
772template class TrackerTraitsGPU<13>;
773#endif
774} // namespace o2::its
std::ostringstream debug
uint64_t vertex
Definition RawEventData.h:9
int32_t i
std::vector< o2::MCCompLabel > labels
std::vector< o2::its::TrackITS > tracks
Compile-time launch geometry of the ITS tracking kernels, per GPU family. Poor man's RTC to be remove...
uint16_t pos
Definition RawData.h:3
uint32_t j
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
Utility functions for vertex handling.
int nClusters
StringRef key
void get(int &trackID, int &evID, int &srcID, bool &fake) const
void computeLayerTracklets(const int iteration, int) final
void initialiseTimeFrame(const int iteration) final
void computeVertexCandidates(const int iteration) final
void computeLayerCells(const int iteration) final
void adoptTimeFrame(TimeFrame< NLayers > *tf) final
void computeVertices(const int iteration) final
static constexpr KeyType makeKey(SlabSite site, int iteration, int variant, int slot) noexcept
GLint first
Definition glcorearb.h:399
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLsizei GLenum const void * indices
Definition glcorearb.h:400
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLuint GLuint stream
Definition glcorearb.h:1806
auto get(const std::byte *buffer, size_t=0)
Definition DataHeader.h:457
void pruneOverpopulatedRofs(std::vector< VtxVec > &rofVertices, std::vector< LabVec > &rofLabels, const float nSigma, const int minContributors)
Caps ROFs whose vertex count is an outlier of the TF.
Definition VertexUtils.h:81
const bool const bool extendBot
const bool extendTop
float getDebrisThreshold(const float goodSig, const double rofLoad, const int suppressLowMultDebris)
Definition VertexUtils.h:70
const float const float const float bz
int finalizeCellNeighboursHandler(CellNeighbour *cellNeighbours, int *neighboursLUT, const int nTargetCells, const int capacity, o2::its::ExternalAllocator *alloc, gpu::Stream &stream)
VertexLabel computeMainVertexLabel(const Container &elements)
Definition VertexUtils.h:37
Vertex makeDiamondVertex(const TrackingParameters &trkParam)
Definition VertexUtils.h:61
int runOnSlab(CapacityEstimator &estimator, const CapacityEstimator::KeyType key, const double scale, Emit &&emit, const size_t floorCapacity=0)
void empty(int)
std::unique_ptr< GPUReconstructionTimeframe > tf
static float getDistance2FromPoint(const Line &line, const std::array< float, 3 > &point)
const auto & getTrackingTopologyView() const
Definition TimeFrame.h:151
static void fitPeaksHandler(const int *nPeaksDevice, const int *peakLineIdx, const gpu::LineWindow *win, const gpu::LineProjSoA sortedSoa, const o2::its::Line *lines, const float *lineChi2, const float *linePt, const float goodLineChi2Cut, const float goodLinePtCut, const float pairCut2, const float nSigmaCut, const int minContributors, const float beamX, const float beamY, const uint8_t *isPeakFine, const float fineMaxDrift, gpu::VertexCand *cands, gpu::Stream &stream)
static void dedupVertexCandidatesHandler(const int *nPeaksDevice, const int *peakLineIdx, const int *peakOffsets, const gpu::LineProjSoA sortedSoa, const float duplicateZCut, const float duplicateZScale, gpu::VertexCand *cands, gpu::Stream &stream)
static void scanDensityHandler(const int nLines, const gpu::LineProjSoA sortedSoa, const int *rofOffsets, int *density, gpu::LineWindow *win, const float zWindow, gpu::Stream &stream)
static void registerClusterOwnershipHandler(const CellSeed *cellsLayersDevice, const int nCells, unsigned long long **clusterOwnersDeviceArray, gpu::Stream &stream)
static void linearizeCellsToLinesHandler(const int nCells, const CellSeed *cells, const unsigned long long *const *clusterOwners, const int *rofFramesClustersL1, const int nRofsL1, const int ownedClustersCut, o2::its::Line *lines, int *lineRof, int *lineClusters, int *lineSlots, const float beamX, const float beamY, const float bz, const float curvatureScale, const float maxZ, const float minPt, float *linesZs, o2::its::TimeEstBC *lineTimes, float *lineChi2, float *linePt, o2::its::ExternalAllocator *alloc, gpu::Stream &stream)
static void findPeaksHandler(const int nLines, const int nRofs, const gpu::LineProjSoA sortedSoa, const int *rofOffsets, const int *density, const gpu::LineWindow *win, uint8_t *isPeak, const int *densityFine, const gpu::LineWindow *winFine, const int fineMinDensity, uint8_t *isPeakFine, int *peakScan, int *peakLineIdx, int *peakOffsets, o2::its::ExternalAllocator *alloc, gpu::Stream &stream)
static void sortLinesHandler(const int nLines, const int nRofs, const gpu::LineProjSoA soa, const gpu::LineProjSoA sortedSoa, const int *lineRof, int *rofOffsets, o2::its::ExternalAllocator *alloc, gpu::Stream &stream)