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