CMS 3D CMS Logo

PFRecHitProducerKernel.dev.cc
Go to the documentation of this file.
1 #include <type_traits>
2 
3 #include <alpaka/alpaka.hpp>
4 
7 
9 
11  using namespace particleFlowRecHitProducer;
12 
13  // Kernel to apply cuts to calorimeter hits and construct PFRecHits
14  template <typename CAL>
16  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
17  ALPAKA_FN_ACC void operator()(const TAcc& acc,
18  const typename CAL::ParameterType::ConstView params,
19  const typename CAL::TopologyTypeDevice::ConstView topology,
20  const typename CAL::CaloRecHitSoATypeDevice::ConstView recHits,
22  uint32_t* __restrict__ denseId2pfRecHit,
23  uint32_t* __restrict__ num_pfRecHits) const {
24  // Strided loop over CaloRecHits
25  for (int32_t i : cms::alpakatools::uniform_elements(acc, recHits.metadata().size())) {
26  // Check energy thresholds/quality cuts (specialised for HCAL/ECAL)
27  if (!applyCuts(recHits[i], params, topology))
28  continue;
29 
30  // Use atomic operation to determine index of the PFRecHit to be constructed
31  // The index needs to be unique and consequtive across all threads in all blocks.
32  // This is achieved using the alpaka::hierarchy::Blocks argument.
33  const uint32_t j = alpaka::atomicInc(acc, num_pfRecHits, 0xffffffff, alpaka::hierarchy::Blocks{});
34 
35  // Construct PFRecHit from CAL recHit (specialised for HCAL/ECAL)
36  constructPFRecHit(pfRecHits[j], recHits[i]);
37 
38  // Fill denseId -> pfRecHit index map
39  denseId2pfRecHit[CAL::detId2denseId(pfRecHits.detId(j))] = j;
40  }
41  }
42 
43  ALPAKA_FN_ACC static bool applyCuts(const typename CAL::CaloRecHitSoATypeDevice::ConstView::const_element rh,
44  const typename CAL::ParameterType::ConstView params,
45  const typename CAL::TopologyTypeDevice::ConstView topology);
46 
47  ALPAKA_FN_ACC static void constructPFRecHit(
48  reco::PFRecHitDeviceCollection::View::element pfrh,
49  const typename CAL::CaloRecHitSoATypeDevice::ConstView::const_element rh);
50  };
51 
52  template <>
54  const typename HCAL::CaloRecHitSoATypeDevice::ConstView::const_element rh,
55  const HCAL::ParameterType::ConstView params,
56  const HCAL::TopologyTypeDevice::ConstView topology) {
57  // Reject HCAL recHits below enery threshold
58  float threshold = 9999.;
59  const uint32_t detId = rh.detId();
60  const uint32_t depth = HCAL::getDepth(detId);
61  const uint32_t subdet = getSubdet(detId);
62 
63  // skip bad channels
64  if (rh.chi2() < 0)
65  return false;
66 
67  if (topology.cutsFromDB()) {
68  const auto& denseId = HCAL::detId2denseId(detId);
69  if (denseId != HCAL::kInvalidDenseId) {
70  threshold = topology.noiseThreshold()[denseId];
71  } else {
72  printf("Encountered invalid denseId for detId %u (subdetector %u)!", detId, subdet);
73  return false;
74  }
75  } else {
76  if (subdet == HcalBarrel) {
77  threshold = params.energyThresholds()[depth - 1];
78  } else if (subdet == HcalEndcap) {
79  threshold = params.energyThresholds()[depth - 1 + HCAL::kMaxDepthHB];
80  } else {
81  printf("Rechit with detId %u has invalid subdetector %u!\n", detId, subdet);
82  return false;
83  }
84  }
85  return rh.energy() >= threshold;
86  }
87 
88  template <>
90  const ECAL::CaloRecHitSoATypeDevice::ConstView::const_element rh,
91  const ECAL::ParameterType::ConstView params,
92  const ECAL::TopologyTypeDevice::ConstView topology) {
93  // Reject ECAL recHits below energy threshold
94  if (rh.energy() < params.energyThresholds()[ECAL::detId2denseId(rh.detId())])
95  return false;
96 
97  // Reject ECAL recHits of bad quality
98  if ((ECAL::checkFlag(rh.flags(), ECAL::Flags::kOutOfTime) && rh.energy() > params.cleaningThreshold()) ||
100  ECAL::checkFlag(rh.flags(), ECAL::Flags::kDiWeird))
101  return false;
102 
103  return true;
104  }
105 
106  template <>
108  reco::PFRecHitDeviceCollection::View::element pfrh,
109  const HCAL::CaloRecHitSoATypeDevice::ConstView::const_element rh) {
110  pfrh.detId() = rh.detId();
111  pfrh.denseId() = HCAL::detId2denseId(rh.detId());
112  pfrh.energy() = rh.energy();
113  pfrh.time() = rh.timeM0();
114  pfrh.depth() = HCAL::getDepth(pfrh.detId());
115  const uint32_t subdet = getSubdet(pfrh.detId());
116  if (subdet == HcalBarrel)
117  pfrh.layer() = PFLayer::HCAL_BARREL1;
118  else if (subdet == HcalEndcap)
119  pfrh.layer() = PFLayer::HCAL_ENDCAP;
120  else
121  pfrh.layer() = PFLayer::NONE;
122  }
123 
124  template <>
126  reco::PFRecHitDeviceCollection::View::element pfrh,
127  const ECAL::CaloRecHitSoATypeDevice::ConstView::const_element rh) {
128  pfrh.detId() = rh.detId();
129  pfrh.denseId() = ECAL::detId2denseId(rh.detId());
130  pfrh.energy() = rh.energy();
131  pfrh.time() = rh.time();
132  pfrh.depth() = 1;
133  const uint32_t subdet = getSubdet(pfrh.detId());
134  if (subdet == EcalBarrel)
135  pfrh.layer() = PFLayer::ECAL_BARREL;
136  else if (subdet == EcalEndcap)
137  pfrh.layer() = PFLayer::ECAL_ENDCAP;
138  else
139  pfrh.layer() = PFLayer::NONE;
140  }
141 
142  // Kernel to associate topology information of PFRecHits
143  template <typename CAL>
145  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
146  ALPAKA_FN_ACC void operator()(const TAcc& acc,
147  const typename CAL::TopologyTypeDevice::ConstView topology,
149  const uint32_t* __restrict__ denseId2pfRecHit,
150  uint32_t* __restrict__ num_pfRecHits) const {
151  // First thread updates size field pfRecHits SoA
152  if (const int32_t thread = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0u]; thread == 0)
153  pfRecHits.size() = *num_pfRecHits;
154 
155  // Assign position information and associate neighbours
156  for (int32_t i : cms::alpakatools::uniform_elements(acc, *num_pfRecHits)) {
157  const uint32_t denseId = CAL::detId2denseId(pfRecHits.detId(i));
158 
159  pfRecHits.x(i) = topology.positionX(denseId);
160  pfRecHits.y(i) = topology.positionY(denseId);
161  pfRecHits.z(i) = topology.positionZ(denseId);
162 
163  for (uint32_t n = 0; n < 8; n++) {
164  pfRecHits.neighbours(i)(n) = -1;
165  const uint32_t denseId_neighbour = topology.neighbours(denseId)(n);
166  if (denseId_neighbour != CAL::kInvalidDenseId) {
167  const uint32_t pfRecHit_neighbour = denseId2pfRecHit[denseId_neighbour];
168  if (pfRecHit_neighbour != 0xffffffff)
169  pfRecHits.neighbours(i)(n) = (int32_t)pfRecHit_neighbour;
170  }
171  }
172  }
173  }
174  };
175 
176  template <typename CAL>
177  PFRecHitProducerKernel<CAL>::PFRecHitProducerKernel(Queue& queue, const uint32_t num_recHits)
178  : denseId2pfRecHit_(cms::alpakatools::make_device_buffer<uint32_t[]>(queue, CAL::kSize)),
179  num_pfRecHits_(cms::alpakatools::make_device_buffer<uint32_t>(queue)),
180  work_div_(cms::alpakatools::make_workdiv<Acc1D>(1, 1)) {
181  alpaka::memset(queue, denseId2pfRecHit_, 0xff); // Reset denseId -> pfRecHit index map
182  alpaka::memset(queue, num_pfRecHits_, 0x00); // Reset global pfRecHit counter
183 
184  const uint32_t items = 64;
185  const uint32_t groups = cms::alpakatools::divide_up_by(num_recHits, items);
186  work_div_ = cms::alpakatools::make_workdiv<Acc1D>(groups, items);
187  }
188 
189  template <typename CAL>
191  const typename CAL::CaloRecHitSoATypeDevice& recHits,
192  const typename CAL::ParameterType& params,
193  const typename CAL::TopologyTypeDevice& topology,
195  alpaka::exec<Acc1D>(queue,
196  work_div_,
198  params.view(),
199  topology.view(),
200  recHits.view(),
201  pfRecHits.view(),
202  denseId2pfRecHit_.data(),
203  num_pfRecHits_.data());
204  }
205 
206  template <typename CAL>
208  const typename CAL::TopologyTypeDevice& topology,
210  alpaka::exec<Acc1D>(queue,
211  work_div_,
213  topology.view(),
214  pfRecHits.view(),
215  denseId2pfRecHit_.data(),
216  num_pfRecHits_.data());
217  }
218 
219  // Instantiate templates
220  template class PFRecHitProducerKernel<HCAL>;
221  template class PFRecHitProducerKernel<ECAL>;
222 } // namespace ALPAKA_ACCELERATOR_NAMESPACE
cms::alpakatools::device_buffer< Device, uint32_t > num_pfRecHits_
ALPAKA_FN_ACC auto uniform_elements(TAcc const &acc, TArgs... args)
Definition: workdivision.h:311
WorkDiv< Dim1D > make_workdiv(Idx blocks, Idx elements)
Definition: workdivision.h:47
void associateTopologyInfo(Queue &queue, const typename CAL::TopologyTypeDevice &topology, reco::PFRecHitDeviceCollection &pfRecHits)
constexpr Idx divide_up_by(Idx value, Idx divisor)
Definition: workdivision.h:20
PFRecHitProducerKernel(Queue &queue, const uint32_t num_recHits)
ALPAKA_FN_ACC void operator()(const TAcc &acc, const typename CAL::TopologyTypeDevice::ConstView topology, reco::PFRecHitDeviceCollection::View pfRecHits, const uint32_t *__restrict__ denseId2pfRecHit, uint32_t *__restrict__ num_pfRecHits) const
std::enable_if_t< alpaka::isDevice< TDev > and not std::is_array_v< T >, device_buffer< TDev, T > > make_device_buffer(TDev const &device)
Definition: memory.h:185
static ALPAKA_FN_ACC void constructPFRecHit(reco::PFRecHitDeviceCollection::View::element pfrh, const typename CAL::CaloRecHitSoATypeDevice::ConstView::const_element rh)
PortableCollection<::reco::PFRecHitSoA > PFRecHitDeviceCollection
static constexpr bool checkFlag(uint32_t flagBits, int flag)
T1 atomicInc(T1 *a, T2 b)
Definition: cudaCompat.h:48
std::vector< Block > Blocks
Definition: Block.h:99
Namespace of DDCMS conversion namespace.
static ALPAKA_FN_ACC bool applyCuts(const typename CAL::CaloRecHitSoATypeDevice::ConstView::const_element rh, const typename CAL::ParameterType::ConstView params, const typename CAL::TopologyTypeDevice::ConstView topology)
void processRecHits(Queue &queue, const typename CAL::CaloRecHitSoATypeDevice &recHits, const typename CAL::ParameterType &params, const typename CAL::TopologyTypeDevice &topology, reco::PFRecHitDeviceCollection &pfRecHits)
cms::alpakatools::device_buffer< Device, uint32_t[]> denseId2pfRecHit_
ALPAKA_FN_ACC void operator()(const TAcc &acc, const typename CAL::ParameterType::ConstView params, const typename CAL::TopologyTypeDevice::ConstView topology, const typename CAL::CaloRecHitSoATypeDevice::ConstView recHits, reco::PFRecHitDeviceCollection::View pfRecHits, uint32_t *__restrict__ denseId2pfRecHit, uint32_t *__restrict__ num_pfRecHits) const