Project
Loading...
Searching...
No Matches
Tracker.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.
15
16#include "ITStracking/Tracker.h"
21
22#include <cassert>
23#include <algorithm>
24#include <limits>
25#include <format>
26#include <cstdlib>
27#include <string>
28
29namespace o2::its
30{
32
33template <int NLayers>
35{
36}
37
38template <int NLayers>
39float Tracker<NLayers>::clustersToTracks(const LogFunc& logger, const LogFunc& error)
40{
41 LogFunc evalLog = [](const std::string&) {};
42
43 float total{0};
44 mTraits->updateTrackingParameters(mTrkParams);
45
46 int maxNvertices{-1};
47 if (mTrkParams[0].PerPrimaryVertexProcessing) {
48 maxNvertices = mTimeFrame->getROFVertexLookupTableView().getMaxVerticesPerROF();
49 }
50
51 int iteration{0}, iVertex{0};
52 auto handleException = [&](const auto& err) {
53 if (mTrkParams[iteration].MaxMemory == std::numeric_limits<size_t>::max()) {
54 LOGP(error, "Allocation failed in {} in iteration {} iVtx={} ({:.2f} GB of host artefacts, no host limit set), check the detector status and/or the selections.",
55 StateNames[mCurStep], iteration, iVertex,
56 (double)mTimeFrame->getArtefactsMemory() / GB);
57 } else {
58 LOGP(error, "Too much memory in {} in iteration {} iVtx={}: {:.2f} GB. Current limit is {:.2f} GB, check the detector status and/or the selections.",
59 StateNames[mCurStep], iteration, iVertex,
60 (double)mTimeFrame->getArtefactsMemory() / GB,
61 (double)mTrkParams[iteration].MaxMemory / GB);
62 }
63 if (typeid(err) != typeid(std::bad_alloc)) { // only print if the exceptions is different from what is expected
64 LOGP(error, "Exception: {}", err.what());
65 }
66 if (mTrkParams[iteration].DropTFUponFailure) {
67 mMemoryPool->print();
68 mTimeFrame->wipe();
69 mTimeFrame->getCapacityEstimator().reset();
70 ++mNumberOfDroppedTFs;
71 error(std::format("...Dropping TimeSlice {} (out of {} dropped {})...", mTimeSlice, mTimeFrameCounter, mNumberOfDroppedTFs));
72 } else {
73 throw err;
74 }
75 };
76
77 try {
78 for (iteration = 0; iteration < (int)mTrkParams.size(); ++iteration) {
79 mMemoryPool->setMaxMemory(mTrkParams[iteration].MaxMemory);
80 if (mTrkParams[iteration].PassFlags[IterationStep::UseUPCMask]) {
81 mTimeFrame->useUPCMask();
82 }
83 float timeFrame{0.}, timeTracklets{0.}, timeCells{0.}, timeNeighbours{0.}, timeRoads{0.};
84 size_t nTracklets{0}, nCells{0}, nNeighbours{0};
85 int nTracks{-static_cast<int>(mTimeFrame->getNumberOfTracks())};
86 iVertex = std::min(maxNvertices, 0);
87 logger(std::format("==== ITS {} Tracking iteration {} summary ====", mTraits->getName(), iteration));
88 total += timeFrame = evaluateTask(&Tracker::initialiseTimeFrame, StateNames[mCurStep = TFInit], iteration, evalLog, iteration);
89 logger(std::format(" - TimeFrame initialisation completed in {:.2f} ms", timeFrame));
90 do {
91 timeTracklets += evaluateTask(&Tracker::computeTracklets, StateNames[mCurStep = Trackleting], iteration, evalLog, iteration, iVertex);
92 nTracklets += mTraits->getTFNumberOfTracklets();
93 timeCells += evaluateTask(&Tracker::computeCells, StateNames[mCurStep = Celling], iteration, evalLog, iteration);
94 nCells += mTraits->getTFNumberOfCells();
95 timeNeighbours += evaluateTask(&Tracker::findCellsNeighbours, StateNames[mCurStep = Neighbouring], iteration, evalLog, iteration);
96 nNeighbours += mTimeFrame->getNumberOfNeighbours();
97 timeRoads += evaluateTask(&Tracker::findRoads, StateNames[mCurStep = Roading], iteration, evalLog, iteration);
98 } while (++iVertex < maxNvertices);
99 logger(std::format(" - Tracklet finding: {} tracklets found in {:.2f} ms", nTracklets, timeTracklets));
100 logger(std::format(" - Cell finding: {} cells found in {:.2f} ms", nCells, timeCells));
101 logger(std::format(" - Neighbours finding: {} neighbours found in {:.2f} ms", nNeighbours, timeNeighbours));
102 logger(std::format(" - Track finding: {} tracks found in {:.2f} ms", nTracks + mTimeFrame->getNumberOfTracks(), timeRoads));
103 if (mTrkParams[iteration].PassFlags[IterationStep::TrackFollowerTop] || mTrkParams[iteration].PassFlags[IterationStep::TrackFollowerBot]) {
104 logger(std::format(" - Integrated track extension: {} tracks accepted using {} clusters", mTimeFrame->getNExtendedTracks(), mTimeFrame->getNExtendedClusters()));
105 }
106 total += timeTracklets + timeCells + timeNeighbours + timeRoads;
107 }
108 } catch (const BoundedMemoryResource::MemoryLimitExceeded& err) {
109 handleException(err);
110 return -1.f;
111 } catch (const std::bad_alloc& err) {
112 handleException(err);
113 return -1.f;
114 } catch (const std::exception& err) {
115 error(std::format("Uncaught exception, all bets are off... {}", err.what()));
116 // clear tracks explicitly since if not fatalising on exception this may contain partial output
117 mTimeFrame->getTracks().clear();
118 return -1.f;
119 }
120
121 if (mTimeFrame->hasMCinformation()) {
122 computeTracksMClabels();
123 }
124 rectifyClusterIndices();
125 sortTracks();
126
127 ++mTimeFrameCounter;
128 mTotalTime += total;
129
130 return total;
131}
132
133template <int NLayers>
135{
136 for (auto& track : mTimeFrame->getTracks()) {
137 std::vector<std::pair<MCCompLabel, size_t>> occurrences;
138 occurrences.clear();
139
140 for (int iCluster = 0; iCluster < TrackITSExt::MaxClusters; ++iCluster) {
141 const int index = track.getClusterIndex(iCluster);
143 continue;
144 }
145 auto labels = mTimeFrame->getClusterLabels(iCluster, index);
146 bool found{false};
147 for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) {
148 std::pair<o2::MCCompLabel, size_t>& occurrence = occurrences[iOcc];
149 for (const auto& label : labels) {
150 if (label == occurrence.first) {
151 ++occurrence.second;
152 found = true;
153 // break; // uncomment to stop to the first hit
154 }
155 }
156 }
157 if (!found) {
158 for (const auto& label : labels) {
159 occurrences.emplace_back(label, 1);
160 }
161 }
162 }
163 std::sort(std::begin(occurrences), std::end(occurrences), [](auto e1, auto e2) {
164 return e1.second > e2.second;
165 });
166
167 auto maxOccurrencesValue = occurrences[0].first;
168 uint32_t pattern = track.getPattern();
169 // set fake clusters pattern
170 for (int ic{TrackITSExt::MaxClusters}; ic--;) {
171 auto clid = track.getClusterIndex(ic);
172 if (clid != constants::UnusedIndex) {
173 auto labelsSpan = mTimeFrame->getClusterLabels(ic, clid);
174 for (const auto& currentLabel : labelsSpan) {
175 if (currentLabel == maxOccurrencesValue) {
176 pattern |= 0x1 << (16 + ic); // set bit if correct
177 break;
178 }
179 }
180 }
181 }
182 track.setPattern(pattern);
183 if (occurrences[0].second < track.getNumberOfClusters()) {
184 maxOccurrencesValue.setFakeFlag();
185 }
186 mTimeFrame->getTracksLabel().emplace_back(maxOccurrencesValue);
187 }
188}
189
190template <int NLayers>
192{
193 for (auto& track : mTimeFrame->getTracks()) {
194 for (int iCluster = 0; iCluster < TrackITSExt::MaxClusters; ++iCluster) {
195 const int index = track.getClusterIndex(iCluster);
197 track.setExternalClusterIndex(iCluster, mTimeFrame->getClusterExternalIndex(iCluster, index));
198 }
199 }
200 }
201}
202
203template <int NLayers>
204void Tracker<NLayers>::sortTracks()
205{
206 auto& trks = mTimeFrame->getTracks();
207 bounded_vector<size_t> indices(trks.size(), mMemoryPool.get());
208 std::iota(indices.begin(), indices.end(), 0);
209 std::sort(indices.begin(), indices.end(), [&trks](size_t i, size_t j) {
210 // provide tracks sorted by lower-bound
211 const auto& a = trks[i];
212 const auto& b = trks[j];
213 const auto aLower = a.getTimeStamp().getTimeStamp() - a.getTimeStamp().getTimeStampError();
214 const auto bLower = b.getTimeStamp().getTimeStamp() - b.getTimeStamp().getTimeStampError();
215 if (aLower != bLower) {
216 return aLower < bLower;
217 }
218 return a.isBetter(b, 1e9); // then sort tracks in quality
219 });
220 bounded_vector<TrackITSExt> sortedTrks(mMemoryPool.get());
221 sortedTrks.reserve(trks.size());
222 for (size_t idx : indices) {
223 sortedTrks.push_back(trks[idx]);
224 }
225 trks.swap(sortedTrks);
226 if (mTimeFrame->hasMCinformation()) {
227 auto& trksLabels = mTimeFrame->getTracksLabel();
228 bounded_vector<MCCompLabel> sortedLabels(mMemoryPool.get());
229 sortedLabels.reserve(trksLabels.size());
230 for (size_t idx : indices) {
231 sortedLabels.push_back(trksLabels[idx]);
232 }
233 trksLabels.swap(sortedLabels);
234 }
235}
236
237template <int NLayers>
239{
240 mTimeFrame = &tf;
241 mTraits->adoptTimeFrame(&tf);
242}
243
244template <int NLayers>
245void Tracker<NLayers>::addTimingStatCurStep(int iteration, double timeMs)
246{
247 if (iteration < 0) {
248 return;
249 }
250 if (mTimingStats.size() < (iteration + 1)) {
251 mTimingStats.resize(iteration + 1);
252 }
253 mTimingStats[iteration][mCurStep].add(timeMs);
254}
255
256template <int NLayers>
258{
259 auto avgTF = mTotalTime * 1.e-3 / ((mTimeFrameCounter > 0) ? (double)mTimeFrameCounter : -1.0);
260 auto avgTFwithDropped = mTotalTime * 1.e-3 / (((mTimeFrameCounter + mNumberOfDroppedTFs) > 0) ? (double)(mTimeFrameCounter + mNumberOfDroppedTFs) : -1.0);
261 LOGP(info, "Tracker summary: Processed {} TFs (dropped {}) in TOT={:.2f} s, AVG/TF={:.2f} ({:.2f}) s", mTimeFrameCounter, mNumberOfDroppedTFs, mTotalTime * 1.e-3, avgTF, avgTFwithDropped);
262 for (size_t iteration = 0; iteration < mTimingStats.size(); ++iteration) {
263 for (size_t state = 0; state < NSteps; ++state) {
264 const auto& stats = mTimingStats[iteration][state];
265 if (!stats.calls) {
266 continue;
267 }
268 LOGP(info, " - iter {} {}: calls={} total={:.2f} ms avg={:.2f} ms", iteration, StateNames[state], stats.calls, stats.totalTimeMs, stats.averageTimeMs());
269 }
270 }
271}
272
273template class Tracker<7>;
274// ALICE3 upgrade
275#ifdef ENABLE_UPGRADES
276template class Tracker<11>;
277template class Tracker<13>;
278#endif
279
280} // namespace o2::its
std::vector< std::string > labels
benchmark::State & state
int32_t i
#define GB
Definition Utils.h:40
uint32_t j
Definition RawData.h:0
static constexpr int MaxClusters
< heavy version of TrackITS, with clusters embedded
Definition TrackITS.h:207
Tracker(TrackerTraits< NLayers > *traits)
Definition Tracker.cxx:34
void adoptTimeFrame(TimeFrame< NLayers > &tf)
Definition Tracker.cxx:238
void computeTracksMClabels()
Definition Tracker.cxx:134
float clustersToTracks(const LogFunc &=[](const std::string &s) { std::cout<< s<< '\n';}, const LogFunc &=[](const std::string &s) { std::cerr<< s<< '\n';})
Definition Tracker.cxx:39
GLuint index
Definition glcorearb.h:781
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
constexpr int UnusedIndex
Definition Constants.h:32
constexpr float GB
Definition Constants.h:27
const bool const int TrackITSInternal< NLayers > & track
std::unique_ptr< GPUReconstructionTimeframe > tf
std::array< uint16_t, 5 > pattern