Geant4  10.01.p02
G4MTRunManagerKernel.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 
27 #include "G4MTRunManagerKernel.hh"
28 #include "G4RegionStore.hh"
29 #include "G4StateManager.hh"
30 #include "G4AutoLock.hh"
31 
32 std::vector<G4WorkerRunManager*>* G4MTRunManagerKernel::workerRMvector = 0;
33 
34 namespace {
35  G4Mutex workerRMMutex = G4MUTEX_INITIALIZER;
36 }
37 
39 {
40  //This version of the constructor should never be called in sequential mode!
41 #ifndef G4MULTITHREADED
43  msg<<"Geant4 code is compiled without multi-threading support (-DG4MULTITHREADED is set to off).";
44  msg<<" This type of RunManager can only be used in mult-threaded applications.";
45  G4Exception("G4RunManagerKernel::G4RunManagerKernel()","Run0035",FatalException,msg);
46 #endif
47  if(!workerRMvector) workerRMvector = new std::vector<G4WorkerRunManager*>;
48  //Set flag that a MT-type kernel has been instantiated
50 }
51 
53 {
54  if(!workerRMvector)
55  {
56  if(workerRMvector->size()>0)
57  {
59  msg<<"G4MTRunManagerKernel is to be deleted while "
60  <<workerRMvector->size()<<" G4WorkerRunManager are still alive.";
61  G4Exception("G4RunManagerKernel::~G4RunManagerKernel()",
62  "Run10035",FatalException,msg);
63  }
64  delete workerRMvector;
65  workerRMvector = 0;
66  }
67 }
68 
70 {
71  //Behavior is the same as base class (sequential mode)
72  //ShadowProcess pointer == process poitner
74 }
75 
76 #include "G4WorkerRunManager.hh"
80 #include "G4WorkerThread.hh"
81 #include "G4UImanager.hh"
82 #include "G4LogicalVolume.hh"
83 #include "G4VPhysicalVolume.hh"
84 #include "G4PVReplica.hh"
85 #include "G4Region.hh"
86 #include "G4Material.hh"
87 #include "G4PhysicsVector.hh"
88 #include "G4VDecayChannel.hh"
89 #include "G4PhysicalVolumeStore.hh"
90 #include "G4MaterialTable.hh"
91 #include "G4PolyconeSide.hh"
92 #include "G4PolyhedraSide.hh"
93 #include "G4PVParameterised.hh"
94 #include "G4VUserPhysicsList.hh"
95 #include "G4VPhysicsConstructor.hh"
96 #include "G4VModularPhysicsList.hh"
97 
100 { return wThreadContext; }
101 
103 {
107  // Here is not sequential anymore and G4UserWorkerThreadInitialization is
108  // a shared user initialization class
109  // This means this method cannot use data memebers of G4RunManagerKernel
110  // unless they are invariant ("read-only") and can be safely shared.
111  // All the rest that is not invariant should be incapsualted into
112  // the context (or, as for wThreadContext be G4ThreadLocal)
114 //#ifdef G4MULTITHREADED
115 // turnontpmalloc();
116 //#endif
117 
118  wThreadContext = static_cast<G4WorkerThread*>(context);
120 
121 
122  //============================
123  //Step-0: Thread ID
124  //============================
125  //Initliazie per-thread stream-output
126  //The following line is needed before we actually do IO initialization
127  //becasue the constructor of UI manager resets the IO destination.
128  G4int thisID = wThreadContext->GetThreadId();
131 
132  //============================
133  //Optimization Step
134  //============================
135  //Enforce thread affinity if requested
136 #if !defined(WIN32)
137  if ( masterRM->GetPinAffinity() != 0 ) {
138  G4cout<<"AFFINITY SET"<<G4endl;
139  //Assign this thread to cpus in a round robin way
140  G4int offset = masterRM->GetPinAffinity();
141  G4int cpuindex = 0;
142  if ( std::abs(offset)>G4Threading::G4GetNumberOfCores() ) {
143  G4Exception("G4MTRunManagerKernel::StarThread","Run0035",JustWarning,"Cannot set thread affinity, affinity parameter larger than number of cores");
144  }
145  if ( offset == 0 ) {
146  offset = 1;
147  G4Exception("G4MTRunManagerKernel::StarThread","Run0035",JustWarning,"Affinity parameter==0, using 1 instead.");
148  }
149  if (offset>0) { //Start assigning affinity to given CPU
150  --offset;
151  cpuindex = (thisID+offset) % G4Threading::G4GetNumberOfCores(); //Round robin
152  } else {//Exclude the given CPU
153  offset *= -1;
154  --offset;
155  G4int myidx = thisID%(G4Threading::G4GetNumberOfCores()-1);
156  cpuindex = myidx + (myidx>=offset);
157  }
158  G4cout<<"AFFINITY:"<<cpuindex<<G4endl;
159  //Avoid compilation warning in C90 standard w/o MT
160 #if defined(G4MULTITHREADED)
161  G4Thread t = G4THREADSELF();
162 #else
163  G4Thread t;
164 #endif
165  G4bool success = G4Threading::G4SetPinAffinity(cpuindex,t);
166  if ( ! success ) {
167  G4Exception("G4MTRunManagerKernel::StarThread","Run0035",JustWarning,"Cannot set thread affinity.");
168  }
169  }
170 #endif
171 
172  //============================
173  //Step-1: Random number engine
174  //============================
175  //RNG Engine needs to be initialized by "cloning" the master one.
176  const CLHEP::HepRandomEngine* masterEngine = masterRM->getMasterRandomEngine();
177  masterRM->GetUserWorkerThreadInitialization()->SetupRNGEngine(masterEngine);
178 
179  //============================
180  //Step-2: Initialize worker thread
181  //============================
182  if(masterRM->GetUserWorkerInitialization())
184  if(masterRM->GetUserActionInitialization())
185  {
187  if ( sv ) { G4VSteppingVerbose::SetInstance(sv); }
188  }
189  //Now initialize worker part of shared objects (geometry/physics)
191  G4WorkerRunManager* wrm
194  G4AutoLock wrmm(&workerRMMutex);
195  workerRMvector->push_back(wrm);
196  wrmm.unlock();
197 
198  //================================
199  //Step-3: Setup worker run manager
200  //================================
201  // Set the detector and physics list to the worker thread. Share with master
202  const G4VUserDetectorConstruction* detector = masterRM->GetUserDetectorConstruction();
203  wrm->G4RunManager::SetUserInitialization(const_cast<G4VUserDetectorConstruction*>(detector));
204  const G4VUserPhysicsList* physicslist = masterRM->GetUserPhysicsList();
205  wrm->SetUserInitialization(const_cast<G4VUserPhysicsList*>(physicslist));
206 
207  //================================
208  //Step-4: Initialize worker run manager
209  //================================
210  if(masterRM->GetUserActionInitialization())
211  { masterRM->GetNonConstUserActionInitialization()->Build(); }
212  if(masterRM->GetUserWorkerInitialization())
213  { masterRM->GetUserWorkerInitialization()->WorkerStart(); }
214  wrm->Initialize();
215 
216  //================================
217  //Step5: Loop over requests from the master thread
218  //================================
220  while( nextAction != G4MTRunManager::ENDWORKER )
221  {
222  if( nextAction == G4MTRunManager::NEXTITERATION ) // start the next run
223  {
224  //The following code deals with changing materials between runs
225  static G4ThreadLocal G4bool skipInitialization = true;
226  if(skipInitialization)
227  {
228  // re-initialization is not necessary for the first run
229  skipInitialization = false;
230  }
231  else
232  {
233 // ReinitializeGeometry();
235  }
236 
237  // Execute UI commands stored in the masther UI manager
238  std::vector<G4String> cmds = masterRM->GetCommandStack();
239  G4UImanager* uimgr = G4UImanager::GetUIpointer(); //TLS instance
240  std::vector<G4String>::const_iterator it = cmds.begin();
241  for(;it!=cmds.end();it++)
242  { uimgr->ApplyCommand(*it); }
243  //Start this run
244  G4int numevents = masterRM->GetNumberOfEventsToBeProcessed();
245  G4String macroFile = masterRM->GetSelectMacro();
246  G4int numSelect = masterRM->GetNumberOfSelectEvents();
247  if ( macroFile == "" || macroFile == " " )
248  {
249  wrm->BeamOn(numevents);
250  }
251  else
252  {
253  wrm->BeamOn(numevents,macroFile,numSelect);
254  }
255  }
256  else
257  {
259  d<<"Cannot continue, this worker has been requested an unknwon action: "
260  <<nextAction<<" expecting: ENDWORKER(=" <<G4MTRunManager::ENDWORKER
261  <<") or NEXTITERATION(="<<G4MTRunManager::NEXTITERATION<<")";
262  G4Exception("G4MTRunManagerKernel::StartThread","Run0035",FatalException,d);
263  }
264 
265  //Now wait for master thread to signal new action to be performed
266  nextAction = masterRM->ThisWorkerWaitForNextAction();
267  } //No more actions to perform
268 
269  //===============================
270  //Step-6: Terminate worker thread
271  //===============================
272  if(masterRM->GetUserWorkerInitialization())
273  { masterRM->GetUserWorkerInitialization()->WorkerStop(); }
274 
275  wrmm.lock();
276  std::vector<G4WorkerRunManager*>::iterator itrWrm = workerRMvector->begin();
277  for(;itrWrm!=workerRMvector->end();itrWrm++)
278  {
279  if((*itrWrm)==wrm)
280  {
281  workerRMvector->erase(itrWrm);
282  break;
283  }
284  }
285  wrmm.unlock();
286  delete wrm;
288  wThreadContext = 0;
289 
290  return static_cast<void*>(0);
291 }
292 
293 //Now moved to G4WorkerThread
294 //void G4MTRunManagerKernel::ReinitializeGeometry()
295 //{
296 // G4AutoLock wrmm(&workerRMMutex);
297 // //=================================================
298 // //Step-0: keep sensitive detector and field manager
299 // //=================================================
300 // typedef std::map<G4LogicalVolume*,std::pair<G4VSensitiveDetector*,G4FieldManager*> > LV2SDFM;
301 // LV2SDFM lvmap;
302 // G4PhysicalVolumeStore* mphysVolStore = G4PhysicalVolumeStore::GetInstance();
303 // for(size_t ip=0;ip<mphysVolStore->size();ip++)
304 // {
305 // G4VPhysicalVolume* pv = (*mphysVolStore)[ip];
306 // G4LogicalVolume *lv = pv->GetLogicalVolume();
307 // G4VSensitiveDetector* sd = lv->GetSensitiveDetector();
308 // G4FieldManager* fm = lv->GetFieldManager();
309 // if(sd||fm) lvmap[lv] = std::make_pair(sd,fm);
310 // }
311 //
312 // //===========================
313 // //Step-1: Clean the instances
314 // //===========================
315 // const_cast<G4LVManager&>(G4LogicalVolume::GetSubInstanceManager()).FreeSlave();
316 // const_cast<G4PVManager&>(G4VPhysicalVolume::GetSubInstanceManager()).FreeSlave();
317 // const_cast<G4PVRManager&>(G4PVReplica::GetSubInstanceManager()).FreeSlave();
318 // const_cast<G4RegionManager&>(G4Region::GetSubInstanceManager()).FreeSlave();
319 // const_cast<G4PlSideManager&>(G4PolyconeSide::GetSubInstanceManager()).FreeSlave();
320 // const_cast<G4PhSideManager&>(G4PolyhedraSide::GetSubInstanceManager()).FreeSlave();
321 //
322 // //===========================
323 // //Step-2: Re-create instances
324 // //===========================
325 // const_cast<G4LVManager&>(G4LogicalVolume::GetSubInstanceManager()).SlaveCopySubInstanceArray();
326 // const_cast<G4PVManager&>(G4VPhysicalVolume::GetSubInstanceManager()).SlaveCopySubInstanceArray();
327 // const_cast<G4PVRManager&>(G4PVReplica::GetSubInstanceManager()).SlaveCopySubInstanceArray();
328 // const_cast<G4RegionManager&>(G4Region::GetSubInstanceManager()).SlaveInitializeSubInstance();
329 // const_cast<G4PlSideManager&>(G4PolyconeSide::GetSubInstanceManager()).SlaveInitializeSubInstance();
330 // const_cast<G4PhSideManager&>(G4PolyhedraSide::GetSubInstanceManager()).SlaveInitializeSubInstance();
331 //
332 // //===============================
333 // //Step-3: Re-initialize instances
334 // //===============================
335 // for(size_t ip=0;ip<mphysVolStore->size();ip++)
336 // {
337 // G4VPhysicalVolume* physVol = (*mphysVolStore)[ip];
338 // G4LogicalVolume* g4LogicalVolume = physVol->GetLogicalVolume();
339 // G4VSolid* g4VSolid = g4LogicalVolume->GetMasterSolid(); // shadow pointer
340 // G4PVReplica* g4PVReplica = 0;
341 // g4PVReplica = dynamic_cast<G4PVReplica*>(physVol);
342 // if(g4PVReplica) // if the volume is a replica
343 // {
344 // G4VSolid *slaveg4VSolid = g4VSolid->Clone();
345 // g4LogicalVolume->InitialiseWorker(g4LogicalVolume,slaveg4VSolid,0);
346 // }
347 // else
348 // { g4LogicalVolume->InitialiseWorker(g4LogicalVolume,g4VSolid,0); }
349 // }
350 //
351 // //===================================================
352 // //Step-4: Restore sensitive detector and field manaer
353 // //===================================================
354 // LV2SDFM::const_iterator it = lvmap.begin();
355 // for(; it!=lvmap.end() ; ++it )
356 // {
357 // G4LogicalVolume* lv = it->first;
358 // G4VSensitiveDetector* sd = (it->second).first;
359 // G4FieldManager* fm = (it->second).second;
360 // lv->SetFieldManager(fm, false);
361 // lv->SetSensitiveDetector(sd);
362 // }
363 // wrmm.unlock();
364 //}
365 
366 #include "G4ParticleDefinition.hh"
367 #include "G4ParticleTable.hh"
369 #include "G4DecayTable.hh"
370 #include "G4VDecayChannel.hh"
371 
373 {
376  pItr->reset();
377  while((*pItr)())
378  {
379  G4DecayTable* dt = pItr->value()->GetDecayTable();
380  if(dt)
381  {
382  G4int nCh = dt->entries();
383  for(G4int i=0;i<nCh;i++)
384  { dt->GetDecayChannel(i)->GetDaughter(0); }
385  }
386  }
387 }
388 
390 {
391  G4AutoLock wrmm(&workerRMMutex);
392  std::vector<G4WorkerRunManager*>::iterator itr = workerRMvector->begin();
393  for(;itr!=workerRMvector->end();itr++)
394  { (*itr)->AbortRun(softAbort); }
395 }
396 
static void * StartThread(void *context)
G4bool G4SetPinAffinity(G4int idx, G4Thread &at)
Definition: G4Threading.cc:131
std::vector< G4String > GetCommandStack()
virtual void SetupShadowProcess() const
void SetMultithreadedApplication(G4bool value)
Definition: G4Threading.cc:133
void SetUpForAThread(G4int tId)
Definition: G4UImanager.cc:713
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
virtual void SetupRNGEngine(const CLHEP::HepRandomEngine *aRNGEngine) const
static void UpdateGeometryAndPhysicsVectorFromMaster()
G4String GetSelectMacro() const
const G4VUserDetectorConstruction * GetUserDetectorConstruction() const
static std::vector< G4WorkerRunManager * > * workerRMvector
G4ParticleDefinition * GetDaughter(G4int anIndex)
static void BuildGeometryAndPhysicsVector()
void G4SetThreadId(G4int aNewValue)
Definition: G4Threading.cc:129
virtual void BeamOn(G4int n_event, const char *macroFile=0, G4int n_select=-1)
G4VDecayChannel * GetDecayChannel(G4int index) const
const G4UserWorkerInitialization * GetUserWorkerInitialization() const
virtual G4WorkerRunManager * CreateWorkerRunManager() const
#define G4ThreadLocal
Definition: tls.hh:89
virtual void SetUserInitialization(G4VUserPhysicsList *userInit)
int G4int
Definition: G4Types.hh:78
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:175
G4int G4Thread
Definition: G4Threading.hh:174
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:58
G4int entries() const
void SetupShadowProcess() const
G4GLOB_DLL std::ostream G4cout
void reset(G4bool ifSkipIon=true)
bool G4bool
Definition: G4Types.hh:79
static G4WorkerThread * GetWorkerThread()
static G4MTRunManager * GetMasterRunManager()
G4int G4GetNumberOfCores()
Definition: G4Threading.cc:126
virtual WorkerActionRequest ThisWorkerWaitForNextAction()
#define G4THREADSELF(nothing)
Definition: G4Threading.hh:183
virtual void Build() const =0
G4int GetPinAffinity() const
G4int GetThreadId() const
G4int GetNumberOfEventsToBeProcessed() const
const G4VUserActionInitialization * GetUserActionInitialization() const
static G4ThreadLocal G4WorkerThread * wThreadContext
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
G4int GetNumberOfSelectEvents() const
void SetWorkerThread(G4WorkerThread *wc)
Sets the worker context.
const G4UserWorkerThreadInitialization * GetUserWorkerThreadInitialization() const
G4int G4Mutex
Definition: G4Threading.hh:173
static void SetInstance(G4VSteppingVerbose *Instance)
static G4ParticleTable * GetParticleTable()
G4VUserActionInitialization * GetNonConstUserActionInitialization() const
const CLHEP::HepRandomEngine * getMasterRandomEngine() const
virtual G4VSteppingVerbose * InitializeSteppingVerbose() const
static void DestroyGeometryAndPhysicsVector()
virtual void Initialize()
#define G4endl
Definition: G4ios.hh:61
const G4VUserPhysicsList * GetUserPhysicsList() const
void BroadcastAbortRun(G4bool softAbort)
G4PTblDicIterator * GetIterator() const
G4int ApplyCommand(const char *aCommand)
Definition: G4UImanager.cc:432