From 9de84fd42cd069d45817363f277cf296eb8043b1 Mon Sep 17 00:00:00 2001 From: Steve Farrell <sfarrell@cern.ch> Date: Thu, 14 Sep 2017 03:02:10 +0200 Subject: [PATCH] Adding G4ThreadInitTool implementation. Relocating this tool from G4HiveEx (named G4InitTool) to G4AtlasTools with some minor changes, including improved method of assigning G4 thread ID and replacing some usages of 'auto'. Former-commit-id: bad94e42f1337fd2c2ef7b1f29c1bc4b89c9b2fb --- .../G4AtlasTools/src/G4ThreadInitTool.cxx | 119 ++++++++++++++++++ .../G4AtlasTools/src/G4ThreadInitTool.h | 47 +++++++ .../src/components/G4AtlasTools_entries.cxx | 2 + 3 files changed, 168 insertions(+) create mode 100644 Simulation/G4Atlas/G4AtlasTools/src/G4ThreadInitTool.cxx create mode 100644 Simulation/G4Atlas/G4AtlasTools/src/G4ThreadInitTool.h diff --git a/Simulation/G4Atlas/G4AtlasTools/src/G4ThreadInitTool.cxx b/Simulation/G4Atlas/G4AtlasTools/src/G4ThreadInitTool.cxx new file mode 100644 index 00000000000..ce2d101c3d0 --- /dev/null +++ b/Simulation/G4Atlas/G4AtlasTools/src/G4ThreadInitTool.cxx @@ -0,0 +1,119 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// Main header include +#include "G4ThreadInitTool.h" + +// Geant4 includes +#include "G4WorkerRunManager.hh" +#include "G4UImanager.hh" +#include "G4MTRunManager.hh" +#include "G4WorkerThread.hh" +#include "G4UserWorkerThreadInitialization.hh" +#include "G4RunManager.hh" +#include "G4VUserActionInitialization.hh" +#include "G4UserWorkerInitialization.hh" +#include "G4AutoDelete.hh" + +// System includes +#include <unistd.h> +#include <sys/syscall.h> + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +G4ThreadInitTool::G4ThreadInitTool(const std::string& type, + const std::string& name, + const IInterface* parent) + : base_class(type, name, parent), + m_nInitThreads(0) +{} + +//----------------------------------------------------------------------------- +// Worker thread initialization. +// This code is modeled after G4MTRunManagerKernel::StartThread. +//----------------------------------------------------------------------------- +void G4ThreadInitTool::initThread() +{ + ATH_MSG_INFO("==> tbb thread started with id: 0x" << + std::hex << pthread_self() << std::dec); + + // Define the G4 worker thread context and setup its cleanup mechanism. + auto wThreadContext = new G4WorkerThread; + G4AutoDelete::Register(wThreadContext); + + // Assign the thread ID + static std::atomic_uint tid(0); + wThreadContext->SetThreadId( tid++ ); + G4Threading::G4SetThreadId( wThreadContext->GetThreadId() ); + + // Setup thread-local geometry and physics + wThreadContext->BuildGeometryAndPhysicsVector(); + + // Retrieve the master thread run manager + G4MTRunManager* masterRM = G4MTRunManager::GetMasterRunManager(); + // Worker thread initialization object + const G4UserWorkerThreadInitialization* workerInitializer = + masterRM->GetUserWorkerThreadInitialization(); + + // Random number setup. + // TODO: revisit this once MT AthRNGSvc is available. + const CLHEP::HepRandomEngine* masterEngine = masterRM->getMasterRandomEngine(); + workerInitializer->SetupRNGEngine(masterEngine); + + // Create the thread-local worker run manager (G4AtlasWorkerRunManager) + ATH_MSG_INFO("Creating worker RM"); + G4WorkerRunManager* wrm = workerInitializer->CreateWorkerRunManager(); + wrm->SetWorkerThread(wThreadContext); + + // Share detector from master with worker. + ATH_MSG_INFO("Assigning detector construction"); + const G4VUserDetectorConstruction* detector = + masterRM->GetUserDetectorConstruction(); + // I don't want to const-cast here, but this is what they do in G4's + // StartThread function, so there is likely no alternative. + wrm->G4RunManager::SetUserInitialization + (const_cast<G4VUserDetectorConstruction*>(detector)); + // Share physics list from master with worker. + const G4VUserPhysicsList* physicslist = masterRM->GetUserPhysicsList(); + wrm->SetUserInitialization(const_cast<G4VUserPhysicsList*>(physicslist)); + + // Build thread-local user actions - NOT CURRENTLY USED. + if(masterRM->GetUserActionInitialization()) { + masterRM->GetNonConstUserActionInitialization()->Build(); + } + + // Start user worker initialization + if(masterRM->GetUserWorkerInitialization()) { + masterRM->GetUserWorkerInitialization()->WorkerStart(); + } + + // Initialize the worker run manager + ATH_MSG_INFO("Initializing worker RM"); + wrm->Initialize(); + + // Copy the UI commands to the worker + std::vector<G4String> cmds = masterRM->GetCommandStack(); + ATH_MSG_INFO (cmds.size() << " commands in UI stack"); + G4UImanager* uimgr = G4UImanager::GetUIpointer(); + for(const auto& it : cmds) { + ATH_MSG_INFO ("Adding command to worker: " << it); + uimgr->ApplyCommand(it); + } + + // Atomic increment number of initialized threads + m_nInitThreads++; + + ATH_MSG_INFO("==> tbb thread end of initThread with id: 0x" << + std::hex << pthread_self() << std::dec); +} + +//----------------------------------------------------------------------------- +// Worker thread termination +//----------------------------------------------------------------------------- +void G4ThreadInitTool::terminateThread() +{ + // Atomic decrement number of initialized threads + m_nInitThreads--; +} diff --git a/Simulation/G4Atlas/G4AtlasTools/src/G4ThreadInitTool.h b/Simulation/G4Atlas/G4AtlasTools/src/G4ThreadInitTool.h new file mode 100644 index 00000000000..b1e2ce119f3 --- /dev/null +++ b/Simulation/G4Atlas/G4AtlasTools/src/G4ThreadInitTool.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef G4ATLASTOOLS_G4THREADINITTOOL_H +#define G4ATLASTOOLS_G4THREADINITTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/IThreadInitTool.h" + +#include <string> +#include <atomic> + +/// @class G4ThreadInitTool +/// @brief A tool which sets up the worker-thread-local workspace for Geant4. +/// +/// @author Steve Farrell <Steven.Farrell@cern.ch> +/// +class G4ThreadInitTool : virtual public extends1<AthAlgTool, IThreadInitTool> +{ + + public: + + /// Standard tool constructor + G4ThreadInitTool(const std::string&, const std::string&, const IInterface*); + + /// Set up the Geant4 workspace for this worker thread + virtual void initThread() override final; + + /// Tear down the Geant4 workspace for this worker thread + virtual void terminateThread() override final; + + /// Counter used for barrier mechanism in thread initialization. + /// This number needs to be correctly reported to properly ensure + /// scheduling of thread-initialization tasks on every thread. + virtual unsigned int nInit() const override final { + return m_nInitThreads; + } + + private: + + /// Counter of threads that have been initialized + std::atomic_uint m_nInitThreads; + +}; // class G4ThreadInitTool + +#endif // G4ATLASTOOLS_G4THREADINITTOOL_H diff --git a/Simulation/G4Atlas/G4AtlasTools/src/components/G4AtlasTools_entries.cxx b/Simulation/G4Atlas/G4AtlasTools/src/components/G4AtlasTools_entries.cxx index c74a873e541..e19ec7de5c5 100644 --- a/Simulation/G4Atlas/G4AtlasTools/src/components/G4AtlasTools_entries.cxx +++ b/Simulation/G4Atlas/G4AtlasTools/src/components/G4AtlasTools_entries.cxx @@ -14,6 +14,7 @@ #include "../FastSimulationMasterTool.h" #include "G4AtlasTools/GlobalFieldManagerTool.h" #include "G4AtlasTools/DetectorFieldManagerTool.h" +#include "../G4ThreadInitTool.h" DECLARE_TOOL_FACTORY( PhysicsListToolBase ) DECLARE_TOOL_FACTORY( DetectorGeometryBase ) @@ -29,3 +30,4 @@ DECLARE_TOOL_FACTORY( FastSimulationMasterTool ) DECLARE_TOOL_FACTORY( AddPhysicsDecayTool ) DECLARE_TOOL_FACTORY( GlobalFieldManagerTool ) DECLARE_TOOL_FACTORY( DetectorFieldManagerTool ) +DECLARE_TOOL_FACTORY( G4ThreadInitTool ) -- GitLab