Skip to content

[PWGHF] Cache prongs propagation in trackIndexSkimCreator - #17906

Merged
fgrosa merged 1 commit into
AliceO2Group:masterfrom
fchinu:ml-based-track-selector
Sep 14, 2026
Merged

fgrosa merged 1 commit into
AliceO2Group:masterfrom
fchinu:ml-based-track-selector

Conversation

@fchinu

@fchinu fchinu commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

While developing #17878, I realised that the CPU time of the track-index skim creator can be reduced significantly by building each track once per collision, reducing the track_as, getTrackParCov calls and, if needed, the propagation to the collision's primary vertex, and reusing it in the pair and triplet loops.
In the tests I did locally on central Pb-Pb data, I see a reduction in CPU time by a factor ~2x:
performanceMetricsCached.json
performanceMetricsDefault.json

@github-actions github-actions Bot added the pwghf PWG-HF label Sep 14, 2026
@github-actions github-actions Bot changed the title Cache prongs propagation in trackIndexSkimCreator [PWGHF] Cache prongs propagation in trackIndexSkimCreator Sep 14, 2026
@github-actions

Copy link
Copy Markdown

O2 linter results: ❌ 0 errors, ⚠️ 8 warnings, 🔕 7 disabled

@vkucera

vkucera commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

Hi @fchinu , thanks for the development. I have a few doubts/questions.

  • I don't see how the caching can help for two-prong candidates where there should be no duplicated calculation.
  • For the three-prong candidates, it seems to me that you are calculating the track properties for all tracks upfront while the current implementation does the calculations only after applying the track selection.

@fchinu

fchinu commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Hi @vkucera, thanks for having a look! I would say that it helps also for 2 prongs, since the two loops are nested, and the negative prong information is extracted once per positive track.

for (auto trackIndexPos1 = groupedTrackIndicesPos1.begin(); trackIndexPos1 != groupedTrackIndicesPos1.end(); ++trackIndexPos1) {
const auto trackPos1 = trackIndexPos1.template track_as<TTracks>();
// retrieve the selection flag that corresponds to this collision
const auto isSelProngPos1 = trackIndexPos1.isSelProng();
const bool sel2ProngStatusPos = TESTBIT(isSelProngPos1, CandidateType::Cand2Prong);
const bool sel3ProngStatusPos1 = TESTBIT(isSelProngPos1, CandidateType::Cand3Prong);
auto trackParVarPos1 = getTrackParCov(trackPos1);
std::array pVecTrackPos1{trackPos1.pVector()};
std::array dcaInfoPos1{trackPos1.dcaXY(), trackPos1.dcaZ()};
if (thisCollId != trackPos1.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it
o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParVarPos1, 2.f, noMatCorr, &dcaInfoPos1);
getPxPyPz(trackParVarPos1, pVecTrackPos1);
}
// first loop over negative tracks
for (auto trackIndexNeg1 = groupedTrackIndicesNeg1.begin(); trackIndexNeg1 != groupedTrackIndicesNeg1.end(); ++trackIndexNeg1) {

Maybe I am missing something? For the 3 prongs, it is true that we calculate everything upfront without applying preselections, but it seems like that calculating the properties only once per collision is faster than once per triplet being built.
One thing worth mentioning is that the tests were ran by considering only Ds and D+, but I have now ran tests with all candidates and only for 2p, and there is an improvement in all the cases:
All channels: default: 3428s, cached: 1938s, ratio: 0.57
2P only: default: 727s cached: 569s, ratio: 0.78
As one would expect, the effect is smaller for 2p, since there is less combinatorics there, and the amount of duplicated work is lower, but in the end we produce derived data also considering 3p, where the effect is larger

@vkucera

vkucera commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

Hi @fchinu , you are right, thanks for the clarification. Indeed, there is also duplication for the negative tracks in the 2-prong loop.
From the graphs, there seems to be no obvious memory increase, even though, AFAIU, you duplicate the grouped track table and the track-collision association table for each collision. If you can validate the output as well, it would be good to go.
Very nice improvement! Thanks again!

@fchinu

fchinu commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Thanks a lot @vkucera for approving the PR! For bookkeeping I write here what we discussed earlier:
The outputs are validated, and show no difference in the tables produced by the track index skim creator. Indeed, it is very nice to see that there is no visible increase in memory consumption, maybe that could be due to how tracks retrieval from the tables is performed in the framework, though I'm not fully sure

@fgrosa
fgrosa enabled auto-merge (squash) September 14, 2026 17:30
@fgrosa
fgrosa merged commit 8d580a4 into AliceO2Group:master Sep 14, 2026
15 of 17 checks passed
@vkucera

vkucera commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

@fgrosa Please don't enable the auto-merge before the tests finish. Now the result of the code check cannot be reported.

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

Labels

pwghf PWG-HF

Development

Successfully merging this pull request may close these issues.

3 participants