diff --git a/Reconstruction/eflowRec/eflowRec/eflowCellIntegrator.h b/Reconstruction/eflowRec/eflowRec/eflowCellIntegrator.h index 9552c649688ca7ee6decd28e7373266ed1824184..2a6c92a1118f324b5994ca4067d88deacf9aa271 100644 --- a/Reconstruction/eflowRec/eflowRec/eflowCellIntegrator.h +++ b/Reconstruction/eflowRec/eflowRec/eflowCellIntegrator.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ /* @@ -125,14 +125,14 @@ public: inline void setEtaSq(double xSq) { m_etaSq = xSq; } - inline double evaluateStdExp(double rSq) { return m_norm * exp(-rSq * m_oneOverTwoSigmaSq); } - inline double evaluateLookupExp(double rSq) { return m_lookupExp->evaluate(rSq * m_oneOverTwoSigmaSq)*m_norm; } + inline double evaluateStdExp(double rSq) const { return m_norm * exp(-rSq * m_oneOverTwoSigmaSq); } + inline double evaluateLookupExp(double rSq) const { return m_lookupExp->evaluate(rSq * m_oneOverTwoSigmaSq)*m_norm; } /** The evaluate method for the integration. The implementation depends on the template parameter */ inline double evaluate(double y); private: - eflowLookupExp* m_lookupExp; + const eflowLookupExp* m_lookupExp; double m_oneOverTwoSigmaSq; double m_norm; double m_etaSq; diff --git a/Reconstruction/eflowRec/eflowRec/eflowLayerIntegrator.h b/Reconstruction/eflowRec/eflowRec/eflowLayerIntegrator.h index 0b40f27bde0bfa031ee4010784c422b4ade9cacc..3cad7d660950c6a1ae9b4eaf4cd7c2d4736cf8d9 100644 --- a/Reconstruction/eflowRec/eflowRec/eflowLayerIntegrator.h +++ b/Reconstruction/eflowRec/eflowRec/eflowLayerIntegrator.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ #ifndef EFLOWLAYERINTEGRATOR_H @@ -44,8 +44,8 @@ class eflowLayerIntegrator { void measureNewClus(const xAOD::CaloCluster* clus, const eflowTrackCaloPoints& trackCalo); void measureNewClus(eflowTrackClusterLink* trackClusterLink); - void measureNewClus(std::vector<eflowRecCluster*> efRecClusters, eflowRecTrack* track); - void measureNewClus(std::vector<xAOD::CaloCluster*> clusVec, const eflowTrackCaloPoints& trackCalo); + void measureNewClus(const std::vector<eflowRecCluster*>& efRecClusters, eflowRecTrack* track); + void measureNewClus(const std::vector<xAOD::CaloCluster*>& clusVec, const eflowTrackCaloPoints& trackCalo); eflowFirstIntENUM getFirstIntLayer() const; diff --git a/Reconstruction/eflowRec/eflowRec/eflowLookupExp.h b/Reconstruction/eflowRec/eflowRec/eflowLookupExp.h index 9515dae2b9a63516b6ae37a5919138972ea64786..253098a40c11c9f0ee425e5fd1a874513ce9220b 100644 --- a/Reconstruction/eflowRec/eflowRec/eflowLookupExp.h +++ b/Reconstruction/eflowRec/eflowRec/eflowLookupExp.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ /* @@ -21,24 +21,7 @@ /** Lookup-table based exponential function to save CPU time, which is used by eflowCellIntegrator */ class eflowLookupExp{ public: - static eflowLookupExp* getInstance(int nExpBins = 50, int nExpSubBins = 1000){ - - //Creation of the unique_ptr is not thread-safe - therefore we get a mutex and pass it to a lock-guard - //The lock is released automatically when getInstance returns - //The mutex is static so that all threads check the status of the *same* mutex - static std::mutex mutex_instance; - std::lock_guard<std::mutex> lock(mutex_instance); - - if ( !m_instance) { - m_instance = std::make_unique<eflowLookupExp>(nExpBins, nExpSubBins); - } else { - /* Make sure the requested bin numbers are consistent with the existing instance */ - if ( (m_instance->m_nExpBins != nExpBins) || (m_instance->m_nExpSubBins != nExpSubBins) ) { - throw std::runtime_error("eflowLookupExp: Instance with different bin numbers than existing requested!"); - } - } - return m_instance.get(); - } + static const eflowLookupExp* getInstance(int nExpBins = 50, int nExpSubBins = 1000); //private: eflowLookupExp(int nExpBins, int nExpSubBins) : @@ -52,14 +35,11 @@ public: for (int iSub = 0; iSub <= nExpSubBins; ++iSub){ m_subExp[iSub] = exp(-substep* iSub); } - //initialise to nullptr, in this explicit instance it wil never be used. - //Hence it will always be a nullptr - m_instance = nullptr; } public: ~eflowLookupExp(){ } - double evaluate(double x) { + double evaluate(double x) const { int iExpBin = (int) x; int iSubBin(((x-iExpBin)*m_nExpSubBins)); @@ -74,7 +54,6 @@ private: int m_nExpSubBins; std::vector<double> m_exp; std::vector<double> m_subExp; - static std::unique_ptr<eflowLookupExp> m_instance; }; diff --git a/Reconstruction/eflowRec/eflowRec/eflowTrackClusterLink.h b/Reconstruction/eflowRec/eflowRec/eflowTrackClusterLink.h index 8c28ec9ec3149a301c36b0660b54b3984dd9c0e8..22d32cc1cb51bf24390e10aeac4cdaf1ccd61193 100644 --- a/Reconstruction/eflowRec/eflowRec/eflowTrackClusterLink.h +++ b/Reconstruction/eflowRec/eflowRec/eflowTrackClusterLink.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ /* @@ -13,7 +13,7 @@ #define EFLOWTRACKCLUSTERLINK_H_ #include <utility> -#include <map> +#include <unordered_map> #include <vector> #include <iostream> #include <mutex> @@ -27,36 +27,21 @@ class eflowRecTrack; class eflowRecCluster; /** - Stores pointers to an eflowRecTrack and an eflowRecCluster. These pointers are inserted in the InstanceMap stored. We also store a vector of energy density, around the track impact point in each calorimeter layer, corresponding to the layers in the calorimeter. + Stores pointers to an eflowRecTrack and an eflowRecCluster. + These pointers kept in a cache internal to the getInstance function. + We also store a vector of energy density, around the track impact point + in each calorimeter layer, corresponding to the layers in the calorimeter. */ class eflowTrackClusterLink { -private: - typedef std::map<std::pair<eflowRecTrack*, eflowRecCluster*>, std::unique_ptr<eflowTrackClusterLink> > InstanceMap; - public: eflowTrackClusterLink(eflowRecTrack* track, eflowRecCluster* cluster) : m_track(track), m_cluster(cluster) { } virtual ~eflowTrackClusterLink() { } - static eflowTrackClusterLink* getInstance(eflowRecTrack* track, eflowRecCluster* cluster){ - std::pair<eflowRecTrack*, eflowRecCluster*> thisPair(std::make_pair(track, cluster)); - - //Read and write from the map is not thread-safe - therefore we get a mutex and pass it to a lock-guard - //The lock is released automatically when getInstance returns - //The mutex is static so that all threads check the status of the *same* mutex - static std::mutex mutex_instance; - std::lock_guard<std::mutex> lock(mutex_instance); - /* The find returns a valid iterator. If there is no existing entry it returns the end iterator */ - InstanceMap::iterator mapIterator = m_instances.find(thisPair); - - if (m_instances.end() == mapIterator){ - /* If no existing entry we create a new unique_ptr and add an entry into the map */ - m_instances[thisPair] = std::make_unique<eflowTrackClusterLink>(track,cluster); - return m_instances[thisPair].get(); - } - else return (*mapIterator).second.get(); - } + static eflowTrackClusterLink* getInstance(eflowRecTrack* track, + eflowRecCluster* cluster, + const EventContext& ctx = Gaudi::Hive::currentContext()); eflowRecCluster* getCluster() const { return m_cluster; } eflowRecTrack* getTrack() const { return m_track; } @@ -67,13 +52,26 @@ public: const std::vector<double>& getClusterIntegral() const { return m_clusterIntegral; } private: + using key_t = std::pair<eflowRecTrack*, eflowRecCluster*>; + struct Hasher + { + size_t operator() (const key_t& k) const + { + return std::hash<eflowRecTrack*>()(k.first) ^ + std::hash<eflowRecCluster*>()(k.second); + } + }; + struct Cache + { + std::mutex m_mutex; + std::unordered_map<key_t, std::unique_ptr<eflowTrackClusterLink>, Hasher > m_map; + EventContext::ContextEvt_t m_evt = static_cast<EventContext::ContextEvt_t>(-1); + }; + eflowRecTrack* m_track; eflowRecCluster* m_cluster; std::vector<double> m_clusterIntegral; - - static InstanceMap m_instances; - }; #endif /* EFLOWTRACKCLUSTERLINK_H_ */ diff --git a/Reconstruction/eflowRec/src/PFCellLevelSubtractionTool.cxx b/Reconstruction/eflowRec/src/PFCellLevelSubtractionTool.cxx index 6461f12d191356abc2edb0bbcdc9ad74e464c396..d18a13b629e24cb98f97cfa719e6f70f8486d8a6 100644 --- a/Reconstruction/eflowRec/src/PFCellLevelSubtractionTool.cxx +++ b/Reconstruction/eflowRec/src/PFCellLevelSubtractionTool.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ #include "eflowRec/PFCellLevelSubtractionTool.h" @@ -112,6 +112,8 @@ void PFCellLevelSubtractionTool::execute(eflowCaloObjectContainer* theEflowCaloO unsigned int PFCellLevelSubtractionTool::matchAndCreateEflowCaloObj(unsigned int n, eflowData& data) const { unsigned int nMatches(0); + const EventContext& ctx = Gaudi::Hive::currentContext(); + /* Create eflowTrackClusterLink after matching */ unsigned int nTrack = data.tracks->size(); for (unsigned int iTrack=0; iTrack<nTrack; ++iTrack) { @@ -131,7 +133,7 @@ unsigned int PFCellLevelSubtractionTool::matchAndCreateEflowCaloObj(unsigned int for (auto& matchpair : bestClusters_02) { eflowRecCluster* theCluster = matchpair.first; float distancesq = matchpair.second; - eflowTrackClusterLink* trackClusterLink = eflowTrackClusterLink::getInstance(thisEfRecTrack, theCluster); + eflowTrackClusterLink* trackClusterLink = eflowTrackClusterLink::getInstance(thisEfRecTrack, theCluster, ctx); if(distancesq<0.15*0.15) { // Narrower cone is a subset of the selected clusters // Distance returned is deltaR^2 @@ -147,7 +149,7 @@ unsigned int PFCellLevelSubtractionTool::matchAndCreateEflowCaloObj(unsigned int nMatches++; for (auto& matchpair : bestClusters) { eflowRecCluster* theCluster = matchpair.first; - eflowTrackClusterLink* trackClusterLink = eflowTrackClusterLink::getInstance(thisEfRecTrack, theCluster); + eflowTrackClusterLink* trackClusterLink = eflowTrackClusterLink::getInstance(thisEfRecTrack, theCluster, ctx); thisEfRecTrack->addClusterMatch(trackClusterLink); theCluster->addTrackMatch(trackClusterLink); } diff --git a/Reconstruction/eflowRec/src/PFRecoverSplitShowersTool.cxx b/Reconstruction/eflowRec/src/PFRecoverSplitShowersTool.cxx index 06b16f46c9774355cd3a667d461bec66565034ec..8991d32b5f540f188da66fb89b9b1d69fe15a7b6 100644 --- a/Reconstruction/eflowRec/src/PFRecoverSplitShowersTool.cxx +++ b/Reconstruction/eflowRec/src/PFRecoverSplitShowersTool.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ #include "eflowRec/PFRecoverSplitShowersTool.h" @@ -141,6 +141,9 @@ void PFRecoverSplitShowersTool::fillTracksToRecover(eflowData& data) const { } unsigned int PFRecoverSplitShowersTool::matchAndCreateEflowCaloObj(eflowData& data) const { + + const EventContext& ctx = Gaudi::Hive::currentContext(); + /* Cache the original number of eflowCaloObjects */ const unsigned int nCaloObj = data.caloObjects->size(); @@ -176,7 +179,7 @@ unsigned int PFRecoverSplitShowersTool::matchAndCreateEflowCaloObj(eflowData& da eflowRecCluster* thisEFRecCluster = trkClusLink->getCluster(); // Look up whether this cluster is intended for recovery if( data.clustersToConsider.find(trkClusLink->getCluster()) == data.clustersToConsider.end() ) {continue;} - eflowTrackClusterLink* trackClusterLink = eflowTrackClusterLink::getInstance(thisEfRecTrack,thisEFRecCluster); + eflowTrackClusterLink* trackClusterLink = eflowTrackClusterLink::getInstance(thisEfRecTrack,thisEFRecCluster, ctx); thisEfRecTrack->addClusterMatch(trackClusterLink); thisEFRecCluster->addTrackMatch(trackClusterLink); } diff --git a/Reconstruction/eflowRec/src/eflowLayerIntegrator.cxx b/Reconstruction/eflowRec/src/eflowLayerIntegrator.cxx index 39f1e0d5725a6c67a86cae86ab914cb7e9753280..388b0ed874fe507b4c0973c173e9d80658f28e78 100644 --- a/Reconstruction/eflowRec/src/eflowLayerIntegrator.cxx +++ b/Reconstruction/eflowRec/src/eflowLayerIntegrator.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ /******************************************************************** @@ -129,23 +129,20 @@ void eflowLayerIntegrator::addToAllClustersIntegral(const std::vector<double>& c } } -void eflowLayerIntegrator::measureNewClus(std::vector<xAOD::CaloCluster*> clusVec, const eflowTrackCaloPoints& trackCalo) { +void eflowLayerIntegrator::measureNewClus(const std::vector<xAOD::CaloCluster*>& clusVec, const eflowTrackCaloPoints& trackCalo) { resetAllClustersIntegralForNewTrack(trackCalo); - std::vector<xAOD::CaloCluster*>::iterator itCluster = clusVec.begin(); - std::vector<xAOD::CaloCluster*>::iterator itClusterEnd = clusVec.end(); - for (; itCluster != itClusterEnd; itCluster++){ - measureCluster(*itCluster, trackCalo); + for (xAOD::CaloCluster* cluster : clusVec) { + measureCluster(cluster, trackCalo); } } -void eflowLayerIntegrator::measureNewClus(std::vector<eflowRecCluster*> efRecClusters, eflowRecTrack* track) { +void eflowLayerIntegrator::measureNewClus(const std::vector<eflowRecCluster*>& efRecClusters, eflowRecTrack* track) { resetAllClustersIntegralForNewTrack(track->getTrackCaloPoints()); - std::vector<eflowRecCluster*>::iterator itCluster = efRecClusters.begin(); - std::vector<eflowRecCluster*>::iterator endCluster = efRecClusters.end(); - for (; itCluster != endCluster; itCluster++){ - measureCluster(eflowTrackClusterLink::getInstance(track, *itCluster)); + const EventContext& ctx = Gaudi::Hive::currentContext(); + for (eflowRecCluster* cluster : efRecClusters) { + measureCluster(eflowTrackClusterLink::getInstance(track, cluster, ctx)); } } diff --git a/Reconstruction/eflowRec/src/eflowLookupExp.cxx b/Reconstruction/eflowRec/src/eflowLookupExp.cxx index 32bf9c4e015c8d32252a6e841a87fdf80fae1d9e..4f0609ab200dcad1d35e520a7f2663705109ff0a 100644 --- a/Reconstruction/eflowRec/src/eflowLookupExp.cxx +++ b/Reconstruction/eflowRec/src/eflowLookupExp.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ /* @@ -10,8 +10,21 @@ */ #include "eflowRec/eflowLookupExp.h" +#include "CxxUtils/CachedUniquePtr.h" +#include "CxxUtils/checker_macros.h" -//eflowLookupExp* eflowLookupExp::m_instance = nullptr; -std::unique_ptr<eflowLookupExp> eflowLookupExp::m_instance = nullptr; +const eflowLookupExp* eflowLookupExp::getInstance(int nExpBins /*= 50*/, + int nExpSubBins /*= 1000*/) +{ + static CxxUtils::CachedUniquePtr<eflowLookupExp> cached ATLAS_THREAD_SAFE; + if (!cached) { + cached.set (std::make_unique<eflowLookupExp>(nExpBins, nExpSubBins)); + } + if ( (cached->m_nExpBins != nExpBins) || (cached->m_nExpSubBins != nExpSubBins) ) + { + throw std::runtime_error("eflowLookupExp: Instance with different bin numbers than existing requested!"); + } + return cached.get(); +} diff --git a/Reconstruction/eflowRec/src/eflowTrackClusterLink.cxx b/Reconstruction/eflowRec/src/eflowTrackClusterLink.cxx index 1b3fe56f21fc3e8dcdff568fcfda9a03dbf470d6..a207efc41a161826bfdaa2d172d15710b1e3b887 100644 --- a/Reconstruction/eflowRec/src/eflowTrackClusterLink.cxx +++ b/Reconstruction/eflowRec/src/eflowTrackClusterLink.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration */ /* @@ -10,5 +10,28 @@ */ #include "eflowRec/eflowTrackClusterLink.h" +#include "AthenaKernel/SlotSpecificObj.h" +#include "CxxUtils/checker_macros.h" -std::map<std::pair<eflowRecTrack*, eflowRecCluster*>, std::unique_ptr<eflowTrackClusterLink> > eflowTrackClusterLink::m_instances; + + +eflowTrackClusterLink* +eflowTrackClusterLink::getInstance(eflowRecTrack* track, + eflowRecCluster* cluster, + const EventContext& ctx) +{ + static SG::SlotSpecificObj<Cache> slots ATLAS_THREAD_SAFE; + Cache& c = *slots.get (ctx); + std::lock_guard lock (c.m_mutex); + if (c.m_evt != ctx.evt()) { + c.m_map.clear(); + c.m_evt = ctx.evt(); + } + + key_t key (track, cluster); + auto it = c.m_map.try_emplace (key, std::unique_ptr<eflowTrackClusterLink>()).first; + if (!it->second) { + it->second = std::make_unique<eflowTrackClusterLink>(track,cluster); + } + return it->second.get(); +}