From 4792033ace6cb03726ae8b433308abceebc39435 Mon Sep 17 00:00:00 2001 From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch> Date: Thu, 25 Apr 2024 17:52:07 +0200 Subject: [PATCH] MuonR4 geometry - Fix crashes when running with multiple threads MuonR4 geometry - Fix crashes when running with multiple threads --- .../GeoModelUtilities/GeoAlignmentStore.h | 12 +- .../TransientConstSharedPtr.h | 2 + .../MuonCondAlgR4/python/ConditionsConfig.py | 3 + .../src/ActsMuonAlignCondAlg.cxx | 21 +- .../MuonCondAlgR4/src/ActsMuonAlignCondAlg.h | 2 + .../python/MuonGeoModelConfig.py | 11 +- .../MdtReadoutElement.icc | 9 +- .../MuonReadoutElement.h | 2 +- .../src/MuonReadoutElement.cxx | 2 +- .../src/AlignStoreProviderAlg.cxx | 7 +- .../src/AlignStoreProviderAlg.h | 2 + Tracking/Acts/ActsGeoUtils/CMakeLists.txt | 25 ++- .../test/test_AlignStoreAccess.cxx | 212 ++++++++++++++++++ .../test/test_TicketAlignStore.cxx | 5 +- 14 files changed, 280 insertions(+), 35 deletions(-) create mode 100644 Tracking/Acts/ActsGeoUtils/test/test_AlignStoreAccess.cxx diff --git a/DetectorDescription/GeoModel/GeoModelUtilities/GeoModelUtilities/GeoAlignmentStore.h b/DetectorDescription/GeoModel/GeoModelUtilities/GeoModelUtilities/GeoAlignmentStore.h index 1365d710d29e..4756f948abc6 100755 --- a/DetectorDescription/GeoModel/GeoModelUtilities/GeoModelUtilities/GeoAlignmentStore.h +++ b/DetectorDescription/GeoModel/GeoModelUtilities/GeoModelUtilities/GeoAlignmentStore.h @@ -15,6 +15,9 @@ #include "GeoModelKernel/GeoDefinitions.h" #include "GeoModelKernel/GeoVAlignmentStore.h" +#include "GeoModelKernel/GeoVFullPhysVol.h" +#include "GeoModelKernel/GeoAlignableTransform.h" + #include "GeoModelUtilities/TransformMap.h" #include "GeoModelUtilities/TransientConstSharedPtr.h" @@ -86,16 +89,13 @@ public: PositioningMapPtr getDefAbsPositions() const; }; -ATH_ALWAYS_INLINE -const GeoTrf::Transform3D* GeoAlignmentStore::getDelta(const GeoAlignableTransform* axf) const { +inline const GeoTrf::Transform3D* GeoAlignmentStore::getDelta(const GeoAlignableTransform* axf) const { return m_deltas->getTransform(axf); } -ATH_ALWAYS_INLINE -const GeoTrf::Transform3D* GeoAlignmentStore::getAbsPosition(const GeoVFullPhysVol* fpv) const { +inline const GeoTrf::Transform3D* GeoAlignmentStore::getAbsPosition(const GeoVFullPhysVol* fpv) const { return m_absPositions->getTransform(fpv); } -ATH_ALWAYS_INLINE -const GeoTrf::Transform3D* GeoAlignmentStore::getDefAbsPosition(const GeoVFullPhysVol* fpv) const { +inline const GeoTrf::Transform3D* GeoAlignmentStore::getDefAbsPosition(const GeoVFullPhysVol* fpv) const { return m_defAbsPositions->getTransform(fpv); } diff --git a/DetectorDescription/GeoModel/GeoModelUtilities/GeoModelUtilities/TransientConstSharedPtr.h b/DetectorDescription/GeoModel/GeoModelUtilities/GeoModelUtilities/TransientConstSharedPtr.h index 4773302dfcad..aa146ac891aa 100644 --- a/DetectorDescription/GeoModel/GeoModelUtilities/GeoModelUtilities/TransientConstSharedPtr.h +++ b/DetectorDescription/GeoModel/GeoModelUtilities/GeoModelUtilities/TransientConstSharedPtr.h @@ -81,6 +81,8 @@ namespace GeoModel { /// Is the pointer defined operator bool() const { return m_ptr.get() != nullptr; } bool operator!() const { return !m_ptr; } + /// How many clients does the pointer have + size_t use_count() const { return m_ptr.use_count(); } /// Smaller operator to insert the pointer into sets bool operator<(const TransientConstSharedPtr& other) const { return m_ptr.get() < other.m_ptr.get(); } diff --git a/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/python/ConditionsConfig.py b/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/python/ConditionsConfig.py index 5ad7f49accea..3fe6b2af8f8c 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/python/ConditionsConfig.py +++ b/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/python/ConditionsConfig.py @@ -11,6 +11,9 @@ def ActsMuonAlignCondAlgCfg(flags, name="ActsMuonAlignCondAlg", **kwargs): from MuonConfig.MuonGeometryConfig import MuonAlignmentCondAlgCfg kwargs.setdefault("applyMmPassivation", flags.Muon.applyMMPassivation) + kwargs.setdefault("FillAlignCache", True) + kwargs.setdefault("FillGeoAlignStore", False) + if kwargs["applyMmPassivation"]: from MuonConfig.MuonCondAlgConfig import NswPassivationDbAlgCfg diff --git a/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/src/ActsMuonAlignCondAlg.cxx b/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/src/ActsMuonAlignCondAlg.cxx index 2a310f550dd8..8a7fe1e1a8d4 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/src/ActsMuonAlignCondAlg.cxx +++ b/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/src/ActsMuonAlignCondAlg.cxx @@ -275,7 +275,19 @@ StatusCode ActsMuonAlignCondAlg::execute(const EventContext& ctx) const { } /// Propagate the cache throughout the geometry ATH_CHECK(declareDependencies(ctx, subDet, writeHandle)); - if (m_fillAlignStoreCache) { + if (m_fillGeoAlignStore) { + /// Ensure that the rigid transformations of the detector elements are applied + for (const MuonReadoutElement* re : readoutEles) { + if (re->detectorType() == subDet) { + const Amg::Transform3D& detTrf{re->getMaterialGeom()->getAbsoluteTransform(writeCdo->geoModelAlignment.get())}; + ATH_MSG_VERBOSE("Detector element "<<m_idHelperSvc->toStringDetEl(re->identify())<<" is located at " + <<Amg::toString(detTrf)); + } + } + /// There's no need to cache the delta parameters longer + writeCdo->geoModelAlignment->getDeltas()->clear(); + writeCdo->geoModelAlignment->lockPosCache(); + } else if (m_fillAlignStoreCache) { for (const MuonReadoutElement* re : readoutEles){ numAligned+= re->storeAlignedTransforms(*writeCdo); } @@ -284,11 +296,8 @@ StatusCode ActsMuonAlignCondAlg::execute(const EventContext& ctx) const { } ATH_CHECK(writeHandle.record(std::move(writeCdo))); } - /// Check that all readout elements were properly aligned - if (m_fillAlignStoreCache && numAligned != readoutEles.size()){ - ATH_MSG_FATAL("Only "<<numAligned<<" out of "<<readoutEles.size()<<" were picked up by the alignment cutalg"); - return StatusCode::FAILURE; - } + + ATH_MSG_VERBOSE("Only "<<numAligned<<" out of "<<readoutEles.size()<<" were picked up by the alignment cutalg"); alignDeltas.clear(); techTransforms.clear(); /// Whipe the GeoModelCache diff --git a/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/src/ActsMuonAlignCondAlg.h b/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/src/ActsMuonAlignCondAlg.h index 99515b55ee15..4d3c951ddb7e 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/src/ActsMuonAlignCondAlg.h +++ b/MuonSpectrometer/MuonPhaseII/MuonConditions/MuonCondAlgR4/src/ActsMuonAlignCondAlg.h @@ -99,6 +99,8 @@ private: Gaudi::Property<bool> m_applyBLines{this, "applyBLines", false}; /// Flag toggling whether the alignment store shall be filled with the transforms or not Gaudi::Property<bool> m_fillAlignStoreCache{this, "FillAlignCache", false}; + /// Flag toggling whether the GeoAlignmentStore shall be filled + Gaudi::Property<bool> m_fillGeoAlignStore{this, "FillGeoAlignStore", true}; }; diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/python/MuonGeoModelConfig.py b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/python/MuonGeoModelConfig.py index aa44649c1614..9e4712e820d1 100755 --- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/python/MuonGeoModelConfig.py +++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonGeoModelR4/python/MuonGeoModelConfig.py @@ -95,7 +95,8 @@ def MuonAlignStoreCfg(flags): name="ActsDetAlignmentAlgMdt", CondAlignStore="MdtActsAlignContainer" if flags.Muon.enableAlignment else "", EventAlignStore="MdtActsAlignContainer", - SplitPhysVolCache = True, + SplitPhysVolCache = False, + SplitActsTrfCache = False, FillAlignCache = False, LoadTrackingGeoSvc = False, DetectorType=DetectorType.Mdt)) @@ -104,7 +105,8 @@ def MuonAlignStoreCfg(flags): name="ActsDetAlignmentAlgRpc", CondAlignStore="RpcActsAlignContainer" if flags.Muon.enableAlignment else "", EventAlignStore="RpcActsAlignContainer", - SplitPhysVolCache = True, + SplitPhysVolCache = False, + SplitActsTrfCache = False, FillAlignCache = False, LoadTrackingGeoSvc = False, DetectorType=DetectorType.Rpc)) @@ -113,7 +115,8 @@ def MuonAlignStoreCfg(flags): name="ActsDetAlignmentAlgTgc", CondAlignStore="TgcActsAlignContainer" if flags.Muon.enableAlignment else "", EventAlignStore="TgcActsAlignContainer", - SplitPhysVolCache = True, + SplitPhysVolCache = False, + SplitActsTrfCache = False, FillAlignCache = False, LoadTrackingGeoSvc = False, DetectorType=DetectorType.Tgc)) @@ -123,6 +126,7 @@ def MuonAlignStoreCfg(flags): CondAlignStore="sTgcActsAlignContainer" if flags.Muon.enableAlignment else "", EventAlignStore="sTgcActsAlignContainer", SplitPhysVolCache = False, + SplitActsTrfCache = False, FillAlignCache = False, LoadTrackingGeoSvc = False, DetectorType=DetectorType.sTgc)) @@ -134,6 +138,7 @@ def MuonAlignStoreCfg(flags): flags.Muon.applyMMPassivation else "", EventAlignStore="MmActsAlignContainer", SplitPhysVolCache = False, + SplitActsTrfCache = False, FillAlignCache = False, LoadTrackingGeoSvc = False, DetectorType=DetectorType.Mm)) diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MdtReadoutElement.icc b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MdtReadoutElement.icc index 4c4d9055d50f..6e0b284cc257 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MdtReadoutElement.icc +++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MdtReadoutElement.icc @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration */ #ifndef MUONREADOUTGEOMETRYR4_MDTREADOUTELEMENT_ICC #define MUONREADOUTGEOMETRYR4_MDTREADOUTELEMENT_ICC @@ -8,8 +8,11 @@ namespace ActsTrk{ template <> inline Amg::Transform3D TransformCacheDetEle<MuonGMR4::MdtReadoutElement>::fetchTransform(const DetectorAlignStore* store) const { - const unsigned int tubeNum = m_parent->tubeNumber(hash()) + 1; - if (tubeNum == 0) { + using RE = MuonGMR4::MdtReadoutElement; + static const unsigned int layerTube = RE::tubeNumber(RE::measurementHash(0,0)); + /// Check whether the hash represents a tube or the central layer + const unsigned int tubeNum = m_parent->tubeNumber(hash()); + if (tubeNum == layerTube) { const Amg::Translation3D toCenter{0.5*m_parent->moduleHeight() * Amg::Vector3D::UnitY()}; return m_parent->toStation(store) * m_parent->toChamberLayer(hash()) * toCenter * Amg::getRotateY3D(90*Gaudi::Units::deg); diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h index 712433110208..b2df86d6ba5c 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h +++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h @@ -168,7 +168,7 @@ class MuonReadoutElement : public GeoVDetectorElement, public AthMessaging, publ friend class ActsTrk::TransformCacheDetEle<MuonGMR4::MuonReadoutElement>; protected: /// Returns the transformation into the center of the readout volume - Amg::Transform3D toStation(const ActsTrk::DetectorAlignStore* alignStore) const; + const Amg::Transform3D& toStation(const ActsTrk::DetectorAlignStore* alignStore) const; /// Inserts a transfomration for caching template <class MuonDetImpl> StatusCode insertTransform(const IdentifierHash& hash); diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx index 224f0e346993..4fcb4d60fcd4 100644 --- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx +++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx @@ -51,7 +51,7 @@ const Amg::Transform3D& MuonReadoutElement::localToGlobalTrans(const ActsGeometr return dummyTrans; } -Amg::Transform3D MuonReadoutElement::toStation(const DetectorAlignStore* alignStore) const { +const Amg::Transform3D& MuonReadoutElement::toStation(const DetectorAlignStore* alignStore) const { return getMaterialGeom()->getAbsoluteTransform(alignStore ? alignStore->geoModelAlignment.get() : nullptr); } void MuonReadoutElement::releaseUnAlignedTrfs() const { diff --git a/Tracking/Acts/ActsAlignmentAlgs/src/AlignStoreProviderAlg.cxx b/Tracking/Acts/ActsAlignmentAlgs/src/AlignStoreProviderAlg.cxx index 3333da3850a1..5e024e097f61 100644 --- a/Tracking/Acts/ActsAlignmentAlgs/src/AlignStoreProviderAlg.cxx +++ b/Tracking/Acts/ActsAlignmentAlgs/src/AlignStoreProviderAlg.cxx @@ -56,7 +56,12 @@ StatusCode AlignStoreProviderAlg::execute(const EventContext& ctx) const { newAlignment = std::make_unique<DetectorAlignStore>(**readHandle); /// Setup a separate cache for the full physical volume transfomrations if (m_splitPhysVolCache) { - if (newAlignment->geoModelAlignment) newAlignment->geoModelAlignment->clearPosCache(); + if (newAlignment->geoModelAlignment) { + newAlignment->geoModelAlignment = std::make_unique<GeoAlignmentStore>(*newAlignment->geoModelAlignment); + newAlignment->geoModelAlignment->clearPosCache(); + } + } + if (m_splitActsTrfCache) { using TrackingStore = DetectorAlignStore::TrackingAlignStore; newAlignment->trackingAlignment = std::make_unique<TrackingStore>(newAlignment->detType); } diff --git a/Tracking/Acts/ActsAlignmentAlgs/src/AlignStoreProviderAlg.h b/Tracking/Acts/ActsAlignmentAlgs/src/AlignStoreProviderAlg.h index 3d9f60f186ff..70ecaa4f1c23 100644 --- a/Tracking/Acts/ActsAlignmentAlgs/src/AlignStoreProviderAlg.h +++ b/Tracking/Acts/ActsAlignmentAlgs/src/AlignStoreProviderAlg.h @@ -44,6 +44,8 @@ namespace ActsTrk{ /// Flag toggling whether the full GeoAlignmentStore shall be written to store gate or whether the /// absolute transforms are split into two different stores Gaudi::Property<bool> m_splitPhysVolCache{this, "SplitPhysVolCache", false}; + /// Flag toggline whether the final transforms of the ActsDet volumes shall be split per event + Gaudi::Property<bool> m_splitActsTrfCache{this, "SplitActsTrfCache", false}; /// Flag toggling whether the alignment store shall be filled with the transforms or not Gaudi::Property<bool> m_fillAlignStoreCache{this, "FillAlignCache", true}; /// Static cast of >DetectorType< property diff --git a/Tracking/Acts/ActsGeoUtils/CMakeLists.txt b/Tracking/Acts/ActsGeoUtils/CMakeLists.txt index cb32c059083f..8336db9442d9 100644 --- a/Tracking/Acts/ActsGeoUtils/CMakeLists.txt +++ b/Tracking/Acts/ActsGeoUtils/CMakeLists.txt @@ -18,18 +18,19 @@ atlas_add_library( ActsGeoUtils LINK_LIBRARIES ${GEOMODEL_LIBRARIES} GeoPrimitives Identifier ActsGeometryInterfacesLib GeoModelUtilities CxxUtils) -# we also add unit tests. -# Build them from the files in test/ -file(GLOB_RECURSE tests "test/*.cxx") - -foreach(_theTestSource ${tests}) - get_filename_component(_theTest ${_theTestSource} NAME_WE) - atlas_add_test( ${_theTest} SOURCES ${_theTestSource} - INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} - LINK_LIBRARIES ${ROOT_LIBRARIES} ActsGeoUtils - POST_EXEC_SCRIPT nopost.sh) - +if( NOT SIMULATIONBASE ) + # we also add unit tests. + # Build them from the files in test/ + file(GLOB_RECURSE tests "test/*.cxx") + + foreach(_theTestSource ${tests}) + get_filename_component(_theTest ${_theTestSource} NAME_WE) + atlas_add_test( ${_theTest} SOURCES ${_theTestSource} + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} ActsGeoUtils + POST_EXEC_SCRIPT nopost.sh) + endforeach() +endif() -endforeach() diff --git a/Tracking/Acts/ActsGeoUtils/test/test_AlignStoreAccess.cxx b/Tracking/Acts/ActsGeoUtils/test/test_AlignStoreAccess.cxx new file mode 100644 index 000000000000..48d2b28d3ec6 --- /dev/null +++ b/Tracking/Acts/ActsGeoUtils/test/test_AlignStoreAccess.cxx @@ -0,0 +1,212 @@ +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ + +#include "GeoPrimitives/GeoPrimitivesHelpers.h" + +#include "ActsGeometryInterfaces/DetectorAlignStore.h" +#include "ActsGeometryInterfaces/ActsGeometryContext.h" +#include "ActsGeometryInterfaces/IDetectorElement.h" + +#include "ActsGeoUtils/TransformCache.h" +#include <stdlib.h> + +#include "GeoModelKernel/GeoAlignableTransform.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoVDetectorElement.h" +#include "GeoModelHelpers/defineWorld.h" + +#include <thread> +#include <future> +#include <chrono> +#include <random> + +class TestDetElement : public ActsTrk::IDetectorElement, public GeoVDetectorElement{ + public: + TestDetElement(GeoIntrusivePtr<GeoVFullPhysVol> detVol): + GeoVDetectorElement(detVol) { } + + Identifier identify() const override final { + return Identifier{}; + } + ActsTrk::DetectorType detectorType() const override final { + return ActsTrk::DetectorType::Csc; + } + unsigned int storeAlignedTransforms(const ActsTrk::DetectorAlignStore& store) const override final { + m_cache.getTransform(&store); + return 1; + } + const Amg::Transform3D& transform(const Acts::GeometryContext& gctx) const override final { + return m_cache.transform(gctx); + } + const Acts::Surface& surface() const override final { + static const std::shared_ptr<Acts::Surface> surf{}; + return *surf; + } + Acts::Surface& surface() override final { + static const std::shared_ptr<Acts::Surface> surf{}; + return *surf; + } + double thickness() const override final { return 0.;} + + private: + ActsTrk::TransformCacheDetEle<TestDetElement> m_cache{IdentifierHash{1}, this}; +}; + +template<> Amg::Transform3D + ActsTrk::TransformCacheDetEle<TestDetElement>::fetchTransform(const ActsTrk::DetectorAlignStore* store) const { + return m_parent->getMaterialGeom()->getAbsoluteTransform(store->geoModelAlignment.get()) * Amg::getRotateX3D(M_PI); +} + +/** Returns how many threads have not yet finished their work*/ +template <class T> size_t count_active(const std::vector<std::future<T>>& threads) { + size_t counts{0}; + for (const std::future<T>& thread : threads) { + using namespace std::chrono_literals; + if (thread.wait_for(0ms) != std::future_status::ready) ++counts; + } + return counts; +} + + +class WorkerTask { + public: + WorkerTask(const std::vector<std::shared_ptr<TestDetElement>>& detElements, + std::shared_ptr<GeoAlignmentStore> condAlignment): + m_detEles{detElements} { + // m_store->geoModelAlignment = condAlignment; + m_store->geoModelAlignment = std::make_unique<GeoAlignmentStore>(*condAlignment); + m_store->geoModelAlignment->clearPosCache(); + } + bool execute() { + ActsGeometryContext gctx{}; + gctx.setStore(m_store); + Amg::Transform3D combinedTrf{Amg::Transform3D::Identity()}; + for (unsigned int daemon = 0 ; daemon < 666; ++daemon) { + for (const auto& det : m_detEles) { + const Amg::Transform3D& trf{det->transform(gctx.context())}; + // assert(trf.data()[0] != 624626.56); + + combinedTrf = trf * combinedTrf; + Amg::Vector3D vec = trf.inverse() * Amg::Vector3D{51515,6262,7272}; + + if (vec.dot(vec) < 0. || std::pow(vec.eta() * vec.theta(), 2) < 0.) { + std::cout<<"Confusion "<<std::endl; + } + } + } + m_executed = true; + return true; + } + bool executed() const { return m_executed; } + private: + std::vector<std::shared_ptr<TestDetElement>> m_detEles{}; + std::shared_ptr<ActsTrk::DetectorAlignStore> m_store{std::make_unique<ActsTrk::DetectorAlignStore>(ActsTrk::DetectorType::Csc)}; + bool m_executed{false}; + +}; + +class WorkerNode { + public: + WorkerNode() = default; + + bool hasTask() const { + std::shared_lock guard{m_mutex}; + return m_hasTask; + } + void assignTask(std::unique_ptr<WorkerTask> task) { + if (hasTask()) return; + std::unique_lock guard {m_mutex}; + m_task = std::move(task); + m_hasTask = true; + } + bool executeTask() { + while (!m_abort) { + if (m_task) { + m_task->execute(); + std::unique_lock guard{m_mutex}; + m_task.reset(); + m_hasTask = false; + } else { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } + return true; + } + void finalize() { + m_abort = true; + } + private: + mutable std::shared_mutex m_mutex{}; + bool m_hasTask{false}; + std::atomic<bool> m_abort{false}; + std::unique_ptr<WorkerTask> m_task{}; +}; + + +int main() { + + unsigned int nThreads = std::min(8u, std::thread::hardware_concurrency()); + constexpr unsigned int numTrials = 40; + + /* Define the world and place randomly the volumes */ + PVLink world{createGeoWorld()}; + + /** Define the GeoAlignmentStore to move the volumes coherently */ + std::shared_ptr<GeoAlignmentStore> condAlignment = std::make_shared<GeoAlignmentStore>(); + + std::vector<std::shared_ptr<TestDetElement>> detElements{}; + + for (unsigned int k =0 ; k < 25; ++k) { + GeoIntrusivePtr<GeoAlignableTransform> alignTrf = make_intrusive<GeoAlignableTransform>(Amg::getTranslateX3D(k+1)); + condAlignment->setDelta(alignTrf, Amg::getTranslateY3D(k+1) * Amg::getRotateX3D(M_PI_2)); + world->add(alignTrf); + + GeoIntrusivePtr<GeoPhysVol> alignBox = make_intrusive<GeoPhysVol>(world->getLogVol()); + world->add(alignBox); + for (unsigned int d = 0 ; d < 66; ++d) { + world->add(make_intrusive<GeoTransform>(Amg::getTranslateZ3D(d+6))); + GeoIntrusivePtr<GeoFullPhysVol> detVol{make_intrusive<GeoFullPhysVol>(world->getLogVol())}; + world->add(detVol); + detElements.emplace_back(std::make_unique<TestDetElement>(detVol)); + } + } + condAlignment->lockDelta(); + + std::vector<std::unique_ptr<WorkerNode>> workers{}; + std::vector<std::future<bool>> threads{}; + + for (unsigned int node = 0 ; node < nThreads; ++node) { + workers.emplace_back(std::make_unique<WorkerNode>()); + WorkerNode* testerPtr = workers.back().get(); + threads.emplace_back(std::async(std::launch::async,[testerPtr](){return testerPtr->executeTask();})); + + } + + std::random_device rd; + std::mt19937 g(rd()); + + unsigned int executedAttempts{}; + while (executedAttempts < numTrials) { + for (auto& worker : workers) { + if (!worker->hasTask()) { + worker->assignTask(std::make_unique<WorkerTask>(detElements, condAlignment)); + std::cout<<"Launch new worker "<<executedAttempts<<" "<<std::endl; + if (executedAttempts % 100 == 0) std::shuffle(detElements.begin(),detElements.end(), g); + ++executedAttempts; + } + } + std::this_thread::sleep_for(std::chrono::nanoseconds(100)); + } + for (auto & worker : workers) { + worker->finalize(); + } + while (count_active(threads) > 0){ + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + + return EXIT_SUCCESS; +} + diff --git a/Tracking/Acts/ActsGeoUtils/test/test_TicketAlignStore.cxx b/Tracking/Acts/ActsGeoUtils/test/test_TicketAlignStore.cxx index 9cfbd5201fff..25b6d5ea6c3d 100644 --- a/Tracking/Acts/ActsGeoUtils/test/test_TicketAlignStore.cxx +++ b/Tracking/Acts/ActsGeoUtils/test/test_TicketAlignStore.cxx @@ -1,5 +1,6 @@ - - +/* + Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration +*/ #include "ActsGeometryInterfaces/DetectorAlignStore.h" #include <stdlib.h> -- GitLab