ATLAS Offline Software
Loading...
Searching...
No Matches
G4ThreadInitTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Main header include
6#include "G4ThreadInitTool.h"
8
9// Geant4 includes
10#include "G4WorkerRunManager.hh"
11#include "G4UImanager.hh"
12#include "G4MTRunManager.hh"
13#include "G4WorkerThread.hh"
14#include "G4UserWorkerThreadInitialization.hh"
15#include "G4RunManager.hh"
16#include "G4VUserActionInitialization.hh"
17#include "G4UserWorkerInitialization.hh"
18#include "G4AutoDelete.hh"
19
20// Framework includes
21#include "GaudiKernel/ConcurrencyFlags.h"
22
23// System includes
24#include <unistd.h>
25#include <sys/syscall.h>
26
27//-----------------------------------------------------------------------------
28// Constructor
29//-----------------------------------------------------------------------------
31 const std::string& name,
32 const IInterface* parent)
33 : base_class(type, name, parent),
35{}
36
37//-----------------------------------------------------------------------------
38// Worker thread initialization.
39// This code is modeled after G4MTRunManagerKernel::StartThread.
40//-----------------------------------------------------------------------------
42{
43 ATH_MSG_INFO("==> tbb thread started with id: 0x" <<
44 std::hex << pthread_self() << std::dec);
45
46 // Define the G4 worker thread context and setup its cleanup mechanism.
47 auto wThreadContext = new G4WorkerThread;
48 G4AutoDelete::Register(wThreadContext);
49
50 // Assign the thread ID
51 static std::atomic_uint tid(0);
52 wThreadContext->SetThreadId( tid++ );
53 G4Threading::G4SetThreadId( wThreadContext->GetThreadId() );
54
55 // Setup thread-local geometry and physics
56 wThreadContext->BuildGeometryAndPhysicsVector();
57
58 // Retrieve the master thread run manager
59 G4MTRunManager* masterRM = G4MTRunManager::GetMasterRunManager();
60
61 // For offloading EM showers to GPUs via AdePT, the G4 worker threads must know the number of G4 workers
62 // Since this is so far known by Gaudi and not the G4MTRunManager, we need to pass
63 // back the number of G4 worker threads to the G4MTRunManager, so that they are available in AdePT.
64 masterRM->SetNumberOfThreads(Gaudi::Concurrency::ConcurrencyFlags::numThreads());
65
66 // Worker thread initialization object
67 const G4UserWorkerThreadInitialization* workerInitializer =
68 masterRM->GetUserWorkerThreadInitialization();
69
70 // Random number setup.
71 // TODO: revisit this once MT AthRNGSvc is available.
72 const CLHEP::HepRandomEngine* masterEngine = masterRM->getMasterRandomEngine();
73 workerInitializer->SetupRNGEngine(masterEngine);
74
75 // Create the thread-local worker run manager (G4AtlasWorkerRunManager)
76 ATH_MSG_INFO("Creating worker RM");
77 G4WorkerRunManager* wrm = workerInitializer->CreateWorkerRunManager();
78 wrm->SetWorkerThread(wThreadContext);
79
80 // Share detector from master with worker.
81 ATH_MSG_INFO("Assigning detector construction");
82 // I don't want to const-cast here, but this is what they do in G4's
83 // StartThread function, so there is likely no alternative.
84 // Should not be a problem for threading.
85 G4VUserDetectorConstruction* detector ATLAS_THREAD_SAFE =
86 const_cast<G4VUserDetectorConstruction*> (masterRM->GetUserDetectorConstruction());
87 wrm->G4RunManager::SetUserInitialization (detector);
88 // Share physics list from master with worker.
89 // Should not be a problem for threading.
90 G4VUserPhysicsList* physicslist ATLAS_THREAD_SAFE =
91 const_cast<G4VUserPhysicsList*>(masterRM->GetUserPhysicsList());
92 wrm->SetUserInitialization(physicslist);
93
94 // Build thread-local user actions - NOT CURRENTLY USED.
95 if(masterRM->GetUserActionInitialization()) {
96 masterRM->GetNonConstUserActionInitialization()->Build();
97 }
98
99 // Start user worker initialization
100 if(masterRM->GetUserWorkerInitialization()) {
101 masterRM->GetUserWorkerInitialization()->WorkerStart();
102 }
103
104 // Initialize the worker run manager
105 ATH_MSG_INFO("Initializing worker RM");
106 wrm->Initialize();
107
108 // Start user worker run
109 if(masterRM->GetUserWorkerInitialization()) {
110 masterRM->GetUserWorkerInitialization()->WorkerRunStart();
111 }
112
113 // Copy the UI commands to the worker
114 std::vector<G4String> cmds = masterRM->GetCommandStack();
115 ATH_MSG_INFO (cmds.size() << " commands in UI stack");
116 G4UImanager* uimgr = G4UImanager::GetUIpointer();
117 for(const auto& it : cmds) {
118 ATH_MSG_INFO ("Adding command to worker: " << it);
119 uimgr->ApplyCommand(it);
120 }
121
122 // Atomic increment number of initialized threads
124
125 ATH_MSG_INFO("==> tbb thread end of initThread with id: 0x" <<
126 std::hex << pthread_self() << std::dec);
127}
128
129//-----------------------------------------------------------------------------
130// Worker thread termination
131//-----------------------------------------------------------------------------
133{
134 ATH_MSG_DEBUG("terminateThread ==> tbb thread 0x" <<
135 std::hex << pthread_self() << std::dec);
136
137 // Geant4 worker finalization
138 auto runMgr = G4RunManager::GetRunManager();
139 ATH_MSG_DEBUG("G4RunManager ptr" << runMgr);
140 if(runMgr) {
141 runMgr->RunTermination();
142 ATH_MSG_INFO("terminateThread ==> safely called G4AtlasWorkerRunManager::RunTermination for tbb thread 0x" <<
143 std::hex << pthread_self() << std::dec);
144 // Atomic decrement number of initialized threads
146 }
147 else {
148 ATH_MSG_WARNING("skipping attempt to call terminateThread for tbb thread 0x" <<
149 std::hex << pthread_self() << std::dec <<
150 " without having first called initThread.");
151 // Not decrementing m_nInitThreads as initThread was not called in this case.
152 }
153}
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
virtual void terminateThread() override final
Tear down the Geant4 workspace for this worker thread.
std::atomic_uint m_nInitThreads
Counter of threads that have been initialized.
G4ThreadInitTool(const std::string &, const std::string &, const IInterface *)
Standard tool constructor.
virtual void initThread() override final
Set up the Geant4 workspace for this worker thread.