Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // G4WorkerThread implementation 26 // G4WorkerThread implementation 27 // 27 // 28 // Authors: X.Dong, A.Dotti, 2013 28 // Authors: X.Dong, A.Dotti, 2013 29 // ------------------------------------------- 29 // -------------------------------------------------------------------- 30 30 31 #include "G4WorkerThread.hh" 31 #include "G4WorkerThread.hh" >> 32 #include "G4MTRunManager.hh" >> 33 #include "G4WorkerRunManager.hh" 32 34 33 #include "G4GeometryWorkspace.hh" 35 #include "G4GeometryWorkspace.hh" >> 36 #include "G4ParticlesWorkspace.hh" >> 37 #include "G4PhysicsListWorkspace.hh" >> 38 #include "G4SolidsWorkspace.hh" >> 39 34 #include "G4LogicalVolume.hh" 40 #include "G4LogicalVolume.hh" 35 #include "G4LogicalVolumeStore.hh" 41 #include "G4LogicalVolumeStore.hh" 36 #include "G4MTRunManager.hh" << 37 #include "G4ParticlesWorkspace.hh" << 38 #include "G4PhysicalVolumeStore.hh" 42 #include "G4PhysicalVolumeStore.hh" 39 #include "G4PhysicsListWorkspace.hh" << 40 #include "G4Region.hh" 43 #include "G4Region.hh" 41 #include "G4RegionStore.hh" 44 #include "G4RegionStore.hh" 42 #include "G4SolidsWorkspace.hh" << 43 #include "G4WorkerRunManager.hh" << 44 45 45 // ------------------------------------------- 46 // -------------------------------------------------------------------- 46 void G4WorkerThread::SetThreadId(G4int tid) 47 void G4WorkerThread::SetThreadId(G4int tid) 47 { 48 { 48 threadId = tid; 49 threadId = tid; 49 } 50 } 50 51 51 // ------------------------------------------- 52 // -------------------------------------------------------------------- 52 G4int G4WorkerThread::GetThreadId() const 53 G4int G4WorkerThread::GetThreadId() const 53 { 54 { 54 return threadId; 55 return threadId; 55 } 56 } 56 57 57 // ------------------------------------------- 58 // -------------------------------------------------------------------- 58 void G4WorkerThread::SetNumberThreads(G4int nw 59 void G4WorkerThread::SetNumberThreads(G4int nw) 59 { 60 { 60 numThreads = nw; 61 numThreads = nw; 61 } 62 } 62 63 63 // ------------------------------------------- 64 // -------------------------------------------------------------------- 64 G4int G4WorkerThread::GetNumberThreads() const 65 G4int G4WorkerThread::GetNumberThreads() const 65 { 66 { 66 return numThreads; 67 return numThreads; 67 } 68 } 68 69 69 // ------------------------------------------- 70 // -------------------------------------------------------------------- 70 void G4WorkerThread::BuildGeometryAndPhysicsVe 71 void G4WorkerThread::BuildGeometryAndPhysicsVector() 71 { 72 { 72 // Initialise all split classes 73 // Initialise all split classes 73 // with copy of data from master thread 74 // with copy of data from master thread 74 75 75 G4GeometryWorkspace::GetPool()->CreateAndUse 76 G4GeometryWorkspace::GetPool()->CreateAndUseWorkspace(); 76 G4SolidsWorkspace::GetPool()->CreateAndUseWo 77 G4SolidsWorkspace::GetPool()->CreateAndUseWorkspace(); 77 G4ParticlesWorkspace::GetPool()->CreateAndUs 78 G4ParticlesWorkspace::GetPool()->CreateAndUseWorkspace(); 78 G4PhysicsListWorkspace::GetPool()->CreateAnd 79 G4PhysicsListWorkspace::GetPool()->CreateAndUseWorkspace(); 79 } 80 } 80 81 81 // ------------------------------------------- 82 // -------------------------------------------------------------------- 82 void G4WorkerThread::DestroyGeometryAndPhysics 83 void G4WorkerThread::DestroyGeometryAndPhysicsVector() 83 { 84 { 84 // Clear all split classes 85 // Clear all split classes 85 86 86 G4GeometryWorkspace::GetPool()->CleanUpAndDe 87 G4GeometryWorkspace::GetPool()->CleanUpAndDestroyAllWorkspaces(); 87 G4SolidsWorkspace::GetPool()->CleanUpAndDest 88 G4SolidsWorkspace::GetPool()->CleanUpAndDestroyAllWorkspaces(); 88 G4ParticlesWorkspace::GetPool()->CleanUpAndD 89 G4ParticlesWorkspace::GetPool()->CleanUpAndDestroyAllWorkspaces(); 89 G4PhysicsListWorkspace::GetPool()->CleanUpAn 90 G4PhysicsListWorkspace::GetPool()->CleanUpAndDestroyAllWorkspaces(); 90 } 91 } 91 92 92 // ------------------------------------------- 93 // -------------------------------------------------------------------- 93 void G4WorkerThread::UpdateGeometryAndPhysicsV 94 void G4WorkerThread::UpdateGeometryAndPhysicsVectorFromMaster() 94 { 95 { 95 // ========================================= 96 // ================================================= 96 // Step-0: keep sensitive detector and field 97 // Step-0: keep sensitive detector and field manager 97 // ========================================= 98 // ================================================= 98 // First remember SD and Filed Associated wi 99 // First remember SD and Filed Associated with worker 99 // in order to re-use it 100 // in order to re-use it 100 // (note that all the stuff after this will 101 // (note that all the stuff after this will reset SD and Field) 101 using LV2SDFM = std::map<G4LogicalVolume*, s << 102 using LV2SDFM = std::map<G4LogicalVolume*, >> 103 std::pair<G4VSensitiveDetector*, G4FieldManager*>>; 102 LV2SDFM lvmap; 104 LV2SDFM lvmap; 103 105 104 using R2FSM = std::map<G4Region*, std::pair< << 106 using R2FSM = std::map<G4Region*, >> 107 std::pair<G4FastSimulationManager*, G4UserSteppingAction*>>; 105 R2FSM rgnmap; 108 R2FSM rgnmap; 106 109 107 G4LogicalVolumeStore* mLogVolStore = G4Logic 110 G4LogicalVolumeStore* mLogVolStore = G4LogicalVolumeStore::GetInstance(); 108 for (auto lv : *mLogVolStore) { << 111 for(std::size_t ip = 0; ip < mLogVolStore->size(); ++ip) >> 112 { >> 113 G4LogicalVolume* lv = (*mLogVolStore)[ip]; >> 114 109 // The following needs an explanation. 115 // The following needs an explanation. 110 // Consider the case in which the user add 116 // Consider the case in which the user adds one LogVolume between 111 // the runs. The problem is that the threa 117 // the runs. The problem is that the thread-local part (split class) 112 // of the G4LogicalVolume object is not in 118 // of the G4LogicalVolume object is not initialized for workers 113 // because the initialization is done once 119 // because the initialization is done once when the thread starts 114 // (see G4MTRunManagerKernel::StartThread 120 // (see G4MTRunManagerKernel::StartThread Step-2 that calls 115 // G4WorkerThread::BuildGeometryAndPhysics 121 // G4WorkerThread::BuildGeometryAndPhysicsVector in this class). 116 // The problem is that pointers of SD and 122 // The problem is that pointers of SD and FM for these newly added LV 117 // may be invalid pointers (because never 123 // may be invalid pointers (because never initialized, we have seen 118 // this behavior in our testing). If now w 124 // this behavior in our testing). If now we remember them and re-use 119 // them in Step-4 below we set invalid poi 125 // 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 giv 126 // Thus we need a way to know if for a given LV we need to remember 121 // or not the SD and FM pointers. 127 // or not the SD and FM pointers. 122 // To solve this problem: We assume that t 128 // To solve this problem: We assume that the ConstructSDandField() is 123 // called also by Master thread, thus for 129 // called also by Master thread, thus for newly added LV the shadow 124 // pointers of SD and Fields are correct. 130 // pointers of SD and Fields are correct. 125 // (LIMITATION: this assumption may be too 131 // (LIMITATION: this assumption may be too stringent, a user to save 126 // memory could instantiate SD only for wo 132 // memory could instantiate SD only for workers, but we require this 127 // not to happen!). 133 // not to happen!). 128 // Thus if a SD and FieldMgr are needed fo 134 // Thus if a SD and FieldMgr are needed for this particular LV, and 129 // shadow are !=0 it means that user wants 135 // shadow are !=0 it means that user wants an SD and FM to be 130 // associated with LV, we get the values a 136 // associated with LV, we get the values and we remember them. 131 // 137 // 132 G4VSensitiveDetector* sd = nullptr; 138 G4VSensitiveDetector* sd = nullptr; 133 G4FieldManager* fmgr = nullptr; << 139 G4FieldManager* fmgr = nullptr; 134 if (lv->GetMasterSensitiveDetector() != nu << 140 if(lv->GetMasterSensitiveDetector() != nullptr) >> 141 { 135 sd = lv->GetSensitiveDetector(); 142 sd = lv->GetSensitiveDetector(); 136 } 143 } 137 if (lv->GetMasterFieldManager() != nullptr << 144 if(lv->GetMasterFieldManager() != nullptr) >> 145 { 138 fmgr = lv->GetFieldManager(); 146 fmgr = lv->GetFieldManager(); 139 } 147 } 140 if (sd != nullptr || fmgr != nullptr) { << 148 if(sd != nullptr || fmgr != nullptr) >> 149 { 141 lvmap[lv] = std::make_pair(sd, fmgr); 150 lvmap[lv] = std::make_pair(sd, fmgr); 142 } 151 } 143 } 152 } 144 G4RegionStore* mRegStore = G4RegionStore::Ge 153 G4RegionStore* mRegStore = G4RegionStore::GetInstance(); 145 for (auto reg : *mRegStore) { << 154 for(std::size_t ir = 0; ir < mRegStore->size(); ++ir) >> 155 { >> 156 G4Region* reg = (*mRegStore)[ir]; 146 G4FastSimulationManager* fsm = reg->GetFas 157 G4FastSimulationManager* fsm = reg->GetFastSimulationManager(); 147 G4UserSteppingAction* usa = reg->GetRegion << 158 G4UserSteppingAction* usa = reg->GetRegionalSteppingAction(); 148 if (reg != nullptr || usa != nullptr) { << 159 if(reg != nullptr || usa != nullptr) >> 160 { 149 rgnmap[reg] = std::make_pair(fsm, usa); 161 rgnmap[reg] = std::make_pair(fsm, usa); 150 } 162 } 151 } 163 } 152 164 153 //=========================== 165 //=========================== 154 // Step-1: Clean the workspace 166 // Step-1: Clean the workspace 155 //=========================== 167 //=========================== 156 G4GeometryWorkspace* geomWorkspace = G4Geome << 168 G4GeometryWorkspace* geomWorkspace = >> 169 G4GeometryWorkspace::GetPool()->GetWorkspace(); 157 geomWorkspace->DestroyWorkspace(); 170 geomWorkspace->DestroyWorkspace(); 158 G4SolidsWorkspace* solidWorkspace = G4Solids << 171 G4SolidsWorkspace* solidWorkspace = >> 172 G4SolidsWorkspace::GetPool()->GetWorkspace(); 159 solidWorkspace->DestroyWorkspace(); 173 solidWorkspace->DestroyWorkspace(); 160 174 161 //=========================== 175 //=========================== 162 // Step-2: Re-create and initialize workspac 176 // Step-2: Re-create and initialize workspace 163 //=========================== 177 //=========================== 164 geomWorkspace->InitialiseWorkspace(); 178 geomWorkspace->InitialiseWorkspace(); 165 solidWorkspace->InitialiseWorkspace(); 179 solidWorkspace->InitialiseWorkspace(); 166 180 167 //========================================== 181 //=================================================== 168 // Step-4: Restore sensitive detector and fi 182 // Step-4: Restore sensitive detector and field manaer 169 //========================================== 183 //=================================================== 170 for (const auto& it : lvmap) { << 184 for(auto it = lvmap.cbegin(); it != lvmap.cend(); ++it) 171 G4LogicalVolume* lv = it.first; << 185 { 172 G4VSensitiveDetector* sd = (it.second).fir << 186 G4LogicalVolume* lv = it->first; 173 G4FieldManager* fmgr = (it.second).second; << 187 G4VSensitiveDetector* sd = (it->second).first; 174 if (fmgr != nullptr) // What should be th << 188 G4FieldManager* fmgr = (it->second).second; 175 { // We use always false for MT mode << 189 if(fmgr != nullptr) // What should be the second parameter? >> 190 { // We use always false for MT mode 176 lv->SetFieldManager(fmgr, false); 191 lv->SetFieldManager(fmgr, false); 177 } 192 } 178 if (sd != nullptr) { << 193 if(sd) >> 194 { 179 lv->SetSensitiveDetector(sd); 195 lv->SetSensitiveDetector(sd); 180 } 196 } 181 } 197 } 182 for (const auto& it3 : rgnmap) { << 198 for(auto it3 = rgnmap.cbegin(); it3 != rgnmap.cend(); ++it3) 183 G4Region* reg = it3.first; << 199 { 184 G4FastSimulationManager* fsm = (it3.second << 200 G4Region* reg = it3->first; 185 if (fsm != nullptr) reg->SetFastSimulation << 201 G4FastSimulationManager* fsm = (it3->second).first; 186 G4UserSteppingAction* usa = (it3.second).s << 202 if(fsm != nullptr) 187 if (usa != nullptr) reg->SetRegionalSteppi << 203 reg->SetFastSimulationManager(fsm); >> 204 G4UserSteppingAction* usa = (it3->second).second; >> 205 if(usa != nullptr) >> 206 reg->SetRegionalSteppingAction(usa); 188 } 207 } 189 } 208 } 190 209 191 // ------------------------------------------- 210 // -------------------------------------------------------------------- 192 void G4WorkerThread::SetPinAffinity(G4int affi 211 void G4WorkerThread::SetPinAffinity(G4int affinity) const 193 { 212 { 194 if (affinity == 0) return; << 213 if(affinity == 0) >> 214 return; 195 215 196 #if !defined(WIN32) 216 #if !defined(WIN32) 197 G4cout << "AFFINITY SET" << G4endl; 217 G4cout << "AFFINITY SET" << G4endl; 198 // Assign this thread to cpus in a round rob 218 // Assign this thread to cpus in a round robin way 199 G4int offset = affinity; << 219 G4int offset = affinity; 200 G4int cpuindex = 0; 220 G4int cpuindex = 0; 201 if (std::abs(offset) > G4Threading::G4GetNum << 221 if(std::abs(offset) > G4Threading::G4GetNumberOfCores()) >> 222 { 202 G4Exception("G4WorkerThread::SetPinAffinit 223 G4Exception("G4WorkerThread::SetPinAffinity()", "Run0100", JustWarning, 203 "Cannot set thread affinity, a 224 "Cannot set thread affinity, affinity parameter larger than " 204 "number of cores"); 225 "number of cores"); 205 return; 226 return; 206 } 227 } 207 if (offset > 0) // Start assigning affinity << 228 if(offset > 0) // Start assigning affinity to given CPU 208 { 229 { 209 --offset; 230 --offset; 210 cpuindex = (GetThreadId() + offset) % G4Th 231 cpuindex = (GetThreadId() + offset) % G4Threading::G4GetNumberOfCores(); 211 // Round robin 232 // Round robin 212 } 233 } 213 else // Exclude the given CPU 234 else // Exclude the given CPU 214 { 235 { 215 offset *= -1; 236 offset *= -1; 216 --offset; 237 --offset; 217 G4int myidx = GetThreadId() % (G4Threading 238 G4int myidx = GetThreadId() % (G4Threading::G4GetNumberOfCores() - 1); 218 cpuindex = myidx + static_cast<G4int>(myid << 239 cpuindex = myidx + (myidx >= offset); 219 } 240 } 220 G4cout << "Setting affinity to:" << cpuindex 241 G4cout << "Setting affinity to:" << cpuindex << G4endl; 221 242 222 # if defined(G4MULTITHREADED) 243 # if defined(G4MULTITHREADED) 223 // Avoid compilation warning in C90 standard 244 // Avoid compilation warning in C90 standard w/o MT 224 G4NativeThread t = pthread_self(); 245 G4NativeThread t = pthread_self(); 225 # else 246 # else 226 G4NativeThread t; 247 G4NativeThread t; 227 # endif 248 # endif 228 G4bool success = G4Threading::G4SetPinAffini 249 G4bool success = G4Threading::G4SetPinAffinity(cpuindex, t); 229 if (!success) { << 250 if(!success) >> 251 { 230 G4Exception("G4MTRunManagerKernel::StarThr 252 G4Exception("G4MTRunManagerKernel::StarThread()", "Run0101", JustWarning, 231 "Cannot set thread affinity.") 253 "Cannot set thread affinity."); 232 } 254 } 233 #endif 255 #endif 234 } 256 } 235 257