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 
22 #include <vector>
23 #include <typeinfo>
24 
25 
26 namespace {
27 
28 
29 class TempInterface
30  : public SG::AuxVectorData
31 {
32 public:
33  TempInterface (size_t size) : m_size (size) {}
35 
36  virtual size_t size_v() const { return m_size; }
37  virtual size_t capacity_v() const { return m_size; }
38 
39 private:
40  size_t m_size;
41 };
42 
43 
44 } // anonymous namespace
45 
46 
47 namespace SG {
48 
49 
61  (const SG::IConstAuxStore& orig,
63  const SG::ThinningInfo* info)
64 {
65  size_t size = orig.size();
66  if (size == 0) {
67  copy.resize(0);
68  return;
69  }
70 
71  const ThinningDecisionBase* dec = info ? info->m_decision : nullptr;
72 
73  size_t nremaining = dec ? dec->thinnedSize() : size;
74  if( nremaining == 0) {
75  copy.resize(0);
76  return;
77  }
78 
79  // Access the auxiliary type registry:
81 
82  // The auxiliary IDs that the original container has:
83  SG::auxid_set_t auxids = orig.getAuxIDs();
84  SG::auxid_set_t decors = orig.getDecorIDs();
85 
86  SG::auxid_set_t dyn_auxids;
87  SG::auxid_set_t sel_auxids;
88  if (const IAuxStoreIO* iio = dynamic_cast<const IAuxStoreIO*> (&orig)) {
89  dyn_auxids = iio->getDynamicAuxIDs();
90  sel_auxids = iio->getSelectedAuxIDs();
91  }
92 
93  SG::auxid_set_t new_auxids = copy.getAuxIDs();
94 
95  copy.resize (nremaining);
96 
97  // Loop over all the variables of the original container:
98  for (SG::auxid_t auxid : auxids) {
99  // Skip null auxids (happens if we don't have the dictionary)
100  if(auxid == SG::null_auxid) continue;
101 
102  // Skip linked variables (they'll be handled when we copy the variable
103  // from which they're linked).
104  if (r.isLinked (auxid)) continue;
105 
106  // Skip non-selected dynamic variables.
107  // Handle variable vetoes requested via ThinningInfo.
108  // We want to allow vetoing a variable if it's defined
109  // as a dynamic variable in the source source, or if it doesn't
110  // exist in the destination source (in which case it will be
111  // dynamic there). The latter case happens for example when
112  // we save a static store object as the AuxContainerBaseClass
113  // in order to make all variables dynamic.
114  if (dyn_auxids.test(auxid) || !new_auxids.test(auxid)) {
115  if (info) {
116  if (info->vetoed(auxid)) continue;
117  }
118  }
119 
120  // Also check for a veto requested through the store selection interface.
121  // (But this shouldn't really be used anymore.)
122  if (dyn_auxids.test(auxid) && !sel_auxids.test(auxid)) {
123  continue;
124  }
125 
126  // Access the source variable:
127  const void* src = orig.getData (auxid);
128 
129  if (!src) continue;
130 
131  // Warn if this is a decoration --- decorations should have been locked
132  // by now, except for mcEventWeights, for which this is expected.
133  if (decors.test (auxid) && r.getName (auxid) != "mcEventWeights") {
134  std::ostringstream ss;
135  ss << "unlocked decoration " << r.getName(auxid)
136  << " (" << auxid << ") in object of type "
137  << AthContainers_detail::typeinfoName (typeid (orig));
138  ATHCONTAINERS_WARNING("copyAuxStoreThinned", ss.str());
139  }
140 
141  // FIXME: Do this via proper interfaces.
142  if (const IAuxStoreIO* iio = dynamic_cast<const IAuxStoreIO*> (&orig))
143  {
144  const std::type_info* typ = iio->getIOType (auxid);
145  if (strstr (typ->name(), "PackedContainer") != nullptr) {
146  // This cast gets a warning from the undefined behavior sanitizer
147  // in gcc6. Done like this deliberately for now, so suppress ubsan
148  // checking for this function.
149  const PackedParameters& parms =
150  reinterpret_cast<const PackedContainer<int>* > (iio->getIOData (auxid))->parms();
151  copy.setOption (auxid, AuxDataOption ("nbits", parms.nbits()));
152  copy.setOption (auxid, AuxDataOption ("float", parms.isFloat()));
153  copy.setOption (auxid, AuxDataOption ("signed", parms.isSigned()));
154  copy.setOption (auxid, AuxDataOption ("rounding", parms.rounding()));
155  copy.setOption (auxid, AuxDataOption ("nmantissa", parms.nmantissa()));
156  copy.setOption (auxid, AuxDataOption ("scale", parms.scale()));
157  }
158  }
159 
160  // Get the element size, type name and compression info for the current auxid
161  // This information is later passed to the helper function lossyFloatCompress
162  const size_t eltSize{ r.getEltSize(auxid) };
163  const std::string typeName{ r.getTypeName(auxid) };
164  const unsigned int nmantissa{ info != nullptr ? info->compression(auxid) : 0 };
165 
166  // Create the target variable:
167  void* dst = copy.getData (auxid, nremaining, nremaining);
168 
169  // Also create a linked variable if needed.
170  SG::auxid_t linked_auxid = r.linkedVariable (auxid);
171  if (linked_auxid != null_auxid) {
172  const IAuxTypeVector* v = orig.linkedVector (auxid);
173  if (v) {
174  size_t sz = v->size();
175  copy.getData (linked_auxid, 0, sz);
176  }
177  }
178 
179  TempInterface srciface (orig.size());
180  srciface.setStore (&orig);
181  TempInterface dstiface (copy.size());
182  dstiface.setStore (&copy);
183 
184  // Copy over all elements.
185  if (nremaining == size) {
186  // No thinning.
187  r.copyForOutput (auxid, dstiface, 0, srciface, 0, size);
188  }
189  else {
190  // Some elements are thinned.
191  for (std::size_t isrc = 0, idst = 0; isrc < size; ++isrc) {
192  if (!dec || !dec->thinned(isrc)) {
193  r.copyForOutput (auxid, dstiface, idst, srciface, isrc, 1);
194  ++idst;
195  }
196  }
197  }
198  // Apply lossy float compression here (in-place).
199  // Maybe it would be better to do this via the registry during copy.
200  lossyFloatCompress(dst, 0, nremaining, eltSize, typeName, nmantissa);
201  }
202 }
203 
213 void lossyFloatCompress (void* dst,
214  const std::size_t idst,
215  const std::size_t n,
216  const std::size_t eltSize,
217  const std::string& typeName,
218  const unsigned int nmantissa)
219 {
220  // Check if there is anything to be done
221  // Total number of explicit mantissa bits for a 32 bit float is 23
222  // 0 is used to denote no compression should be applied to the variable
223  static const unsigned int NMANTISSA_MAX = 23;
224  if (nmantissa == 0 || nmantissa >= NMANTISSA_MAX) return;
225 
226  // Setup all possible compressors: done only once
227  static const std::vector<CxxUtils::FloatCompressor> compressors = [] {
228  std::vector<CxxUtils::FloatCompressor> result;
229  result.reserve(NMANTISSA_MAX);
230  for (std::size_t idx = 0; idx < NMANTISSA_MAX; ++idx)
231  result.emplace_back(idx);
232  return result;
233  }();
234 
235  // Get the pointer to the memory
236  char* eltPtr = reinterpret_cast<char*>(dst) + idst*eltSize;
237 
238  // This is where we apply in-place lossy float compression
239  if(typeName == "float") {
240  // cppcheck-suppress invalidPointerCast
241  float* f = reinterpret_cast<float*> (eltPtr);
242  for (size_t i = 0; i < n; i++) {
243  *f = compressors[nmantissa].reduceFloatPrecision(*f);
244  ++f;
245  }
246  } else if (typeName == "std::vector<float>"){
247  for (size_t i = 0; i < n; i++) {
248  std::vector<float> &vals = *(reinterpret_cast<std::vector<float>*>(eltPtr));
249  for(auto &val: vals) {
250  val = compressors[nmantissa].reduceFloatPrecision(val);
251  }
252  eltPtr += eltSize;
253  }
254  }
255 }
256 
257 } // 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:213
SG
Forward declaration.
Definition: CaloCellPacker_400_500.h:32
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:639
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:61
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.
Athena::typeinfoName
std::string typeinfoName(const std::type_info &ti)
Convert a type_info to a demangled string.
Definition: AthenaKernel/src/ClassName.cxx:23
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.
ATHCONTAINERS_WARNING
#define ATHCONTAINERS_WARNING(ctx, msg)
Definition: error.h:57
SG::PackedParameters::nbits
uint8_t nbits() const
The number of bits used to store each element.
error.h
Helper for emitting error messages.
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
SG::IConstAuxStore::getDecorIDs
virtual const SG::auxid_set_t & getDecorIDs() const =0
Return a set of identifiers for decorations in this store.
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