ATLAS Offline Software
Loading...
Searching...
No Matches
CP::SystematicsCache< CalibData > Class Template Referencefinal

helper class to cache systematics varied calibration constants inside a ISystematicsTool or IRentrantSystematicsTool More...

#include <SystematicsCache.h>

Inheritance diagram for CP::SystematicsCache< CalibData >:
Collaboration diagram for CP::SystematicsCache< CalibData >:

Public Member Functions

template<typename T2>
 SystematicsCache (T2 *val_parent)
void initialize (CP::SystematicSet val_affectingSystematics, std::function< StatusCode(const CP::SystematicSet &sys, CalibData &result)> val_calc) noexcept
 initialize with the list of affecting systematics and a function to calculate the calibration data for each systematic
const CP::SystematicSetaffectingSystematics () const noexcept
 the list of affecting systematics
bool isAffectedBySystematic (const SystematicVariation &systematic) const
 whether we are affected by the given systematic variation
StatusCode get (const CP::SystematicSet &sys, const CalibData *&result) const
 get the pointer to the cached calibration data for the given systematic, calculating it if necessary
StatusCode add (const CP::SystematicSet &sys, CalibData value)
 add an individual systematic variation
StatusCode add (const SystematicVariation &variation, CalibData value)
MsgStream & msg () const
MsgStream & msg (const MSG::Level lvl) const
bool msgLvl (const MSG::Level lvl) const
 Test the output level of the object.

Private Attributes

CP::SystematicSet m_affectingSystematics
 the list of affecting systematics
std::function< StatusCode(const CP::SystematicSet &sys, CalibData &result)> m_calc
 the function to calculate the calibration data for a given systematics
tbb::concurrent_unordered_map< CP::SystematicSet, std::shared_ptr< const CalibData >, SystematicSetHash > m_cache ATLAS_THREAD_SAFE
 the cache of previously calculated calibration data
std::mutex m_calcMutex
 a mutex to protext against concurrent execution of m_calc
std::function< MsgStream &()> m_msg
 the message stream we use

Detailed Description

template<typename CalibData>
class CP::SystematicsCache< CalibData >

helper class to cache systematics varied calibration constants inside a ISystematicsTool or IRentrantSystematicsTool

The general pattern for how systematics are supposed to be implemented inside systematics tools is that the first time a specific systematic variation is requested the tool should calculate the calibration constants for that particular systematic, store it in an (unordered) map and look it up from that map in all subsequent uses. This class tries to implement that particular logic in a thread-safe and (reasonably) fool-proof way.

The basic way to use this class is:

class MyTool : public asg::AsgTool, virtual public IMyTool {
...
struct ConfigData {...};
CP::SystematicsCache<ConfigData> m_calibCache {this};
const ConfigData *m_currentConfig {nullptr};
};
StatusCode MyTool :: initialize () {
...
CP::SystematicSet affectingSystematics = ...;
ANA_CHECK (m_calibCache.initialize (std::move (affectingSystematics),
[this] (const CP::SystematicSet& sys,
ConfigData& myconfig) {
myconfig = ...;
return StatusCode;});
ANA_CHECK (applySystematicVariation (CP::SystematicSet()));
return StatusCode::SUCCESS;
}
StatusCode MyTool :: applySystematicVariation (const CP::SystematicSet& sys, ...) {
return m_calibCache.get (sys, m_currentConfig);
}
CP::SystematicSet MyTool :: affectingSystematics () const {
return m_calibCache.affectingSystematics(); }
#define ANA_CHECK(EXP)
check whether the given expression was successful
helper class to cache systematics varied calibration constants inside a ISystematicsTool or IRentrant...
const CP::SystematicSet & affectingSystematics() const noexcept
the list of affecting systematics
Base class for the dual-use tool implementation classes.
Definition AsgTool.h:47
::StatusCode StatusCode
StatusCode definition for legacy code.

There are not too many constraints on the structure and lambda function, just make sure the structure is default constructable and the lambda function is safe to execute while a lock is held (i.e. if you acquire a lock make sure not to create a dead-lock). It is currently not anticipated that this lambda function needs to be thread-safe itself (even if multiple threads use the same tool, they would still just run through the same systematics in the same order). It is guaranteed that the function is called exactly once for each unique set of affecting systematics, and that only a single copy of the calibration data is stored for each unique set of affecting systematics.

Note that while the above example uses a lambda function it is probably a good idea to write this as a separate helper function and have the lambda function wrap that helper. The rationale for that recommendation is that this is usually a rather long function with tedious logic and making it part of initialize can affect the readability of either one.

Definition at line 84 of file SystematicsCache.h.

Constructor & Destructor Documentation

◆ SystematicsCache()

template<typename CalibData>
template<typename T2>
CP::SystematicsCache< CalibData >::SystematicsCache ( T2 * val_parent)

Function Implementations

Definition at line 150 of file SystematicsCache.h.

153 {}
AsgMessagingForward(T *owner)
forwarding constructor

Member Function Documentation

◆ add() [1/2]

template<typename CalibData>
StatusCode CP::SystematicsCache< CalibData >::add ( const CP::SystematicSet & sys,
CalibData value )

add an individual systematic variation

Definition at line 254 of file SystematicsCache.h.

256 {
258 if (emplace_result.second == false)
259 {
260 ANA_MSG_ERROR ("failed to add systematic, already present: " << sys.name());
261 return StatusCode::FAILURE;
262 }
263
264 for (const auto& var : sys)
266
267 return StatusCode::SUCCESS;
268 }
#define ANA_MSG_ERROR(xmsg)
Macro printing error messages.
CP::SystematicSet m_affectingSystematics
the list of affecting systematics

◆ add() [2/2]

template<typename CalibData>
StatusCode CP::SystematicsCache< CalibData >::add ( const SystematicVariation & variation,
CalibData value )

Definition at line 273 of file SystematicsCache.h.

275 {
277 sys.insert (variation);
278 return add (sys, std::move (value));
279 }
StatusCode add(const CP::SystematicSet &sys, CalibData value)
add an individual systematic variation

◆ affectingSystematics()

template<typename CalibData>
const CP::SystematicSet & CP::SystematicsCache< CalibData >::affectingSystematics ( ) const
noexcept

the list of affecting systematics

Definition at line 169 of file SystematicsCache.h.

171 {
173 }

◆ get()

template<typename CalibData>
StatusCode CP::SystematicsCache< CalibData >::get ( const CP::SystematicSet & sys,
const CalibData *& result ) const

get the pointer to the cached calibration data for the given systematic, calculating it if necessary

Definition at line 188 of file SystematicsCache.h.

190 {
191 // fast-path, check if we already calculated this
192 auto iter = m_cache.find (sys);
193 if (ATH_LIKELY (iter != m_cache.end())) //[[likely]], removed until C++20 support
194 {
195 result = iter->second.get();
196 return StatusCode::SUCCESS;
197 }
198
199 // create a lock to prevent the concurrent (or duplicate)
200 // execution of the \ref m_calc function. if that function is
201 // thread-safe this lock is not strictly necessary. however,
202 // given that it is hard to enforce that the function is indeed
203 // thread-safe and there are essentially no performance gains to
204 // be had, this seems safer (unless \ref m_calc acquires mutexes
205 // in a way that causes a dead-lock).
207
208 // check if another thread already calculated this value while we
209 // acquired the lock
210 iter = m_cache.find (sys);
211 if (iter != m_cache.end())
212 {
213 result = iter->second.get();
214 return StatusCode::SUCCESS;
215 }
216
217 // we will only ever calculate the systematics for our set of
218 // affecting systematics, any systematics that are not affecting
219 // us will be ignored
222
224 {
225 // check if our affecting systematics are known already
226 auto iter = m_cache.find (mysys);
227 if (iter != m_cache.end())
228 mycalib = iter->second;
229 else
230 {
231 // this will now actually calculate the systematics. note
232 // that if this fails, nothing gets cached, but we should also
233 // be aborting
236
237 // store for the affecting systematic
238 auto emplace_result = m_cache.emplace (mysys, value);
239 mycalib = emplace_result.first->second;
240 }
241 }
242
243 // store for user requested systematics as well, which may or may
244 // not be the same as the affecting systematics, but if it is
245 // already there, this will do nothing.
246 m_cache.emplace (sys, mycalib);
247 result = mycalib.get();
248 return StatusCode::SUCCESS;
249 }
StatusCode get(const CP::SystematicSet &sys, const CalibData *&result) const
get the pointer to the cached calibration data for the given systematic, calculating it if necessary
std::function< StatusCode(const CP::SystematicSet &sys, CalibData &result)> m_calc
the function to calculate the calibration data for a given systematics
std::mutex m_calcMutex
a mutex to protext against concurrent execution of m_calc

◆ initialize()

template<typename CalibData>
void CP::SystematicsCache< CalibData >::initialize ( CP::SystematicSet val_affectingSystematics,
std::function< StatusCode(const CP::SystematicSet &sys, CalibData &result)> val_calc )
noexcept

initialize with the list of affecting systematics and a function to calculate the calibration data for each systematic

Definition at line 157 of file SystematicsCache.h.

◆ isAffectedBySystematic()

template<typename CalibData>
bool CP::SystematicsCache< CalibData >::isAffectedBySystematic ( const SystematicVariation & systematic) const

whether we are affected by the given systematic variation

this is mostly for implementing the ISystematicsTool interface and should probably not be used by anyone.

Definition at line 178 of file SystematicsCache.h.

180 {
181 // this is not technically correct, but what a lot of people do
183 }

◆ msg() [1/2]

template<typename CalibData>
MsgStream & asg::AsgMessagingForward::msg ( ) const

Public Members

Definition at line 54 of file AsgMessagingForward.cxx.

25 {
26 return m_msg();
27 }
std::function< MsgStream &()> m_msg
the message stream we use

◆ msg() [2/2]

template<typename CalibData>
MsgStream & asg::AsgMessagingForward::msg ( const MSG::Level lvl) const

Public Members

Definition at line 61 of file AsgMessagingForward.cxx.

30 {
31 MsgStream& msg = m_msg ();
32 msg << lvl;
33 return msg;
34 }
MsgStream & msg() const

◆ msgLvl()

bool asg::AsgMessagingForward::msgLvl ( const MSG::Level lvl) const
inherited

Test the output level of the object.

Parameters
lvlThe message level to test against
Returns
boolean Indicting if messages at given level will be printed
true If messages at level "lvl" will be printed

Definition at line 11 of file AsgMessagingForward.cxx.

12 {
13 MsgStream& msg = m_msg();
14 if (msg.level() <= lvl)
15 {
16 msg << lvl;
17 return true;
18 } else
19 {
20 return false;
21 }
22 }
MsgStream & msg() const
The standard message stream.

Member Data Documentation

◆ ATLAS_THREAD_SAFE

template<typename CalibData>
tbb::concurrent_unordered_map<CP::SystematicSet,std::shared_ptr<const CalibData>,SystematicSetHash> m_cache CP::SystematicsCache< CalibData >::ATLAS_THREAD_SAFE
mutableprivate

the cache of previously calculated calibration data

Definition at line 135 of file SystematicsCache.h.

◆ m_affectingSystematics

template<typename CalibData>
CP::SystematicSet CP::SystematicsCache< CalibData >::m_affectingSystematics
private

the list of affecting systematics

Private Members

Definition at line 128 of file SystematicsCache.h.

◆ m_calc

template<typename CalibData>
std::function<StatusCode (const CP::SystematicSet& sys, CalibData& result)> CP::SystematicsCache< CalibData >::m_calc
private

the function to calculate the calibration data for a given systematics

Definition at line 132 of file SystematicsCache.h.

◆ m_calcMutex

template<typename CalibData>
std::mutex CP::SystematicsCache< CalibData >::m_calcMutex
mutableprivate

a mutex to protext against concurrent execution of m_calc

see the comment inside get for a detailed explanation of why this is used/needed.

Definition at line 141 of file SystematicsCache.h.

◆ m_msg

std::function<MsgStream& ()> asg::AsgMessagingForward::m_msg
privateinherited

the message stream we use

This used to be a simple pointer to the MsgStream itself, but in AthenaMT the actual object used is local to the thread. So instead of pointing to it directly we are now using a function to look it up, which will get the thread-local object.

Definition at line 77 of file AsgMessagingForward.h.


The documentation for this class was generated from the following file: