From 837a5ad71acbd77c8576561200188d37d04c9838 Mon Sep 17 00:00:00 2001 From: Breno Orzari Date: Mon, 27 Apr 2026 16:43:47 +0200 Subject: [PATCH] Adding recHit masking to extended pixel tracks --- .../python/allPixelTrackMask_cff.py | 8 + .../python/pixelTrackMask_cff.py | 3 + .../python/upgradeWorkflowComponents.py | 21 + .../TrackSoA/interface/TrackDefinitions.h | 17 + DataFormats/TrackSoA/interface/TracksSoA.h | 4 +- .../interface/TrackingRecHitsDevice.h | 3 + .../interface/TrackingRecHitsHost.h | 2 + .../interface/TrackingRecHitsSoA.h | 6 + .../alpaka/TrackingRecHitsSoACollection.h | 5 + .../src/alpaka/classes_cuda_def.xml | 2 + .../src/alpaka/classes_rocm_def.xml | 2 + DataFormats/TrackingRecHitSoA/src/classes.cc | 1 + .../TrackingRecHitSoA/src/classes_def.xml | 4 + .../plugins/alpaka/PixelRecHitKernel.h | 12 + .../plugins/alpaka/PixelRecHitKernels.dev.cc | 24 ++ .../plugins/alpaka/PixelRecHits.h | 11 + .../alpaka/SiPixelRecHitExtendedAlpaka.cc | 12 +- .../plugins/alpaka/CAHitNtuplet.cc | 20 +- .../plugins/alpaka/CAHitNtupletGenerator.cc | 86 +++- .../plugins/alpaka/CAHitNtupletGenerator.h | 35 ++ .../CAHitNtupletGeneratorKernels.dev.cc | 87 +++- .../alpaka/CAHitNtupletGeneratorKernels.h | 35 +- .../alpaka/CAHitNtupletGeneratorKernelsImpl.h | 136 +++++++ .../plugins/alpaka/CAPixelDoublets.h | 5 +- .../plugins/alpaka/CAPixelDoubletsAlgos.h | 8 +- .../plugins/alpaka/CAStructures.h | 1 + .../plugins/alpaka/PixelTracksMaskingSoA.cc | 89 +++++ .../plugins/alpaka/PixelTracksSoAMerger.cc | 378 ++++++++++++++++++ RecoTracker/PixelSeeding/src/classes_def.xml | 2 + .../PixelTrackProducerFromSoAAlpaka.cc | 15 + .../python/PixelTracks_cff.py | 150 +++++++ .../RecoTrack/python/TrackValidation_cff.py | 50 +++ 32 files changed, 1218 insertions(+), 16 deletions(-) create mode 100644 Configuration/ProcessModifiers/python/allPixelTrackMask_cff.py create mode 100644 Configuration/ProcessModifiers/python/pixelTrackMask_cff.py create mode 100644 RecoTracker/PixelSeeding/plugins/alpaka/PixelTracksMaskingSoA.cc create mode 100644 RecoTracker/PixelSeeding/plugins/alpaka/PixelTracksSoAMerger.cc diff --git a/Configuration/ProcessModifiers/python/allPixelTrackMask_cff.py b/Configuration/ProcessModifiers/python/allPixelTrackMask_cff.py new file mode 100644 index 0000000000000..4cf737f31cccd --- /dev/null +++ b/Configuration/ProcessModifiers/python/allPixelTrackMask_cff.py @@ -0,0 +1,8 @@ +import FWCore.ParameterSet.Config as cms + +from Configuration.ProcessModifiers.alpaka_cff import alpaka +from Configuration.ProcessModifiers.pixelTrackMask_cff import pixelTrackMask +from Configuration.ProcessModifiers.phase2CAExtension_cff import phase2CAExtension + +# collect all PixelTrackMask-related process modifiers here +allPixelTrackMask = cms.ModifierChain(alpaka,pixelTrackMask,phase2CAExtension) diff --git a/Configuration/ProcessModifiers/python/pixelTrackMask_cff.py b/Configuration/ProcessModifiers/python/pixelTrackMask_cff.py new file mode 100644 index 0000000000000..e45f7604c7321 --- /dev/null +++ b/Configuration/ProcessModifiers/python/pixelTrackMask_cff.py @@ -0,0 +1,3 @@ +import FWCore.ParameterSet.Config as cms + +pixelTrackMask = cms.Modifier() diff --git a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py index 24aa47cd0de7e..218e1bd8f4ad0 100644 --- a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py +++ b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py @@ -1513,6 +1513,27 @@ def setup_(self, step, stepName, stepDict, k, properties): offset = 0.4021, ) +# Pixel-only quadruplets with CA Extension and recHit masking workflow running on GPU (optional) +# - Pixel-only with CA Extension and recHit masking reconstruction with Alpaka, with DQM and validation +# - harvesting + +upgradeWFs['PatatrackPixelOnlyAlpakaCAExtensionMask'] = PatatrackWorkflow( + digi = { + '--procModifiers': 'allPixelTrackMask', + '--customise' : 'HeterogeneousCore/AlpakaServices/customiseAlpakaServiceMemoryFilling.customiseAlpakaServiceMemoryFilling', + }, + reco = { + '-s': 'RAW2DIGI:RawToDigi_pixelOnly,RECO:reconstruction_pixelTrackingOnly,VALIDATION:@pixelTrackingOnlyValidation,DQM:@pixelTrackingOnlyDQM', + '--procModifiers': 'allPixelTrackMask', + '--customise' : 'HeterogeneousCore/AlpakaServices/customiseAlpakaServiceMemoryFilling.customiseAlpakaServiceMemoryFilling', + }, + harvest = { + '-s': 'HARVESTING:@trackingOnlyValidation+@pixelTrackingOnlyDQM' + }, + suffix = 'Patatrack_PixelOnlyAlpakaCAExtensionMask', + offset = 0.4022, +) + # Pixel-only quadruplets workflow running on GPU (optional) # - Pixel-only reconstruction with Alpaka, with standard and CPUvsGPU DQM and validation # - harvesting for CPUvsGPU validation diff --git a/DataFormats/TrackSoA/interface/TrackDefinitions.h b/DataFormats/TrackSoA/interface/TrackDefinitions.h index 56a30bec35dcf..0573002eddce4 100644 --- a/DataFormats/TrackSoA/interface/TrackDefinitions.h +++ b/DataFormats/TrackSoA/interface/TrackDefinitions.h @@ -20,6 +20,23 @@ namespace pixelTrack { return ret; } + enum class Iteration : uint8_t { + promptHighPt, + promptLowPt, + notIteration + }; // Not sure if a notIteration will be needed + constexpr uint32_t iterationSize{uint8_t(Iteration::notIteration)}; + constexpr std::string_view iterationName[iterationSize]{"promptHighPt", "promptLowPt"}; + inline Iteration iterationByName(std::string_view name) { + auto qp = std::find(iterationName, iterationName + iterationSize, name) - iterationName; + auto ret = static_cast(qp); + + if (ret == pixelTrack::Iteration::notIteration) + throw std::invalid_argument(std::string(name) + " is not a pixelTrack::Iteration!"); + + return ret; + } + #ifdef GPU_SMALL_EVENTS // kept for testing and debugging constexpr uint32_t maxNumber() { return 2 * 1024; } diff --git a/DataFormats/TrackSoA/interface/TracksSoA.h b/DataFormats/TrackSoA/interface/TracksSoA.h index b0656a437abe0..fe03d617f91aa 100644 --- a/DataFormats/TrackSoA/interface/TracksSoA.h +++ b/DataFormats/TrackSoA/interface/TracksSoA.h @@ -18,6 +18,7 @@ namespace reco { using Vector5f = Eigen::Matrix; using Vector15f = Eigen::Matrix; using Quality = pixelTrack::Quality; + using Iteration = pixelTrack::Iteration; GENERATE_SOA_LAYOUT(TrackLayout, SOA_COLUMN(Quality, quality), @@ -29,7 +30,8 @@ namespace reco { SOA_EIGEN_COLUMN(Vector5f, state), SOA_EIGEN_COLUMN(Vector15f, covariance), SOA_SCALAR(int, nTracks), - SOA_COLUMN(uint32_t, hitOffsets)) + SOA_COLUMN(uint32_t, hitOffsets), + SOA_COLUMN(Iteration, iteration)) GENERATE_SOA_LAYOUT(TrackHitsLayout, SOA_COLUMN(uint32_t, id), SOA_COLUMN(uint32_t, detId)) diff --git a/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsDevice.h b/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsDevice.h index 15c41d6aa5de8..19158695b3c56 100644 --- a/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsDevice.h +++ b/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsDevice.h @@ -20,6 +20,9 @@ namespace reco { template using HitPortableCollectionDevice = PortableDeviceCollection; + template + using TrackingRecHitsMaskingDevice = PortableDeviceCollection; + template class TrackingRecHitDevice : public HitPortableCollectionDevice { public: diff --git a/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsHost.h b/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsHost.h index c0f388b2ce228..0163ecb84950a 100644 --- a/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsHost.h +++ b/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsHost.h @@ -20,6 +20,8 @@ namespace reco { using HitPortableCollectionHost = PortableHostCollection; + using TrackingRecHitsMaskingHost = PortableHostCollection; + class TrackingRecHitHost : public HitPortableCollectionHost { public: explicit TrackingRecHitHost(edm::Uninitialized) diff --git a/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsSoA.h b/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsSoA.h index e3cffcd9f089b..1531c5bd34e03 100644 --- a/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsSoA.h +++ b/DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsSoA.h @@ -49,6 +49,8 @@ namespace reco { SOA_SCALAR(int32_t, endCapZPos), SOA_SCALAR(int32_t, endCapZNeg)) + GENERATE_SOA_LAYOUT(TrackingRecHitsMaskingLayout, SOA_COLUMN(uint32_t, recHitMask)); + using TrackingRecHitSoA = TrackingHitsLayout<>; using TrackingRecHitView = TrackingRecHitSoA::View; using TrackingRecHitConstView = TrackingRecHitSoA::ConstView; @@ -65,6 +67,10 @@ namespace reco { using AverageGeometryView = AverageGeometrySoA::View; using AverageGeometryConstView = AverageGeometrySoA::ConstView; + using TrackingRecHitsMaskingSoA = TrackingRecHitsMaskingLayout<>; + using TrackingRecHitsMaskingView = TrackingRecHitsMaskingSoA::View; + using TrackingRecHitsMaskingConstView = TrackingRecHitsMaskingSoA::ConstView; + }; // namespace reco #endif diff --git a/DataFormats/TrackingRecHitSoA/interface/alpaka/TrackingRecHitsSoACollection.h b/DataFormats/TrackingRecHitSoA/interface/alpaka/TrackingRecHitsSoACollection.h index 2de8024bbb2d4..f6ec43b0f3f00 100644 --- a/DataFormats/TrackingRecHitSoA/interface/alpaka/TrackingRecHitsSoACollection.h +++ b/DataFormats/TrackingRecHitSoA/interface/alpaka/TrackingRecHitsSoACollection.h @@ -23,6 +23,10 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE::reco { using TrackingRecHitsSoACollection = std::conditional_t, ::reco::TrackingRecHitHost, ::reco::TrackingRecHitDevice>; + + using TrackingRecHitsMaskingCollection = std::conditional_t, + ::reco::TrackingRecHitsMaskingHost, + ::reco::TrackingRecHitsMaskingDevice>; } // namespace ALPAKA_ACCELERATOR_NAMESPACE::reco namespace cms::alpakatools { @@ -87,5 +91,6 @@ namespace cms::alpakatools { } // namespace cms::alpakatools ASSERT_DEVICE_MATCHES_HOST_COLLECTION(reco::TrackingRecHitsSoACollection, reco::TrackingRecHitHost); +ASSERT_DEVICE_MATCHES_HOST_COLLECTION(reco::TrackingRecHitsMaskingCollection, reco::TrackingRecHitsMaskingHost); #endif // DataFormats_TrackingRecHitSoA_interface_alpaka_TrackingRecHitsSoACollection_h diff --git a/DataFormats/TrackingRecHitSoA/src/alpaka/classes_cuda_def.xml b/DataFormats/TrackingRecHitSoA/src/alpaka/classes_cuda_def.xml index 95532fe05d10d..f5ecace84c7e4 100644 --- a/DataFormats/TrackingRecHitSoA/src/alpaka/classes_cuda_def.xml +++ b/DataFormats/TrackingRecHitSoA/src/alpaka/classes_cuda_def.xml @@ -2,5 +2,7 @@ + + diff --git a/DataFormats/TrackingRecHitSoA/src/alpaka/classes_rocm_def.xml b/DataFormats/TrackingRecHitSoA/src/alpaka/classes_rocm_def.xml index 2aa4145b5dd88..c4f6bb31aa1bc 100644 --- a/DataFormats/TrackingRecHitSoA/src/alpaka/classes_rocm_def.xml +++ b/DataFormats/TrackingRecHitSoA/src/alpaka/classes_rocm_def.xml @@ -2,5 +2,7 @@ + + diff --git a/DataFormats/TrackingRecHitSoA/src/classes.cc b/DataFormats/TrackingRecHitSoA/src/classes.cc index 06ad17217cbaf..806aa94b049ed 100644 --- a/DataFormats/TrackingRecHitSoA/src/classes.cc +++ b/DataFormats/TrackingRecHitSoA/src/classes.cc @@ -2,3 +2,4 @@ #include "DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsHost.h" SET_PORTABLEHOSTCOLLECTION_READ_RULES(reco::HitPortableCollectionHost); +SET_PORTABLEHOSTCOLLECTION_READ_RULES(reco::TrackingRecHitsMaskingHost); diff --git a/DataFormats/TrackingRecHitSoA/src/classes_def.xml b/DataFormats/TrackingRecHitSoA/src/classes_def.xml index b05698402834d..d8928fc1ef2b1 100644 --- a/DataFormats/TrackingRecHitSoA/src/classes_def.xml +++ b/DataFormats/TrackingRecHitSoA/src/classes_def.xml @@ -12,4 +12,8 @@ + + + + diff --git a/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHitKernel.h b/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHitKernel.h index a36b3a065abc6..5e2853b7abff4 100644 --- a/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHitKernel.h +++ b/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHitKernel.h @@ -39,6 +39,18 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { ParamsOnDevice const* cpeParams, Queue queue) const; }; + class PixelRecHitMaskingKernel { + public: + PixelRecHitMaskingKernel() = default; + ~PixelRecHitMaskingKernel() = default; + + PixelRecHitMaskingKernel(const PixelRecHitMaskingKernel&) = delete; + PixelRecHitMaskingKernel(PixelRecHitMaskingKernel&&) = delete; + PixelRecHitMaskingKernel& operator=(const PixelRecHitMaskingKernel&) = delete; + PixelRecHitMaskingKernel& operator=(PixelRecHitMaskingKernel&&) = delete; + + reco::TrackingRecHitsMaskingCollection makeHitsMaskingAsync(uint32_t const nHits, Queue queue) const; + }; } // namespace pixelgpudetails } // namespace ALPAKA_ACCELERATOR_NAMESPACE diff --git a/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHitKernels.dev.cc b/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHitKernels.dev.cc index 17c920ea5e6fb..2b7c3e9798767 100644 --- a/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHitKernels.dev.cc +++ b/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHitKernels.dev.cc @@ -78,6 +78,30 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { return hits_d; } + TrackingRecHitsMaskingCollection PixelRecHitMaskingKernel::makeHitsMaskingAsync(uint32_t const nHits, + Queue queue) const { + using namespace pixelRecHits; + + TrackingRecHitsMaskingCollection mask_d(queue, nHits); + + int threadsPerBlock = 128; + int blocks = cms::alpakatools::divide_up_by(nHits, threadsPerBlock); + const auto workDiv1D = cms::alpakatools::make_workdiv(blocks, threadsPerBlock); + +#ifdef GPU_DEBUG + std::cout << "launching LaunchZerosPixelMask kernel on " << alpaka::core::demangled << " with " << blocks + << " blocks" << std::endl; +#endif + alpaka::exec(queue, workDiv1D, LaunchZerosPixelMask{}, mask_d.view()); + +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "makeHitsMaskingAsync -> DONE!" << std::endl; +#endif + + return mask_d; + } + template class PixelRecHitKernel; template class PixelRecHitKernel; template class PixelRecHitKernel; diff --git a/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHits.h b/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHits.h index 4dfdea37fdc85..4077e34f89c13 100644 --- a/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHits.h +++ b/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/PixelRecHits.h @@ -220,6 +220,17 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { } }; + class LaunchZerosPixelMask { + public: + ALPAKA_FN_ACC void operator()(Acc1D const& acc, ::reco::TrackingRecHitsMaskingView mask) const { + for (uint32_t ic : cms::alpakatools::independent_group_elements(acc, mask.metadata().size())) { + assert(ic < (uint32_t)mask.metadata().size()); + mask[ic].recHitMask() = 0; + } + alpaka::syncBlockThreads(acc); + } + }; + } // namespace pixelRecHits } // namespace ALPAKA_ACCELERATOR_NAMESPACE diff --git a/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/SiPixelRecHitExtendedAlpaka.cc b/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/SiPixelRecHitExtendedAlpaka.cc index 011332f056cee..ecb044e6b2134 100644 --- a/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/SiPixelRecHitExtendedAlpaka.cc +++ b/RecoLocalTracker/SiPixelRecHits/plugins/alpaka/SiPixelRecHitExtendedAlpaka.cc @@ -23,6 +23,8 @@ #include "RecoLocalTracker/SiPixelRecHits/interface/alpaka/PixelCPEFastParamsCollection.h" #include "RecoLocalTracker/SiPixelRecHits/interface/pixelCPEforDevice.h" +#include "PixelRecHitKernel.h" + //#define GPU_DEBUG namespace ALPAKA_ACCELERATOR_NAMESPACE { @@ -41,13 +43,17 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { const device::EDGetToken trackerRecHitToken_; const device::EDPutToken outputRecHitsSoAToken_; + const device::EDPutToken outputRecHitsMaskToken_; + + const pixelgpudetails::PixelRecHitMaskingKernel Algo_; }; SiPixelRecHitExtendedAlpaka::SiPixelRecHitExtendedAlpaka(const edm::ParameterSet& iConfig) : EDProducer(iConfig), pixelRecHitToken_(consumes(iConfig.getParameter("pixelRecHitsSoA"))), trackerRecHitToken_(consumes(iConfig.getParameter("trackerRecHitsSoA"))), - outputRecHitsSoAToken_(produces()) {} + outputRecHitsSoAToken_(produces()), + outputRecHitsMaskToken_(produces()) {} void SiPixelRecHitExtendedAlpaka::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { edm::ParameterSetDescription desc; @@ -185,6 +191,10 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { // emplace the merged SoA collection in the event iEvent.emplace(outputRecHitsSoAToken_, std::move(output)); + + // create masking vector with zeros and emplace in the event + iEvent.emplace(outputRecHitsMaskToken_, + Algo_.makeHitsMaskingAsync(static_cast(output.nHits()), iEvent.queue())); } } // namespace ALPAKA_ACCELERATOR_NAMESPACE diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtuplet.cc b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtuplet.cc index 729247ed9718d..a52138e2e4cec 100644 --- a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtuplet.cc +++ b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtuplet.cc @@ -102,6 +102,8 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { using HitsOnDevice = reco::TrackingRecHitsSoACollection; using HitsOnHost = ::reco::TrackingRecHitHost; + using MapToHit = reco::TrackingRecHitsMaskingCollection; + using TkSoAHost = ::reco::TracksHost; using TkSoADevice = reco::TracksSoACollection; @@ -331,10 +333,13 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { const edm::ESGetToken tokenField_; const device::EDGetToken tokenHit_; const device::EDPutToken tokenTrack_; + const device::EDGetToken tokenHitMask_; const ::reco::FormulaEvaluator maxNumberOfDoublets_; const ::reco::FormulaEvaluator maxNumberOfTuples_; + const pixelTrack::Iteration iterationName_; + Algo deviceAlgo_; }; @@ -345,8 +350,10 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { tokenField_(esConsumes()), tokenHit_(consumes(iConfig.getParameter("pixelRecHitSrc"))), tokenTrack_(produces()), + tokenHitMask_(consumes(iConfig.getParameter("hitMask"))), maxNumberOfDoublets_(iConfig.getParameter("maxNumberOfDoublets")), maxNumberOfTuples_(iConfig.getParameter("maxNumberOfTuples")), + iterationName_(pixelTrack::iterationByName(iConfig.getParameter("iterationName"))), deviceAlgo_(iConfig) { iCache->tokenGeometry_ = esConsumes(); iCache->tokenTopology_ = esConsumes(); @@ -357,6 +364,14 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { edm::ParameterSetDescription desc; desc.add("pixelRecHitSrc", edm::InputTag("siPixelRecHitsPreSplittingAlpaka")); + desc.add( + "hitMask", + edm::InputTag( + "hltPhase2PixelRecHitsExtendedSoA")); // This is just an example, it has to be changed for each tracking iteration + // Set as the HLT module to not modify the HLT menu + desc.add( + "iterationName", + std::string("promptHighPt")); // This is just an example, it has to be changed for each tracking iteration Algo::fillPSetDescription(desc); descriptions.addWithDefaultLabel(desc); @@ -381,8 +396,11 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { uint32_t const maxTuples = maxNumberOfTuples_.evaluate(nHitsV, emptyV); uint32_t const maxDoublets = maxNumberOfDoublets_.evaluate(nHitsV, emptyV); + auto const& mask = iEvent.get(tokenHitMask_); + iEvent.emplace(tokenTrack_, - deviceAlgo_.makeTuplesAsync(hits, geometry, bf, maxDoublets, maxTuples, iEvent.queue())); + deviceAlgo_.makeTuplesAsync( + hits, geometry, bf, maxDoublets, maxTuples, mask, iterationName_, iEvent.queue())); } else { edm::LogWarning("CAHitNtupletAlpaka") << "No hit on BPix1 (" << hits.offsetBPIX2() diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGenerator.cc b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGenerator.cc index 74a807924fa2a..dd18bb78b836a 100644 --- a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGenerator.cc +++ b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGenerator.cc @@ -382,12 +382,15 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { } template - reco::TracksSoACollection CAHitNtupletGenerator::makeTuplesAsync(HitsOnDevice const& hits_d, - CAGeometryOnDevice const& geometry_d, - float bfield, - uint32_t nDoublets, - uint32_t nTracks, - Queue& queue) const { + reco::TracksSoACollection CAHitNtupletGenerator::makeTuplesAsync( + HitsOnDevice const& hits_d, + CAGeometryOnDevice const& geometry_d, + float bfield, + uint32_t nDoublets, + uint32_t nTracks, + MapToHit const& mask, + const pixelTrack::Iteration iterationName, + Queue& queue) const { using HelixFit = HelixFit; using GPUKernels = CAHitNtupletGeneratorKernels; using TrackHitSoA = ::reco::TrackHitSoA; @@ -417,7 +420,7 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { m_params, hits_d.nHits(), hits_d.offsetBPIX2(), nDoublets, nTracks, layers.metadata().size(), queue); kernels.prepareHits(trackingHits, hitModules, layers, queue); - kernels.buildDoublets(trackingHits, graph, layers, hits_d.offsetBPIX2(), queue); + kernels.buildDoublets(trackingHits, graph, layers, hits_d.offsetBPIX2(), mask.view(), queue); kernels.launchKernels( trackingHits, hits_d.offsetBPIX2(), layers.metadata().size(), trackCollection.view(), layers, graph, queue); @@ -430,7 +433,7 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { fitter.launchBrokenLineKernels( trackingHits, modules, trackingHits.metadata().size(), TrackerTraits::maxNumberOfQuadruplets, queue); } - kernels.classifyTuples(trackingHits, tracks, queue); + kernels.classifyTuples(trackingHits, tracks, iterationName, queue); #ifdef GPU_DEBUG alpaka::wait(queue); std::cout << "finished building pixel tracks on GPU" << std::endl; @@ -439,6 +442,73 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { return trackCollection; } + reco::TrackingRecHitsMaskingCollection CAHitMaskingAndMerger::makeMaskingAsync(MapToHit const& mask_d, + TkSoADevice const& tracks_d, + const pixelTrack::Quality minQuality, + uint32_t const& iterationIndex, + Queue& queue) const { + const int nHits = mask_d.view().metadata().size(); + + reco::TrackingRecHitsMaskingCollection mask(queue, static_cast(nHits)); + + alpaka::memcpy(queue, + cms::alpakatools::make_device_view(queue, mask.view().recHitMask(), nHits), + cms::alpakatools::make_device_view(queue, mask_d.view().recHitMask(), nHits)); + + CAHitMaskingAndMergerKernels kernels; + + auto tracksd_view = tracks_d.view().tracks(); + auto tracks_hitsd_view = tracks_d.view().trackHits(); + + kernels.updateMasking(mask.view(), tracksd_view, tracks_hitsd_view, minQuality, iterationIndex, queue); +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "finished updating pixel masking on GPU" << std::endl; +#endif + + return mask; + } + + void CAHitMaskingAndMerger::updateHitOffsets( + int const& tksBeg, int const& tksEnd, int const& nHits, TkSoADevice& tracks_d, Queue& queue) const { + CAHitMaskingAndMergerKernels kernels; + + auto tracksd_view = tracks_d.view().tracks(); + + kernels.updateHitOffsets(tksBeg, tksEnd, nHits, tracksd_view, queue); +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "finished updating track SoAs hit offsets on GPU" << std::endl; +#endif + + return; + } + + reco::TracksSoACollection CAHitMaskingAndMerger::makeFilteredTracks(int const& nTracks, + int const& nHits, + TkSoADevice const& inpTracks, + pixelTrack::Quality const& minQuality, + double const& matchFraction, + Queue& queue) const { + CAHitMaskingAndMergerKernels kernels; + + reco::TracksSoACollection tracks(queue, nTracks, nHits); + + auto tracksd_view = tracks.view().tracks(); + auto tracks_hitsd_view = tracks.view().trackHits(); + auto inptracksd_view = inpTracks.view().tracks(); + auto inptracks_hitsd_view = inpTracks.view().trackHits(); + + kernels.filterTracks( + tracksd_view, tracks_hitsd_view, inptracksd_view, inptracks_hitsd_view, minQuality, matchFraction, queue); +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "finished filtering track SoAs on GPU" << std::endl; +#endif + + return tracks; + } + template class CAHitNtupletGenerator; template class CAHitNtupletGenerator; template class CAHitNtupletGenerator; diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGenerator.h b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGenerator.h index efffa56aaddc6..5097cfd7e0e68 100644 --- a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGenerator.h +++ b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGenerator.h @@ -34,6 +34,8 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { using HitsOnDevice = reco::TrackingRecHitsSoACollection; using HitsOnHost = ::reco::TrackingRecHitHost; + using MapToHit = reco::TrackingRecHitsMaskingCollection; + using TkSoADevice = reco::TracksSoACollection; using Quality = ::pixelTrack::Quality; @@ -61,12 +63,45 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { float bfield, uint32_t maxDoublets, uint32_t maxTuples, + MapToHit const& mask, + const pixelTrack::Iteration iterationName, Queue& queue) const; private: Params m_params; }; + class CAHitMaskingAndMerger { + public: + using MapToHit = reco::TrackingRecHitsMaskingCollection; + using TkSoADevice = reco::TracksSoACollection; + + public: + CAHitMaskingAndMerger() = default; + ~CAHitMaskingAndMerger() = default; + + CAHitMaskingAndMerger(const CAHitMaskingAndMerger&) = delete; + CAHitMaskingAndMerger(CAHitMaskingAndMerger&&) = delete; + CAHitMaskingAndMerger& operator=(const CAHitMaskingAndMerger&) = delete; + CAHitMaskingAndMerger& operator=(CAHitMaskingAndMerger&&) = delete; + + MapToHit makeMaskingAsync(MapToHit const& mask_d, + TkSoADevice const& tracks_d, + const pixelTrack::Quality minQuality, + uint32_t const& iterationIndex, + Queue& queue) const; + + void updateHitOffsets( + int const& tksBeg, int const& tksEnd, int const& nHits, TkSoADevice& tracks_d, Queue& queue) const; + + TkSoADevice makeFilteredTracks(int const& nTracks, + int const& nHits, + TkSoADevice const& inpTracks, + pixelTrack::Quality const& minQuality, + double const& matchFraction, + Queue& queue) const; + }; + } // namespace ALPAKA_ACCELERATOR_NAMESPACE #endif // RecoTracker_PixelSeeding_plugins_alpaka_CAHitNtupletGenerator_h diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernels.dev.cc b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernels.dev.cc index c0b100414eb67..7a68a76a82ea1 100644 --- a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernels.dev.cc +++ b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernels.dev.cc @@ -481,6 +481,7 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { const ::reco::CAGraphSoAConstView &cc, const ::reco::CALayersSoAConstView &ll, uint32_t offsetBPIX2, + const MapToHitConstView &maskPtr, Queue &queue) { using namespace caPixelDoublets; using namespace caHitNtupletGeneratorKernels; @@ -521,7 +522,8 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { this->device_layerStarts_->data(), this->device_hitPhiHist_->data(), this->device_hitToCell_->data(), - this->m_params.algoParams_); + this->m_params.algoParams_, + maskPtr); HitToCell::template launchFinalize(this->device_hitToCellView_, queue); @@ -551,6 +553,7 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { template void CAHitNtupletGeneratorKernels::classifyTuples(const HitsConstView &hh, TkSoAView &tracks_view, + pixelTrack::Iteration const iterationName, Queue &queue) { using namespace caHitNtupletGeneratorKernels; @@ -578,6 +581,13 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { std::cout << "Kernel_classifyTracks -> done!" << std::endl; #endif + alpaka::exec( + queue, workDiv1D, Kernel_assignIteration{}, tracks_view, this->device_hitContainer_->data(), iterationName); +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Kernel_assignIteration -> done!" << std::endl; +#endif + if (this->m_params.algoParams_.lateFishbone_) { // apply fishbone cleaning to good tracks numberOfBlocks = cms::alpakatools::divide_up_by(3 * maxDoublets / 4, blockSize); @@ -794,6 +804,81 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { #endif } + void CAHitMaskingAndMergerKernels::updateMasking(::reco::TrackingRecHitsMaskingView &mask_view, + const ::reco::TrackSoAConstView &trackd_view, + const ::reco::TrackHitSoAConstView &trackhitd_view, + const pixelTrack::Quality minQuality, + uint32_t const &iterationIndex, + Queue &queue) { + using namespace caHitNtupletGeneratorKernels; + +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Starting CAHitMaskingAndMergerKernels::updateMasking" << std::endl; +#endif + + int threadsPerBlock = 128; + int blocks = int((trackd_view.metadata().size() + threadsPerBlock - 1) / threadsPerBlock); + const auto workDiv1D = cms::alpakatools::make_workdiv(blocks, threadsPerBlock); + alpaka::exec( + queue, workDiv1D, Kernel_updateMasking{}, mask_view, trackd_view, trackhitd_view, minQuality, iterationIndex); +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Kernel_updateMasking -> done!" << std::endl; +#endif + } + + void CAHitMaskingAndMergerKernels::updateHitOffsets( + int const &tksBeg, int const &tksEnd, int const &nHits, ::reco::TrackSoAView &trackd_view, Queue &queue) { + using namespace caHitNtupletGeneratorKernels; + +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Starting CAHitMaskingAndMergerKernels::updateHitOffsets" << std::endl; +#endif + + int threadsPerBlock = 1; + int blocks = 1; + const auto workDiv1D = cms::alpakatools::make_workdiv(blocks, threadsPerBlock); + alpaka::exec(queue, workDiv1D, Kernel_updateHitOffsets{}, tksBeg, tksEnd, nHits, trackd_view); +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Kernel_updateHitOffsets -> done!" << std::endl; +#endif + } + + void CAHitMaskingAndMergerKernels::filterTracks(::reco::TrackSoAView &track_view, + ::reco::TrackHitSoAView &trackHit_view, + const ::reco::TrackSoAConstView &inpTrack_view, + const ::reco::TrackHitSoAConstView &inpTrackHit_view, + const pixelTrack::Quality minQuality, + const double matchFraction, + Queue &queue) { + using namespace caHitNtupletGeneratorKernels; + +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Starting CAHitMaskingAndMergerKernels::filterTracks" << std::endl; +#endif + + int threadsPerBlock = 128; + int blocks = inpTrack_view.metadata().size(); + const auto workDiv1D = cms::alpakatools::make_workdiv(blocks, threadsPerBlock); + alpaka::exec(queue, + workDiv1D, + Kernel_filterTracks{}, + track_view, + trackHit_view, + inpTrack_view, + inpTrackHit_view, + minQuality, + matchFraction); +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Kernel_filterTracks -> done!" << std::endl; +#endif + } + /* This will make sense when we will be able to run this once per job in Alpaka template diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernels.h b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernels.h index b973cadccb97f..7c27871d938e6 100644 --- a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernels.h +++ b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernels.h @@ -168,12 +168,16 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { const ::reco::CAGraphSoAConstView& cc, Queue& queue); - void classifyTuples(const HitsConstView& hh, TkSoAView& track_view, Queue& queue); + void classifyTuples(const HitsConstView& hh, + TkSoAView& track_view, + const pixelTrack::Iteration iterationName, + Queue& queue); void buildDoublets(const HitsConstView& hh, const ::reco::CAGraphSoAConstView& cc, const ::reco::CALayersSoAConstView& ll, uint32_t offsetBPIX2, + const MapToHitConstView& maskView, Queue& queue); static void printCounters(); @@ -242,6 +246,35 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE { uint32_t maxNumberOfDoublets_; }; + class CAHitMaskingAndMergerKernels { + public: + CAHitMaskingAndMergerKernels() = default; + ~CAHitMaskingAndMergerKernels() = default; + + CAHitMaskingAndMergerKernels(const CAHitMaskingAndMergerKernels&) = delete; + CAHitMaskingAndMergerKernels(CAHitMaskingAndMergerKernels&&) = delete; + CAHitMaskingAndMergerKernels& operator=(const CAHitMaskingAndMergerKernels&) = delete; + CAHitMaskingAndMergerKernels& operator=(CAHitMaskingAndMergerKernels&&) = delete; + + void updateMasking(::reco::TrackingRecHitsMaskingView& mask_view, + const ::reco::TrackSoAConstView& trackd_view, + const ::reco::TrackHitSoAConstView& trackhitd_view, + const pixelTrack::Quality minQuality, + uint32_t const& iterationIndex, + Queue& queue); + + void updateHitOffsets( + int const& tksBeg, int const& tksEnd, int const& nHits, ::reco::TrackSoAView& trackd_view, Queue& queue); + + void filterTracks(::reco::TrackSoAView& track_view, + ::reco::TrackHitSoAView& trackHit_view, + const ::reco::TrackSoAConstView& inpTrack_view, + const ::reco::TrackHitSoAConstView& inpTrackHit_view, + const pixelTrack::Quality minQuality, + const double matchFraction, + Queue& queue); + }; + } // namespace ALPAKA_ACCELERATOR_NAMESPACE #endif // RecoTracker_PixelSeeding_plugins_alpaka_CAHitNtupletGeneratorKernels_h diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernelsImpl.h b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernelsImpl.h index 83ecaec41e3f3..15c43f93088a8 100644 --- a/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernelsImpl.h +++ b/RecoTracker/PixelSeeding/plugins/alpaka/CAHitNtupletGeneratorKernelsImpl.h @@ -646,6 +646,142 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE::caHitNtupletGeneratorKernels { } }; + class Kernel_assignIteration { + public: + ALPAKA_FN_ACC void operator()(Acc1D const &acc, + TkSoAView tracks_view, + HitContainer const *__restrict__ foundNtuplets, + pixelTrack::Iteration iterationName) const { + for (auto it : cms::alpakatools::uniform_elements(acc, foundNtuplets->nOnes())) { + tracks_view[it].iteration() = iterationName; + } + } + }; + + class Kernel_updateMasking { + public: + ALPAKA_FN_ACC void operator()(Acc1D const &acc, + ::reco::TrackingRecHitsMaskingView mask_view, + const ::reco::TrackSoAConstView &trackd_view, + const ::reco::TrackHitSoAConstView &trackhitd_view, + const pixelTrack::Quality minQuality, + uint32_t const &iterationIndex) const { + if (alpaka::getIdx(acc)[0] == 0) { + int getHit = 0; + for (int j = 0; j < int(trackd_view.nTracks()); ++j) { + getHit = getHit + ::reco::nHits(trackd_view, j); + + if (trackd_view[j].quality() < minQuality) + continue; + + for (uint32_t k = 0; k < uint32_t(::reco::nHits(trackd_view, j)); ++k) { + mask_view[trackhitd_view[getHit - k - 1].id()].recHitMask() = iterationIndex; + } + } + } + } + }; + + class Kernel_updateHitOffsets { + public: + ALPAKA_FN_ACC void operator()(Acc1D const &acc, + int const &tksBeg, + int const &tksEnd, + int const &nHits, + ::reco::TrackSoAView trackd_view) const { + if (alpaka::getIdx(acc)[0] == 0) { + for (int i = tksBeg; i < tksEnd; ++i) { + trackd_view[i].hitOffsets() += nHits; + } + } + alpaka::syncBlockThreads(acc); + } + }; + + class Kernel_filterTracks { + public: + ALPAKA_FN_ACC void operator()(Acc1D const &acc, + ::reco::TrackSoAView track_view, + ::reco::TrackHitSoAView trackHit_view, + const ::reco::TrackSoAConstView &inpTrack_view, + const ::reco::TrackHitSoAConstView &inpTrackHit_view, + const pixelTrack::Quality minQuality, + const double matchFraction) const { + if (alpaka::getIdx(acc)[0] == 0) { + uint32_t auxOutputTkIndex = 0; + uint32_t auxOutputHitIndex = 0; + + for (uint32_t i = 0; i < uint32_t(inpTrack_view.metadata().size()); ++i) { + if (inpTrack_view[i].quality() < minQuality) + continue; + + bool hasDuplicate = false; + for (uint32_t j : cms::alpakatools::uniform_elements_x(acc, inpTrack_view.metadata().size())) { + if (j < i + 1) + continue; + if (inpTrack_view[j].quality() < minQuality) + continue; + + if (::reco::nHits(inpTrack_view, i) == ::reco::nHits(inpTrack_view, j)) { + uint32_t matchedHits = 0; + for (uint32_t k = 0; k < uint32_t(::reco::nHits(inpTrack_view, i)); ++k) { + uint32_t auxHitOffsetsId = 0; + if (i > 0) + auxHitOffsetsId = inpTrack_view[i - 1].hitOffsets(); + if (inpTrackHit_view[auxHitOffsetsId + k].id() == + inpTrackHit_view[inpTrack_view[j - 1].hitOffsets() + k].id()) + ++matchedHits; + } + if (double(matchedHits) / double(::reco::nHits(inpTrack_view, i)) > matchFraction) + hasDuplicate = true; + } + + if (hasDuplicate) + break; + } + alpaka::syncBlockThreads(acc); + + if (hasDuplicate) + continue; + + track_view[auxOutputTkIndex].quality() = inpTrack_view[i].quality(); + track_view[auxOutputTkIndex].chi2() = inpTrack_view[i].chi2(); + track_view[auxOutputTkIndex].nLayers() = inpTrack_view[i].nLayers(); + track_view[auxOutputTkIndex].eta() = inpTrack_view[i].eta(); + track_view[auxOutputTkIndex].pt() = inpTrack_view[i].pt(); + for (uint32_t k = 0; k < 5; ++k) + track_view[auxOutputTkIndex].state()[k] = inpTrack_view[i].state()[k]; + for (uint32_t k = 0; k < 15; ++k) + track_view[auxOutputTkIndex].covariance()[k] = inpTrack_view[i].covariance()[k]; + if (auxOutputTkIndex != 0) { + track_view[auxOutputTkIndex].hitOffsets() = + track_view[auxOutputTkIndex - 1].hitOffsets() + ::reco::nHits(inpTrack_view, i); + } else { + track_view[auxOutputTkIndex].hitOffsets() = ::reco::nHits(inpTrack_view, i); + } + + uint32_t auxHitOffsetsIdBegin = 0; + if (i > 0) + auxHitOffsetsIdBegin = inpTrack_view[i - 1].hitOffsets(); + + uint32_t auxHitOffsetsIdEnd = inpTrack_view[i].hitOffsets(); + if (i > 0) + auxHitOffsetsIdEnd = inpTrack_view[i].hitOffsets(); + + for (uint32_t k = auxHitOffsetsIdBegin; k < auxHitOffsetsIdEnd; ++k) { + trackHit_view[auxOutputHitIndex].id() = inpTrackHit_view[k].id(); + trackHit_view[auxOutputHitIndex].detId() = inpTrackHit_view[k].detId(); + ++auxOutputHitIndex; + } + + ++auxOutputTkIndex; + } + alpaka::syncBlockThreads(acc); + track_view.nTracks() = auxOutputTkIndex; + } + } + }; + template class Kernel_doStatsForTracks { public: diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/CAPixelDoublets.h b/RecoTracker/PixelSeeding/plugins/alpaka/CAPixelDoublets.h index 46997a61b064b..35bd28c28e27f 100644 --- a/RecoTracker/PixelSeeding/plugins/alpaka/CAPixelDoublets.h +++ b/RecoTracker/PixelSeeding/plugins/alpaka/CAPixelDoublets.h @@ -28,9 +28,10 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE::caPixelDoublets { uint32_t const* __restrict__ offsets, PhiBinner const* phiBinner, HitToCell* outerHitHisto, - AlgoParams const& params) const { + AlgoParams const& params, + MapToHitConstView maskView) const { doubletsFromHisto( - acc, maxNumOfDoublets, cells, nCells, hh, cc, ll, offsets, phiBinner, outerHitHisto, params); + acc, maxNumOfDoublets, cells, nCells, hh, cc, ll, offsets, phiBinner, outerHitHisto, params, maskView); } }; diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/CAPixelDoubletsAlgos.h b/RecoTracker/PixelSeeding/plugins/alpaka/CAPixelDoubletsAlgos.h index 000bca422857f..07357fed0a407 100644 --- a/RecoTracker/PixelSeeding/plugins/alpaka/CAPixelDoubletsAlgos.h +++ b/RecoTracker/PixelSeeding/plugins/alpaka/CAPixelDoubletsAlgos.h @@ -169,7 +169,8 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE::caPixelDoublets { uint32_t const* __restrict__ offsets, PhiBinner const* phiBinner, HitToCell* outerHitHisto, - AlgoParams const& params) { + AlgoParams const& params, + MapToHitConstView maskView) { const bool doClusterCut = params.minYsizeB1_ > 0 or params.minYsizeB2_ > 0; const bool doZSizeCut = params.maxDYsize12_ > 0 or params.maxDYsize_ > 0 or params.maxDYPred_ > 0; @@ -232,6 +233,9 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE::caPixelDoublets { auto i = (0 == pairLayerId) ? j : j - innerLayerCumulativeSize[pairLayerId - 1]; i += offsets[inner]; + if (maskView[i].recHitMask() > 0) + continue; + ALPAKA_ASSERT_ACC(i >= offsets[inner]); ALPAKA_ASSERT_ACC(i < offsets[inner + 1]); #ifdef DOUBLETS_DEBUG @@ -341,6 +345,8 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE::caPixelDoublets { for (uint32_t pIndex : cms::alpakatools::independent_group_elements_x(acc, maxpIndex)) { // FIXME implement alpaka::ldg and use it here? or is it const* __restrict__ enough? auto oi = p[pIndex]; + if (maskView[oi].recHitMask() > 0) + continue; ALPAKA_ASSERT_ACC(oi >= offsets[outer]); ALPAKA_ASSERT_ACC(oi < offsets[outer + 1]); #ifdef DOUBLETS_DEBUG diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/CAStructures.h b/RecoTracker/PixelSeeding/plugins/alpaka/CAStructures.h index 661e42dbdf1ea..3f6de3a92c526 100644 --- a/RecoTracker/PixelSeeding/plugins/alpaka/CAStructures.h +++ b/RecoTracker/PixelSeeding/plugins/alpaka/CAStructures.h @@ -47,6 +47,7 @@ namespace caStructures { using HitsView = ::reco::TrackingRecHitView; using HitModulesConstView = ::reco::HitModuleSoAConstView; using HitsConstView = ::reco::TrackingRecHitConstView; + using MapToHitConstView = ::reco::TrackingRecHitsMaskingConstView; //Tracks data formats using TkSoAView = ::reco::TrackSoAView; diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/PixelTracksMaskingSoA.cc b/RecoTracker/PixelSeeding/plugins/alpaka/PixelTracksMaskingSoA.cc new file mode 100644 index 0000000000000..0d19c8ff333ef --- /dev/null +++ b/RecoTracker/PixelSeeding/plugins/alpaka/PixelTracksMaskingSoA.cc @@ -0,0 +1,89 @@ +#include + +#include "DataFormats/TrackSoA/interface/TracksHost.h" +#include "DataFormats/TrackSoA/interface/alpaka/TracksSoACollection.h" +#include "DataFormats/TrackSoA/interface/TracksDevice.h" +#include "DataFormats/TrackingRecHitSoA/interface/alpaka/TrackingRecHitsSoACollection.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/global/EDProducer.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/EDGetToken.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/EDPutToken.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/Event.h" + +#include "CAHitNtupletGenerator.h" + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + class PixelTracksMaskingSoA : public global::EDProducer<> { + using Algo = CAHitMaskingAndMerger; + + public: + explicit PixelTracksMaskingSoA(const edm::ParameterSet& iConfig); + ~PixelTracksMaskingSoA() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + + private: + void produce(edm::StreamID streamID, device::Event& iEvent, const device::EventSetup& iSetup) const override; + + uint32_t const iterationIndex_; + pixelTrack::Quality const minQuality_; + + const device::EDGetToken inputRecHitsMaskToken_; + const device::EDGetToken inputTrackSoAToken_; + + const device::EDPutToken outputRecHitsMaskToken_; + + Algo deviceAlgo_; + }; + + PixelTracksMaskingSoA::PixelTracksMaskingSoA(const edm::ParameterSet& iConfig) + : EDProducer(iConfig), + iterationIndex_(iConfig.getParameter("iterationIndex")), + minQuality_(pixelTrack::qualityByName(iConfig.getParameter("minQuality"))), + inputRecHitsMaskToken_(consumes(iConfig.getParameter("recHitsMaskSoASrc"))), + inputTrackSoAToken_(consumes(iConfig.getParameter("tracksSoASrc"))), + outputRecHitsMaskToken_(produces()) { + if (minQuality_ == pixelTrack::Quality::notQuality) { + throw cms::Exception("PixelTrackConfiguration") + << iConfig.getParameter("minQuality") + " is not a pixelTrack::Quality"; + } + if (minQuality_ < pixelTrack::Quality::dup) { + throw cms::Exception("PixelTrackConfiguration") + << iConfig.getParameter("minQuality") + " not supported"; + } + } + + void PixelTracksMaskingSoA::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + desc.add( + "recHitsMaskSoASrc", + edm::InputTag("siPixelRecHitsExtendedPreSplittingAlpaka")); // has to be changed for each iteration + desc.add("tracksSoASrc", + edm::InputTag("pixelTracksHighPtAlpaka")); // has to be changed for each iteration + desc.add("minQuality", "highPurity"); + desc.add("iterationIndex", 0); + + descriptions.addWithDefaultLabel(desc); + } + + void PixelTracksMaskingSoA::produce(edm::StreamID streamID, + device::Event& iEvent, + const device::EventSetup& es) const { + // get both Pixel and Tracker SoA collections + auto queue = iEvent.queue(); + const auto& inpMaskColl = iEvent.get(inputRecHitsMaskToken_); + const auto& inpTkColl = iEvent.get(inputTrackSoAToken_); + + iEvent.emplace(outputRecHitsMaskToken_, + deviceAlgo_.makeMaskingAsync(inpMaskColl, inpTkColl, minQuality_, iterationIndex_, iEvent.queue())); + } +} // namespace ALPAKA_ACCELERATOR_NAMESPACE + +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/MakerMacros.h" +DEFINE_FWK_ALPAKA_MODULE(PixelTracksMaskingSoA); diff --git a/RecoTracker/PixelSeeding/plugins/alpaka/PixelTracksSoAMerger.cc b/RecoTracker/PixelSeeding/plugins/alpaka/PixelTracksSoAMerger.cc new file mode 100644 index 0000000000000..b7510de4eb1ab --- /dev/null +++ b/RecoTracker/PixelSeeding/plugins/alpaka/PixelTracksSoAMerger.cc @@ -0,0 +1,378 @@ +#include + +#include + +#include "DataFormats/TrackSoA/interface/TracksHost.h" +#include "DataFormats/TrackSoA/interface/alpaka/TracksSoACollection.h" +#include "DataFormats/TrackSoA/interface/TracksDevice.h" +#include "DataFormats/TrackingRecHitSoA/interface/alpaka/TrackingRecHitsSoACollection.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/global/EDProducer.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/EDGetToken.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/EDPutToken.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/Event.h" +#include "HeterogeneousCore/AlpakaInterface/interface/config.h" +#include "HeterogeneousCore/AlpakaInterface/interface/memory.h" + +#include "CAHitNtupletGenerator.h" + +// #define GPU_DEBUG +// #define NTRACKS_DEBUG +// #define DUPLICATE_DEBUG + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + class PixelTracksSoAMerger : public global::EDProducer<> { + using Algo = CAHitMaskingAndMerger; + + public: + explicit PixelTracksSoAMerger(const edm::ParameterSet& iConfig); + ~PixelTracksSoAMerger() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + + private: + void produce(edm::StreamID streamID, device::Event& iEvent, const device::EventSetup& iSetup) const override; + + pixelTrack::Quality const minQuality_; + double const matchFraction_; + + std::vector> inputTkSoATokenV_; + std::vector inputTkSoATagV_; + + const device::EDPutToken outputTkSoAToken_; + + Algo deviceAlgo_; + }; + + PixelTracksSoAMerger::PixelTracksSoAMerger(const edm::ParameterSet& iConfig) + : EDProducer(iConfig), + minQuality_(pixelTrack::qualityByName(iConfig.getParameter("minQuality"))), + matchFraction_(iConfig.getParameter("matchFraction")), + inputTkSoATagV_(iConfig.getParameter>("inputTkSoAs")), + outputTkSoAToken_(produces()) { + for (const auto& it : inputTkSoATagV_) { + inputTkSoATokenV_.push_back(consumes(it)); + } + if (minQuality_ == pixelTrack::Quality::notQuality) { + throw cms::Exception("PixelTrackConfiguration") + << iConfig.getParameter("minQuality") + " is not a pixelTrack::Quality"; + } + if (minQuality_ < pixelTrack::Quality::dup) { + throw cms::Exception("PixelTrackConfiguration") + << iConfig.getParameter("minQuality") + " not supported"; + } + } + + void PixelTracksSoAMerger::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + desc.add>( + "inputTkSoAs", {edm::InputTag("pixelTracksHighPtAlpaka"), edm::InputTag("pixelTracksLowPtAlpaka")}); + desc.add("minQuality", "highPurity"); + desc.add("matchFraction", 0.0); + + descriptions.addWithDefaultLabel(desc); + } + + namespace { + // This utility unrolls the SoA columns (tuples) at compile time, calling the provided functor 'f' + // once for each element. The index is passed as a std::integral_constant so it + // is available at compile time. + template + void unrollColumns(F&& f, std::index_sequence) { + (f(std::integral_constant{}), ...); + } + // User-facing wrapper to deduce the size of the tuple and create the index sequence + // Usage: mergeSoAColumns([&](auto columnIndex) { ... }); + template + void mergeSoAColumns(F&& f) { + unrollColumns(std::forward(f), std::make_index_sequence{}); + } + } // namespace + + void PixelTracksSoAMerger::produce(edm::StreamID streamID, + device::Event& iEvent, + const device::EventSetup& es) const { + // get both Pixel and Tracker SoA collections + auto queue = iEvent.queue(); + + std::vector inputTkSoAs; + for (const auto& it : inputTkSoATokenV_) { + auto const& aux = iEvent.get(it); + inputTkSoAs.push_back(&aux); + } + + // input SoA collections have the same layout + // each of them is made up of two SoAs: + // - one that contains the tracks + // - one that contains the hits associated to the tracks + // this code merges and copy them into a new SoA collection + + std::vector nTks; + std::vector nHits; + + for (const auto& it : inputTkSoAs) { + auto nTksAuxDev = it->view().tracks().metadata().size(); + auto nHitsAuxDev = it->view().trackHits().metadata().size(); + + reco::TracksHost itHost(queue, nTksAuxDev, nHitsAuxDev); + + alpaka::memcpy(queue, itHost.buffer(), it->buffer()); + alpaka::wait(queue); + + int nTksAux = itHost.view().tracks().nTracks(); + + nTks.push_back(nTksAux); + + int nHitsAux = 0; + for (int i = 0; i < nTksAux; ++i) { + nHitsAux += ::reco::nHits(itHost.view().tracks(), i); + } + + nHits.push_back(nHitsAux); + } + + std::vector cumulNTks{0}; + std::vector cumulNHits{0}; + + int auxCumulNTks = 0; + int auxCumulNHits = 0; + + for (int i = 0; i < int(nTks.size()); ++i) { + auxCumulNTks = auxCumulNTks + nTks[i]; + auxCumulNHits = auxCumulNHits + nHits[i]; + cumulNTks.push_back(auxCumulNTks); + cumulNHits.push_back(auxCumulNHits); + } + + // the outputTemp is also a SoA collection with the same layout as the input ones + auto outputTemp = reco::TracksSoACollection( + queue, std::reduce(nTks.begin(), nTks.end()), std::reduce(nHits.begin(), nHits.end())); + +#ifdef NTRACKS_DEBUG + std::cout << "----------------- Merging Input Tracks -----------------\n"; + for (int i = 0; i < int(nTks.size()); ++i) + std::cout << "Number of tracks input " << i + 1 << ": " << nTks[i] << '\n'; + std::cout << "Total number of tracks: " << outputTemp.view().tracks().metadata().size() << '\n'; + for (int i = 0; i < int(nHits.size()); ++i) + std::cout << "Number of hits input " << i + 1 << ": " << nHits[i] << '\n'; + std::cout << "Total number of hits: " << outputTemp.view().trackHits().metadata().size() << '\n' + << "---------------------------------------------------------------------\n"; +#endif + + // start from the tracks SoA, use metarecords to loop over all the columns + auto outView = outputTemp.view().tracks(); + + // start a loop here over the input SoAs to be easier to access each object + int nSoAsAux = 0; // auxiliar index to correctly access nTks and nHits + for (const auto& it : inputTkSoAs) { + if (nTks[nSoAsAux] == 0) { + nSoAsAux = nSoAsAux + 1; // still need to increase the SoA position to correctly access the cumul vectors + continue; + } + + auto inpTkView = it->view().tracks(); + + // auxiliar for correctly memcpy-ing eigen columns + int nEigenAux = 5; + + // layout type (same for all views) + using ViewType = decltype(outView); + using LayoutType = typename ViewType::Metadata::TypeOf_Layout; + + // build descriptors (tuple of spans: one span for each column) + auto outDesc = LayoutType::Descriptor(outView); + auto inpTkDesc = LayoutType::ConstDescriptor(inpTkView); + + // merge all columns using a compile-time loop + + // number of columns (same for all hits SoAs) + constexpr std::size_t N = std::tuple_size_v; + mergeSoAColumns([&](auto columnIndex) { + auto& outCol = std::get(outDesc.buff); + const auto& inpTkCol = std::get(inpTkDesc.buff); + // distinguish between scalar and column types + if constexpr (std::get(outDesc.columnTypes) == cms::soa::SoAColumnType::scalar) { + // scalar type, copy the value directly + // for some reason this doesn't work on device, so it is done after the loop in the iterations finishes + // alpaka::memcpy(queue, + // cms::alpakatools::make_device_view(queue, outCol.data(), 1), + // cms::alpakatools::make_device_view(queue, &nTotal, 1)); + +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Copied scalar with index " << columnIndex << '\n'; +#endif + } else if constexpr (std::get(outDesc.columnTypes) == cms::soa::SoAColumnType::eigen) { + for (int i = 0; i < nEigenAux; ++i) { + // eigen column type, copy the whole column with the number of eigen elements + alpaka::memcpy( + queue, + cms::alpakatools::make_device_view( + queue, outCol.data() + cumulNTks[nSoAsAux] + (i * (outCol.size() / nEigenAux)), nTks[nSoAsAux]), + cms::alpakatools::make_device_view( + queue, inpTkCol.data() + (i * (inpTkCol.size() / nEigenAux)), nTks[nSoAsAux])); + +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Copied eigen column with index " << columnIndex << ", " << i << '\n'; +#endif + } + nEigenAux = nEigenAux + 10; + } else { + // column type, copy the whole column + alpaka::memcpy(queue, + cms::alpakatools::make_device_view(queue, outCol.data() + cumulNTks[nSoAsAux], nTks[nSoAsAux]), + cms::alpakatools::make_device_view(queue, inpTkCol.data(), nTks[nSoAsAux])); +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Copied column with index " << columnIndex << '\n'; +#endif + } + }); + + // update outputTemp hitOffsets to take into account the previous SoAs + deviceAlgo_.updateHitOffsets( + cumulNTks[nSoAsAux], cumulNTks[nSoAsAux + 1], cumulNHits[nSoAsAux], outputTemp, queue); + + // copy track hits information + alpaka::memcpy(queue, + cms::alpakatools::make_device_view( + queue, outputTemp.view().trackHits().id().data() + cumulNHits[nSoAsAux], nHits[nSoAsAux]), + cms::alpakatools::make_device_view(queue, it->view().trackHits().id().data(), nHits[nSoAsAux])); + alpaka::memcpy(queue, + cms::alpakatools::make_device_view( + queue, outputTemp.view().trackHits().detId().data() + cumulNHits[nSoAsAux], nHits[nSoAsAux]), + cms::alpakatools::make_device_view(queue, it->view().trackHits().detId().data(), nHits[nSoAsAux])); +#ifdef GPU_DEBUG + alpaka::wait(queue); + std::cout << "Copied track hits\n"; + +#endif + + nSoAsAux = nSoAsAux + 1; + } + + // correctly copy total of nTracks + const int nTotal = cumulNTks[cumulNTks.size() - 1]; + alpaka::memcpy(queue, + cms::alpakatools::make_device_view(queue, outputTemp.view().tracks().nTracks()), + cms::alpakatools::make_host_view(nTotal)); + +#ifdef DUPLICATE_DEBUG + + // This block copies all input and output collections to host to print quantities and ensure that outN = inpN + // "out1", "out2", ..., "outN" refer to the position of the input inside of the output collection, but there is only one output SoA + // It only prints at most the first 10 tracks of each input collection, defined in std::min_element(nTks.begin(), nTks.end()))),10) + // This is also useful to check for duplicate tracks in distinct input collections + + auto nTksOutDebug = outputTemp.view().tracks().metadata().size(); + auto nHitsOutDebug = outputTemp.view().trackHits().metadata().size(); + + reco::TracksHost outputTempHost(queue, nTksOutDebug, nHitsOutDebug); + + alpaka::memcpy(queue, outputTempHost.buffer(), outputTemp.buffer()); + alpaka::wait(queue); + + auto outViewHost = outputTempHost.view().tracks(); + + std::vector inputTkSoAsHost; + + for (int k = 0; k < int(cumulNTks.size()) - 1; ++k) { + auto nTksInpDebug = inputTkSoAs[k]->view().tracks().metadata().size(); + auto nHitsInpDebug = inputTkSoAs[k]->view().trackHits().metadata().size(); + + reco::TracksHost inputTempHost(queue, nTksInpDebug, nHitsInpDebug); + + alpaka::memcpy(queue, inputTempHost.buffer(), inputTkSoAs[k]->buffer()); + alpaka::wait(queue); + + inputTkSoAsHost.push_back(std::move(inputTempHost)); + } + + std::cout << "Number of tracks: " << outViewHost.nTracks() << std::endl; + + for (int i = 0; i < std::min(int(*(std::min_element(nTks.begin(), nTks.end()))), 10); ++i) { + std::cout << "Number of tracks: " << outViewHost.nTracks() << std::endl; + std::cout << "------------------------------------------------------------------------------------------" + << std::endl; + + std::cout << "track quality ("; + for (int k = 1; k < int(cumulNTks.size()); ++k) + std::cout << "inp" << k << " - out" << k << " -- "; + std::cout << "): "; + for (int k = 0; k < int(cumulNTks.size()) - 1; ++k) + std::cout << pixelTrack::qualityName[int(inputTkSoAsHost[k].view().tracks()[i].quality())] << " - " + << pixelTrack::qualityName[int(outViewHost[i + cumulNTks[k]].quality())] << " -- "; + std::cout << std::endl; + std::cout << "------------------------------------------------------------------------------------------" + << std::endl; + + std::cout << "track pt ("; + for (int k = 1; k < int(cumulNTks.size()); ++k) + std::cout << "inp" << k << " - out" << k << " -- "; + std::cout << "): "; + for (int k = 0; k < int(cumulNTks.size()) - 1; ++k) + std::cout << inputTkSoAsHost[k].view().tracks()[i].pt() << " - " << outViewHost[i + cumulNTks[k]].pt() + << " -- "; + std::cout << std::endl; + std::cout << "------------------------------------------------------------------------------------------" + << std::endl; + + std::cout << "track eta ("; + for (int k = 1; k < int(cumulNTks.size()); ++k) + std::cout << "inp" << k << " - out" << k << " -- "; + std::cout << "): "; + for (int k = 0; k < int(cumulNTks.size()) - 1; ++k) + std::cout << inputTkSoAsHost[k].view().tracks()[i].eta() << " - " << outViewHost[i + cumulNTks[k]].eta() + << " -- "; + std::cout << std::endl; + std::cout << "------------------------------------------------------------------------------------------" + << std::endl; + + for (int j = 0; j < 5; ++j) { + std::cout << "track state " << j << "("; + for (int k = 1; k < int(cumulNTks.size()); ++k) + std::cout << "inp" << k << " - out" << k << " -- "; + std::cout << "): "; + for (int k = 0; k < int(cumulNTks.size()) - 1; ++k) + std::cout << inputTkSoAsHost[k].view().tracks()[i].state()(j) << " - " + << outViewHost[i + cumulNTks[k]].state()(j) << " -- "; + std::cout << std::endl; + } + std::cout << "------------------------------------------------------------------------------------------" + << std::endl; + + for (int j = 0; j < 15; ++j) { + std::cout << "track covariance " << j << "("; + for (int k = 1; k < int(cumulNTks.size()); ++k) + std::cout << "inp" << k << " - out" << k << " -- "; + std::cout << "): "; + for (int k = 0; k < int(cumulNTks.size()) - 1; ++k) + std::cout << inputTkSoAsHost[k].view().tracks()[i].covariance()(j) << " - " + << outViewHost[i + cumulNTks[k]].covariance()(j) << " -- "; + std::cout << std::endl; + } + std::cout << "==========================================================================================" + << std::endl; + } +#endif + + // calculate the total number of tracks and hits + int totTracks = std::reduce(nTks.begin(), nTks.end()); + int totHits = std::reduce(nHits.begin(), nHits.end()); + + // emplace the merged SoA collection in the event + iEvent.emplace(outputTkSoAToken_, + deviceAlgo_.makeFilteredTracks(totTracks, totHits, outputTemp, minQuality_, matchFraction_, queue)); + } + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE + +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/MakerMacros.h" +DEFINE_FWK_ALPAKA_MODULE(PixelTracksSoAMerger); diff --git a/RecoTracker/PixelSeeding/src/classes_def.xml b/RecoTracker/PixelSeeding/src/classes_def.xml index ea89a65a45dbb..8a8824c379705 100644 --- a/RecoTracker/PixelSeeding/src/classes_def.xml +++ b/RecoTracker/PixelSeeding/src/classes_def.xml @@ -1,4 +1,6 @@ + + diff --git a/RecoTracker/PixelTrackFitting/plugins/PixelTrackProducerFromSoAAlpaka.cc b/RecoTracker/PixelTrackFitting/plugins/PixelTrackProducerFromSoAAlpaka.cc index 09d1f829966e4..6a23b11657900 100644 --- a/RecoTracker/PixelTrackFitting/plugins/PixelTrackProducerFromSoAAlpaka.cc +++ b/RecoTracker/PixelTrackFitting/plugins/PixelTrackProducerFromSoAAlpaka.cc @@ -200,6 +200,8 @@ void PixelTrackProducerFromSoAAlpaka::produce(edm::StreamID streamID, std::cout << "Converting soa helix in reco tracks" << std::endl; #endif + // int aux = 0; // To check for events with too many zeros in eta and phi + // index map: trackId(in SoA) -> trackId(in legacy edm) auto indToEdmP = std::make_unique(); auto &indToEdm = *indToEdmP; @@ -367,6 +369,9 @@ void PixelTrackProducerFromSoAAlpaka::produce(edm::StreamID streamID, auto const hitOffs = tsoa.view().tracks().hitOffsets(); auto const hitIdxs = tsoa.view().trackHits().id(); auto nTracks = tsoa.view().tracks().nTracks(); + // auto const iteration = tsoa.view().tracks().iteration(); // To check for events with too many zeros in eta and phi + // // But can be more general and used for validation of distinct iterations + // // Has to be implemented yet tracks.reserve(nTracks); @@ -390,6 +395,9 @@ void PixelTrackProducerFromSoAAlpaka::produce(edm::StreamID streamID, auto nHits = reco::nHits(tsoa.view().tracks(), it); assert(nHits >= 3); auto q = quality[it]; + // auto auxIt = iteration[it]; // To check for events with too many zeros in eta and phi + // // But can be more general and used for validation of distinct iterations + // // Has to be implemented yet // apply cuts on quality and number of hits if (q < minQuality_) @@ -399,6 +407,11 @@ void PixelTrackProducerFromSoAAlpaka::produce(edm::StreamID streamID, if (nHits < minNumberOfHits_) //move to nLayers? continue; + // // To check for events with too many zeros in eta and phi + // if (auxIt == pixelTrack::iterationByName("promptLowPt") && abs(tsoa.view().tracks().eta()[it]) < 0.001) { + // ++aux; + // } + hits.resize(nHits); auto start = (it == 0) ? 0 : hitOffs[it - 1]; auto end = hitOffs[it]; @@ -496,6 +509,8 @@ void PixelTrackProducerFromSoAAlpaka::produce(edm::StreamID streamID, tracks.emplace_back(track.release(), hits); } + // if (aux > 0) std::cout << "========================================\n" << "The amount of zeros in this event is: " << aux << "\n========================================" << std::endl; // To check for events with too many zeros in eta and phi + #ifdef GPU_DEBUG std::cout << "processed " << nt << " good tuples " << tracks.size() << " out of " << indToEdm.size() << std::endl; #endif diff --git a/RecoTracker/PixelTrackFitting/python/PixelTracks_cff.py b/RecoTracker/PixelTrackFitting/python/PixelTracks_cff.py index aa925389560ed..0f2de3a161523 100644 --- a/RecoTracker/PixelTrackFitting/python/PixelTracks_cff.py +++ b/RecoTracker/PixelTrackFitting/python/PixelTracks_cff.py @@ -130,6 +130,7 @@ def _modifyForPPonAAandNotPhase2(producer): from Configuration.ProcessModifiers.phase2CAExtension_cff import phase2CAExtension phase2CAExtension.toReplaceWith(pixelTracksAlpaka,_pixelTracksAlpakaPhase2Extended.clone( + hitMask = "siPixelRecHitsExtendedPreSplittingAlpaka", pixelRecHitSrc = "siPixelRecHitsExtendedPreSplittingAlpaka", )) @@ -161,11 +162,160 @@ def _modifyForPPonAAandNotPhase2(producer): requireQuadsFromConsecutiveLayers = cms.bool(True) )) +pixelTracksHighPt = pixelTracks.clone() +pixelTracksLowPt = pixelTracks.clone() + alpaka.toReplaceWith(pixelTracksTask, cms.Task( # Build the pixel ntuplets and the pixel tracks in SoA format with alpaka on the device pixelTracksAlpaka, # Build the pixel ntuplets and the pixel tracks in SoA format with alpaka on the cpu (if requested by the validation) pixelTracksAlpakaSerial, + # Just to validate recHits masking machinery + pixelTracksHighPt, + # Just to validate recHits masking machinery + pixelTracksLowPt, + # Convert the pixel tracks from SoA to legacy format + pixelTracks) +) + +pixelTracksHighPtAlpakaPhase2Extended = _pixelTracksAlpakaPhase2Extended.clone( + hitMask = "siPixelRecHitsExtendedPreSplittingAlpaka", + pixelRecHitSrc = "siPixelRecHitsExtendedPreSplittingAlpaka", + iterationName = "promptHighPt", +) + +pixelTracksHighPtAlpaka = _pixelTracksAlpakaPhase1.clone() + +from Configuration.ProcessModifiers.pixelTrackMask_cff import pixelTrackMask +(pixelTrackMask & phase2CAExtension).toReplaceWith(pixelTracksHighPtAlpaka,pixelTracksHighPtAlpakaPhase2Extended.clone()) + +# pixel tracks SoA producer on the cpu, for validation +pixelTracksHighPtAlpakaSerial = makeSerialClone(pixelTracksHighPtAlpaka, + pixelRecHitSrc = 'siPixelRecHitsPreSplittingAlpakaSerial' +) + +# pixel tracks SoA merger +from RecoTracker.PixelSeeding.pixelTracksMaskingSoA_cfi import pixelTracksMaskingSoA as _pixelTracksMaskingSoA + +pixelTracksHighPtMaskingSoA = _pixelTracksMaskingSoA.clone( + iterationIndex = 1, + minQuality = "tight", + tracksSoASrc = "pixelTracksHighPtAlpaka", +) + +lowPtPtMinCut = 0.45 # 0.45 works, but 0.40 starts showing too many tracks with "zero" eta and phi + # Maybe there is another cell cut that balances this, but need to check + +pixelTracksLowPtAlpakaPhase2Extended = _pixelTracksAlpakaPhase2Extended.clone( + hitMask = "pixelTracksHighPtMaskingSoA", + pixelRecHitSrc = "siPixelRecHitsExtendedPreSplittingAlpaka", + ptmin = lowPtPtMinCut + 0.05, + maxNumberOfDoublets = str(12400000), + maxNumberOfTuples = str(32 * 32 * 1024), + hardCurvCut = cms.double(0.035), + iterationName = "promptLowPt", +) + +pixelTracksLowPtAlpakaPhase2Extended.trackQualityCuts.minPt = cms.double(lowPtPtMinCut + 0.05) +pixelTracksLowPtAlpakaPhase2Extended.geometry.ptCuts = cms.vdouble( + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut, + lowPtPtMinCut, lowPtPtMinCut, lowPtPtMinCut + ) + +pixelTracksLowPtAlpaka = _pixelTracksAlpakaPhase1.clone() + +(pixelTrackMask & phase2CAExtension).toReplaceWith(pixelTracksLowPtAlpaka,pixelTracksLowPtAlpakaPhase2Extended.clone()) + +# pixel tracks SoA producer on the cpu, for validation +pixelTracksLowPtAlpakaSerial = makeSerialClone(pixelTracksLowPtAlpaka, + pixelRecHitSrc = 'siPixelRecHitsPreSplittingAlpakaSerial' +) + +# legacy pixel tracks from SoA +from RecoTracker.PixelTrackFitting.pixelTrackProducerFromSoAAlpaka_cfi import pixelTrackProducerFromSoAAlpaka as _pixelTrackProducerFromSoAAlpaka + +(alpaka & ~phase2CAExtension).toReplaceWith(pixelTracks, _pixelTrackProducerFromSoAAlpaka.clone( + pixelRecHitLegacySrc = "siPixelRecHitsPreSplitting", +)) + +# pixel tracks SoA merger +from RecoTracker.PixelSeeding.pixelTracksSoAMerger_cfi import pixelTracksSoAMerger as _pixelTracksSoAMerger + +(pixelTrackMask & phase2CAExtension).toReplaceWith(pixelTracksAlpaka, _pixelTracksSoAMerger.clone( + inputTkSoAs = cms.VInputTag("pixelTracksHighPtAlpaka","pixelTracksLowPtAlpaka"), + minQuality = cms.string('tight'), + matchFraction = cms.double(0.0), +)) + +(pixelTrackMask & phase2CAExtension).toReplaceWith(pixelTracksHighPt, _pixelTrackProducerFromSoAAlpaka.clone( + pixelRecHitLegacySrc = "siPixelRecHitsPreSplitting", + beamSpot = cms.InputTag("offlineBeamSpot"), + minNumberOfHits = cms.int32(0), + minQuality = cms.string('tight'), + trackSrc = cms.InputTag("pixelTracksHighPtAlpaka"), + outerTrackerRecHitSrc = cms.InputTag("siPhase2RecHits"), + outerTrackerRecHitSoAConverterSrc = cms.InputTag("phase2OTRecHitsSoAConverter"), + useOTExtension = cms.bool(True), + requireQuadsFromConsecutiveLayers = cms.bool(True) +)) + +(pixelTrackMask & phase2CAExtension).toReplaceWith(pixelTracksLowPt, _pixelTrackProducerFromSoAAlpaka.clone( + pixelRecHitLegacySrc = "siPixelRecHitsPreSplitting", + beamSpot = cms.InputTag("offlineBeamSpot"), + minNumberOfHits = cms.int32(0), + minQuality = cms.string('tight'), + trackSrc = cms.InputTag("pixelTracksLowPtAlpaka"), + outerTrackerRecHitSrc = cms.InputTag("siPhase2RecHits"), + outerTrackerRecHitSoAConverterSrc = cms.InputTag("phase2OTRecHitsSoAConverter"), + useOTExtension = cms.bool(True), + requireQuadsFromConsecutiveLayers = cms.bool(True) +)) + +(pixelTrackMask & phase2CAExtension).toReplaceWith(pixelTracks, _pixelTrackProducerFromSoAAlpaka.clone( + pixelRecHitLegacySrc = "siPixelRecHitsPreSplitting", + beamSpot = cms.InputTag("offlineBeamSpot"), + minNumberOfHits = cms.int32(0), + minQuality = cms.string('tight'), + trackSrc = cms.InputTag("pixelTracksAlpaka"), + outerTrackerRecHitSrc = cms.InputTag("siPhase2RecHits"), + outerTrackerRecHitSoAConverterSrc = cms.InputTag("phase2OTRecHitsSoAConverter"), + useOTExtension = cms.bool(True), + requireQuadsFromConsecutiveLayers = cms.bool(True) +)) + +# Used 2 iterations to check that the machinery works +(pixelTrackMask & phase2CAExtension).toReplaceWith(pixelTracksTask, cms.Task( + # Build the highPt pixel ntuplets and the pixel tracks in SoA format with alpaka on the device + pixelTracksHighPtAlpaka, + # Build the highPt pixel ntuplets and the pixel tracks in SoA format with alpaka on the cpu (if requested by the validation) + pixelTracksHighPtAlpakaSerial, + # Updates the TrackingRecHitsMasking collection for next iteration + pixelTracksHighPtMaskingSoA, + # Convert the highPt pixel tracks from SoA to legacy format for validation + pixelTracksHighPt, + + # Build the lowPt pixel ntuplets and the pixel tracks in SoA format with alpaka on the device + pixelTracksLowPtAlpaka, + # Build the lowPt pixel ntuplets and the pixel tracks in SoA format with alpaka on the cpu (if requested by the validation) + pixelTracksLowPtAlpakaSerial, + # Convert the lowPt pixel tracks from SoA to legacy format for validation + pixelTracksLowPt, + + # Merge the produced SoAs directly + pixelTracksAlpaka, # Convert the pixel tracks from SoA to legacy format pixelTracks) ) diff --git a/Validation/RecoTrack/python/TrackValidation_cff.py b/Validation/RecoTrack/python/TrackValidation_cff.py index e177ac6065221..514b7c58d2f3e 100644 --- a/Validation/RecoTrack/python/TrackValidation_cff.py +++ b/Validation/RecoTrack/python/TrackValidation_cff.py @@ -1073,6 +1073,22 @@ def _uniqueFirstLayers(layerList): trackAssociation = "trackingParticlePixelTrackAsssociation" ) +trackingParticleHighPtPixelTrackAsssociation = trackingParticleRecoTrackAsssociation.clone( + label_tr = "pixelTracksHighPt", + associator = "quickTrackAssociatorByHitsPreSplitting", +) +PixelVertexAssociatorByPositionAndHighPtTracks = VertexAssociatorByPositionAndTracks.clone( + trackAssociation = "trackingParticleHighPtPixelTrackAsssociation" +) + +trackingParticleLowPtPixelTrackAsssociation = trackingParticleRecoTrackAsssociation.clone( + label_tr = "pixelTracksLowPt", + associator = "quickTrackAssociatorByHitsPreSplitting", +) +PixelVertexAssociatorByPositionAndLowPtTracks = VertexAssociatorByPositionAndTracks.clone( + trackAssociation = "trackingParticleLowPtPixelTrackAsssociation" +) + _pixelTracksCustom = dict( src = "pixelTracks", vertexTag = "pixelVertices", @@ -1124,6 +1140,34 @@ def _uniqueFirstLayers(layerList): cores = "" ) +trackValidatorHighPtPixelTrackingOnly = trackValidator.clone( + dirName = "Tracking/PixelTrack/", + label = [ + "pixelTracksHighPt", + ], + doResolutionPlotsForLabels = [], + trackCollectionForDrCalculation = "pixelTracksHighPt", + associators = ["trackingParticleHighPtPixelTrackAsssociation"], + label_vertex = "pixelVertices", + vertexAssociator = "PixelVertexAssociatorByPositionAndHighPtTracks", + dodEdxPlots = False, + cores = "" +) + +trackValidatorLowPtPixelTrackingOnly = trackValidator.clone( + dirName = "Tracking/PixelTrack/", + label = [ + "pixelTracksLowPt", + ], + doResolutionPlotsForLabels = [], + trackCollectionForDrCalculation = "pixelTracksLowPt", + associators = ["trackingParticleLowPtPixelTrackAsssociation"], + label_vertex = "pixelVertices", + vertexAssociator = "PixelVertexAssociatorByPositionAndLowPtTracks", + dodEdxPlots = False, + cores = "" +) + trackValidatorFromPVPixelTrackingOnly = trackValidatorPixelTrackingOnly.clone( dirName = "Tracking/PixelTrackFromPV/", label = [ @@ -1168,6 +1212,10 @@ def _uniqueFirstLayers(layerList): tracksValidationTruthPixelTrackingOnly = tracksValidationTruth.copy() tracksValidationTruthPixelTrackingOnly.replace(trackingParticleRecoTrackAsssociation, trackingParticlePixelTrackAsssociation) tracksValidationTruthPixelTrackingOnly.replace(VertexAssociatorByPositionAndTracks, PixelVertexAssociatorByPositionAndTracks) +tracksValidationTruthPixelTrackingOnly.add(trackingParticleHighPtPixelTrackAsssociation) +tracksValidationTruthPixelTrackingOnly.add(PixelVertexAssociatorByPositionAndHighPtTracks) +tracksValidationTruthPixelTrackingOnly.add(trackingParticleLowPtPixelTrackAsssociation) +tracksValidationTruthPixelTrackingOnly.add(PixelVertexAssociatorByPositionAndLowPtTracks) tracksValidationTruthPixelTrackingOnly.add(trackingParticlesBHadron) tracksValidationTruthPixelTrackingOnly.add( pixelTracks3hits ) tracksValidationTruthPixelTrackingOnly.add( pixelTracks4hits ) @@ -1229,6 +1277,8 @@ def _uniqueFirstLayers(layerList): tracksValidationPixelTrackingOnly = cms.Sequence( trackValidatorPixelTrackingOnly + + trackValidatorHighPtPixelTrackingOnly + + trackValidatorLowPtPixelTrackingOnly + trackValidatorFromPVPixelTrackingOnly + trackValidatorFromPVAllTPPixelTrackingOnly + trackValidatorBHadronPixelTrackingOnly,