Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
G4MTRunManager.cc
이 파일의 문서화 페이지로 가기
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 
28 #include "G4MTRunManager.hh"
29 #include "G4MTRunManagerKernel.hh"
30 #include "G4Timer.hh"
31 #include "G4StateManager.hh"
32 #include "G4ScoringManager.hh"
37 #include "G4WorkerThread.hh"
38 #include "G4Run.hh"
39 #include "G4UImanager.hh"
40 #include "G4AutoLock.hh"
41 #include "G4WorkerRunManager.hh"
42 #include "G4UserRunAction.hh"
43 #include "G4ProductionCutsTable.hh"
44 #include "G4Timer.hh"
45 #include "G4TiMemory.hh"
46 
51 
52 namespace {
53  G4Mutex cmdHandlingMutex = G4MUTEX_INITIALIZER;
54  G4Mutex scorerMergerMutex = G4MUTEX_INITIALIZER;
55  G4Mutex runMergerMutex = G4MUTEX_INITIALIZER;
56  G4Mutex setUpEventMutex = G4MUTEX_INITIALIZER;
57 }
58 
60 {
62  return fMasterRM;
66 }
67 
69 {
70  return fMasterRM->kernel;
71 }
72 
74 {
75  return fMasterRM->MTkernel;
76 }
77 
79  nworkers(2),forcedNwokers(-1),pinAffinity(0),
80  masterRNGEngine(0),
81  nextActionRequest(WorkerActionRequest::UNDEFINED),
82  eventModuloDef(0),eventModulo(1),
83  nSeedsUsed(0),nSeedsFilled(0),
84  nSeedsMax(10000),nSeedsPerEvent(2)
85 {
86  if ( fMasterRM )
87  {
88  G4Exception("G4MTRunManager::G4MTRunManager", "Run0110",FatalException,
89  "Another instance of a G4MTRunManager already exists.");
90  }
91  fMasterRM = this;
92  MTkernel = static_cast<G4MTRunManagerKernel*>(kernel);
93 #ifndef G4MULTITHREADED
95  msg << "Geant4 code is compiled without multi-threading support"
96  << "(-DG4MULTITHREADED is set to off).\n";
97  msg << "G4MTRunManager can only be used in multi-threaded applications.";
98  G4Exception("G4MTRunManager::G4MTRunManager","Run0111",FatalException,msg);
99 #endif
100 
101  G4int numberOfStaticAllocators = kernel->GetNumberOfStaticAllocators();
102  if(numberOfStaticAllocators>0)
103  {
105  msg1 << "There are " << numberOfStaticAllocators
106  << " static G4Allocator objects detected.\n"
107  << "In multi-threaded mode, all G4Allocator objects must be dynamicly instantiated.";
108  G4Exception("G4MTRunManager::G4MTRunManager","Run1035",FatalException,msg1);
109  }
112 
113  //Check if a default RandomNumberGenerator has been created by user,
114  // if not create default one
115  //Note this call forces creation of defaults if not already there
116  //G4Random::getTheEngine(); //User did not specify RNG, create defaults
117  //Now remember the master instance of the RNG Engine
118  masterRNGEngine = G4Random::getTheEngine();
119 
121  randDbl = new double[nSeedsPerEvent*nSeedsMax];
122 
123  char* env = getenv("G4FORCENUMBEROFTHREADS");
124  if(env)
125  {
126  G4String envS = env;
127  if(envS=="MAX"||envS=="max")
129  else
130  {
131  std::istringstream is(env);
132  G4int val = -1;
133  is >> val;
134  if(val>0)
135  { forcedNwokers = val; }
136  else
137  {
139  msg2 << "Environment variable G4FORCENUMBEROFTHREADS has an invalid value <"
140  << envS << ">. It has to be an integer or a word \"max\".\n"
141  << "G4FORCENUMBEROFTHREADS is ignored.";
142  G4Exception("G4MTRunManager::G4MTRunManager","Run1039",JustWarning,msg2);
143  }
144  }
145  if(forcedNwokers>0)
146  {
148  G4cout << "### Number of threads is forced to " << forcedNwokers
149  << " by Environment variable G4FORCENUMBEROFTHREADS." << G4endl;
150  }
151  }
152 }
153 
155 {
156  //TODO: Currently does not work due to concurrent deletion of something
157  // that is shared:
158  //G4ProcessTable::DeleteMessenger from ~G4RunManager
159  //G4cout<<"Destroy MTRunManager"<<G4endl;//ANDREA
161  delete [] randDbl;
162 }
163 
165 {
166  std::ostringstream os;
167  os << randomNumberStatusDir << "G4Master_"<<fn <<".rndm";
168  G4Random::saveEngineStatus(os.str().c_str());
169 }
170 
172 {
173  if ( threads.size() != 0 )
174  {
176  msg << "Number of threads cannot be changed at this moment \n"
177  << "(old threads are still alive). Method ignored.";
178  G4Exception("G4MTRunManager::SetNumberOfThreads(G4int)",
179  "Run0112", JustWarning, msg);
180  }
181  else if ( forcedNwokers > 0 )
182  {
184  msg << "Number of threads is forced to " << forcedNwokers
185  << " by G4FORCENUMBEROFTHREADS shell variable.\n"
186  << "Method ignored.";
187  G4Exception("G4MTRunManager::SetNumberOfThreads(G4int)",
188  "Run0113", JustWarning, msg);
189  }
190  else
191  {
192  nworkers = n;
193  }
194 }
195 
197 {
199 
200  // make sure all worker threads are set up.
201  BeamOn(0);
202  SetRunIDCounter(0);
204 }
205 
211 {
212  //Nothing to do
213 }
215 {
216  //Nothing to do
217 }
218 
220  G4AutoLock l(&cmdHandlingMutex);
221  uiCmdsForWorkers.clear();
222  std::vector<G4String>* cmdCopy = G4UImanager::GetUIpointer()->GetCommandStack();
223  for ( std::vector<G4String>::const_iterator it = cmdCopy->begin() ;
224  it != cmdCopy->end(); ++it )
225  uiCmdsForWorkers.push_back(*it);
226  cmdCopy->clear();
227  delete cmdCopy;
228 }
229 
230 std::vector<G4String> G4MTRunManager::GetCommandStack()
231 {
232  G4AutoLock l(&cmdHandlingMutex);
233  return uiCmdsForWorkers;
234 }
235 
237 {
238  //Now loop on requested number of workers
239  //This will also start the workers
240  //Currently we do not allow to change the
241  //number of threads: threads area created once
242  if ( threads.size() == 0 ) {
243  for ( G4int nw = 0 ; nw<nworkers; ++nw) {
244  //Create a new worker and remember it
246  context->SetNumberThreads(nworkers);
247  context->SetThreadId(nw);
249  threads.push_back(thread);
250  }
251  }
252  //Signal to threads they can start a new run
254 }
255 
256 
257 void G4MTRunManager::InitializeEventLoop(G4int n_event, const char* macroFile, G4int n_select)
258 {
261  numberOfEventToBeProcessed = n_event;
263 
264  if(!fakeRun)
265  {
266  nSeedsUsed = 0;
267  nSeedsFilled = 0;
268 
269  if(verboseLevel>0)
270  { timer->Start(); }
271 
272  n_select_msg = n_select;
273  if(macroFile!=0)
274  {
275  if(n_select_msg<0) n_select_msg = n_event;
276  msgText = "/control/execute ";
277  msgText += macroFile;
278  selectMacro = macroFile;
279  }
280  else
281  {
282  n_select_msg = -1;
283  selectMacro = "";
284  }
285 
286  //initialize seeds
287  //If user did not implement InitializeSeeds,
288  // use default: nSeedsPerEvent seeds per event
289  if( eventModuloDef > 0 )
290  {
293  {
295  if(eventModulo<1) eventModulo =1;
297  msgd << "Event modulo is reduced to " << eventModulo
298  << " to distribute events to all threads.";
299  G4Exception("G4MTRunManager::InitializeEventLoop()",
300  "Run10035", JustWarning, msgd);
301  }
302  }
303  else
304  {
305  eventModulo = int(std::sqrt(double(numberOfEventToBeProcessed/nworkers)));
306  if(eventModulo<1) eventModulo =1;
307  }
308  if ( InitializeSeeds(n_event) == false && n_event>0 )
309  {
312  {
313  case 0:
314  nSeedsFilled = n_event;
315  break;
316  case 1:
318  break;
319  case 2:
320  nSeedsFilled = n_event/eventModulo + 1;
321  break;
322  default:
324  msgd << "Parameter value <" << seedOncePerCommunication
325  << "> of seedOncePerCommunication is invalid. It is reset to 0." ;
326  G4Exception("G4MTRunManager::InitializeEventLoop()",
327  "Run10036", JustWarning, msgd);
328  seedOncePerCommunication = 0;
329  nSeedsFilled = n_event;
330  }
331 
332  // Generates up to nSeedsMax seed pairs only.
335  helper->Fill(randDbl,nSeedsFilled,n_event,nSeedsPerEvent);
336  }
337  }
338 
339  //Now initialize workers. Check if user defined a WorkerThreadInitialization
342 
343  //Prepare UI commands for threads
345 
346  //Start worker threads
348 
349  // We need a barrier here. Wait for workers to start event loop.
350  //This will return only when all workers have started processing events.
352 }
353 
355 {
357  G4int nFill = 0;
359  {
360  case 0:
362  break;
363  case 1:
364  nFill = nworkers - nSeedsFilled;
365  break;
366  case 2:
367  default:
368  nFill = (numberOfEventToBeProcessed - nSeedsFilled*eventModulo)/eventModulo + 1;
369  }
370  // Generates up to nSeedsMax seed pairs only.
371  if(nFill>nSeedsMax) nFill=nSeedsMax;
373  helper->Refill(randDbl,nFill);
374  nSeedsFilled += nFill;
375 //G4cout<<"helper->Refill() for "<<nFill<<" events."<<G4endl;
376 }
377 
379 {
380  //Wait for all worker threads to have finished the run
381  //i.e. wait for them to return from RunTermination()
382  //This guarantee that userrunaction for workers has been called
383 
384  // Wait now for all threads to finish event-loop
386  //Now call base-class methof
389 }
390 
392 {
394  //Call base class stuff...
396 
397  masterWorlds.clear();
399  std::vector<G4VPhysicalVolume*>::iterator itrW
401  for(size_t iWorld=0;iWorld<nWorlds;iWorld++)
402  {
403  addWorld(iWorld,*itrW);
404  itrW++;
405  }
406 }
407 
409 {
410  userWorkerInitialization = userInit;
411 }
412 
414 {
416 }
417 
419 {
420  userActionInitialization = userInit;
422 }
423 
425 {
427  //Needed for MT, to be moved in kernel
428 }
429 
431 {
433 }
434 
436 {
437  G4RunManager::SetUserAction(userAction);
438  if(userAction) userAction->SetMaster();
439 }
440 
442 {
443  G4Exception("G4MTRunManager::SetUserAction()", "Run0123", FatalException,
444  "For multi-threaded version, define G4VUserPrimaryGeneratorAction in G4VUserActionInitialization.");
445 }
446 
448 {
449  G4Exception("G4MTRunManager::SetUserAction()", "Run0124", FatalException,
450  "For multi-threaded version, define G4UserEventAction in G4VUserActionInitialization.");
451 }
452 
454 {
455  G4Exception("G4MTRunManager::SetUserAction()", "Run0125", FatalException,
456  "For multi-threaded version, define G4UserStackingAction in G4VUserActionInitialization.");
457 }
458 
460 {
461  G4Exception("G4MTRunManager::SetUserAction()", "Run0126", FatalException,
462  "For multi-threaded version, define G4UserTrackingAction in G4VUserActionInitialization.");
463 }
464 
466 {
467  G4Exception("G4MTRunManager::SetUserAction()", "Run0127", FatalException,
468  "For multi-threaded version, define G4UserSteppingAction in G4VUserActionInitialization.");
469 }
470 
471 void G4MTRunManager::MergeScores(const G4ScoringManager* localScoringManager)
472 {
473  G4AutoLock l(&scorerMergerMutex);
474  if(masterScM) masterScM->Merge(localScoringManager);
475 }
476 
477 void G4MTRunManager::MergeRun(const G4Run* localRun)
478 {
479  G4AutoLock l(&runMergerMutex);
480  if(currentRun) currentRun->Merge(localRun);
481 }
482 
483 G4bool G4MTRunManager::SetUpAnEvent(G4Event* evt,long& s1,long& s2,long& s3,G4bool reseedRequired)
484 {
485  G4AutoLock l(&setUpEventMutex);
487  {
489  if(reseedRequired)
490  {
492  G4int idx_rndm = nSeedsPerEvent*nSeedsUsed;
493  s1 = helper->GetSeed(idx_rndm);
494  s2 = helper->GetSeed(idx_rndm+1);
495  if(nSeedsPerEvent==3) s3 = helper->GetSeed(idx_rndm+2);
496  nSeedsUsed++;
497  if(nSeedsUsed==nSeedsFilled) RefillSeeds();
498  }
500  return true;
501  }
502  return false;
503 }
504 
506 {
507  G4AutoLock l(&setUpEventMutex);
509  {
510  G4int nev = eventModulo;
514  if(reseedRequired)
515  {
517  G4int nevRnd = nev;
518  if(seedOncePerCommunication>0) nevRnd = 1;
519  for(int i=0;i<nevRnd;i++)
520  {
521  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed));
522  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed+1));
523  if(nSeedsPerEvent==3)
524  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed+2));
525  nSeedsUsed++;
526  if(nSeedsUsed==nSeedsFilled) RefillSeeds();
527  }
528  }
529  numberOfEventProcessed += nev;
530  return nev;
531  }
532  return 0;
533 }
534 
536 {
537  //Force workers to execute (if any) all UI commands left in the stack
539  //Ask workers to exit
541  //Now join threads.
542 #ifdef G4MULTITHREADED //protect here to prevent warning in compilation
543  while ( ! threads.empty() )
544  {
545  G4Thread* t = * ( threads.begin() );
546  threads.pop_front();
548  //G4THREADJOIN(*t);
549  delete t;
550  }
551 #endif
552  threads.clear();
553 }
554 
556 {
557  // This method is valid only for GeomClosed or EventProc state
558  G4ApplicationState currentState =
560  if(currentState==G4State_GeomClosed || currentState==G4State_EventProc)
561  {
562  runAborted = true;
563  MTkernel->BroadcastAbortRun(softAbort);
564  }
565  else
566  {
567  G4cerr << "Run is not in progress. AbortRun() ignored." << G4endl;
568  }
569 }
570 
572 {
573  // nothing to do in the master thread
574 }
575 
580 }
581 
584 }
585 
590 }
591 
594 }
595 
598  //nextActionRequest is a shared resource, but there is no
599  //data-race thanks to the barrier: all threads are waiting
600  nextActionRequest = newRequest;
602 }
603 
606  return nextActionRequest;
607 }
608 
614 }
615 
618 }
620 {
621  if ( n == 0 )
622  {
623  G4Exception("G4MTRunManager::SetPinAffinity",
624  "Run0114",FatalException,
625  "Pin affinity must be >0 or <0.");
626  }
627  pinAffinity = n;
628  return;
629 }
static G4MTRunManager * GetMasterRunManager()
G4String msgText
virtual G4bool InitializeSeeds(G4int)
void SetNumberOfThreads(G4int n)
std::vector< G4String > * GetCommandStack()
Definition: G4UImanager.cc:744
static G4MTRunManager * fMasterRM
G4MTBarrier endOfEventLoopBarrier
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:45
G4VUserActionInitialization * userActionInitialization
virtual void PrepareCommandsStack()
virtual void ProcessOneEvent(G4int i_event)
void ResetCounter()
Definition: G4MTBarrier.cc:83
void Start()
#define G4endl
Definition: G4ios.hh:61
void Wait()
Definition: G4MTBarrier.cc:56
virtual void SetUserAction(G4UserRunAction *userAction)
G4Timer * timer
virtual void WaitForReadyWorkers()
Definition: G4MTBarrier.cc:76
std::vector< G4VPhysicalVolume * >::iterator GetWorldsIterator()
virtual void flatArray(const int size, double *vect)=0
std::vector< G4String > GetCommandStack()
G4MTRunManagerKernel * MTkernel
G4int G4GetNumberOfCores()
Definition: G4Threading.cc:127
virtual G4Thread * CreateAndStartWorker(G4WorkerThread *workerThreadContext)
void Fill(G4double *dbl, G4int nev, G4int nev_tot, G4int nrpe)
Definition: G4RNGHelper.hh:77
virtual void RunTermination()
virtual const T GetSeed(const G4int &sdId)
Definition: G4RNGHelper.hh:58
virtual void CreateAndStartWorkers()
virtual void ConstructScoringWorlds()
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:73
std::map< G4int, G4VPhysicalVolume * > masterWorlds_t
virtual void ThisWorkerEndEventLoop()
virtual void SetUserInitialization(G4VUserDetectorConstruction *userInit)
G4MTBarrier processUIBarrier
virtual void BeamOn(G4int n_event, const char *macroFile=0, G4int n_select=-1)
virtual void TerminateEventLoop()
virtual ~G4MTRunManager()
G4int numberOfEventProcessed
virtual void NewActionRequest(WorkerActionRequest newRequest)
bool G4bool
Definition: G4Types.hh:79
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:88
virtual void InitializeEventLoop(G4int n_event, const char *macroFile=0, G4int n_select=-1)
virtual void ConstructScoringWorlds()
virtual void AbortRun(G4bool softAbort=false)
static G4ScoringManager * GetScoringManagerIfExist()
G4MTBarrier nextActionRequestBarrier
virtual void WaitForReadyWorkers()
void Merge(const G4ScoringManager *scMan)
virtual void SetUserInitialization(G4VUserPhysicsList *userPL)
void MergeRun(const G4Run *localRun)
G4int n_select_msg
static G4int seedOncePerCommunication
virtual G4bool SetUpAnEvent(G4Event *, long &s1, long &s2, long &s3, G4bool reseedRequired=true)
typedef int(XMLCALL *XML_NotStandaloneHandler)(void *userData)
G4Run * currentRun
WorkerActionRequest nextActionRequest
void SetActiveThreads(unsigned int val)
Definition: G4MTBarrier.hh:139
G4UserWorkerInitialization * userWorkerInitialization
void SetPinAffinity(G4int n=1)
virtual void ThisWorkerReady()
size_t GetNoWorlds() const
virtual void TerminateOneEvent()
static G4ScoringManager * masterScM
G4GLOB_DLL std::ostream G4cerr
virtual void SetUserAction(G4UserRunAction *userAction)
G4bool runAborted
Definition: G4Run.hh:46
void BroadcastAbortRun(G4bool softAbort)
static G4TransportationManager * GetTransportationManager()
static masterWorlds_t masterWorlds
void SetThreadId(G4int threadId)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.hh:65
const XML_Char * context
Definition: expat.h:434
G4int numberOfEventToBeProcessed
virtual void TerminateWorkers()
int G4int
Definition: G4Types.hh:78
G4String selectMacro
void MergeScores(const G4ScoringManager *localScoringManager)
G4ApplicationState GetCurrentState() const
std::queue< G4long > G4SeedsQueue
Definition: G4RNGHelper.hh:128
void ReleaseBarrier()
Definition: G4MTBarrier.cc:69
G4UserWorkerThreadInitialization * userWorkerThreadInitialization
static G4RunManagerKernel * GetMasterRunManagerKernel()
virtual void StoreRNGStatus(const G4String &filenamePrefix)
G4GLOB_DLL std::ostream G4cout
virtual void Initialize()
G4ApplicationState
size_t GetNumberActiveThreads() const
virtual void AbortEvent()
Char_t n[5]
virtual void WaitForEndEventLoopWorkers()
virtual G4int SetUpNEvents(G4Event *, G4SeedsQueue *seedsQueue, G4bool reseedRequired=true)
#define TIMEMORY_AUTO_TIMER(str)
Definition: G4TiMemory.hh:66
static G4TemplateRNGHelper< T > * GetInstance()
Definition: G4RNGHelper.cc:37
virtual void Merge(const G4Run *)
Definition: G4Run.cc:54
CLHEP::HepRandomEngine * masterRNGEngine
virtual void SetMaster(G4bool val=true)
void Refill(G4double *dbl, G4int nev)
Definition: G4RNGHelper.hh:88
virtual WorkerActionRequest ThisWorkerWaitForNextAction()
G4String randomNumberStatusDir
void SetEventID(G4int i)
Definition: G4Event.hh:115
virtual void RequestWorkersProcessCommandsStack()
void ThisWorkerReady()
Definition: G4MTBarrier.cc:45
virtual void ThisWorkerProcessCommandsStackDone()
G4int GetNumberOfStaticAllocators() const
G4int verboseLevel
virtual void Initialize()
void SetMasterUIManager(G4bool val)
Definition: G4UImanager.hh:260
std::vector< G4String > uiCmdsForWorkers
virtual void RunTermination()
static void addWorld(G4int counter, G4VPhysicalVolume *w)
static G4MTRunManagerKernel * GetMTMasterRunManagerKernel()
void SetRunIDCounter(G4int i)
void SetNumberThreads(G4int numnberThreads)
G4RunManagerKernel * kernel
G4ThreadsList threads
static G4StateManager * GetStateManager()
G4MTBarrier beginOfEventLoopBarrier
std::mutex G4Mutex
Definition: G4Threading.hh:84