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