ATLAS Offline Software
Loading...
Searching...
No Matches
CaloBCIDCoeffs.cxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
3 */
10
11
17#include "CxxUtils/vec.h"
18#include "CxxUtils/features.h"
19
20
21namespace {
22
23
24// Vector types.
26using 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)
38template class std::vector<vf, vf_vector::allocator_type>;
39
40
41namespace {
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
55inline
56void 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
138CaloBCIDCoeffs::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) {
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
184void 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
227void 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 = (nshapes-1) + i - j;
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
277void 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}
Luminosity-dependent pileup offset correction conditions object.
float & coeff(size_t icoeff, size_t icell)
Indexing into m_coeffs.
unsigned int m_nsamples
Number of samples per cell (length of OFC vector).
CxxUtils::vec_aligned_vector< float > m_coeffs
Storage for coeffients, m_ncoeff per cell, laid out in groups of CHUNKSIZE like this: icoeff0,...
size_t nsamples_coeff() const
Return the number of samples per cell used in the calculation (after padding).
unsigned int m_ncell
Number of cells.
size_t nshapes() const
Return the number of shape points per cell.
unsigned int m_npad
Number of padding cells we need to add to get a multiple of CHUNKSIZE.
CaloBCIDCoeffs(const std::vector< HWIdentifier > &hwids, const LArOnlineID_Base &online_id, const ILArOFC &ofcs, const ILArShape &shapes, const ILArMinBiasAverage &minbias)
Constructor.
void calc(const float *lumi, CxxUtils::vec_aligned_vector< float > &out) const
Perform the calculation for a given set of per-bunch luminosities.
static constexpr size_t CHUNKSIZE
Number of cells that we calculate at one time.
unsigned int m_nsamples_coeff
Number of samples per cell used in the calculation, after padding.
unsigned int m_nshapes
Number of shape points per cell.
unsigned int m_ncoeff
Number of coefficients per cell (length of dot product).
void fillCoeffs(const std::vector< HWIdentifier > &hwids, const LArOnlineID_Base &online_id, const ILArOFC &ofcs, const ILArShape &shapes, const ILArMinBiasAverage &minbias)
Initialize all coefficients.
void findCellCoeffs(const float *ofcs, const float *shapes, bool ishec, std::vector< float > &cell_coeffs) const
Find coefficients for one cell.
virtual const float & minBiasAverage(const HWIdentifier &id) const =0
access to average of E in minimum bias events index by Identifier
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)
virtual ShapeRef_t Shape(const HWIdentifier &id, int gain, int tbin=0, int mode=0) const =0
Helper for the Liquid Argon Calorimeter cell identifiers.
virtual bool isHECchannel(const HWIdentifier id) const =0
Some additional feature test macros.
typename vecDetail::vec_typedef< T, N >::type vec
Define a nice alias for the vectorized type.
Definition vec.h:207
aligned_vector< T, 64 > vec_aligned_vector
A std::vector with alignment sufficient for any vector instructions on this platform.
ATH_ALWAYS_INLINE void vbroadcast(VEC &v, T x)
Copy a scalar to each element of a vectorized type.
Definition vec.h:251
long long ll
Vectorization helpers.