Geant4-11
G4TaskRunManagerKernel.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26
28#include "G4AutoLock.hh"
29#include "G4RegionStore.hh"
30#include "G4StateManager.hh"
31
32#include "G4DecayTable.hh"
33#include "G4LogicalVolume.hh"
34#include "G4Material.hh"
35#include "G4MaterialTable.hh"
36#include "G4PVParameterised.hh"
37#include "G4PVReplica.hh"
39#include "G4ParticleTable.hh"
42#include "G4PhysicsVector.hh"
43#include "G4PolyconeSide.hh"
44#include "G4PolyhedraSide.hh"
45#include "G4Region.hh"
46#include "G4Run.hh"
47#include "G4TaskManager.hh"
48#include "G4TiMemory.hh"
49#include "G4UImanager.hh"
52#include "G4VDecayChannel.hh"
54#include "G4VPhysicalVolume.hh"
57#include "G4VUserPhysicsList.hh"
59#include "G4WorkerThread.hh"
60
61#include <atomic>
62#include <memory>
63
64//============================================================================//
65
66std::vector<G4String> G4TaskRunManagerKernel::initCmdStack = {};
67
68//============================================================================//
69
71 : G4RunManagerKernel(masterRMK)
72{
73 // This version of the constructor should never be called in sequential mode!
74#ifndef G4MULTITHREADED
76 msg << "Geant4 code is compiled without multi-threading support "
77 "(-DG4MULTITHREADED "
78 "is set to off).";
79 msg << " This type of RunManager can only be used in mult-threaded "
80 "applications.";
81 G4Exception("G4RunManagerKernel::G4RunManagerKernel()", "Run0109",
82 FatalException, msg);
83#endif
84 // Set flag that a MT-type kernel has been instantiated
86}
87
88//============================================================================//
89
91
92//============================================================================//
93
95{
96 // Behavior is the same as base class (sequential mode)
97 // ShadowProcess pointer == process poitner
99}
100
101//============================================================================//
102
103namespace
104{
105 using WorkerRunManPtr_t = std::unique_ptr<G4WorkerTaskRunManager>;
106 using WorkerThreadPtr_t = std::unique_ptr<G4WorkerThread>;
107
109 {
110 G4ThreadLocalStatic WorkerRunManPtr_t _instance{ nullptr };
111 return _instance;
112 }
113
115 {
116 G4ThreadLocalStatic WorkerThreadPtr_t _instance{ nullptr };
117 return _instance;
118 }
119
120} // namespace
121
122//============================================================================//
123
125{
126 return context().get();
127}
128
129//============================================================================//
130
132{
133 if(context() && workerRM())
134 return;
135
137 if(G4MTRunManager::GetMasterThreadId() == G4ThisThread::get_id())
138 {
139 G4TaskManager* taskManager = mrm->GetTaskManager();
140 auto _fut = taskManager->async(InitializeWorker);
141 _fut->wait();
142 return;
143 }
144
148 // Here is not sequential anymore and G4UserWorkerThreadInitialization is
149 // a shared user initialization class
150 // This means this method cannot use data memebers of G4RunManagerKernel
151 // unless they are invariant ("read-only") and can be safely shared.
152 // All the rest that is not invariant should be incapsualted into
153 // the context (or, as for wThreadContext be G4ThreadLocal)
155
157 context().reset(new G4WorkerThread);
158
159 //============================
160 // Step-0: Thread ID
161 //============================
162 // Initliazie per-thread stream-output
163 // The following line is needed before we actually do IO initialization
164 // becasue the constructor of UI manager resets the IO destination.
165 context()->SetNumberThreads(mrm->GetThreadPool()->size());
166 context()->SetThreadId(G4ThreadPool::get_this_thread_id() - 1);
167 G4int thisID = context()->GetThreadId();
170
171 //============================
172 // Optimization: optional
173 //============================
174 // Enforce thread affinity if requested
175 context()->SetPinAffinity(mrm->GetPinAffinity());
176
177 //============================
178 // Step-1: Random number engine
179 //============================
180 // RNG Engine needs to be initialized by "cloning" the master one.
181 const CLHEP::HepRandomEngine* masterEngine = mrm->getMasterRandomEngine();
183
184 //============================
185 // Step-2: Initialize worker thread
186 //============================
189
191 {
194 if(sv)
196 }
197 // Now initialize worker part of shared objects (geometry/physics)
198 context()->BuildGeometryAndPhysicsVector();
199 workerRM().reset(static_cast<G4WorkerTaskRunManager*>(
201 auto& wrm = workerRM();
202 wrm->SetWorkerThread(context().get());
203
204 //================================
205 // Step-3: Setup worker run manager
206 //================================
207 // Set the detector and physics list to the worker thread. Share with master
208 const G4VUserDetectorConstruction* detector =
210 wrm->G4RunManager::SetUserInitialization(
211 const_cast<G4VUserDetectorConstruction*>(detector));
212 const G4VUserPhysicsList* physicslist = mrm->GetUserPhysicsList();
213 wrm->SetUserInitialization(const_cast<G4VUserPhysicsList*>(physicslist));
214
215 //================================
216 // Step-4: Initialize worker run manager
217 //================================
222
223 workerRM()->Initialize();
224
225 for(auto& itr : initCmdStack)
227
228 wrm->ProcessUI();
229}
230
231//============================================================================//
232
234{
235 // because of TBB
236 if(G4MTRunManager::GetMasterThreadId() == G4ThisThread::get_id())
237 {
238 G4TaskManager* taskManager =
240 auto _fut = taskManager->async(ExecuteWorkerInit);
241 return _fut->get();
242 }
243
244 // this check is for TBB as there is not a way to run an initialization
245 // routine on each thread
246 if(!workerRM())
248
249 auto& wrm = workerRM();
250 assert(wrm.get() != nullptr);
251 wrm->DoCleanup();
252}
253
254//============================================================================//
255
257{
258 // because of TBB
259 if(G4MTRunManager::GetMasterThreadId() == G4ThisThread::get_id())
260 {
261 G4TaskManager* taskManager =
263 auto _fut = taskManager->async(ExecuteWorkerTask);
264 return _fut->get();
265 }
266
267 // this check is for TBB as there is not a way to run an initialization
268 // routine on each thread
269 if(!workerRM())
271
272 auto& wrm = workerRM();
273 assert(wrm.get() != nullptr);
274 wrm->DoWork();
275}
276
277//============================================================================//
278
280{
281 if(workerRM())
283}
284
285//============================================================================//
286
288{
289 if(workerRM())
291 workerRM().reset();
292 context().reset();
293}
294
295//============================================================================//
296
299{
300 if(!wrm)
301 return;
302
303 wrm->TerminateEventLoop();
304 wrm->RunTermination();
305}
306
307//============================================================================//
308
310{
311 if(!wrm)
312 return;
313
314 //===============================
315 // Step-6: Terminate worker thread
316 //===============================
318 if(mrm && mrm->GetUserWorkerInitialization())
320
321 G4WorkerThread* _context = wrm->GetWorkerThread();
323
325}
326
327//============================================================================//
328
330{
331 return initCmdStack;
332}
333
334//============================================================================//
335
337{
340 pItr->reset();
341 while((*pItr)())
342 {
343 G4DecayTable* dt = pItr->value()->GetDecayTable();
344 if(dt)
345 {
346 G4int nCh = dt->entries();
347 for(G4int i = 0; i < nCh; i++)
348 {
349 dt->GetDecayChannel(i)->GetDaughter(0);
350 }
351 }
352 }
353}
354
355//============================================================================//
356
358{
359 G4ConsumeParameters(softAbort);
360}
361
362//============================================================================//
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4VDecayChannel * GetDecayChannel(G4int index) const
G4int entries() const
G4int GetPinAffinity() const
const CLHEP::HepRandomEngine * getMasterRandomEngine() const
static G4ThreadId GetMasterThreadId()
void reset(G4bool ifSkipIon=true)
G4PTblDicIterator * GetIterator() const
static G4ParticleTable * GetParticleTable()
virtual void SetupShadowProcess() const
const G4UserWorkerInitialization * GetUserWorkerInitialization() const
const G4VUserDetectorConstruction * GetUserDetectorConstruction() const
const G4VUserActionInitialization * GetUserActionInitialization() const
G4VUserActionInitialization * GetNonConstUserActionInitialization() const
const G4VUserPhysicsList * GetUserPhysicsList() const
const G4UserWorkerThreadInitialization * GetUserWorkerThreadInitialization() const
void BroadcastAbortRun(G4bool softAbort)
static G4TASK_DLL std::vector< G4String > initCmdStack
static G4WorkerThread * GetWorkerThread()
static std::vector< G4String > & InitCommandStack()
static G4TaskRunManager * GetMasterRunManager()
void SetUpForAThread(G4int tId)
Definition: G4UImanager.cc:860
G4int ApplyCommand(const char *aCommand)
Definition: G4UImanager.cc:485
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:77
virtual void SetupRNGEngine(const CLHEP::HepRandomEngine *aRNGEngine) const
virtual G4WorkerRunManager * CreateWorkerRunManager() const
G4ParticleDefinition * GetDaughter(G4int anIndex)
static void SetInstance(G4VSteppingVerbose *Instance)
virtual void Build() const =0
virtual G4VSteppingVerbose * InitializeSteppingVerbose() const
virtual void RunTermination() override
virtual void TerminateEventLoop() override
G4WorkerThread * GetWorkerThread() const
static void DestroyGeometryAndPhysicsVector()
std::shared_ptr< PackagedTask< RetT, Args... > > async(FuncT &&func, Args &&... args)
Definition: TaskManager.hh:100
TaskManager * GetTaskManager() const
ThreadPool * GetThreadPool() const
static uintmax_t get_this_thread_id()
Definition: ThreadPool.cc:122
size_type size() const
Definition: ThreadPool.hh:163
G4int WorkerThreadJoinsPool()
Definition: G4Threading.cc:132
G4int WorkerThreadLeavesPool()
Definition: G4Threading.cc:131
void SetMultithreadedApplication(G4bool value)
Definition: G4Threading.cc:129
void G4SetThreadId(G4int aNewValue)
Definition: G4Threading.cc:125
auto get(Tuple< Elements... > &t) -> decltype(get_height< sizeof...(Elements) - I - 1 >(t))
Definition: Tuple.hh:139
std::unique_ptr< G4WorkerThread > WorkerThreadPtr_t
std::unique_ptr< G4WorkerTaskRunManager > WorkerRunManPtr_t
void G4ConsumeParameters(_Args &&...)
Definition: templates.hh:187
#define G4ThreadLocalStatic
Definition: tls.hh:76