ATLAS Offline Software
Loading...
Searching...
No Matches
copyAuxStoreThinned.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
11
12
22#include <vector>
23#include <typeinfo>
24
25
26namespace {
27
28
29class TempInterface
30 : public SG::AuxVectorData
31{
32public:
33 TempInterface (size_t size) : m_size (size) {}
34 using AuxVectorData::setStore;
35
36 virtual size_t size_v() const override { return m_size; }
37 virtual size_t capacity_v() const override { return m_size; }
38
39private:
40 size_t m_size;
41};
42
43
44} // anonymous namespace
45
46
47namespace SG {
48
49
61 (const SG::IConstAuxStore& orig,
62 SG::IAuxStore& copy,
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
213void 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
Handle mappings between names and auxid_t.
Interface providing I/O for a generic auxiliary store.
Interface for non-const operations on an auxiliary store.
Interface for const operations on an auxiliary store.
static Double_t sz
static Double_t ss
Hold thinning decisions for one container.
bool test(bit_t bit) const
Test to see if a bit is set.
Hold information about an option setting request.
Handle mappings between names and auxid_t.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Manage lookup of vectors of auxiliary data.
Interface providing I/O for a generic auxiliary store.
Definition IAuxStoreIO.h:44
Interface for non-const operations on an auxiliary store.
Definition IAuxStore.h:48
Abstract interface for manipulating vectors of arbitrary types.
Interface for const operations on an auxiliary store.
virtual const SG::auxid_set_t & getDecorIDs() const =0
Return a set of identifiers for decorations in this store.
virtual const IAuxTypeVector * linkedVector(SG::auxid_t) const
Return interface for a linked variable.
virtual const SG::auxid_set_t & getAuxIDs() const =0
Return a set of identifiers for existing data items in this store.
virtual const void * getData(SG::auxid_t auxid) const =0
Return the data vector for one aux data item.
virtual size_t size() const =0
Return the number of elements in the store.
Container to hold aux data to be stored in a packed form.
const PackedParameters & parms() const
Return the packing parameters for this container.
Describe how the contents of a PackedContainer are to be saved.
bool isSigned() const
Are elements being written as signed numbers?
bool isFloat() const
Are elements being written as floating-point numbers?
uint8_t nbits() const
The number of bits used to store each element.
bool rounding() const
Should floats be rounded during writing?
uint8_t nmantissa() const
The number of bits used for the mantissa portion of a float-point representation, excluding a sign bi...
float scale() const
Return the scale for floating-point numbers.
Hold thinning decisions for one container.
bool thinned(size_t ndx) const
Return true if element ndx should be thinned.
size_t thinnedSize() const
Return the size of the container being thinned after thinning.
Hold thinning/slimming information for a given object.
A set of aux data identifiers.
Definition AuxTypes.h:47
Helper to copy an aux store while applying thinning.
Helper for emitting error messages.
#define ATHCONTAINERS_WARNING(ctx, msg)
Definition error.h:57
int r
Definition globals.cxx:22
Forward declaration.
void copyAuxStoreThinned(const SG::IConstAuxStore &orig, SG::IAuxStore &copy, const SG::ThinningInfo *info)
Helper to copy an aux store while applying thinning.
static const auxid_t null_auxid
To signal no aux data item.
Definition AuxTypes.h:30
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.
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
Helper to disable undefined behavior sanitizer for a function.
#define NO_SANITIZE_UNDEFINED