ATLAS Offline Software
Public Member Functions | Private Attributes | List of all members
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 More...
 
const CP::SystematicSetaffectingSystematics () const noexcept
 the list of affecting systematics More...
 
bool isAffectedBySystematic (const SystematicVariation &systematic) const
 whether we are affected by the given systematic variation More...
 
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 More...
 
StatusCode add (const CP::SystematicSet &sys, CalibData value)
 add an individual systematic variation More...
 
StatusCode add (const SystematicVariation &variation, CalibData value)
 
bool msgLvl (const MSG::Level lvl) const
 Test the output level of the object. More...
 
MsgStream & msg () const
 The standard message stream. More...
 
MsgStream & msg (const MSG::Level lvl) const
 The standard message stream. More...
 

Private Attributes

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

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};
};
...
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(); }

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.

152  : AsgMessagingForward (val_parent)
153  {}

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  {
257  auto emplace_result = m_cache.emplace (sys, std::make_shared<CalibData> (std::move (value)));
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  }

◆ 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  {
276  SystematicSet sys;
277  sys.insert (variation);
278  return add (sys, std::move (value));
279  }

◆ affectingSystematics()

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

the list of affecting systematics

Definition at line 169 of file SystematicsCache.h.

171  {
172  return m_affectingSystematics;
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).
206  std::lock_guard<std::mutex> lock (m_calcMutex);
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
220  CP::SystematicSet mysys;
222 
223  std::shared_ptr<const CalibData> mycalib;
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
234  auto value = std::make_shared<CalibData> ();
235  ANA_CHECK (m_calc (mysys, *value));
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  }

◆ 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.

160  {
161  m_calc = std::move (val_calc);
162  m_affectingSystematics = std::move (val_affectingSystematics);
163  m_cache.clear ();
164  }

◆ 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]

MsgStream & asg::AsgMessagingForward::msg ( ) const
inherited

The standard message stream.

Returns
A reference to the default message stream of this object.

Definition at line 24 of file AsgMessagingForward.cxx.

25  {
26  return m_msg();
27  }

◆ msg() [2/2]

MsgStream & asg::AsgMessagingForward::msg ( const MSG::Level  lvl) const
inherited

The standard message stream.

Parameters
lvlThe message level to set the stream to
Returns
A reference to the default message stream, set to level "lvl"

Definition at line 29 of file AsgMessagingForward.cxx.

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

◆ 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  }

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:
asg::AsgMessagingForward::m_msg
std::function< MsgStream &()> m_msg
the message stream we use
Definition: AsgMessagingForward.h:77
beamspotnt.var
var
Definition: bin/beamspotnt.py:1394
asg::AsgTool
Base class for the dual-use tool implementation classes.
Definition: AsgTool.h:47
get_generator_info.result
result
Definition: get_generator_info.py:21
initialize
void initialize()
Definition: run_EoverP.cxx:894
CP::SystematicSet
Class to wrap a set of SystematicVariations.
Definition: SystematicSet.h:31
ANA_MSG_ERROR
#define ANA_MSG_ERROR(xmsg)
Macro printing error messages.
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:294
athena.value
value
Definition: athena.py:122
ANA_CHECK
#define ANA_CHECK(EXP)
check whether the given expression was successful
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:324
mapkey::sys
@ sys
Definition: TElectronEfficiencyCorrectionTool.cxx:42
asg::AsgMessagingForward::msg
MsgStream & msg() const
The standard message stream.
Definition: AsgMessagingForward.cxx:24
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
CP::SystematicsCache::m_calc
std::function< StatusCode(const CP::SystematicSet &sys, CalibData &result)> m_calc
the function to calculate the calibration data for a given systematics
Definition: SystematicsCache.h:132
CP::SystematicSet::end
const_iterator end() const
description: const iterator to the end of the set
Definition: SystematicSet.h:59
asg::AsgMessagingForward::AsgMessagingForward
AsgMessagingForward(T *owner)
forwarding constructor
Definition: AsgMessagingForward.h:83
CP::SystematicSet::insert
void insert(const SystematicVariation &systematic)
description: insert a systematic into the set
Definition: SystematicSet.cxx:88
CP::SystematicsCache::m_calcMutex
std::mutex m_calcMutex
a mutex to protext against concurrent execution of m_calc
Definition: SystematicsCache.h:141
CP::SystematicSet::find
iterator find(const SystematicVariation &sys) const
description: find an element in the set
Definition: SystematicSet.h:63
ATH_LIKELY
#define ATH_LIKELY(x)
Definition: AthUnlikelyMacros.h:16
CP::SystematicsCache
helper class to cache systematics varied calibration constants inside a ISystematicsTool or IRentrant...
Definition: SystematicsCache.h:85
CP::SystematicsCache::m_affectingSystematics
CP::SystematicSet m_affectingSystematics
the list of affecting systematics
Definition: SystematicsCache.h:128
CP::SystematicsCache::affectingSystematics
const CP::SystematicSet & affectingSystematics() const noexcept
the list of affecting systematics
Definition: SystematicsCache.h:170
CP::SystematicsCache::add
StatusCode add(const CP::SystematicSet &sys, CalibData value)
add an individual systematic variation
Definition: SystematicsCache.h:255
CP::SystematicSet::filterForAffectingSystematics
static StatusCode filterForAffectingSystematics(const SystematicSet &systConfig, const SystematicSet &affectingSystematics, SystematicSet &filteredSystematics)
description: filter the systematics for the affected systematics returns: success guarantee: strong f...
Definition: SystematicSet.cxx:213