Skip to content

ITS: add back the code for track following#15456

Open
mpuccio wants to merge 2 commits into
AliceO2Group:devfrom
mpuccio:track_following
Open

ITS: add back the code for track following#15456
mpuccio wants to merge 2 commits into
AliceO2Group:devfrom
mpuccio:track_following

Conversation

@mpuccio
Copy link
Copy Markdown
Contributor

@mpuccio mpuccio commented May 31, 2026

By default, this is disabled for ITS, but it is required for ALICE3.
This changes the findRoads to avoid the double pass (first count then fill) on CPU, leading to marginal gain on speed while keeping the memory footprint equal (checked on a critical PbPb CTF that Felix gave me)

@mpuccio mpuccio force-pushed the track_following branch from 9012bd5 to d4e7f5a Compare May 31, 2026 06:39
Copy link
Copy Markdown
Collaborator

@f3sch f3sch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work, still have to go through the actual meat of the code but maybe this can be a starting point. Most comments are only of cosmetic nature

}

// return clamped ROF range with strictly positive overlap with timestamp interval
GPUhdi() int2 getROFRange(TimeStamp ts) const noexcept
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's stay consistent and use the RangeReference here instead of int2, e.g. adding to the class a using BCRange = RangeReference<BCType,BCType>;

Comment on lines +115 to +117
if (mNROFsTF == 0) {
return {1, 0};
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes no sense to me, how can we ever have zero ROFs in a TF?

Comment on lines +30 to +65
template <int NLayers>
GPUhdi() constexpr uint32_t makeAddedClustersPatternMask()
{
return (NLayers >= 32) ? 0xffffffffu : ((1u << NLayers) - 1u);
}

template <int NLayers>
GPUhdi() void applyExtendedClustersPattern(TrackITSExt& track, uint32_t diff)
{
diff &= makeAddedClustersPatternMask<NLayers>();
track.setUserField(static_cast<uint16_t>(diff));
if constexpr (NLayers <= kMaxLayersInTrackPattern) {
track.setPattern(track.getPattern() | (diff << kExtendedPatternShift));
} else {
(void)track;
}
}

template <int NLayers>
GPUhdi() uint32_t getAddedClustersPattern(const TrackITSExt& track)
{
const auto mask = makeAddedClustersPatternMask<NLayers>();
if constexpr (NLayers <= kMaxLayersInTrackPattern) {
const auto diff = (track.getPattern() >> kExtendedPatternShift) & mask;
if (diff) {
return diff;
}
}
return track.getUserField() & mask;
}

GPUhdi() void clearAddedClustersPattern(TrackITSExt& track)
{
track.setUserField(0);
track.getParamOut().setUserField(0);
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arguably, these only act on the class itself and should thus be part of it and not be in some other header.

Comment on lines +27 to +28
inline constexpr unsigned int kExtendedPatternShift = 24;
inline constexpr int kMaxLayersInTrackPattern = 8;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see comment below

TrackITSExt track;
};

inline constexpr int MaxTrackExtensionCandidatesPerTrack = 4;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constants should go into the Constants.h header


template <int NLayers>
struct TrackExtensionCandidate {
static constexpr float InvalidChi2 = 1.e20f;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use the constants::UnsetValue?

Comment on lines +106 to +110
template <int NLayers>
GPUhdi() bool isBetterTrackExtensionCandidate(const TrackExtensionCandidate<NLayers>& a, const TrackExtensionCandidate<NLayers>& b)
{
return (a.nAddedClusters > b.nAddedClusters) || (a.nAddedClusters == b.nAddedClusters && a.chi2 < b.chi2);
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and isBetterTrackExtensionHypothesis do essentially the same thing, is there not a way to reuse this logic? Also I would prefer to make these members of the classes themselves since it spiritually is the same as the TrackITS::isBetter.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the same argument should have been made for track::isBetter

Comment on lines +106 to +119
template <int NLayers>
GPUhdi() void initialiseTrackExtensionHypothesis(const TrackITSExt& track,
const bool outward,
TrackExtensionHypothesis<NLayers>& hypo)
{
hypo.param = outward ? track.getParamOut() : track.getParamIn();
hypo.time = track.getTimeStamp();
hypo.chi2 = track.getChi2();
hypo.nClusters = track.getNClusters();
hypo.edgeLayer = outward ? getTrackExtensionLastClusterLayer<NLayers>(track) : getTrackExtensionFirstClusterLayer<NLayers>(track);
for (int iLayer{0}; iLayer < NLayers; ++iLayer) {
hypo.clusters[iLayer] = track.getClusterIndex(iLayer);
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me this seems also something be made as part of the class, e.g., in the constructor or as a initialiseFromTrack function.

Comment on lines +244 to +250
const auto rofTS = rofOverlaps.getLayer(iLayer).getROFTimeBounds(rof, true);
const auto& ts = updated.time;
const float lower = o2::gpu::CAMath::Max(ts.getTimeStamp() - ts.getTimeStampError(), static_cast<float>(rofTS.lower()));
const float upper = o2::gpu::CAMath::Min(ts.getTimeStamp() + ts.getTimeStampError(), static_cast<float>(rofTS.upper()));
updated.time.setTimeStamp(0.5f * (lower + upper));
updated.time.setTimeStampError(0.5f * (upper - lower));
addTrackExtensionHypothesisToBeam(updated, nextHypotheses, nNext, beamWidth);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not use the symmetric timestamp in 'intermediate' artefacts, lets stay consistent and ensure to only use the asymmetrical one, otherwise we have to argue what artefact uses what.

#include "ITStracking/Cell.h"
#include "ITStracking/BoundedAllocator.h"
#include "DataFormatsITS/TimeEstBC.h"
#include "ReconstructionDataFormats/Track.h"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need this header?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants