Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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
29#include "G4AutoLock.hh"
30#include "G4DecayTable.hh"
31#include "G4LogicalVolume.hh"
32#include "G4Material.hh"
33#include "G4MaterialTable.hh"
34#include "G4PVParameterised.hh"
35#include "G4PVReplica.hh"
37#include "G4ParticleTable.hh"
40#include "G4PhysicsVector.hh"
41#include "G4PolyconeSide.hh"
42#include "G4PolyhedraSide.hh"
43#include "G4Region.hh"
44#include "G4RegionStore.hh"
45#include "G4Run.hh"
46#include "G4StateManager.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{
72 // This version of the constructor should never be called in sequential mode!
73#ifndef G4MULTITHREADED
75 msg << "Geant4 code is compiled without multi-threading support "
76 "(-DG4MULTITHREADED "
77 "is set to off).";
78 msg << " This type of RunManager can only be used in mult-threaded "
79 "applications.";
80 G4Exception("G4RunManagerKernel::G4RunManagerKernel()", "Run0109", FatalException, msg);
81#endif
82 // Set flag that a MT-type kernel has been instantiated
84}
85
86//============================================================================//
87
89{
90 // Behavior is the same as base class (sequential mode)
91 // ShadowProcess pointer == process poitner
93}
94
95//============================================================================//
96
97namespace
98{
99using WorkerRunManPtr_t = std::unique_ptr<G4WorkerTaskRunManager>;
100using WorkerThreadPtr_t = std::unique_ptr<G4WorkerThread>;
101
102WorkerRunManPtr_t& workerRM()
103{
104 G4ThreadLocalStatic WorkerRunManPtr_t _instance{nullptr};
105 return _instance;
106}
107
108WorkerThreadPtr_t& context()
109{
110 G4ThreadLocalStatic WorkerThreadPtr_t _instance{nullptr};
111 return _instance;
112}
113
114} // namespace
115
116//============================================================================//
117
119{
120 return context().get();
121}
122
123//============================================================================//
124
126{
127 if (context() && workerRM()) return;
128
130 if (G4MTRunManager::GetMasterThreadId() == G4ThisThread::get_id()) {
131 G4TaskManager* taskManager = mrm->GetTaskManager();
132 auto _fut = taskManager->async(InitializeWorker);
133 _fut->wait();
134 return;
135 }
136
137 //!!!!!!!!!!!!!!!!!!!!!!!!!!
138 //!!!!!! IMPORTANT !!!!!!!!!
139 //!!!!!!!!!!!!!!!!!!!!!!!!!!
140 // Here is not sequential anymore and G4UserWorkerThreadInitialization is
141 // a shared user initialization class
142 // This means this method cannot use data memebers of G4RunManagerKernel
143 // unless they are invariant ("read-only") and can be safely shared.
144 // All the rest that is not invariant should be incapsualted into
145 // the context (or, as for wThreadContext be G4ThreadLocal)
146 //!!!!!!!!!!!!!!!!!!!!!!!!!!
147
149 context() = std::make_unique<G4WorkerThread>();
150
151 //============================
152 // Step-0: Thread ID
153 //============================
154 // Initliazie per-thread stream-output
155 // The following line is needed before we actually do IO initialization
156 // becasue the constructor of UI manager resets the IO destination.
157 context()->SetNumberThreads((G4int)mrm->GetThreadPool()->size());
158 context()->SetThreadId(G4int(G4ThreadPool::get_this_thread_id() - 1));
159 G4int thisID = context()->GetThreadId();
162
163 //============================
164 // Optimization: optional
165 //============================
166 // Enforce thread affinity if requested
167 context()->SetPinAffinity(mrm->GetPinAffinity());
168
169 //============================
170 // Step-1: Random number engine
171 //============================
172 // RNG Engine needs to be initialized by "cloning" the master one.
173 const CLHEP::HepRandomEngine* masterEngine = mrm->getMasterRandomEngine();
175
176 //============================
177 // Step-2: Initialize worker thread
178 //============================
179 if (mrm->GetUserWorkerInitialization() != nullptr)
181
182 if (mrm->GetUserActionInitialization() != nullptr) {
184 if (sv != nullptr) G4VSteppingVerbose::SetInstance(sv);
185 }
186 // Now initialize worker part of shared objects (geometry/physics)
187 context()->BuildGeometryAndPhysicsVector();
188 workerRM().reset(static_cast<G4WorkerTaskRunManager*>(
190 auto& wrm = workerRM();
191 wrm->SetWorkerThread(context().get());
192
193 //================================
194 // Step-3: Setup worker run manager
195 //================================
196 // Set the detector and physics list to the worker thread. Share with master
198 wrm->G4RunManager::SetUserInitialization(const_cast<G4VUserDetectorConstruction*>(detector));
199 const G4VUserPhysicsList* physicslist = mrm->GetUserPhysicsList();
200 wrm->SetUserInitialization(const_cast<G4VUserPhysicsList*>(physicslist));
201
202 //================================
203 // Step-4: Initialize worker run manager
204 //================================
205 if (mrm->GetUserActionInitialization() != nullptr)
207 if (mrm->GetUserWorkerInitialization() != nullptr)
209
210 workerRM()->Initialize();
211
212 for (auto& itr : initCmdStack)
214
215 wrm->ProcessUI();
216}
217
218//============================================================================//
219
221{
222 // because of TBB
223 if (G4MTRunManager::GetMasterThreadId() == G4ThisThread::get_id()) {
225 auto _fut = taskManager->async(ExecuteWorkerInit);
226 return _fut->get();
227 }
228
229 // this check is for TBB as there is not a way to run an initialization
230 // routine on each thread
231 if (!workerRM()) InitializeWorker();
232
233 auto& wrm = workerRM();
234 assert(wrm.get() != nullptr);
235 wrm->DoCleanup();
236}
237
238//============================================================================//
239
241{
242 // because of TBB
243 if (G4MTRunManager::GetMasterThreadId() == G4ThisThread::get_id()) {
245 auto _fut = taskManager->async(ExecuteWorkerTask);
246 return _fut->get();
247 }
248
249 // this check is for TBB as there is not a way to run an initialization
250 // routine on each thread
251 if (!workerRM()) InitializeWorker();
252
253 auto& wrm = workerRM();
254 assert(wrm.get() != nullptr);
255 wrm->DoWork();
256}
257
258//============================================================================//
259
261{
262 if (workerRM()) TerminateWorkerRunEventLoop(workerRM().get());
263}
264
265//============================================================================//
266
268{
269 if (workerRM()) TerminateWorker(workerRM().get());
270 workerRM().reset();
271 context().reset();
272}
273
274//============================================================================//
275
277{
278 if (wrm == nullptr) return;
279
280 wrm->TerminateEventLoop();
281 wrm->RunTermination();
282}
283
284//============================================================================//
285
287{
288 if (wrm == nullptr) return;
289
290 //===============================
291 // Step-6: Terminate worker thread
292 //===============================
294 if ((mrm != nullptr) && (mrm->GetUserWorkerInitialization() != nullptr))
296
297 G4WorkerThread* _context = wrm->GetWorkerThread();
299
301}
302
303//============================================================================//
304
306{
307 return initCmdStack;
308}
309
310//============================================================================//
311
313{
315 pItr->reset();
316 while ((*pItr)()) {
317 G4DecayTable* dt = pItr->value()->GetDecayTable();
318 if (dt != nullptr) {
319 G4int nCh = dt->entries();
320 for (G4int i = 0; i < nCh; i++) {
321 dt->GetDecayChannel(i)->GetDaughter(0);
322 }
323 }
324 }
325}
326
327//============================================================================//
328
333
334//============================================================================//
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
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 SetupShadowProcess() const override
void BroadcastAbortRun(G4bool softAbort)
static G4RUN_DLL std::vector< G4String > initCmdStack
static G4WorkerThread * GetWorkerThread()
static std::vector< G4String > & InitCommandStack()
static G4TaskRunManager * GetMasterRunManager()
void SetUpForAThread(G4int tId)
G4int ApplyCommand(const char *aCommand)
static G4UImanager * GetUIpointer()
virtual void SetupRNGEngine(const CLHEP::HepRandomEngine *aRNGEngine) const
virtual G4WorkerRunManager * CreateWorkerRunManager() const
G4ParticleDefinition * GetDaughter(G4int anIndex)
static void SetInstance(G4VSteppingVerbose *Instance)
virtual G4VSteppingVerbose * InitializeSteppingVerbose() const
virtual void Build() const =0
G4WorkerThread * GetWorkerThread() const
static void DestroyGeometryAndPhysicsVector()
std::shared_ptr< PackagedTask< RetT, Args... > > async(FuncT &&func, Args &&... args)
TaskManager * GetTaskManager() const
ThreadPool * GetThreadPool() const
static uintmax_t get_this_thread_id()
size_type size() const
G4int WorkerThreadJoinsPool()
G4int WorkerThreadLeavesPool()
void SetMultithreadedApplication(G4bool value)
void G4SetThreadId(G4int aNewValue)
void G4ConsumeParameters(_Args &&...)
Definition templates.hh:177
#define G4ThreadLocalStatic
Definition tls.hh:76