ATLAS Offline Software
CaloBCIDCoeffs.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration.
3  */
13 #include "LArElecCalib/ILArOFC.h"
14 #include "LArElecCalib/ILArShape.h"
17 #include "CxxUtils/vec.h"
18 #include "CxxUtils/features.h"
19 
20 
21 namespace {
22 
23 
24 // Vector types.
26 using vf_vector = CxxUtils::vec_aligned_vector<vf>;
27 
28 
29 } // anonymous namespace.
30 
31 
32 // Clang15 seems to have trouble with implicit template instantiation
33 // from multiversioned functions. Need to explictly instantiate
34 // this to prevent link failures.
35 // Further, we cannot use the vec_aligned_vector alias directly
36 // in an explicit instantiation.
37 // (https://stackoverflow.com/questions/25118191/explicitly-instantiate-class-through-template-alias)
38 template class std::vector<vf, vf_vector::allocator_type>;
39 
40 
41 namespace {
42 
43 
50 #if defined(__x86_64__) && HAVE_TARGET_CLONES && HAVE_VECTOR_SIZE_ATTRIBUTE
51 // If we have function multiversioning, compile specialized versions
52 // for different architectures.
53 [[gnu::target_clones("default,sse2,avx,avx2")]]
54 #endif
55 inline
56 void calcImpl (const float* lumi,
57  const unsigned ncell,
58  const unsigned ncoeff,
59  const unsigned int nshapes,
60  const unsigned int npad,
63 {
64  // Vector type.
66 
67  // Broadcast the luminosity values to all vector lanes.
68  vf_vector llv (ncoeff);
69  for (size_t i = 0; i < ncoeff; i++) {
70  CxxUtils::vbroadcast (llv[i], lumi[i - (nshapes-1)]);
71  }
72 
73  // Size the output array, including padding to make it a multiple
74  // of CHUNKSIZE.
75  out.resize(ncell + npad);
76 
77  // Pointers iterating through the coefficients and the output.
78  const vf* cpos = reinterpret_cast<const vf*> (coeffs.data());
79  vf* opos = reinterpret_cast<vf*> (out.data());
80 
81  // Loop over cells in groups of CHUNKSIZE.
82  for (size_t icell = 0; icell < ncell; icell += CaloBCIDCoeffs::CHUNKSIZE) {
83 
84  // Loop over coefficients and calculate the dot product.
85  // It is more efficient to keep three separate accumulators
86  // and add them together at the end --- probably because that
87  // allows memory accesses to overlap with calculations.
88  // There was no significant observed benefit to using
89  // more than three accumulators.
90 
91  // Prepare to loop through luminosity values.
92  vf* ll = llv.data();
93 
94  // Initialize three accumulators.
95  vf sum1 = {0};
96  vf sum2 = {0};
97  vf sum3 = {0};
98 
99  // Loop accumulating the dot product in three pieces.
100  int i = ncoeff;
101  for (; i >= 3; i -= 3) {
102  sum1 += *cpos++ * *ll++;
103  sum2 += *cpos++ * *ll++;
104  sum3 += *cpos++ * *ll++;
105  }
106 
107  // Handle any trailing values if the number of coefficients is not
108  // divisible by three. (Would not usually be executed as we expect
109  // to usually have 36 coefficients.)
110  switch (i) {
111  case 2:
112  sum1 += *cpos++ * *ll++;
113  [[fallthrough]];
114  case 1:
115  sum2 += *cpos++ * *ll++;
116  break;
117  default:
118  break;
119  }
120 
121  // Sum the three accumulators and write CHUNKSIZE cells to the output.
122  *opos++ = sum1 + sum2 + sum3;
123  }
124  // Remove padding from the end of the output vector.
125  out.resize(ncell);
126 }
127 
128 } //end anonymous namespace
129 
138 CaloBCIDCoeffs::CaloBCIDCoeffs (const std::vector<HWIdentifier>& hwids,
139  const LArOnlineID_Base& online_id,
140  const ILArOFC& ofcs,
141  const ILArShape& shapes,
142  const ILArMinBiasAverage& minbias)
143 {
144  // Number of cells we're calculating.
145  m_ncell = hwids.size();
146 
147  // Number of cells of padding we need to add to get a multiple of CHUNKSIZE.
149  if (m_npad == CHUNKSIZE) m_npad = 0;
150 
151  // Number of shape / samples.
152  if (hwids.empty()) {
153  m_nsamples = 0;
154  m_nshapes = 0;
155  }
156  else {
157  m_nsamples = ofcs.OFC_a (hwids[0], 0).size();
158  m_nshapes = shapes.Shape (hwids[0], 0).size();
159  }
160 
161  // Special case for 4 samples: treat this case as if we actually
162  // had 5 samples, just with 0-padding.
164  if (m_nsamples == 4) {
165  m_nsamples_coeff = 5;
166  }
167 
168  // Number of coefficients (length of the dot product).
169  m_ncoeff = (m_nshapes-1) + 1 + (m_nsamples_coeff-1);
170 
171  // Initialize coeffients.
172  fillCoeffs (hwids, online_id, ofcs, shapes, minbias);
173 }
174 
175 
184 void CaloBCIDCoeffs::fillCoeffs (const std::vector<HWIdentifier>& hwids,
185  const LArOnlineID_Base& online_id,
186  const ILArOFC& ofcs,
187  const ILArShape& shapes,
188  const ILArMinBiasAverage& minbias)
189 {
190  // Reserve space for all coefficients.
191  m_coeffs.resize (m_ncoeff * (m_ncell + m_npad));
192 
193  // Temporary vector to hold coefficients for one cell.
194  // Declare outside the loop to reduce allocations.
195  std::vector<float> cell_coeffs (m_ncoeff);
196 
197  for (size_t icell = 0; icell < m_ncell; ++icell) {
198  HWIdentifier hwid = hwids[icell];
199  float cell_minbias = minbias.minBiasAverage (hwid);
200 
201  // If cell_minbias <= 0, we want the result to be 0.
202  // So just leave the coefficients as 0 in that case.
203  if (cell_minbias > 0) {
204  // Calculate coefficients for one cell.
205  findCellCoeffs (ofcs.OFC_a (hwid, 0).data(),
206  shapes.Shape (hwid, 0).data(),
207  online_id.isHECchannel (hwid),
208  cell_coeffs);
209 
210  // Enter them into the coefficients array in the proper places.
211  // Here, we also multiply everything by minbias.
212  for (size_t icoeff = 0; icoeff < m_ncoeff; ++icoeff) {
213  coeff(icoeff, icell) = cell_coeffs[icoeff] * cell_minbias;
214  }
215  }
216  }
217 }
218 
219 
227 void CaloBCIDCoeffs::findCellCoeffs (const float* ofcs,
228  const float* shapes,
229  bool ishec,
230  std::vector<float>& cell_coeffs) const
231 {
232  // Initialize output to zero.
233  std::fill (cell_coeffs.begin(), cell_coeffs.end(), 0);
234 
235  const unsigned nsamples_coeff = m_nsamples_coeff;
236  const unsigned nshapes = m_nshapes;
237 
238  // Loop over all combinations of sample / shape.
239  for (size_t i = 0; i < nsamples_coeff; ++i) {
240  for (size_t j = 0; j < nshapes; ++j) {
241  // Index of coefficient we're filling.
242  size_t ndx = i - j + (nshapes-1);
243 
244  // Find OFC coefficient.
245  float ofc = 0;
246  if (m_nsamples == 4)
247  {
248  // Special case for 4 samples: we actually calclate with five samples,
249  // but pad with 0 at either the beginning or end (depending on
250  // whether this is a HEC cell).
251  if (ishec) {
252  if (i > 0) ofc = ofcs[i-1];
253  }
254  else {
255  if (i < 4) ofc = ofcs[i];
256  }
257  }
258  else {
259  ofc = ofcs[i];
260  }
261 
262  // Do the multiplication and sum.
263  cell_coeffs.at(ndx) += ofc * shapes[j];
264  }
265  }
266 }
267 
268 
277 void CaloBCIDCoeffs::calc (const float* lumi,
279 {
280 
281  //call the implementation method
282  calcImpl(lumi, m_ncell, m_ncoeff, m_nshapes, m_npad, m_coeffs, out);
283 
284 }
CxxUtils::vec_aligned_vector
aligned_vector< T, 64 > vec_aligned_vector
A std::vector with alignment sufficient for any vector instructions on this platform.
Definition: aligned_vector.h:51
features.h
Some additional feature test macros.
CaloBCIDCoeffs::m_coeffs
CxxUtils::vec_aligned_vector< float > m_coeffs
Storage for coeffients, m_ncoeff per cell, laid out in groups of CHUNKSIZE like this: icoeff0,...
Definition: CaloBCIDCoeffs.h:157
WriteCellNoiseToCool.icell
icell
Definition: WriteCellNoiseToCool.py:339
CaloBCIDCoeffs::m_nsamples_coeff
unsigned int m_nsamples_coeff
Number of samples per cell used in the calculation, after padding.
Definition: CaloBCIDCoeffs.h:142
detail::ll
long long ll
Definition: PrimitiveHelpers.h:46
CaloBCIDCoeffs::nshapes
size_t nshapes() const
Return the number of shape points per cell.
Definition: CaloBCIDCoeffs.h:213
CaloBCIDCoeffs::m_nshapes
unsigned int m_nshapes
Number of shape points per cell.
Definition: CaloBCIDCoeffs.h:145
CaloBCIDCoeffs::m_npad
unsigned int m_npad
Number of padding cells we need to add to get a multiple of CHUNKSIZE.
Definition: CaloBCIDCoeffs.h:133
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
CaloBCIDCoeffs::coeff
float & coeff(size_t icoeff, size_t icell)
Indexing into m_coeffs.
Definition: CaloBCIDCoeffs.h:165
CaloBCIDCoeffs::nsamples_coeff
size_t nsamples_coeff() const
Return the number of samples per cell used in the calculation (after padding).
Definition: CaloBCIDCoeffs.h:224
ILArMinBiasAverage
Definition: ILArMinBiasAverage.h:13
ILArOFC.h
HWIdentifier
Definition: HWIdentifier.h:13
CaloBCIDCoeffs::m_ncoeff
unsigned int m_ncoeff
Number of coefficients per cell (length of dot product).
Definition: CaloBCIDCoeffs.h:136
CxxUtils::vec
typename vecDetail::vec_typedef< T, N >::type vec
Define a nice alias for the vectorized type.
Definition: vec.h:207
perfmonmt-refit.coeffs
coeffs
Definition: perfmonmt-refit.py:105
CaloBCIDCoeffs::CHUNKSIZE
static constexpr size_t CHUNKSIZE
Number of cells that we calculate at one time.
Definition: CaloBCIDCoeffs.h:126
CaloBCIDCoeffs::findCellCoeffs
void findCellCoeffs(const float *ofcs, const float *shapes, bool ishec, std::vector< float > &cell_coeffs) const
Find coefficients for one cell.
Definition: CaloBCIDCoeffs.cxx:227
lumiFormat.i
int i
Definition: lumiFormat.py:85
ILArMinBiasAverage::minBiasAverage
virtual const float & minBiasAverage(const HWIdentifier &id) const =0
access to average of E in minimum bias events index by Identifier
LArOnlineID_Base::isHECchannel
virtual bool isHECchannel(const HWIdentifier id) const =0
CaloBCIDCoeffs.h
Luminosity-dependent pileup offset correction conditions object.
CaloBCIDCoeffs::m_nsamples
unsigned int m_nsamples
Number of samples per cell (length of OFC vector).
Definition: CaloBCIDCoeffs.h:139
fill
void fill(H5::Group &out_file, size_t iterations)
Definition: test-hdf5-writer.cxx:95
ILArOFC
Definition: ILArOFC.h:14
CaloBCIDCoeffs::m_ncell
unsigned int m_ncell
Number of cells.
Definition: CaloBCIDCoeffs.h:130
ReadCellNoiseFromCool.ncell
ncell
Definition: ReadCellNoiseFromCool.py:197
ILArShape.h
LArOnlineID_Base
Helper for the Liquid Argon Calorimeter cell identifiers.
Definition: LArOnlineID_Base.h:105
lumiFormat.lumi
lumi
Definition: lumiFormat.py:106
vec.h
Vectorization helpers.
CaloBCIDCoeffs::fillCoeffs
void fillCoeffs(const std::vector< HWIdentifier > &hwids, const LArOnlineID_Base &online_id, const ILArOFC &ofcs, const ILArShape &shapes, const ILArMinBiasAverage &minbias)
Initialize all coefficients.
Definition: CaloBCIDCoeffs.cxx:184
CxxUtils::vbroadcast
ATH_ALWAYS_INLINE void vbroadcast(VEC &v, T x)
Copy a scalar to each element of a vectorized type.
Definition: vec.h:251
ILArOFC::OFC_a
virtual OFCRef_t OFC_a(const HWIdentifier &id, int gain, int tbin=0) const =0
access to OFCs by online ID, gain, and tbin (!=0 for testbeam)
CaloBCIDCoeffs::calc
void calc(const float *lumi, CxxUtils::vec_aligned_vector< float > &out) const
Perform the calculation for a given set of per-bunch luminosities.
Definition: CaloBCIDCoeffs.cxx:277
ILArShape
Definition: ILArShape.h:13
ReadOfcFromCool.ofc
ofc
Definition: ReadOfcFromCool.py:110
CaloBCIDCoeffs::CaloBCIDCoeffs
CaloBCIDCoeffs(const std::vector< HWIdentifier > &hwids, const LArOnlineID_Base &online_id, const ILArOFC &ofcs, const ILArShape &shapes, const ILArMinBiasAverage &minbias)
Constructor.
Definition: CaloBCIDCoeffs.cxx:138
LArOnlineID.h
ILArShape::Shape
virtual ShapeRef_t Shape(const HWIdentifier &id, int gain, int tbin=0, int mode=0) const =0
ILArMinBiasAverage.h