ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tbbTask.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file tbbTask.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 #include "tbbTask.hh"
27 #include "tbbWorkerRunManager.hh"
28 #include "G4Threading.hh"
29 #include "G4String.hh"
30 #include "G4WorkerRunManager.hh"
31 #include "G4MTRunManager.hh"
32 #include "G4UImanager.hh"
34 #include "G4WorkerThread.hh"
35 #include "G4MTRunManagerKernel.hh"
36 #include "G4AutoLock.hh"
39 
40 //Equivalent to G4MTRunManagerKernel::StartThread
41 
43  tbb::concurrent_queue<const G4Run*>* out,
44  G4int nevts)
45 : m_nEvents(nevts),
46  m_taskID(anId),
47  m_output(out),
48  m_beamOnCondition(false)
49 {
50 }
51 
53 {
54 }
55 
56 #include <tbb/atomic.h>
57 namespace {
58  tbb::atomic<int> counter;
59 }
60 
61 tbb::task* tbbTask::execute()
62 {
63  // In tbb we do not have anymore the concept of thread:
64  // tasks run "somewhere"; but there is no control over where.
65  // This somewhere is a thread, created, controlled and 'switched'
66  // to our task by the TBB runtime system.
67  //
68  // The "pedantic" way to proceed is: recreate the "context"
69  // from scratch every time (context=local run manager,
70  // geometry, etc)
71  // This would be a clear waste of resources: there is no
72  // need to initialize multiple times, when the same thread
73  // is used several times, ie for several tasks.
74 
75  // In the current version to avoid this we initialize only
76  // i) the first time we run on each thread, and
77  // ii) at the start of a new run on each thread (reinitialization).
78  // We are confident that this works because TBB co-works with TLS.
79  // In addition this ensures that minimal changes needed to G4 code base.
80  //
81  // Note 1: that this "thread" is responsible for 1 or more TBB task,
82  // e.g. at least one event.
83  // Note 2: In this first example, we do not care about memory usage:
84  // The resources required depend only on the total number of
85  // threads used for at least one event during the simulation.
86  // Note 3: It is possible to do better - this is left for another example.
87  // Here is a sketch how:
88  // If there is a set maximum <N> threads which will be doing
89  // simulation at any point, and that this is smaller than the
90  // number of TBB tasks which can run simulataneously.
91  // What would need to be done is to "acquire" a resource (workspace)
92  // which holds all the memory required for a running task/thread,
93  // and release it at the end of the task to be re-used by other tasks
94  // possibly on different threads. This is demonstrated in another
95  // example.
96 
97  static G4ThreadLocal tbbWorkerRunManager* localRM = 0;
98 
99 
100  //Is this task running for the first time?
101  //How to re-initialize between runs????
102  if (! localRM ) {
103  //It's a new thread, basically repeat what is being done in
104  //G4MTRunManagerKernel::StarThread with an
105  //important difference, do not process data or wait for master to
106  //communicate what to do, it will
107  //not happen!
109  //============================
110  //Step-0: Thread ID
111  //============================
112  //Initliazie per-thread stream-output
113  //The following line is needed before we actually do I/O initialization
114  //because the constructor of UI manager resets the I/O destination.
115  G4int thisId = counter.fetch_and_increment();
116  G4Threading::G4SetThreadId( thisId );
118 
119  //============================
120  //Step-1: Random number engine
121  //============================
122  //RNG Engine needs to be initialized by "cloning" the master one.
123  const CLHEP::HepRandomEngine* masterEngine =
124  masterRM->getMasterRandomEngine();
125  masterRM->GetUserWorkerThreadInitialization()->SetupRNGEngine(masterEngine);
126 
127  //============================
128  //Step-2: Initialize worker thread
129  //============================
130  if(masterRM->GetUserWorkerInitialization())
132  if(masterRM->GetUserActionInitialization()) {
133  G4VSteppingVerbose* sv =
136  }
137  //Now initialize worker part of shared objects (geometry/physics)
139  localRM = static_cast<tbbWorkerRunManager*>(
141  );
142  G4cout<<localRM<<G4endl;
143  //localRM->SetWorkerThread(wThreadContext);
144 // G4AutoLock wrmm(&workerRMMutex);
145 // G4MTRunManagerKernel::workerRMvector->push_back(localRM); //<<<<?????? ANDREA TBB
146 // wrmm.unlock();
147 
148  //================================
149  //Step-3: Setup worker run manager
150  //================================
151  // Set the detector and physics list to the worker thread. Share with master
152  const G4VUserDetectorConstruction* detector =
153  masterRM->GetUserDetectorConstruction();
154  localRM->G4RunManager::SetUserInitialization(
155  const_cast<G4VUserDetectorConstruction*>(detector));
156  const G4VUserPhysicsList* physicslist = masterRM->GetUserPhysicsList();
157  localRM->SetUserInitialization(const_cast<G4VUserPhysicsList*>(physicslist));
158 
159  //================================
160  //Step-4: Initialize worker run manager
161  //================================
162  if(masterRM->GetUserActionInitialization())
163  { masterRM->GetNonConstUserActionInitialization()->Build(); }
164  if(masterRM->GetUserWorkerInitialization())
165  { masterRM->GetUserWorkerInitialization()->WorkerStart(); }
166  localRM->Initialize();
167 
168  //Problem at this point is if there is more than one run...
169  // Execute UI commands stored in the masther UI manager
170  std::vector<G4String> cmds = masterRM->GetCommandStack();
171  G4UImanager* uimgr = G4UImanager::GetUIpointer(); //TLS instance
172  std::vector<G4String>::const_iterator it = cmds.begin();
173  for(;it!=cmds.end();it++)
174  { uimgr->ApplyCommand(*it); }
175  //Start this run
176  G4String macroFile = masterRM->GetSelectMacro();
177  G4int numSelect = masterRM->GetNumberOfSelectEvents();
178  if ( macroFile == "" || macroFile == " " )
179  {
180  localRM->BeamOn(m_nEvents,0,numSelect);
181  }
182  else
183  {
184  localRM->BeamOn(m_nEvents,macroFile,numSelect);
185  }
186  //======= NEW TBB SPECIFIC ===========
187  //Step-5: Initialize and start run
188  //====================================
189  // bla-bla-bla-bla
190  // This is basically BeamOn
191  m_beamOnCondition = localRM->ConfirmBeamOnCondition();
192  if (m_beamOnCondition) {
193  localRM->SetNumberOfEventsToBeProcessed( m_nEvents );
194  localRM->ConstructScoringWorlds();
195  localRM->RunInitialization();
196  //Register this G4Run in output
197  //Note: the idea is that we are going to accumulate everything in
198  //G4Run or derived class. We let the kernel know this is the object
199  //where the output is accumulated for the tbb::tasks that run on
200  //this thread.
201  if ( m_output ) {}
202  }
203  }
204  assert(localRM!=0);
205  if ( m_beamOnCondition ) {
206  localRM->DoEventLoop( m_nEvents );
207  //localRM->RunTermination(); //<<<< How to call this??? ANDREA TBB
208  }
209 
210  //Cannot be done here since thread can be re-used by other task
211  //===============================
212  //Step-6: Terminate worker thread
213  //===============================
214  // if(masterRM->GetUserWorkerInitialization())
215  // { masterRM->GetUserWorkerInitialization()->WorkerStop(); }
216 
217  // wrmm.lock();
218 // std::vector<G4WorkerRunManager*>::iterator itrWrm = workerRMvector->begin();
219  // for(;itrWrm!=workerRMvector->end();itrWrm++)
220  // {
221  // if((*itrWrm)==wrm)
222  // {
223  // workerRMvector->erase(itrWrm);
224  // break;
225  // }
226  // }
227  // wrmm.unlock();
228 
229  // wThreadContext->DestroyGeometryAndPhysicsVector();
230  // wThreadContext = 0;
231 
232  return static_cast<tbb::task*>(NULL);
233 }