From 6abf73f3c2ee0074034937bff5cfdc663cd3f82d Mon Sep 17 00:00:00 2001 From: Markus Frank <markus.frank@cern.ch> Date: Tue, 12 Jul 2016 14:52:43 +0000 Subject: [PATCH] Optimize G4 hits collections --- DDG4/include/DDG4/Geant4HitCollection.h | 46 ++++++++++++++++++++----- DDG4/include/DDG4/Geant4SensDetAction.h | 3 +- DDG4/plugins/Geant4SDActions.cpp | 15 ++++---- DDG4/src/Geant4HitCollection.cpp | 13 ++++++- 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/DDG4/include/DDG4/Geant4HitCollection.h b/DDG4/include/DDG4/Geant4HitCollection.h index d65ef7766..f36d9a25c 100644 --- a/DDG4/include/DDG4/Geant4HitCollection.h +++ b/DDG4/include/DDG4/Geant4HitCollection.h @@ -198,13 +198,15 @@ namespace DD4hep { * \version 1.0 * \ingroup DD4HEP_SIMULATION */ - class Geant4HitCollection: public G4VHitsCollection { + class Geant4HitCollection : public G4VHitsCollection { public: /** Local type declarations */ /// Hit wrapper typedef std::vector<Geant4HitWrapper> WrappedHits; /// Hit manipulator typedef Geant4HitWrapper::HitManipulator Manip; + /// Hit key map for fast random lookup + typedef std::map<VolumeID, size_t> Keys; /// Generic class template to compare/select hits in Geant4HitCollection objects /** @@ -223,6 +225,14 @@ namespace DD4hep { virtual void* operator()(const Geant4HitWrapper& w) const = 0; }; + union CollectionFlags { + unsigned long value; + struct BitItems { + unsigned repeatedLookup:1; + unsigned mappedLookup:1; + } bits; + }; + protected: /// The collection of hit pointers in the wrapped format WrappedHits m_hits; @@ -232,20 +242,18 @@ namespace DD4hep { Manip* m_manipulator; /// Memorize for speedup the last searched hit size_t m_lastHit; + /// Hit key map for fast random lookup + Keys m_keys; /// Optimization flags - union CollectionFlags { - unsigned long value; - struct BitItems { - unsigned repeatedLookup:1; - unsigned mappedLookup:1; - } bits; - } m_flags; + CollectionFlags m_flags; protected: /// Notification to increase the instance counter void newInstance(); /// Find hit in a collection by comparison of attributes void* findHit(const Compare& cmp); + /// Find hit in a collection by comparison of the key + Geant4HitWrapper* findHitByKey(VolumeID key); /// Release all hits from the Geant4 container and pass ownership to the caller void releaseData(const ComponentCast& cast, std::vector<void*>* result); /// Release all hits from the Geant4 container. Ownership stays with the container @@ -279,7 +287,7 @@ namespace DD4hep { { newInstance(); m_hits.reserve(200); - m_flags.value = OPTIMIZE_REPEATEDLOOKUP; + m_flags.value = 0;//OPTIMIZE_REPEATEDLOOKUP; } /// Default destructor virtual ~Geant4HitCollection(); @@ -323,10 +331,29 @@ namespace DD4hep { m_lastHit = m_hits.size(); m_hits.push_back(w); } + /// Add a new hit with a check, that the hit is of the same type + template <typename TYPE> void add(VolumeID key, TYPE* hit_pointer) { + m_lastHit = m_hits.size(); + std::pair<Keys::iterator,bool> ret = m_keys.insert(std::make_pair(key,m_lastHit)); + if ( ret.second ) { + Geant4HitWrapper w(m_manipulator->castHit(hit_pointer)); + m_hits.push_back(w); + return; + } + throw std::runtime_error("Attempt to insert hit with same key to G4 hit-collection "+GetName()); + } /// Find hits in a collection by comparison of attributes template <typename TYPE> TYPE* find(const Compare& cmp) { return (TYPE*) findHit(cmp); } + /// Find hits in a collection by comparison of key value + template <typename TYPE> TYPE* findByKey(VolumeID key) { + Keys::const_iterator i=m_keys.find(key); + if ( i == m_keys.end() ) return 0; + m_lastHit = (*i).second; + TYPE* obj = m_hits.at(m_lastHit); + return obj; + } /// Release all hits from the Geant4 container and pass ownership to the caller template <typename TYPE> std::vector<TYPE*> releaseHits() { std::vector<TYPE*> vec; @@ -334,6 +361,7 @@ namespace DD4hep { releaseData(ComponentCast::instance<TYPE>(), (std::vector<void*>*) &vec); } m_lastHit = ULONG_MAX; + m_keys.clear(); return vec; } /// Release all hits from the Geant4 container and pass ownership to the caller diff --git a/DDG4/include/DDG4/Geant4SensDetAction.h b/DDG4/include/DDG4/Geant4SensDetAction.h index 60b333071..0e6da962a 100644 --- a/DDG4/include/DDG4/Geant4SensDetAction.h +++ b/DDG4/include/DDG4/Geant4SensDetAction.h @@ -312,7 +312,8 @@ namespace DD4hep { /// The true sensitive type of the detector std::string m_sensitiveType; /// Create a new typed hit collection - template <typename TYPE> static Geant4HitCollection* _create(const std::string& det, const std::string& coll, Geant4Sensitive* sd) { + template <typename TYPE> static + Geant4HitCollection* _create(const std::string& det, const std::string& coll, Geant4Sensitive* sd) { return new Geant4HitCollection(det, coll, sd, (TYPE*) 0); } diff --git a/DDG4/plugins/Geant4SDActions.cpp b/DDG4/plugins/Geant4SDActions.cpp index f06639fa9..00bbd71d4 100644 --- a/DDG4/plugins/Geant4SDActions.cpp +++ b/DDG4/plugins/Geant4SDActions.cpp @@ -107,7 +107,8 @@ namespace DD4hep { StepHandler h(step); HitContribution contrib = Hit::extractContribution(step); HitCollection* coll = collection(m_collectionID); - long long int cell; + VolumeID cell = 0; + try { cell = cellID(step); } catch(std::runtime_error &e) { @@ -128,14 +129,15 @@ namespace DD4hep { return true; } - Hit* hit = coll->find<Hit>(CellIDCompare<Hit>(cell)); + //Hit* hit = coll->find<Hit>(CellIDCompare<Hit>(cell)); + Hit* hit = coll->findByKey<Hit>(cell); if ( !hit ) { Geant4TouchableHandler handler(step); DDSegmentation::Vector3D pos = m_segmentation.position(cell); Position global = h.localToGlobal(pos); hit = new Hit(global); hit->cellID = cell; - coll->add(hit); + coll->add(cell, hit); printM2("%s> CREATE hit with deposit:%e MeV Pos:%8.2f %8.2f %8.2f %s [%s]", c_name(),contrib.deposit,pos.X,pos.Y,pos.Z,handler.path().c_str(), coll->GetName().c_str()); @@ -245,7 +247,7 @@ namespace DD4hep { StepHandler h(step); HitContribution contrib = Hit::extractContribution(step,true); HitCollection* coll = collection(m_collectionID); - long long int cell; + VolumeID cell = 0; try { cell = cellID(step); } catch(std::runtime_error &e) { @@ -266,14 +268,15 @@ namespace DD4hep { return true; } - Hit* hit = coll->find<Hit>(CellIDCompare<Hit>(cell)); + //Hit* hit = coll->find<Hit>(CellIDCompare<Hit>(cell)); + Hit* hit = coll->findByKey<Hit>(cell); if ( !hit ) { Geant4TouchableHandler handler(step); DDSegmentation::Vector3D pos = m_segmentation.position(cell); Position global = h.localToGlobal(pos); hit = new Hit(global); hit->cellID = cell; - coll->add(hit); + coll->add(cell, hit); printM2("CREATE hit with deposit:%e MeV Pos:%8.2f %8.2f %8.2f %s", contrib.deposit,pos.X,pos.Y,pos.Z,handler.path().c_str()); if ( 0 == hit->cellID ) { // for debugging only! diff --git a/DDG4/src/Geant4HitCollection.cpp b/DDG4/src/Geant4HitCollection.cpp index 8859627c7..a6f6988f6 100644 --- a/DDG4/src/Geant4HitCollection.cpp +++ b/DDG4/src/Geant4HitCollection.cpp @@ -81,6 +81,7 @@ Geant4HitCollection::Compare::~Compare() { /// Default destructor Geant4HitCollection::~Geant4HitCollection() { m_hits.clear(); + m_keys.clear(); InstanceCount::decrement(this); } @@ -103,6 +104,7 @@ void Geant4HitCollection::newInstance() { void Geant4HitCollection::clear() { m_lastHit = ULONG_MAX; m_hits.clear(); + m_keys.clear(); } /// Find hit in a collection by comparison of attributes @@ -121,6 +123,14 @@ void* Geant4HitCollection::findHit(const Compare& cmp) { return p; } +/// Find hit in a collection by comparison of the key +Geant4HitWrapper* Geant4HitCollection::findHitByKey(VolumeID key) { + Keys::const_iterator i=m_keys.find(key); + if ( i == m_keys.end() ) return 0; + m_lastHit = (*i).second; + return &m_hits.at(m_lastHit); +} + /// Release all hits from the Geant4 container and pass ownership to the caller void Geant4HitCollection::releaseData(const ComponentCast& cast, std::vector<void*>* result) { for (size_t j = 0, n = m_hits.size(); j < n; ++j) { @@ -132,6 +142,7 @@ void Geant4HitCollection::releaseData(const ComponentCast& cast, std::vector<voi result->push_back(m->cast.apply_downCast(cast, w.release())); } m_lastHit = ULONG_MAX; + m_keys.clear(); } /// Release all hits from the Geant4 container. Ownership stays with the container @@ -153,6 +164,7 @@ void Geant4HitCollection::releaseHitsUnchecked(std::vector<void*>& result) { result.push_back(w.release()); } m_lastHit = ULONG_MAX; + m_keys.clear(); } /// Release all hits from the Geant4 container. Ownership stays with the container @@ -161,5 +173,4 @@ void Geant4HitCollection::getHitsUnchecked(std::vector<void*>& result) { Geant4HitWrapper& w = m_hits.at(j); result.push_back(w.data()); } - m_lastHit = ULONG_MAX; } -- GitLab