Geant4 Cross Reference |
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 // 27 28 #include "G4RunManagerFactory.hh" 29 30 #include "G4EnvironmentUtils.hh" 31 #include "G4MTRunManager.hh" 32 #include "G4RunManager.hh" 33 #include "G4TaskRunManager.hh" 34 #include "G4SubEvtRunManager.hh" 35 #include "G4Threading.hh" 36 37 #include "templates.hh" 38 39 //============================================================================// 40 41 namespace 42 { 43 // failure message 44 static void fail(const std::string& _prefix, const std::string& _name, 45 const std::set<std::string>& _opts, G4int _num) 46 { 47 G4ExceptionDescription msg; 48 msg << _prefix << ": \"" << _name << "\". " 49 << "Must be one of: "; 50 std::stringstream ss; 51 for (const auto& itr : _opts) 52 ss << ", \"" << itr << "\""; 53 msg << ss.str().substr(2); 54 auto mnum = std::string("RunManagerFactory000") + std::to_string(_num); 55 G4Exception("G4RunManagerFactory::CreateRunManager", mnum.c_str(), FatalException, msg); 56 } 57 58 static G4RunManager* master_run_manager = nullptr; 59 static G4MTRunManager* mt_master_run_manager = nullptr; 60 static G4RunManagerKernel* master_run_manager_kernel = nullptr; 61 } // namespace 62 63 //============================================================================// 64 65 G4RunManager* G4RunManagerFactory::CreateRunManager(G4RunManagerType _type, 66 G4VUserTaskQueue* _queue, 67 G4bool fail_if_unavail, G4int nthreads) 68 { 69 // If the supplied type is not ...Only, then allow override from environment 70 std::string rm_type = GetName(_type); 71 if (_type == G4RunManagerType::SerialOnly || _type == G4RunManagerType::MTOnly 72 || _type == G4RunManagerType::TaskingOnly || _type == G4RunManagerType::TBBOnly 73 || _type == G4RunManagerType::SubEvtOnly) 74 { 75 // MUST fail if unavail in this case 76 fail_if_unavail = true; 77 } 78 else { 79 // - G4RUN_MANAGER_TYPE can be set to override the "default" 80 // - If the requested type isn't available, then it will fall back to the 81 // system default 82 // - G4FORCE_RUN_MANAGER_TYPE can be set to force a specific type 83 // - A G4Exception is raised if the requested type is not available 84 rm_type = G4GetEnv<std::string>("G4RUN_MANAGER_TYPE", GetName(_type), 85 "Overriding G4RunManager type..."); 86 auto force_rm = 87 G4GetEnv<std::string>("G4FORCE_RUN_MANAGER_TYPE", "", "Forcing G4RunManager type..."); 88 89 if (force_rm.length() > 0) { 90 rm_type = std::move(force_rm); 91 fail_if_unavail = true; 92 } 93 else if (rm_type.empty()) { 94 rm_type = GetDefault(); 95 } 96 } 97 98 // At this point will have a string for the RM type we can check for existence 99 // NB: Comparison at present is case sensitive (needs a comparator in 100 // GetOptions) 101 auto opts = GetOptions(); 102 if (opts.find(rm_type) == opts.end()) { 103 if (fail_if_unavail) { 104 fail("Run manager type is not available", rm_type, opts, 1); 105 } 106 else { 107 rm_type = GetDefault(); 108 } 109 } 110 111 // Construct requested RunManager given type 112 _type = GetType(rm_type); 113 G4RunManager* rm = nullptr; 114 115 switch (_type) { 116 case G4RunManagerType::Serial: 117 rm = new G4RunManager(); 118 break; 119 case G4RunManagerType::MT: 120 #if defined(G4MULTITHREADED) 121 rm = new G4MTRunManager(); 122 #endif 123 break; 124 case G4RunManagerType::Tasking: 125 #if defined(G4MULTITHREADED) 126 rm = new G4TaskRunManager(_queue, false); 127 #endif 128 break; 129 case G4RunManagerType::TBB: 130 #if defined(G4MULTITHREADED) && defined(GEANT4_USE_TBB) 131 rm = new G4TaskRunManager(_queue, true); 132 #endif 133 break; 134 case G4RunManagerType::SubEvt: 135 #if defined(G4MULTITHREADED) 136 #if defined(GEANT4_USE_TBB) 137 rm = new G4SubEvtRunManager(_queue, true); 138 #else 139 rm = new G4SubEvtRunManager(_queue, false); 140 #endif 141 #endif 142 break; 143 // "Only" types are not handled since they are converted above to main type 144 case G4RunManagerType::SerialOnly: 145 break; 146 case G4RunManagerType::MTOnly: 147 break; 148 case G4RunManagerType::TaskingOnly: 149 break; 150 case G4RunManagerType::TBBOnly: 151 break; 152 case G4RunManagerType::SubEvtOnly: 153 break; 154 case G4RunManagerType::Default: 155 break; 156 } 157 158 if (rm == nullptr) fail("Failure creating run manager", GetName(_type), GetOptions(), 2); 159 160 auto mtrm = dynamic_cast<G4MTRunManager*>(rm); 161 if (nthreads > 0 && (mtrm != nullptr)) mtrm->SetNumberOfThreads(nthreads); 162 163 master_run_manager = rm; 164 mt_master_run_manager = mtrm; 165 master_run_manager_kernel = rm->kernel; 166 167 G4ConsumeParameters(_queue); 168 return rm; 169 } 170 171 //============================================================================// 172 173 std::string G4RunManagerFactory::GetDefault() 174 { 175 #if defined(G4MULTITHREADED) 176 return "Tasking"; 177 #else 178 return "Serial"; 179 #endif 180 } 181 182 //============================================================================// 183 184 std::set<std::string> G4RunManagerFactory::GetOptions() 185 { 186 static auto _instance = []() { 187 std::set<std::string> options = {"Serial"}; 188 #if defined(G4MULTITHREADED) 189 options.insert({"MT", "Tasking"}); 190 # if defined(GEANT4_USE_TBB) 191 options.insert("TBB"); 192 # endif 193 options.insert("SubEvt"); 194 #endif 195 return options; 196 }(); 197 return _instance; 198 } 199 200 //============================================================================// 201 202 G4RunManagerType G4RunManagerFactory::GetType(const std::string& key) 203 { 204 // IGNORES CASE! 205 static const auto opts = std::regex::icase; 206 207 if (std::regex_match(key, std::regex("^(Serial).*", opts))) return G4RunManagerType::Serial; 208 if (std::regex_match(key, std::regex("^(MT).*", opts))) return G4RunManagerType::MT; 209 if (std::regex_match(key, std::regex("^(Task).*", opts))) return G4RunManagerType::Tasking; 210 if (std::regex_match(key, std::regex("^(TBB).*", opts))) return G4RunManagerType::TBB; 211 if (std::regex_match(key, std::regex("^(SubEvt).*", opts))) return G4RunManagerType::SubEvt; 212 213 return G4RunManagerType::Default; 214 } 215 216 //============================================================================// 217 218 std::string G4RunManagerFactory::GetName(G4RunManagerType _type) 219 { 220 switch (_type) { 221 case G4RunManagerType::Serial: 222 return "Serial"; 223 case G4RunManagerType::SerialOnly: 224 return "Serial"; 225 case G4RunManagerType::MT: 226 return "MT"; 227 case G4RunManagerType::MTOnly: 228 return "MT"; 229 case G4RunManagerType::Tasking: 230 return "Tasking"; 231 case G4RunManagerType::TaskingOnly: 232 return "Tasking"; 233 case G4RunManagerType::TBB: 234 return "TBB"; 235 case G4RunManagerType::TBBOnly: 236 return "TBB"; 237 case G4RunManagerType::SubEvt: 238 return "SubEvt"; 239 case G4RunManagerType::SubEvtOnly: 240 return "SubEvt"; 241 default: 242 break; 243 }; 244 return ""; 245 } 246 247 //============================================================================// 248 249 G4RunManager* G4RunManagerFactory::GetMasterRunManager() 250 { 251 #if !defined(G4MULTITHREADED) 252 // if serial build just return G4RunManager 253 return G4RunManager::GetRunManager(); 254 #else 255 // if the application used G4RunManagerFactory to create the run-manager 256 if (master_run_manager != nullptr) return master_run_manager; 257 258 // if the application did not use G4RunManagerFactory and is MT 259 if (G4Threading::IsMultithreadedApplication()) { 260 auto mt_rm = GetMTMasterRunManager(); 261 if (mt_rm != nullptr) return mt_rm; 262 } 263 264 // if the application did not use G4RunManagerFactory and is serial 265 return G4RunManager::GetRunManager(); 266 #endif 267 } 268 269 //============================================================================// 270 271 G4MTRunManager* G4RunManagerFactory::GetMTMasterRunManager() 272 { 273 #if defined(G4MULTITHREADED) 274 // if the application used G4RunManagerFactory to create the run-manager 275 if (mt_master_run_manager != nullptr) return mt_master_run_manager; 276 277 // if the application did not use G4RunManagerFactory 278 if (G4Threading::IsMultithreadedApplication()) { 279 auto task_rm = G4TaskRunManager::GetMasterRunManager(); 280 if (task_rm != nullptr) return task_rm; 281 return G4MTRunManager::GetMasterRunManager(); 282 } 283 #endif 284 285 return nullptr; 286 } 287 288 //============================================================================// 289 290 G4RunManagerKernel* G4RunManagerFactory::GetMasterRunManagerKernel() 291 { 292 #if !defined(G4MULTITHREADED) 293 // if serial build just return G4RunManager 294 return G4RunManager::GetRunManager()->kernel; 295 #else 296 // if the application used G4RunManagerFactory to create the run-manager 297 if (master_run_manager_kernel != nullptr) return master_run_manager_kernel; 298 299 // if the application did not use G4RunManagerFactory and is MT 300 if (G4Threading::IsMultithreadedApplication()) { 301 auto mt_rm = GetMTMasterRunManager(); 302 if (mt_rm != nullptr) return mt_rm->kernel; 303 } 304 305 // if the application did not use G4RunManagerFactory and is serial 306 return G4RunManager::GetRunManager()->kernel; 307 #endif 308 } 309 310 //============================================================================// 311