Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:59:08

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 "G4Profiler.hh"
0042 #include "G4RNGHelper.hh"
0043 #include "G4RunManager.hh"
0044 #include "G4TBBTaskGroup.hh"
0045 #include "G4TaskGroup.hh"
0046 #include "G4TaskManager.hh"
0047 #include "G4ThreadPool.hh"
0048 #include "G4Threading.hh"
0049 #include "G4VUserTaskQueue.hh"
0050 
0051 #include "PTL/TaskRunManager.hh"
0052 #include "rundefs.hh"
0053 
0054 #include <list>
0055 #include <map>
0056 
0057 class G4TaskRunManagerKernel;
0058 class G4ScoringManager;
0059 class G4UserTaskInitialization;
0060 class G4UserTaskThreadInitialization;
0061 class G4WorkerTaskRunManager;
0062 class G4RunManagerFactory;
0063 
0064 //============================================================================//
0065 
0066 class G4TaskRunManager : public G4MTRunManager, public PTL::TaskRunManager
0067 {
0068     friend class G4RunManagerFactory;
0069 
0070   public:
0071     // the profiler aliases are only used when compiled with GEANT4_USE_TIMEMORY
0072     using ProfilerConfig = G4ProfilerConfig<G4ProfileType::Run>;
0073     using InitializeSeedsCallback = std::function<G4bool(G4int, G4int&, G4int&)>;
0074     using RunTaskGroup = G4TaskGroup<void>;
0075 
0076   public:
0077     // Returns the singleton instance of the run manager common to all threads
0078     // implementing the master behavior
0079     static G4TaskRunManager* GetMasterRunManager()
0080     {
0081       auto* _rm = G4MTRunManager::GetMasterRunManager();
0082       return dynamic_cast<G4TaskRunManager*>(_rm);
0083     }
0084 
0085     // Returns the singleton instance of the run manager kernel common to all
0086     // threads
0087     static G4TaskRunManagerKernel* GetMTMasterRunManagerKernel();
0088 
0089     // Parameters:
0090     //      taskQueue     : provide a custom task queue
0091     //      useTBB        : only relevant if GEANT4_USE_TBB defined
0092     //      evtGrainsize  : the number of events per task
0093     G4TaskRunManager(G4bool useTBB = G4GetEnv<G4bool>("G4USE_TBB", false));
0094     G4TaskRunManager(G4VUserTaskQueue* taskQueue,
0095                      G4bool useTBB = G4GetEnv<G4bool>("G4USE_TBB", false), G4int evtGrainsize = 0);
0096     ~G4TaskRunManager() override;
0097 
0098     void SetGrainsize(G4int n) { eventGrainsize = n; }
0099     G4int GetGrainsize() const { return eventGrainsize; }
0100     inline G4int GetNumberOfTasks() const { return numberOfTasks; }
0101     inline G4int GetNumberOfEventsPerTask() const { return numberOfEventsPerTask; }
0102 
0103     void SetNumberOfThreads(G4int n) override;
0104     G4int GetNumberOfThreads() const override;
0105     size_t GetNumberActiveThreads() const override
0106     {
0107       return PTL::TaskRunManager::GetNumberActiveThreads();
0108     }
0109     static G4ThreadId GetMasterThreadId();
0110 
0111     // Inherited methods to re-implement for MT case
0112     void Initialize() override;
0113     void InitializeEventLoop(G4int n_event, const char* macroFile = nullptr,
0114                              G4int n_select = -1) override;
0115     void InitializeThreadPool() override;
0116     G4bool ThreadPoolIsInitialized() const { return poolInitialized; }
0117 
0118     void Initialize(uint64_t nthreads) override { PTL::TaskRunManager::Initialize(nthreads); }
0119 
0120     void TerminateOneEvent() override;
0121     void ProcessOneEvent(G4int i_event) override;
0122     void ConstructScoringWorlds() override;
0123     void RunTermination() override;
0124 
0125     // The following method should be invoked by G4WorkerTaskRunManager for each
0126     // event. False is returned if no more event to be processed. Note: G4Event
0127     // object must be instantiated by a worker thread. In case no more
0128     //  event remains to be processed, that worker thread must delete that G4Event
0129     //  object. If a worker runs with its own random number sequence, the Boolean
0130     //  flag reseedRequired should be set to false. This is *NOT* allowed for the
0131     //  first event.
0132     G4bool SetUpAnEvent(G4Event*, G4long& s1, G4long& s2, G4long& s3,
0133                         G4bool reseedRequired = true) override;
0134 
0135     // Same as above method, but the seeds are set only once over "eventModulo"
0136     // events. The return value shows the number of events the caller Worker has
0137     // to process (between 1 and eventModulo depending on number of events yet to
0138     // be processed). G4Event object has the event ID of the first event of this
0139     // bunch. If zero is returned no more event needs to be processed, and worker
0140     // thread must delete that G4Event.
0141     G4int SetUpNEvents(G4Event*, G4SeedsQueue* seedsQueue, G4bool reseedRequired = true) override;
0142 
0143     // To be invoked solely from G4WorkerTaskRunManager to merge the results
0144     void MergeScores(const G4ScoringManager* localScoringManager);
0145     void MergeRun(const G4Run* localRun);
0146 
0147     // Called to force workers to request and process the UI commands stack
0148     // This will block untill all workers have processed UI commands
0149     void RequestWorkersProcessCommandsStack() override;
0150 
0151     // Called by workers to signal to master it has completed processing of
0152     // UI commands
0153     // virtual WorkerActionRequest ThisWorkerWaitForNextAction();
0154     // Worker thread barrier
0155     // This method should be used by workers' run manager to wait,
0156     // after an event loop for the next action to be performed
0157     // (for example execute a new run)
0158     // This returns the action to be performed
0159     void ThisWorkerProcessCommandsStackDone() override;
0160 
0161     void WaitForReadyWorkers() override {}
0162     void WaitForEndEventLoopWorkers() override;
0163     void ThisWorkerReady() override {}
0164     void ThisWorkerEndEventLoop() override {}
0165 
0166     WorkerActionRequest ThisWorkerWaitForNextAction() override
0167     {
0168       return WorkerActionRequest::UNDEFINED;
0169     }
0170 
0171     inline void SetInitializeSeedsCallback(InitializeSeedsCallback f) { initSeedsCallback = f; }
0172 
0173     void AbortRun(G4bool softAbort = false) override;
0174     void AbortEvent() override;
0175 
0176   protected:
0177     virtual void ComputeNumberOfTasks();
0178 
0179     // Initialize the seeds list, if derived class does not implement this method
0180     // A default generation will be used (nevents*2 random seeds)
0181     // Return true if initialization is done.
0182     G4bool InitializeSeeds(G4int /*nevts*/) override { return false; }
0183 
0184     // Adds one seed to the list of seeds
0185     void RefillSeeds() override;
0186     void StoreRNGStatus(const G4String& filenamePrefix) override;
0187 
0188     // Creates worker threads and signal to start
0189     void CreateAndStartWorkers() override;
0190 
0191     void TerminateWorkers() override;
0192     void NewActionRequest(WorkerActionRequest) override {}
0193     virtual void AddEventTask(G4int);
0194 
0195   protected:
0196     // Barriers: synch points between master and workers
0197     RunTaskGroup* workTaskGroup = nullptr;
0198 
0199     // aliases to inherited member values
0200     G4bool& poolInitialized = PTL::TaskRunManager::m_is_initialized;
0201     G4ThreadPool*& threadPool = PTL::TaskRunManager::m_thread_pool;
0202     G4VUserTaskQueue*& taskQueue = PTL::TaskRunManager::m_task_queue;
0203     G4TaskManager*& taskManager = PTL::TaskRunManager::m_task_manager;
0204 
0205     InitializeSeedsCallback initSeedsCallback = [](G4int, G4int&, G4int&) {
0206       return false;
0207     };
0208 
0209   private:
0210     // grainsize
0211     G4bool workersStarted = false;
0212     G4int eventGrainsize = 0;
0213     G4int numberOfEventsPerTask = -1;
0214     G4int numberOfTasks = -1;
0215     CLHEP::HepRandomEngine* masterRNGEngine = nullptr;
0216     // Pointer to the master thread random engine
0217     G4TaskRunManagerKernel* MTkernel = nullptr;
0218 };
0219 
0220 #endif  // G4TaskRunManager_hh