Geant4-11
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// G4WorkerThread implementation
27//
28// Authors: X.Dong, A.Dotti, 2013
29// --------------------------------------------------------------------
30
31#include "G4WorkerThread.hh"
32#include "G4MTRunManager.hh"
33#include "G4WorkerRunManager.hh"
34
38#include "G4SolidsWorkspace.hh"
39
40#include "G4LogicalVolume.hh"
43#include "G4Region.hh"
44#include "G4RegionStore.hh"
45
46// --------------------------------------------------------------------
48{
49 threadId = tid;
50}
51
52// --------------------------------------------------------------------
54{
55 return threadId;
56}
57
58// --------------------------------------------------------------------
60{
61 numThreads = nw;
62}
63
64// --------------------------------------------------------------------
66{
67 return numThreads;
68}
69
70// --------------------------------------------------------------------
72{
73 // Initialise all split classes
74 // with copy of data from master thread
75
80}
81
82// --------------------------------------------------------------------
84{
85 // Clear all split classes
86
91}
92
93// --------------------------------------------------------------------
95{
96 // =================================================
97 // Step-0: keep sensitive detector and field manager
98 // =================================================
99 // First remember SD and Filed Associated with worker
100 // in order to re-use it
101 // (note that all the stuff after this will reset SD and Field)
102 using LV2SDFM = std::map<G4LogicalVolume*,
103 std::pair<G4VSensitiveDetector*, G4FieldManager*>>;
104 LV2SDFM lvmap;
105
106 using R2FSM = std::map<G4Region*,
107 std::pair<G4FastSimulationManager*, G4UserSteppingAction*>>;
108 R2FSM rgnmap;
109
111 for(std::size_t ip = 0; ip < mLogVolStore->size(); ++ip)
112 {
113 G4LogicalVolume* lv = (*mLogVolStore)[ip];
114
115 // The following needs an explanation.
116 // Consider the case in which the user adds one LogVolume between
117 // the runs. The problem is that the thread-local part (split class)
118 // of the G4LogicalVolume object is not initialized for workers
119 // because the initialization is done once when the thread starts
120 // (see G4MTRunManagerKernel::StartThread Step-2 that calls
121 // G4WorkerThread::BuildGeometryAndPhysicsVector in this class).
122 // The problem is that pointers of SD and FM for these newly added LV
123 // may be invalid pointers (because never initialized, we have seen
124 // this behavior in our testing). If now we remember them and re-use
125 // 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
127 // or not the SD and FM pointers.
128 // To solve this problem: We assume that the ConstructSDandField() is
129 // called also by Master thread, thus for newly added LV the shadow
130 // pointers of SD and Fields are correct.
131 // (LIMITATION: this assumption may be too stringent, a user to save
132 // memory could instantiate SD only for workers, but we require this
133 // not to happen!).
134 // Thus if a SD and FieldMgr are needed for this particular LV, and
135 // shadow are !=0 it means that user wants an SD and FM to be
136 // associated with LV, we get the values and we remember them.
137 //
138 G4VSensitiveDetector* sd = nullptr;
139 G4FieldManager* fmgr = nullptr;
140 if(lv->GetMasterSensitiveDetector() != nullptr)
141 {
142 sd = lv->GetSensitiveDetector();
143 }
144 if(lv->GetMasterFieldManager() != nullptr)
145 {
146 fmgr = lv->GetFieldManager();
147 }
148 if(sd != nullptr || fmgr != nullptr)
149 {
150 lvmap[lv] = std::make_pair(sd, fmgr);
151 }
152 }
154 for(std::size_t ir = 0; ir < mRegStore->size(); ++ir)
155 {
156 G4Region* reg = (*mRegStore)[ir];
157 G4FastSimulationManager* fsm = reg->GetFastSimulationManager();
158 G4UserSteppingAction* usa = reg->GetRegionalSteppingAction();
159 if(reg != nullptr || usa != nullptr)
160 {
161 rgnmap[reg] = std::make_pair(fsm, usa);
162 }
163 }
164
165 //===========================
166 // Step-1: Clean the workspace
167 //===========================
168 G4GeometryWorkspace* geomWorkspace =
170 geomWorkspace->DestroyWorkspace();
171 G4SolidsWorkspace* solidWorkspace =
173 solidWorkspace->DestroyWorkspace();
174
175 //===========================
176 // Step-2: Re-create and initialize workspace
177 //===========================
178 geomWorkspace->InitialiseWorkspace();
179 solidWorkspace->InitialiseWorkspace();
180
181 //===================================================
182 // Step-4: Restore sensitive detector and field manaer
183 //===================================================
184 for(auto it = lvmap.cbegin(); it != lvmap.cend(); ++it)
185 {
186 G4LogicalVolume* lv = it->first;
187 G4VSensitiveDetector* sd = (it->second).first;
188 G4FieldManager* fmgr = (it->second).second;
189 if(fmgr != nullptr) // What should be the second parameter?
190 { // We use always false for MT mode
191 lv->SetFieldManager(fmgr, false);
192 }
193 if(sd)
194 {
195 lv->SetSensitiveDetector(sd);
196 }
197 }
198 for(auto it3 = rgnmap.cbegin(); it3 != rgnmap.cend(); ++it3)
199 {
200 G4Region* reg = it3->first;
201 G4FastSimulationManager* fsm = (it3->second).first;
202 if(fsm != nullptr)
203 reg->SetFastSimulationManager(fsm);
204 G4UserSteppingAction* usa = (it3->second).second;
205 if(usa != nullptr)
206 reg->SetRegionalSteppingAction(usa);
207 }
208}
209
210// --------------------------------------------------------------------
212{
213 if(affinity == 0)
214 return;
215
216#if !defined(WIN32)
217 G4cout << "AFFINITY SET" << G4endl;
218 // Assign this thread to cpus in a round robin way
219 G4int offset = affinity;
220 G4int cpuindex = 0;
221 if(std::abs(offset) > G4Threading::G4GetNumberOfCores())
222 {
223 G4Exception("G4WorkerThread::SetPinAffinity()", "Run0100", JustWarning,
224 "Cannot set thread affinity, affinity parameter larger than "
225 "number of cores");
226 return;
227 }
228 if(offset > 0) // Start assigning affinity to given CPU
229 {
230 --offset;
231 cpuindex = (GetThreadId() + offset) % G4Threading::G4GetNumberOfCores();
232 // Round robin
233 }
234 else // Exclude the given CPU
235 {
236 offset *= -1;
237 --offset;
239 cpuindex = myidx + (myidx >= offset);
240 }
241 G4cout << "Setting affinity to:" << cpuindex << G4endl;
242
243# if defined(G4MULTITHREADED)
244 // Avoid compilation warning in C90 standard w/o MT
245 G4NativeThread t = pthread_self();
246# else
248# endif
249 G4bool success = G4Threading::G4SetPinAffinity(cpuindex, t);
250 if(!success)
251 {
252 G4Exception("G4MTRunManagerKernel::StarThread()", "Run0101", JustWarning,
253 "Cannot set thread affinity.");
254 }
255#endif
256}
static const G4double reg
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
static constexpr double second
Definition: G4SIunits.hh:137
G4DummyThread::native_handle_type G4NativeThread
Definition: G4Threading.hh:248
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
static pool_type * GetPool()
static G4LogicalVolumeStore * GetInstance()
void SetFieldManager(G4FieldManager *pFieldMgr, G4bool forceToAllDaughters)
G4VSensitiveDetector * GetMasterSensitiveDetector() const
G4VSensitiveDetector * GetSensitiveDetector() const
G4FieldManager * GetMasterFieldManager() const
G4FieldManager * GetFieldManager() const
void SetSensitiveDetector(G4VSensitiveDetector *pSDetector)
static pool_type * GetPool()
static pool_type * GetPool()
static G4RegionStore * GetInstance()
static pool_type * GetPool()
void CleanUpAndDestroyAllWorkspaces()
G4int GetThreadId() const
static void BuildGeometryAndPhysicsVector()
static void UpdateGeometryAndPhysicsVectorFromMaster()
static void DestroyGeometryAndPhysicsVector()
void SetNumberThreads(G4int numnberThreads)
void SetPinAffinity(G4int aff) const
void SetThreadId(G4int threadId)
G4int GetNumberThreads() const
G4bool G4SetPinAffinity(G4int idx, G4NativeThread &at)
Definition: G4Threading.cc:127
G4int G4GetNumberOfCores()
Definition: G4Threading.cc:121