Geant4  10.03
G4WorkerThread.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 #include "G4WorkerThread.hh"
27 #include "G4WorkerRunManager.hh"
28 #include "G4MTRunManager.hh"
29 
30 #include "G4GeometryWorkspace.hh"
32 #include "G4SolidsWorkspace.hh"
33 #include "G4SolidsWorkspacePool.hh"
34 #include "G4ParticlesWorkspace.hh"
36 
38 {
39  threadId = tid;
40 }
41 
43 {
44  return threadId;
45 }
46 
48 {
49  numThreads = nw;
50 }
51 
53 {
54  return numThreads;
55 }
56 
58 {
59  // Initialise all split classes in the geometry with copy of data from master thread
62 
65 // const_cast<G4VUPLManager&>(G4VUserPhysicsList::GetSubInstanceManager()).NewSubInstances();
66 // const_cast<G4VPCManager&>(G4VPhysicsConstructor::GetSubInstanceManager()).NewSubInstances();
67 // const_cast<G4VMPLManager&>(G4VModularPhysicsList::GetSubInstanceManager()).WorkerCopySubInstanceArray();
68 }
69 
71 {
72 #if 0
73  // Manage Geometry Workspace explicitly
74  fGeometryWrk->ReleaseAndDestroyWorkspace();
75  delete fGeometryWrk;
76  fGeometryWrk=0;
77 #else
78  // Alternative:
79  // Initialise all split classes in the geometry with copy of data from master thread
80  // G4GeometryWorkspacePool::GetInstance()->ReleaseAndDestroyMyWorkspace();
83  G4ParticlesWorkspace::GetPool()->GetWorkspace()->DestroyWorkspace();
84 
85  G4PhysicsListWorkspace::GetPool()->GetWorkspace()->DestroyWorkspace();
86 #endif
87 
88 // const_cast<G4VUPLManager&>(G4VUserPhysicsList::GetSubInstanceManager()).FreeWorker();
89 // const_cast<G4VPCManager&>(G4VPhysicsConstructor::GetSubInstanceManager()).FreeWorker();
90 // const_cast<G4VMPLManager&>(G4VModularPhysicsList::GetSubInstanceManager()).FreeWorker();
91 }
92 
93 #include "G4Region.hh"
94 #include "G4RegionStore.hh"
95 #include "G4LogicalVolume.hh"
96 #include "G4Region.hh"
97 #include "G4PhysicalVolumeStore.hh"
98 #include "G4LogicalVolumeStore.hh"
99 
100 
102 {
103  //=================================================
104  //Step-0: keep sensitive detector and field manager
105  //=================================================
106  // First remember SD and Filed Associated with worker
107  // in order to re-use it
108  // (note that all the stuff after this will reset SD and Field
109  typedef std::map<G4LogicalVolume*,std::pair<G4VSensitiveDetector*,G4FieldManager*> > LV2SDFM;
110  LV2SDFM lvmap;
111 // typedef std::map<G4LogicalVolume*,std::pair<G4Region*,G4bool> > LV2Region;
112 // LV2Region lv2rmap;
113  typedef std::map<G4Region*,std::pair<G4FastSimulationManager*,G4UserSteppingAction*> > R2FSM;
114  R2FSM rgnmap;
116  for(size_t ip=0; ip<mLogVolStore->size(); ip++)
117  {
118  G4LogicalVolume *lv = (*mLogVolStore)[ip];
119  //The following needs an explanation.
120  //Consider the case in which the user adds one LogVolume between the runs. The problem is that the thread-local part
121  //(split class) of the G4LogicalVolume object is not initialized for workers because the initialization is done once when the
122  //thread starts (see G4MTRunManagerKernel::StartThread Step-2 that calls G4WorkerThread::BuildGeometryAndPhysicsVector in this class)
123  //The problem is that pointers of SD and FM for these newly added LV
124  //may be invalid pointers (because never initialized, we have seen this behavior in our testing). If now we remember
125  //them and re-use them in Step-4 below we set invalid pointers to LV for this thread.
126  //Thus we need a way to know if for a given LV we need to remember or not the SD and FM pointers.
127  //To solve this problem: We assume that the ConstructSDandField is called also by Master thread
128  //thus for newly added LV the shadow pointers of SD and Fields are correct.
129  // (LIMITATION: this assumption may be too stringent, a user to save memory could instantiate SD only
130  // for workers, but we require this not to happen!).
131  // Thus is a SD and FieldMgr are needed for this particular LV, and shadow are !=0 it means that user
132  // wants an SD and FM to be associated with LV, we get the values and we remember them.
133  G4VSensitiveDetector* sd = 0;
134  G4FieldManager* fmgr = 0;
135  if ( lv->GetMasterSensitiveDetector() != 0 ) sd = lv->GetSensitiveDetector();
136  if ( lv->GetMasterFieldManager() != 0 ) fmgr = lv->GetFieldManager();
137  if ( sd || fmgr ) lvmap[lv] = std::make_pair(sd,fmgr);
138 // G4Region* rgn = lv->GetRegion();
139 // G4bool isRoot = lv->IsRootRegion();
140 // if ( rgn || isRoot ) lv2rmap[lv] = std::make_pair(rgn,isRoot);
141  }
143  for(size_t ir=0; ir<mRegStore->size(); ir++)
144  {
145  G4Region* reg = (*mRegStore)[ir];
148  if ( reg || usa ) rgnmap[reg] = std::make_pair(fsm,usa);
149  }
150 
151  //===========================
152  //Step-1: Clean the workspace
153  //===========================
155  geomWorkspace->DestroyWorkspace();
157  solidWorkspace->DestroyWorkspace();
158 
159  //===========================
160  //Step-2: Re-create and initialize workspace
161  //===========================
162  geomWorkspace->InitialiseWorkspace();
163  solidWorkspace->InitialiseWorkspace();
164 
165  // Alternative
166  //
167  // To wipe, release and get a new one ...
168  // G4GeometryWorkspacePool *fWorkspaceMgr= G4GeometryWorkspaceOutlet::GetInstance();
169  // fWorkspaceMgr->ReleaseAndDestroyMyWorkspace();
170  // Now re-create
171  // fWorkspaceMgr->CreateAndUseWorkspace();
172 
173 
174  //===================================================
175  //Step-4: Restore sensitive detector and field manaer
176  //===================================================
177  for ( LV2SDFM::const_iterator it = lvmap.begin() ; it != lvmap.end() ; ++it )
178  {
179  G4LogicalVolume* lv = it->first;
180  G4VSensitiveDetector* sd = (it->second).first;
181  G4FieldManager* fmgr = (it->second).second;
182  if(fmgr) lv->SetFieldManager(fmgr, false); //What should be the second parameter? We use always false for MT mode
183  if(sd) lv->SetSensitiveDetector(sd);
184  }
185 
186 // for ( LV2Region::const_iterator it2 = lv2rmap.begin() ; it2 != lv2rmap.end() ; it2++ )
187 // {
188 // G4LogicalVolume* lv2 = it2->first;
189 // G4Region* rgn = (it2->second).first;
190 // if(rgn) lv2->SetRegion(rgn);
191 // G4bool isRoot = (it2->second).second;
192 // lv2->SetRegionRootFlag(isRoot);
193 // }
194 
195 
196  for ( R2FSM::const_iterator it3 = rgnmap.begin() ; it3 != rgnmap.end() ; it3++ )
197  {
198  G4Region* reg = it3->first;
199  G4FastSimulationManager* fsm = (it3->second).first;
200  if(fsm) reg->SetFastSimulationManager(fsm);
201  G4UserSteppingAction* usa = (it3->second).second;
202  if(usa) reg->SetRegionalSteppingAction(usa);
203  }
204 }
205 
207 {
208  if ( affinity == 0 ) return;
209 #if !defined(WIN32)
210  G4cout<<"AFFINITY SET"<<G4endl;
211  //Assign this thread to cpus in a round robin way
212  G4int offset = affinity;
213  G4int cpuindex = 0;
214  if ( std::abs(offset)>G4Threading::G4GetNumberOfCores() ) {
215  G4Exception("G4WorkerThread::SetPinAffinity","Run0100",
216  JustWarning,
217  "Cannot set thread affinity, affinity parameter larger than number of cores");
218  return;
219  }
220  if (offset>0) { //Start assigning affinity to given CPU
221  --offset;
222  cpuindex = (GetThreadId()+offset) % G4Threading::G4GetNumberOfCores(); //Round robin
223  } else {//Exclude the given CPU
224  offset *= -1;
225  --offset;
227  cpuindex = myidx + (myidx>=offset);
228  }
229  G4cout<<"Setting affinity to:"<<cpuindex<<G4endl;
230  //Avoid compilation warning in C90 standard w/o MT
231 #if defined(G4MULTITHREADED)
232  G4Thread t = G4THREADSELF();
233 #else
234  G4Thread t;
235 #endif
236  G4bool success = G4Threading::G4SetPinAffinity(cpuindex,t);
237  if ( ! success ) {
238  G4Exception("G4MTRunManagerKernel::StarThread","Run0101",JustWarning,"Cannot set thread affinity.");
239  }
240 #endif
241 }
G4bool G4SetPinAffinity(G4int idx, G4Thread &at)
Definition: G4Threading.cc:149
G4SolidsWorkspace * GetWorkspace()
static pool_type * GetPool()
G4GeometryWorkspace * GetWorkspace()
G4UserSteppingAction * GetRegionalSteppingAction() const
Definition: G4Region.cc:155
static void UpdateGeometryAndPhysicsVectorFromMaster()
static pool_type * GetPool()
static void BuildGeometryAndPhysicsVector()
static G4SolidsWorkspacePool * GetInstance()
G4FieldManager * GetMasterFieldManager() const
static constexpr double second
Definition: G4SIunits.hh:157
void SetThreadId(G4int threadId)
int G4int
Definition: G4Types.hh:78
G4int G4Thread
Definition: G4Threading.hh:174
void SetFieldManager(G4FieldManager *pFieldMgr, G4bool forceToAllDaughters)
static const G4double reg
void SetPinAffinity(G4int aff) const
static G4RegionStore * GetInstance()
void SetFastSimulationManager(G4FastSimulationManager *fsm)
Definition: G4Region.cc:128
G4VSensitiveDetector * GetMasterSensitiveDetector() const
G4GLOB_DLL std::ostream G4cout
G4int GetNumberThreads() const
bool G4bool
Definition: G4Types.hh:79
G4int G4GetNumberOfCores()
Definition: G4Threading.cc:143
#define G4THREADSELF(nothing)
Definition: G4Threading.hh:183
static G4LogicalVolumeStore * GetInstance()
G4int GetThreadId() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
static void DestroyGeometryAndPhysicsVector()
static G4GeometryWorkspacePool * GetInstance()
#define G4endl
Definition: G4ios.hh:61
G4FieldManager * GetFieldManager() const
void SetRegionalSteppingAction(G4UserSteppingAction *rusa)
Definition: G4Region.cc:146
G4VSensitiveDetector * GetSensitiveDetector() const
void SetNumberThreads(G4int numnberThreads)
G4FastSimulationManager * GetFastSimulationManager() const
Definition: G4Region.cc:137
void SetSensitiveDetector(G4VSensitiveDetector *pSDetector)