ATLAS Offline Software
copyAuxStoreThinned.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
21 #include <vector>
22 
23 
24 namespace {
25 
26 
27 class TempInterface
28  : public SG::AuxVectorData
29 {
30 public:
31  TempInterface (size_t size) : m_size (size) {}
33 
34  virtual size_t size_v() const { return m_size; }
35  virtual size_t capacity_v() const { return m_size; }
36 
37 private:
38  size_t m_size;
39 };
40 
41 
42 } // anonymous namespace
43 
44 
45 namespace SG {
46 
47 
59  (const SG::IConstAuxStore& orig,
61  const SG::ThinningInfo* info)
62 {
63  size_t size = orig.size();
64  if (size == 0) {
65  copy.resize(0);
66  return;
67  }
68 
69  const ThinningDecisionBase* dec = info ? info->m_decision : nullptr;
70 
71  size_t nremaining = dec ? dec->thinnedSize() : size;
72  if( nremaining == 0) {
73  copy.resize(0);
74  return;
75  }
76 
77  // Access the auxiliary type registry:
79 
80  // The auxiliary IDs that the original container has:
81  SG::auxid_set_t auxids = orig.getAuxIDs();
82 
83  SG::auxid_set_t dyn_auxids;
84  SG::auxid_set_t sel_auxids;
85  if (const IAuxStoreIO* iio = dynamic_cast<const IAuxStoreIO*> (&orig)) {
86  dyn_auxids = iio->getDynamicAuxIDs();
87  sel_auxids = iio->getSelectedAuxIDs();
88  }
89 
90  SG::auxid_set_t new_auxids = copy.getAuxIDs();
91 
92  copy.resize (nremaining);
93 
94  // Loop over all the variables of the original container:
95  for (SG::auxid_t auxid : auxids) {
96  // Skip null auxids (happens if we don't have the dictionary)
97  if(auxid == SG::null_auxid) continue;
98 
99  // Skip linked variables (they'll be handled when we copy the variable
100  // from which they're linked).
101  if (r.isLinked (auxid)) continue;
102 
103  // Skip non-selected dynamic variables.
104  // Handle variable vetoes requested via ThinningInfo.
105  // We want to allow vetoing a variable if it's defined
106  // as a dynamic variable in the source source, or if it doesn't
107  // exist in the destination source (in which case it will be
108  // dynamic there). The latter case happens for example when
109  // we save a static store object as the AuxContainerBaseClass
110  // in order to make all variables dynamic.
111  if (dyn_auxids.test(auxid) || !new_auxids.test(auxid)) {
112  if (info) {
113  if (info->vetoed(auxid)) continue;
114  }
115  }
116 
117  // Also check for a veto requested through the store selection interface.
118  // (But this shouldn't really be used anymore.)
119  if (dyn_auxids.test(auxid) && !sel_auxids.test(auxid)) {
120  continue;
121  }
122 
123  // Access the source variable:
124  const void* src = orig.getData (auxid);
125 
126  if (!src) continue;
127 
128  // FIXME: Do this via proper interfaces.
129  if (const IAuxStoreIO* iio = dynamic_cast<const IAuxStoreIO*> (&orig))
130  {
131  const std::type_info* typ = iio->getIOType (auxid);
132  if (strstr (typ->name(), "PackedContainer") != nullptr) {
133  // This cast gets a warning from the undefined behavior sanitizer
134  // in gcc6. Done like this deliberately for now, so suppress ubsan
135  // checking for this function.
136  const PackedParameters& parms =
137  reinterpret_cast<const PackedContainer<int>* > (iio->getIOData (auxid))->parms();
138  copy.setOption (auxid, AuxDataOption ("nbits", parms.nbits()));
139  copy.setOption (auxid, AuxDataOption ("float", parms.isFloat()));
140  copy.setOption (auxid, AuxDataOption ("signed", parms.isSigned()));
141  copy.setOption (auxid, AuxDataOption ("rounding", parms.rounding()));
142  copy.setOption (auxid, AuxDataOption ("nmantissa", parms.nmantissa()));
143  copy.setOption (auxid, AuxDataOption ("scale", parms.scale()));
144  }
145  }
146 
147  // Get the element size, type name and compression info for the current auxid
148  // This information is later passed to the helper function lossyFloatCompress
149  const size_t eltSize{ r.getEltSize(auxid) };
150  const std::string typeName{ r.getTypeName(auxid) };
151  const unsigned int nmantissa{ info != nullptr ? info->compression(auxid) : 0 };
152 
153  // Create the target variable:
154  void* dst = copy.getData (auxid, nremaining, nremaining);
155 
156  // Also create a linked variable if needed.
157  SG::auxid_t linked_auxid = r.linkedVariable (auxid);
158  if (linked_auxid != null_auxid) {
159  const IAuxTypeVector* v = orig.linkedVector (auxid);
160  if (v) {
161  size_t sz = v->size();
162  copy.getData (linked_auxid, 0, sz);
163  }
164  }
165 
166  TempInterface srciface (orig.size());
167  srciface.setStore (&orig);
168  TempInterface dstiface (copy.size());
169  dstiface.setStore (&copy);
170 
171  // Copy over all elements.
172  if (nremaining == size) {
173  // No thinning.
174  r.copyForOutput (auxid, dstiface, 0, srciface, 0, size);
175  }
176  else {
177  // Some elements are thinned.
178  for (std::size_t isrc = 0, idst = 0; isrc < size; ++isrc) {
179  if (!dec || !dec->thinned(isrc)) {
180  r.copyForOutput (auxid, dstiface, idst, srciface, isrc, 1);
181  ++idst;
182  }
183  }
184  }
185  // Apply lossy float compression here (in-place).
186  // Maybe it would be better to do this via the registry during copy.
187  lossyFloatCompress(dst, 0, nremaining, eltSize, typeName, nmantissa);
188  }
189 }
190 
200 void lossyFloatCompress (void* dst,
201  const std::size_t idst,
202  const std::size_t n,
203  const std::size_t eltSize,
204  const std::string& typeName,
205  const unsigned int nmantissa)
206 {
207  // Check if there is anything to be done
208  // Total number of explicit mantissa bits for a 32 bit float is 23
209  // 0 is used to denote no compression should be applied to the variable
210  static const unsigned int NMANTISSA_MAX = 23;
211  if (nmantissa == 0 || nmantissa >= NMANTISSA_MAX) return;
212 
213  // Setup all possible compressors: done only once
214  static const std::vector<CxxUtils::FloatCompressor> compressors = [] {
215  std::vector<CxxUtils::FloatCompressor> result;
216  result.reserve(NMANTISSA_MAX);
217  for (std::size_t idx = 0; idx < NMANTISSA_MAX; ++idx)
218  result.emplace_back(idx);
219  return result;
220  }();
221 
222  // Get the pointer to the memory
223  char* eltPtr = reinterpret_cast<char*>(dst) + idst*eltSize;
224 
225  // This is where we apply in-place lossy float compression
226  if(typeName == "float") {
227  // cppcheck-suppress invalidPointerCast
228  float* f = reinterpret_cast<float*> (eltPtr);
229  for (size_t i = 0; i < n; i++) {
230  *f = compressors[nmantissa].reduceFloatPrecision(*f);
231  ++f;
232  }
233  } else if (typeName == "std::vector<float>"){
234  for (size_t i = 0; i < n; i++) {
235  std::vector<float> &vals = *(reinterpret_cast<std::vector<float>*>(eltPtr));
236  for(auto &val: vals) {
237  val = compressors[nmantissa].reduceFloatPrecision(val);
238  }
239  eltPtr += eltSize;
240  }
241  }
242 }
243 
244 } // namespace SG
grepfile.info
info
Definition: grepfile.py:38
SG::copyAuxStoreThinned
void copyAuxStoreThinned(const SG::IConstAuxStore &orig, SG::IAuxStore &copy, const SG::ThinningInfo *info)
Helper to copy an aux store while applying thinning.
beamspotman.r
def r
Definition: beamspotman.py:676
SG::IConstAuxStore::getData
virtual const void * getData(SG::auxid_t auxid) const =0
Return the data vector for one aux data item.
fitman.sz
sz
Definition: fitman.py:527
get_generator_info.result
result
Definition: get_generator_info.py:21
SG::lossyFloatCompress
void lossyFloatCompress(void *dst, const std::size_t dst_index, const std::size_t n, const std::size_t eltSize, const std::string &typeName, const unsigned int nmantissa)
Helper method to apply lossy float compression.
Definition: copyAuxStoreThinned.cxx:200
SG
Forward declaration.
Definition: CaloCellPacker_400_500.h:32
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:640
WriteCellNoiseToCool.src
src
Definition: WriteCellNoiseToCool.py:513
SG::NO_SANITIZE_UNDEFINED
void copyAuxStoreThinned NO_SANITIZE_UNDEFINED(const SG::IConstAuxStore &orig, SG::IAuxStore &copy, const SG::ThinningInfo *info)
Helper to copy an aux store while applying thinning.
Definition: copyAuxStoreThinned.cxx:59
SG::ThinningDecisionBase
Hold thinning decisions for one container.
Definition: ThinningDecisionBase.h:39
SG::ThinningDecisionBase::thinned
bool thinned(size_t ndx) const
Return true if element ndx should be thinned.
ThinningDecisionBase.h
Hold thinning decisions for one container.
SG::ThinningDecisionBase::thinnedSize
size_t thinnedSize() const
Return the size of the container being thinned after thinning.
Definition: ThinningDecisionBase.cxx:42
SG::IConstAuxStore::size
virtual size_t size() const =0
Return the number of elements in the store.
SG::IAuxStoreIO
Interface providing I/O for a generic auxiliary store.
Definition: IAuxStoreIO.h:44
SG::AuxTypeRegistry
Handle mappings between names and auxid_t.
Definition: AuxTypeRegistry.h:61
SG::AuxVectorData::setStore
void setStore(SG::IAuxStore *store)
Set the store associated with this object.
Definition: AuxVectorData.cxx:116
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
SG::PackedParameters::isSigned
bool isSigned() const
Are elements being written as signed numbers?
SG::PackedParameters::nmantissa
uint8_t nmantissa() const
The number of bits used for the mantissa portion of a float-point representation, excluding a sign bi...
SG::ThinningInfo
Hold thinning/slimming information for a given object.
Definition: ThinningInfo.h:40
SG::auxid_t
size_t auxid_t
Identifier for a particular aux data item.
Definition: AuxTypes.h:27
copyAuxStoreThinned.h
Helper to copy an aux store while applying thinning.
SG::PackedParameters::isFloat
bool isFloat() const
Are elements being written as floating-point numbers?
lumiFormat.i
int i
Definition: lumiFormat.py:85
FloatCompressor.h
beamspotman.n
n
Definition: beamspotman.py:731
IAuxStoreIO.h
Interface providing I/O for a generic auxiliary store.
SG::PackedParameters::nbits
uint8_t nbits() const
The number of bits used to store each element.
hist_file_dump.f
f
Definition: hist_file_dump.py:135
SG::AuxDataOption
Hold information about an option setting request.
Definition: AuxDataOption.h:37
SG::IConstAuxStore::linkedVector
virtual const IAuxTypeVector * linkedVector(SG::auxid_t) const
Return interface for a linked variable.
Definition: IConstAuxStore.h:189
SG::IAuxStore
Interface for non-const operations on an auxiliary store.
Definition: IAuxStore.h:48
python.PyAthena.v
v
Definition: PyAthena.py:154
SG::PackedContainer
Container to hold aux data to be stored in a packed form.
Definition: PackedContainer.h:50
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
SG::IAuxTypeVector
Abstract interface for manipulating vectors of arbitrary types.
Definition: IAuxTypeVector.h:42
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
IAuxStore.h
Interface for non-const operations on an auxiliary store.
ReadCalibFromCool.typeName
typeName
Definition: ReadCalibFromCool.py:477
SG::auxid_set_t
A set of aux data identifiers.
Definition: AuxTypes.h:47
SG::PackedParameters::rounding
bool rounding() const
Should floats be rounded during writing?
no_sanitize_undefined.h
Helper to disable undefined behavior sanitizer for a function.
SG::AuxVectorData
Manage lookup of vectors of auxiliary data.
Definition: AuxVectorData.h:168
calibdata.copy
bool copy
Definition: calibdata.py:27
IConstAuxStore.h
Interface for const operations on an auxiliary store.
SG::IConstAuxStore
Interface for const operations on an auxiliary store.
Definition: IConstAuxStore.h:64
SG::IConstAuxStore::getAuxIDs
virtual const SG::auxid_set_t & getAuxIDs() const =0
Return a set of identifiers for existing data items in this store.
SG::AuxVectorData::capacity_v
virtual size_t capacity_v() const =0
Return the capacity of the container.
SG::AuxVectorData::size_v
virtual size_t size_v() const =0
Return the size of the container.
SG::PackedParameters::scale
float scale() const
Return the scale for floating-point numbers.
SG::PackedParameters
Describe how the contents of a PackedContainer are to be saved.
Definition: PackedParameters.h:66
CxxUtils::ConcurrentBitset::test
bool test(bit_t bit) const
Test to see if a bit is set.
PlotCalibFromCool.vals
vals
Definition: PlotCalibFromCool.py:474