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 // Author: Jonathan Madsen (May 28st 2020) 27 // 28 // class description: 29 // This is a class for run control in GEANT4 for multi-threaded runs 30 // It extends G4RunManager re-implementing multi-threaded behavior in 31 // key methods. See documentation for G4RunManager 32 // Users initializes an instance of this class instead of G4RunManager 33 // to start a multi-threaded simulation. 34 35 #ifndef G4TaskRunManager_hh 36 #define G4TaskRunManager_hh 1 37 38 #include "G4EnvironmentUtils.hh" 39 #include "G4MTBarrier.hh" 40 #include "G4MTRunManager.hh" 41 #include "G4RNGHelper.hh" 42 #include "G4RunManager.hh" 43 #include "G4TBBTaskGroup.hh" 44 #include "G4TaskGroup.hh" 45 #include "G4TaskManager.hh" 46 #include "G4ThreadPool.hh" 47 #include "G4Threading.hh" 48 #include "G4VUserTaskQueue.hh" 49 50 #include "PTL/TaskRunManager.hh" 51 #include "rundefs.hh" 52 53 #include <list> 54 #include <map> 55 56 class G4TaskRunManagerKernel; 57 class G4ScoringManager; 58 class G4UserTaskInitialization; 59 class G4UserTaskThreadInitialization; 60 class G4WorkerTaskRunManager; 61 class G4RunManagerFactory; 62 63 //============================================================================// 64 65 class G4TaskRunManager : public G4MTRunManager, public PTL::TaskRunManager 66 { 67 friend class G4RunManagerFactory; 68 69 public: 70 using InitializeSeedsCallback = std::function<G4bool(G4int, G4int&, G4int&)>; 71 using RunTaskGroup = G4TaskGroup<void>; 72 73 public: 74 // Returns the singleton instance of the run manager common to all threads 75 // implementing the master behavior 76 static G4TaskRunManager* GetMasterRunManager() 77 { 78 auto* _rm = G4MTRunManager::GetMasterRunManager(); 79 return dynamic_cast<G4TaskRunManager*>(_rm); 80 } 81 82 // Returns the singleton instance of the run manager kernel common to all 83 // threads 84 static G4TaskRunManagerKernel* GetMTMasterRunManagerKernel(); 85 86 // Parameters: 87 // taskQueue : provide a custom task queue 88 // useTBB : only relevant if GEANT4_USE_TBB defined 89 // evtGrainsize : the number of events per task 90 G4TaskRunManager(G4bool useTBB = G4GetEnv<G4bool>("G4USE_TBB", false)); 91 G4TaskRunManager(G4VUserTaskQueue* taskQueue, 92 G4bool useTBB = G4GetEnv<G4bool>("G4USE_TBB", false), G4int evtGrainsize = 0); 93 ~G4TaskRunManager() override; 94 95 void SetGrainsize(G4int n) { eventGrainsize = n; } 96 G4int GetGrainsize() const { return eventGrainsize; } 97 inline G4int GetNumberOfTasks() const { return numberOfTasks; } 98 inline G4int GetNumberOfEventsPerTask() const { return numberOfEventsPerTask; } 99 100 void SetNumberOfThreads(G4int n) override; 101 G4int GetNumberOfThreads() const override; 102 size_t GetNumberActiveThreads() const override 103 { 104 return PTL::TaskRunManager::GetNumberActiveThreads(); 105 } 106 static G4ThreadId GetMasterThreadId(); 107 108 // Inherited methods to re-implement for MT case 109 void Initialize() override; 110 void InitializeEventLoop(G4int n_event, const char* macroFile = nullptr, 111 G4int n_select = -1) override; 112 void InitializeThreadPool() override; 113 G4bool ThreadPoolIsInitialized() const { return poolInitialized; } 114 115 void Initialize(uint64_t nthreads) override { PTL::TaskRunManager::Initialize(nthreads); } 116 117 void TerminateOneEvent() override; 118 void ProcessOneEvent(G4int i_event) override; 119 void ConstructScoringWorlds() override; 120 void RunTermination() override; 121 122 // The following method should be invoked by G4WorkerTaskRunManager for each 123 // event. False is returned if no more event to be processed. Note: G4Event 124 // object must be instantiated by a worker thread. In case no more 125 // event remains to be processed, that worker thread must delete that G4Event 126 // object. If a worker runs with its own random number sequence, the Boolean 127 // flag reseedRequired should be set to false. This is *NOT* allowed for the 128 // first event. 129 G4bool SetUpAnEvent(G4Event*, G4long& s1, G4long& s2, G4long& s3, 130 G4bool reseedRequired = true) override; 131 132 // Same as above method, but the seeds are set only once over "eventModulo" 133 // events. The return value shows the number of events the caller Worker has 134 // to process (between 1 and eventModulo depending on number of events yet to 135 // be processed). G4Event object has the event ID of the first event of this 136 // bunch. If zero is returned no more event needs to be processed, and worker 137 // thread must delete that G4Event. 138 G4int SetUpNEvents(G4Event*, G4SeedsQueue* seedsQueue, G4bool reseedRequired = true) override; 139 140 // To be invoked solely from G4WorkerTaskRunManager to merge the results 141 void MergeScores(const G4ScoringManager* localScoringManager) override; 142 void MergeRun(const G4Run* localRun) override; 143 144 // Called to force workers to request and process the UI commands stack 145 // This will block untill all workers have processed UI commands 146 void RequestWorkersProcessCommandsStack() override; 147 148 // Called by workers to signal to master it has completed processing of 149 // UI commands 150 // virtual WorkerActionRequest ThisWorkerWaitForNextAction(); 151 // Worker thread barrier 152 // This method should be used by workers' run manager to wait, 153 // after an event loop for the next action to be performed 154 // (for example execute a new run) 155 // This returns the action to be performed 156 void ThisWorkerProcessCommandsStackDone() override; 157 158 void WaitForReadyWorkers() override {} 159 void WaitForEndEventLoopWorkers() override; 160 void ThisWorkerReady() override {} 161 void ThisWorkerEndEventLoop() override {} 162 163 WorkerActionRequest ThisWorkerWaitForNextAction() override 164 { 165 return WorkerActionRequest::UNDEFINED; 166 } 167 168 inline void SetInitializeSeedsCallback(InitializeSeedsCallback f) { initSeedsCallback = f; } 169 170 void AbortRun(G4bool softAbort = false) override; 171 void AbortEvent() override; 172 173 protected: 174 virtual void ComputeNumberOfTasks(); 175 176 // Initialize the seeds list, if derived class does not implement this method 177 // A default generation will be used (nevents*2 random seeds) 178 // Return true if initialization is done. 179 G4bool InitializeSeeds(G4int /*nevts*/) override { return false; } 180 181 // Adds one seed to the list of seeds 182 void RefillSeeds() override; 183 void StoreRNGStatus(const G4String& filenamePrefix) override; 184 185 // Creates worker threads and signal to start 186 void CreateAndStartWorkers() override; 187 188 void TerminateWorkers() override; 189 void NewActionRequest(WorkerActionRequest) override {} 190 virtual void AddEventTask(G4int); 191 192 protected: 193 // Barriers: synch points between master and workers 194 RunTaskGroup* workTaskGroup = nullptr; 195 196 // aliases to inherited member values 197 G4bool& poolInitialized = PTL::TaskRunManager::m_is_initialized; 198 G4ThreadPool*& threadPool = PTL::TaskRunManager::m_thread_pool; 199 G4VUserTaskQueue*& taskQueue = PTL::TaskRunManager::m_task_queue; 200 G4TaskManager*& taskManager = PTL::TaskRunManager::m_task_manager; 201 202 InitializeSeedsCallback initSeedsCallback = [](G4int, G4int&, G4int&) { 203 return false; 204 }; 205 206 protected: 207 // grainsize 208 G4bool workersStarted = false; 209 G4int eventGrainsize = 0; 210 G4int numberOfEventsPerTask = -1; 211 G4int numberOfTasks = -1; 212 CLHEP::HepRandomEngine* masterRNGEngine = nullptr; 213 // Pointer to the master thread random engine 214 G4TaskRunManagerKernel* MTkernel = nullptr; 215 }; 216 217 #endif // G4TaskRunManager_hh 218