CMS 3D CMS Logo

PixelRecHits.h
Go to the documentation of this file.
1 #ifndef RecoLocalTracker_SiPixelRecHits_alpaka_PixelRecHits_h
2 #define RecoLocalTracker_SiPixelRecHits_alpaka_PixelRecHits_h
3 
4 // C++ headers
5 #include <cassert>
6 #include <cstdint>
7 #include <limits>
8 #include <type_traits>
9 
10 // Alpaka headers
11 #include <alpaka/alpaka.hpp>
12 
13 // CMSSW headers
23 
24 //#define GPU_DEBUG
25 
27  namespace pixelRecHits {
28 
29  template <typename TrackerTraits>
30  class GetHits {
31  public:
32  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
33  ALPAKA_FN_ACC void operator()(const TAcc& acc,
34  pixelCPEforDevice::ParamsOnDeviceT<TrackerTraits> const* __restrict__ cpeParams,
35  BeamSpotPOD const* __restrict__ bs,
37  uint32_t numElements,
38  uint32_t nonEmptyModules,
41  ALPAKA_ASSERT_ACC(cpeParams);
42 
43  // outer loop: one block per module
44  for (uint32_t module : cms::alpakatools::independent_groups(acc, nonEmptyModules)) {
45  // This is necessary only once - consider moving it somewhere else.
46  // Copy the average geometry corrected by the beamspot.
47  if (0 == module) {
48  auto& agc = hits.averageGeometry();
49  auto const& ag = cpeParams->averageGeometry();
50  auto nLadders = TrackerTraits::numberOfLaddersInBarrel;
51 
52  for (uint32_t il : cms::alpakatools::independent_group_elements(acc, nLadders)) {
53  agc.ladderZ[il] = ag.ladderZ[il] - bs->z;
54  agc.ladderX[il] = ag.ladderX[il] - bs->x;
55  agc.ladderY[il] = ag.ladderY[il] - bs->y;
56  agc.ladderR[il] = sqrt(agc.ladderX[il] * agc.ladderX[il] + agc.ladderY[il] * agc.ladderY[il]);
57  agc.ladderMinZ[il] = ag.ladderMinZ[il] - bs->z;
58  agc.ladderMaxZ[il] = ag.ladderMaxZ[il] - bs->z;
59  }
60 
62  agc.endCapZ[0] = ag.endCapZ[0] - bs->z;
63  agc.endCapZ[1] = ag.endCapZ[1] - bs->z;
64  }
65  }
66 
67  // to be moved in common namespace...
70 
71  auto me = clusters[module].moduleId();
72  int nclus = clusters[me].clusInModule();
73 
74  // skip empty modules
75  if (0 == nclus)
76  continue;
77 
78 #ifdef GPU_DEBUG
80  auto k = clusters[1 + module].moduleStart();
81  while (digis[k].moduleId() == invalidModuleId)
82  ++k;
83  ALPAKA_ASSERT_ACC(digis[k].moduleId() == me);
84  }
85 
86  if (me % 100 == 1)
88  printf("hitbuilder: %d clusters in module %d. will write at %d\n",
89  nclus,
90  me,
91  clusters[me].clusModuleStart());
92 #endif
93 
94  auto& clusParams = alpaka::declareSharedVar<pixelCPEforDevice::ClusParams, __COUNTER__>(acc);
95  for (int startClus = 0, endClus = nclus; startClus < endClus; startClus += maxHitsInIter) {
96  auto first = clusters[1 + module].moduleStart();
97 
98  int nClusInIter = alpaka::math::min(acc, maxHitsInIter, endClus - startClus);
99  int lastClus = startClus + nClusInIter;
100  ALPAKA_ASSERT_ACC(nClusInIter <= nclus);
101  ALPAKA_ASSERT_ACC(nClusInIter > 0);
102  ALPAKA_ASSERT_ACC(lastClus <= nclus);
103  ALPAKA_ASSERT_ACC(nclus > maxHitsInIter || (0 == startClus && nClusInIter == nclus && lastClus == nclus));
104 
105  // init
106  for (uint32_t ic : cms::alpakatools::independent_group_elements(acc, nClusInIter)) {
107  clusParams.minRow[ic] = std::numeric_limits<uint32_t>::max();
108  clusParams.maxRow[ic] = 0;
109  clusParams.minCol[ic] = std::numeric_limits<uint32_t>::max();
110  clusParams.maxCol[ic] = 0;
111  clusParams.charge[ic] = 0;
112  clusParams.q_f_X[ic] = 0;
113  clusParams.q_l_X[ic] = 0;
114  clusParams.q_f_Y[ic] = 0;
115  clusParams.q_l_Y[ic] = 0;
116  }
117 
118  alpaka::syncBlockThreads(acc);
119 
120  // one thread or element per "digi"
122  auto id = digis[i].moduleId();
123  if (id == invalidModuleId)
124  continue; // not valid
125  if (id != me)
126  break; // end of module
127  auto cl = digis[i].clus();
128  if (cl < startClus || cl >= lastClus)
129  continue;
130  cl -= startClus;
131  ALPAKA_ASSERT_ACC(cl >= 0);
133  auto x = digis[i].xx();
134  auto y = digis[i].yy();
135  alpaka::atomicMin(acc, &clusParams.minRow[cl], (uint32_t)x, alpaka::hierarchy::Threads{});
136  alpaka::atomicMax(acc, &clusParams.maxRow[cl], (uint32_t)x, alpaka::hierarchy::Threads{});
137  alpaka::atomicMin(acc, &clusParams.minCol[cl], (uint32_t)y, alpaka::hierarchy::Threads{});
138  alpaka::atomicMax(acc, &clusParams.maxCol[cl], (uint32_t)y, alpaka::hierarchy::Threads{});
139  }
140 
141  alpaka::syncBlockThreads(acc);
142 
143  auto pixmx = cpeParams->detParams(me).pixmx;
145  auto id = digis[i].moduleId();
146  if (id == invalidModuleId)
147  continue; // not valid
148  if (id != me)
149  break; // end of module
150  auto cl = digis[i].clus();
151  if (cl < startClus || cl >= lastClus)
152  continue;
153  cl -= startClus;
154  ALPAKA_ASSERT_ACC(cl >= 0);
156  auto x = digis[i].xx();
157  auto y = digis[i].yy();
158  auto ch = digis[i].adc();
159  alpaka::atomicAdd(acc, &clusParams.charge[cl], (int32_t)ch, alpaka::hierarchy::Threads{});
160  ch = alpaka::math::min(acc, ch, pixmx);
161  if (clusParams.minRow[cl] == x)
162  alpaka::atomicAdd(acc, &clusParams.q_f_X[cl], (int32_t)ch, alpaka::hierarchy::Threads{});
163  if (clusParams.maxRow[cl] == x)
164  alpaka::atomicAdd(acc, &clusParams.q_l_X[cl], (int32_t)ch, alpaka::hierarchy::Threads{});
165  if (clusParams.minCol[cl] == y)
166  alpaka::atomicAdd(acc, &clusParams.q_f_Y[cl], (int32_t)ch, alpaka::hierarchy::Threads{});
167  if (clusParams.maxCol[cl] == y)
168  alpaka::atomicAdd(acc, &clusParams.q_l_Y[cl], (int32_t)ch, alpaka::hierarchy::Threads{});
169  }
170 
171  alpaka::syncBlockThreads(acc);
172 
173  // next one cluster per thread...
174  first = clusters[me].clusModuleStart() + startClus;
175  for (uint32_t ic : cms::alpakatools::independent_group_elements(acc, nClusInIter)) {
176  auto h = first + ic; // output index in global memory
177 
178  assert(h < (uint32_t)hits.metadata().size());
179  assert(h < clusters[me + 1].clusModuleStart());
180 
181  pixelCPEforDevice::position<TrackerTraits>(
182  cpeParams->commonParams(), cpeParams->detParams(me), clusParams, ic);
183 
184  pixelCPEforDevice::errorFromDB<TrackerTraits>(
185  cpeParams->commonParams(), cpeParams->detParams(me), clusParams, ic);
186 
187  // store it
188  hits[h].chargeAndStatus().charge = clusParams.charge[ic];
189  hits[h].chargeAndStatus().status = clusParams.status[ic];
190  hits[h].detectorIndex() = me;
191 
192  // local coordinates for computations
193  float xl, yl;
194  hits[h].xLocal() = xl = clusParams.xpos[ic];
195  hits[h].yLocal() = yl = clusParams.ypos[ic];
196 
197  hits[h].clusterSizeX() = clusParams.xsize[ic];
198  hits[h].clusterSizeY() = clusParams.ysize[ic];
199 
200  hits[h].xerrLocal() = clusParams.xerr[ic] * clusParams.xerr[ic] + cpeParams->detParams(me).apeXX;
201  hits[h].yerrLocal() = clusParams.yerr[ic] * clusParams.yerr[ic] + cpeParams->detParams(me).apeYY;
202 
203  // global coordinates and phi computation
204  float xg, yg, zg;
205  cpeParams->detParams(me).frame.toGlobal(xl, yl, xg, yg, zg);
206  // correct for the beamspot position
207  xg -= bs->x;
208  yg -= bs->y;
209  zg -= bs->z;
210 
211  hits[h].xGlobal() = xg;
212  hits[h].yGlobal() = yg;
213  hits[h].zGlobal() = zg;
214  hits[h].rGlobal() = alpaka::math::sqrt(acc, xg * xg + yg * yg);
215  hits[h].iphi() = unsafe_atan2s<7>(yg, xg);
216  }
217  alpaka::syncBlockThreads(acc);
218  } // end loop on batches
219  }
220  }
221  };
222 
223  } // namespace pixelRecHits
224 } // namespace ALPAKA_ACCELERATOR_NAMESPACE
225 
226 #endif // RecoLocalTracker_SiPixelRecHits_plugins_alpaka_PixelRecHits_h
T1 atomicMax(T1 *a, T2 b)
Definition: cudaCompat.h:97
ALPAKA_FN_ACC constexpr bool once_per_block(TAcc const &acc)
constexpr DetParams const &__restrict__ detParams(int i) const
ALPAKA_FN_ACC auto independent_group_elements(TAcc const &acc, TArgs... args)
constexpr int32_t MaxHitsInIter
ALPAKA_FN_ACC auto independent_groups(TAcc const &acc, TArgs... args)
assert(be >=bs)
float ladderZ[TrackerTraits::numberOfLaddersInBarrel]
constexpr uint32_t maxHitsInIter()
T sqrt(T t)
Definition: SSEVec.h:19
constexpr CommonParams const &__restrict__ commonParams() const
constexpr uint16_t invalidModuleId
ALPAKA_FN_ACC void operator()(const TAcc &acc, pixelCPEforDevice::ParamsOnDeviceT< TrackerTraits > const *__restrict__ cpeParams, BeamSpotPOD const *__restrict__ bs, SiPixelDigisSoAConstView digis, uint32_t numElements, uint32_t nonEmptyModules, SiPixelClustersSoAConstView clusters, TrackingRecHitSoAView< TrackerTraits > hits) const
Definition: PixelRecHits.h:33
uint16_t *__restrict__ uint16_t const *__restrict__ uint32_t const *__restrict__ uint32_t *__restrict__ uint32_t const *__restrict__ int32_t *__restrict__ uint32_t numElements
constexpr AverageGeometry const &__restrict__ averageGeometry() const
uint16_t *__restrict__ uint16_t const *__restrict__ uint32_t const *__restrict__ uint32_t *__restrict__ uint32_t const *__restrict__ moduleId
float x
typename TrackingRecHitSoA< TrackerTraits >::template TrackingRecHitSoALayout<>::View TrackingRecHitSoAView
T1 atomicMin(T1 *a, T2 b)
Definition: cudaCompat.h:85
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
T1 atomicAdd(T1 *a, T2 b)
Definition: cudaCompat.h:61
constexpr uint16_t invalidModuleId