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