Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:56:53

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 // Author: Jonathan Madsen (May 28st 2020)
0027 //
0028 // class description:
0029 //   This is a class for run control in GEANT4 for multi-threaded runs
0030 //   It extends G4RunManager re-implementing multi-threaded behavior in
0031 //   key methods. See documentation for G4RunManager
0032 //   Users initializes an instance of this class instead of G4RunManager
0033 //   to start a multi-threaded simulation.
0034 
0035 #ifndef G4TaskRunManager_hh
0036 #define G4TaskRunManager_hh 1
0037 
0038 #include "G4EnvironmentUtils.hh"
0039 #include "G4MTBarrier.hh"
0040 #include "G4MTRunManager.hh"
0041 #include "G4RNGHelper.hh"
0042 #include "G4RunManager.hh"
0043 #include "G4TBBTaskGroup.hh"
0044 #include "G4TaskGroup.hh"
0045 #include "G4TaskManager.hh"
0046 #include "G4ThreadPool.hh"
0047 #include "G4Threading.hh"
0048 #include "G4VUserTaskQueue.hh"
0049 
0050 #include "PTL/TaskRunManager.hh"
0051 #include "rundefs.hh"
0052 
0053 #include <list>
0054 #include <map>
0055 
0056 class G4TaskRunManagerKernel;
0057 class G4ScoringManager;
0058 class G4UserTaskInitialization;
0059 class G4UserTaskThreadInitialization;
0060 class G4WorkerTaskRunManager;
0061 class G4RunManagerFactory;
0062 
0063 //============================================================================//
0064 
0065 class G4TaskRunManager : public G4MTRunManager, public PTL::TaskRunManager
0066 {
0067     friend class G4RunManagerFactory;
0068 
0069   public:
0070     using InitializeSeedsCallback = std::function<G4bool(G4int, G4int&, G4int&)>;
0071     using RunTaskGroup = G4TaskGroup<void>;
0072 
0073   public:
0074     // Returns the singleton instance of the run manager common to all threads
0075     // implementing the master behavior
0076     static G4TaskRunManager* GetMasterRunManager()
0077     {
0078       auto* _rm = G4MTRunManager::GetMasterRunManager();
0079       return dynamic_cast<G4TaskRunManager*>(_rm);
0080     }
0081 
0082     // Returns the singleton instance of the run manager kernel common to all
0083     // threads
0084     static G4TaskRunManagerKernel* GetMTMasterRunManagerKernel();
0085 
0086     // Parameters:
0087     //      taskQueue     : provide a custom task queue
0088     //      useTBB        : only relevant if GEANT4_USE_TBB defined
0089     //      evtGrainsize  : the number of events per task
0090     G4TaskRunManager(G4bool useTBB = G4GetEnv<G4bool>("G4USE_TBB", false));
0091     G4TaskRunManager(G4VUserTaskQueue* taskQueue,
0092                      G4bool useTBB = G4GetEnv<G4bool>("G4USE_TBB", false), G4int evtGrainsize = 0);
0093     ~G4TaskRunManager() override;
0094 
0095     void SetGrainsize(G4int n) { eventGrainsize = n; }
0096     G4int GetGrainsize() const { return eventGrainsize; }
0097     inline G4int GetNumberOfTasks() const { return numberOfTasks; }
0098     inline G4int GetNumberOfEventsPerTask() const { return numberOfEventsPerTask; }
0099 
0100     void SetNumberOfThreads(G4int n) override;
0101     G4int GetNumberOfThreads() const override;
0102     size_t GetNumberActiveThreads() const override
0103     {
0104       return PTL::TaskRunManager::GetNumberActiveThreads();
0105     }
0106     static G4ThreadId GetMasterThreadId();
0107 
0108     // Inherited methods to re-implement for MT case
0109     void Initialize() override;
0110     void InitializeEventLoop(G4int n_event, const char* macroFile = nullptr,
0111                              G4int n_select = -1) override;
0112     void InitializeThreadPool() override;
0113     G4bool ThreadPoolIsInitialized() const { return poolInitialized; }
0114 
0115     void Initialize(uint64_t nthreads) override { PTL::TaskRunManager::Initialize(nthreads); }
0116 
0117     void TerminateOneEvent() override;
0118     void ProcessOneEvent(G4int i_event) override;
0119     void ConstructScoringWorlds() override;
0120     void RunTermination() override;
0121 
0122     // The following method should be invoked by G4WorkerTaskRunManager for each
0123     // event. False is returned if no more event to be processed. Note: G4Event
0124     // object must be instantiated by a worker thread. In case no more
0125     //  event remains to be processed, that worker thread must delete that G4Event
0126     //  object. If a worker runs with its own random number sequence, the Boolean
0127     //  flag reseedRequired should be set to false. This is *NOT* allowed for the
0128     //  first event.
0129     G4bool SetUpAnEvent(G4Event*, G4long& s1, G4long& s2, G4long& s3,
0130                         G4bool reseedRequired = true) override;
0131 
0132     // Same as above method, but the seeds are set only once over "eventModulo"
0133     // events. The return value shows the number of events the caller Worker has
0134     // to process (between 1 and eventModulo depending on number of events yet to
0135     // be processed). G4Event object has the event ID of the first event of this
0136     // bunch. If zero is returned no more event needs to be processed, and worker
0137     // thread must delete that G4Event.
0138     G4int SetUpNEvents(G4Event*, G4SeedsQueue* seedsQueue, G4bool reseedRequired = true) override;
0139 
0140     // To be invoked solely from G4WorkerTaskRunManager to merge the results
0141     void MergeScores(const G4ScoringManager* localScoringManager) override;
0142     void MergeRun(const G4Run* localRun) override;
0143 
0144     // Called to force workers to request and process the UI commands stack
0145     // This will block untill all workers have processed UI commands
0146     void RequestWorkersProcessCommandsStack() override;
0147 
0148     // Called by workers to signal to master it has completed processing of
0149     // UI commands
0150     // virtual WorkerActionRequest ThisWorkerWaitForNextAction();
0151     // Worker thread barrier
0152     // This method should be used by workers' run manager to wait,
0153     // after an event loop for the next action to be performed
0154     // (for example execute a new run)
0155     // This returns the action to be performed
0156     void ThisWorkerProcessCommandsStackDone() override;
0157 
0158     void WaitForReadyWorkers() override {}
0159     void WaitForEndEventLoopWorkers() override;
0160     void ThisWorkerReady() override {}
0161     void ThisWorkerEndEventLoop() override {}
0162 
0163     WorkerActionRequest ThisWorkerWaitForNextAction() override
0164     {
0165       return WorkerActionRequest::UNDEFINED;
0166     }
0167 
0168     inline void SetInitializeSeedsCallback(InitializeSeedsCallback f) { initSeedsCallback = f; }
0169 
0170     void AbortRun(G4bool softAbort = false) override;
0171     void AbortEvent() override;
0172 
0173   protected:
0174     virtual void ComputeNumberOfTasks();
0175 
0176     // Initialize the seeds list, if derived class does not implement this method
0177     // A default generation will be used (nevents*2 random seeds)
0178     // Return true if initialization is done.
0179     G4bool InitializeSeeds(G4int /*nevts*/) override { return false; }
0180 
0181     // Adds one seed to the list of seeds
0182     void RefillSeeds() override;
0183     void StoreRNGStatus(const G4String& filenamePrefix) override;
0184 
0185     // Creates worker threads and signal to start
0186     void CreateAndStartWorkers() override;
0187 
0188     void TerminateWorkers() override;
0189     void NewActionRequest(WorkerActionRequest) override {}
0190     virtual void AddEventTask(G4int);
0191 
0192   protected:
0193     // Barriers: synch points between master and workers
0194     RunTaskGroup* workTaskGroup = nullptr;
0195 
0196     // aliases to inherited member values
0197     G4bool& poolInitialized = PTL::TaskRunManager::m_is_initialized;
0198     G4ThreadPool*& threadPool = PTL::TaskRunManager::m_thread_pool;
0199     G4VUserTaskQueue*& taskQueue = PTL::TaskRunManager::m_task_queue;
0200     G4TaskManager*& taskManager = PTL::TaskRunManager::m_task_manager;
0201 
0202     InitializeSeedsCallback initSeedsCallback = [](G4int, G4int&, G4int&) {
0203       return false;
0204     };
0205 
0206   protected:
0207     // grainsize
0208     G4bool workersStarted = false;
0209     G4int eventGrainsize = 0;
0210     G4int numberOfEventsPerTask = -1;
0211     G4int numberOfTasks = -1;
0212     CLHEP::HepRandomEngine* masterRNGEngine = nullptr;
0213     // Pointer to the master thread random engine
0214     G4TaskRunManagerKernel* MTkernel = nullptr;
0215 };
0216 
0217 #endif  // G4TaskRunManager_hh