From 6a54a0ef2a28f0c509d5f786f761d518ed045ec7 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 8 Sep 2026 14:31:26 +0200 Subject: [PATCH] [Common] Avoid zero-initialising the NN TPC PID prediction buffer The per-DataFrame prediction buffer (masked tracks x output dims x 9 mass hypotheses, ~72 MB for a 1M-track PbPb DataFrame) is a value-initialised std::vector: a full memset touching every page, immediately overwritten in full by the per-hypothesis evaluation loop. Carry it as an uninitialised unique_ptr instead, so each page is touched once, by the write that fills it. All consumers only read it under useNetworkCorrection, so the null buffer with the network disabled is never dereferenced. No change to any computed value. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01DgKXVM9Q9Hcgexfyj7Eqpp --- Common/Tools/PID/pidTPCModule.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index de97ef65eba..5a1362da9ab 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -443,11 +443,8 @@ class pidTPCModule //__________________________________________________ template - std::vector createNetworkPrediction(TCCDB& ccdb, soa::Join const& collisions, M const& mults, T const& tracks, B const& bcs, const size_t size) + std::unique_ptr createNetworkPrediction(TCCDB& ccdb, soa::Join const& collisions, M const& mults, T const& tracks, B const& bcs, const size_t size) { - - std::vector network_prediction; - auto start_network_total = std::chrono::high_resolution_clock::now(); if (pidTPCopts.autofetchNetworks) { const auto& bc = bcs.begin(); @@ -505,7 +502,10 @@ class pidTPCModule const uint64_t track_prop_size = input_dimensions * size; const uint64_t prediction_size = output_dimensions * size; - network_prediction = std::vector(prediction_size * 9); // For each mass hypotheses + // Deliberately uninitialised: the evaluation loop below writes every element + // (one block per mass hypothesis), so zero-initialising would only touch + // every page of an O(100 MB) buffer twice. + std::unique_ptr network_prediction(new float[prediction_size * 9]); // For each mass hypotheses const float nNclNormalization = response->GetNClNormalization(); float duration_network = 0; @@ -624,7 +624,7 @@ class pidTPCModule //__________________________________________________ template - void makePidTables(const int flagFull, NSF& tableFull, const int flagTiny, NST& tableTiny, const o2::track::PID::ID pid, const float tpcSignal, const T& trk, const int64_t multTPC, const std::vector& network_prediction, const int& count_tracks, const int& tracksForNet_size) + void makePidTables(const int flagFull, NSF& tableFull, const int flagTiny, NST& tableTiny, const o2::track::PID::ID pid, const float tpcSignal, const T& trk, const int64_t multTPC, const float* network_prediction, const int& count_tracks, const int& tracksForNet_size) { if (flagFull != 1 && flagTiny != 1) { return; @@ -750,7 +750,7 @@ class pidTPCModule reserveTable(pidTPCopts.pidTinyAl, products.tablePIDTinyAl); const uint64_t tracksForNet_size = (pidTPCopts.skipTPCOnly) ? totalTPCnotStandalone : totalTPCtracks; - std::vector network_prediction; + std::unique_ptr network_prediction; if (pidTPCopts.useNetworkCorrection) { network_prediction = createNetworkPrediction(ccdb, cols, pidmults, tracks, bcs, tracksForNet_size); @@ -951,7 +951,7 @@ class pidTPCModule } auto makePidTablesDefault = [&trk, &tpcSignalToEvaluatePID, &multTPC, &network_prediction, &count_tracks, &tracksForNet_size, this](const int flagFull, auto& tableFull, const int flagTiny, auto& tableTiny, const o2::track::PID::ID pid) { - this->makePidTables(flagFull, tableFull, flagTiny, tableTiny, pid, tpcSignalToEvaluatePID, trk, multTPC, network_prediction, count_tracks, tracksForNet_size); + this->makePidTables(flagFull, tableFull, flagTiny, tableTiny, pid, tpcSignalToEvaluatePID, trk, multTPC, network_prediction.get(), count_tracks, tracksForNet_size); }; makePidTablesDefault(pidTPCopts.pidFullEl, products.tablePIDFullEl, pidTPCopts.pidTinyEl, products.tablePIDTinyEl, o2::track::PID::Electron);