Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:58:42

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 // G4MTRunManager
0027 //
0028 // Class description:
0029 //
0030 // This is a class for run control in Geant4 of multi-threaded runs.
0031 // It extends G4RunManager re-implementing multi-threaded behavior in
0032 // key methods (see documentation for G4RunManager).
0033 // Users initialise an instance of this class instead of G4RunManager
0034 // to start a multi-threaded simulation.
0035 
0036 // Original authors: X.Dong, A.Dotti - February 2013
0037 // --------------------------------------------------------------------
0038 #ifndef G4MTRunManager_hh
0039 #define G4MTRunManager_hh 1
0040 
0041 #include "G4MTBarrier.hh"
0042 #include "G4Profiler.hh"
0043 #include "G4RNGHelper.hh"
0044 #include "G4RunManager.hh"
0045 #include "G4Threading.hh"
0046 
0047 #include <list>
0048 #include <map>
0049 
0050 class G4MTRunManagerKernel;
0051 class G4ScoringManager;
0052 class G4UserWorkerInitialization;
0053 class G4UserWorkerThreadInitialization;
0054 class G4RunManagerFactory;
0055 
0056 // TODO: Split random number storage from this class
0057 
0058 class G4MTRunManager : public G4RunManager
0059 {
0060     friend class G4RunManagerFactory;
0061 
0062   public:
0063     // The profiler aliases are only used when compiled with
0064     // GEANT4_USE_TIMEMORY.
0065     using ProfilerConfig = G4ProfilerConfig<G4ProfileType::Run>;
0066 
0067     // Map of defined worlds.
0068     using masterWorlds_t = std::map<G4int, G4VPhysicalVolume*>;
0069 
0070   public:
0071     G4MTRunManager();
0072     ~G4MTRunManager() override;
0073 
0074     void SetNumberOfThreads(G4int n) override;
0075     G4int GetNumberOfThreads() const override { return nworkers; }
0076     void SetPinAffinity(G4int n = 1);
0077     inline G4int GetPinAffinity() const { return pinAffinity; }
0078 
0079     // Inherited methods to re-implement for MT case
0080     void Initialize() override;
0081     void InitializeEventLoop(G4int n_event, const char* macroFile = nullptr,
0082                              G4int n_select = -1) override;
0083     virtual void InitializeThreadPool() {}
0084 
0085     // The following do not do anything for this runmanager
0086     void TerminateOneEvent() override;
0087     void ProcessOneEvent(G4int i_event) override;
0088     void ConstructScoringWorlds() override;
0089     void RunTermination() override;
0090 
0091     // The following method should be invoked by G4WorkerRunManager for each
0092     // event. False is returned if no more event to be processed.
0093     // Note: G4Event object must be instantiated by a worker thread.
0094     // In case no more events remain to be processed, that worker thread must
0095     // delete that G4Event object. If a worker runs with its own random number
0096     // sequence, the Boolean flag 'reseedRequired' should be set to false.
0097     // This is *NOT* allowed for the first event.
0098     virtual G4bool SetUpAnEvent(G4Event*, G4long& s1, G4long& s2, G4long& s3,
0099                                 G4bool reseedRequired = true);
0100 
0101     // Same as above method, but seeds are set only once over "eventModulo"
0102     // events. The return value shows the number of events the caller Worker
0103     // has to process (between 1 and eventModulo depending on number of events
0104     // yet to be processed). G4Event object has the event ID of the first
0105     // event of this bunch. If zero is returned no more events need to be
0106     // processed, and worker thread must delete that G4Event.
0107     // Called by Initialize() method.
0108     virtual G4int SetUpNEvents(G4Event*, G4SeedsQueue* seedsQueue, G4bool reseedRequired = true);
0109 
0110     // This method is invoked just before spawning the threads to
0111     // collect from UI manager the list of commands that threads
0112     // will execute.
0113     std::vector<G4String> GetCommandStack();
0114 
0115     // Returns number of currently active threads.
0116     // This number may be different from the number of threads currently
0117     // in running state, e.g. the number returned by:
0118     // G4Threading::GetNumberOfActiveWorkerThreads() method.
0119     virtual size_t GetNumberActiveThreads() const { return threads.size(); }
0120 
0121     static G4ThreadId GetMasterThreadId();
0122 
0123     // Worker threads barrier: this method should be called by each
0124     // worker when ready to start thread event-loop.
0125     // This method will return only when all workers are ready.
0126     virtual void ThisWorkerReady();
0127 
0128     // Worker threads barrier: this method should be called by each
0129     // worker when worker event loop is terminated.
0130     virtual void ThisWorkerEndEventLoop();
0131 
0132     static G4ScoringManager* GetMasterScoringManager();
0133     static masterWorlds_t& GetMasterWorlds();
0134     static void addWorld(G4int counter, G4VPhysicalVolume* w);
0135 
0136     inline const CLHEP::HepRandomEngine* getMasterRandomEngine() const { return masterRNGEngine; }
0137 
0138     // Returns the singleton instance of the run manager common to all
0139     // threads implementing the master behavior
0140     static G4MTRunManager* GetMasterRunManager();
0141 
0142     // Returns the singleton instance of the run manager kernel common to all
0143     // threads
0144     static G4RunManagerKernel* GetMasterRunManagerKernel();
0145     static G4MTRunManagerKernel* GetMTMasterRunManagerKernel();
0146 
0147     void SetUserInitialization(G4VUserPhysicsList* userPL) override;
0148     void SetUserInitialization(G4VUserDetectorConstruction* userDC) override;
0149     void SetUserInitialization(G4UserWorkerInitialization* userInit) override;
0150     void SetUserInitialization(G4UserWorkerThreadInitialization* userInit) override;
0151     void SetUserInitialization(G4VUserActionInitialization* userInit) override;
0152     void SetUserAction(G4UserRunAction* userAction) override;
0153     void SetUserAction(G4VUserPrimaryGeneratorAction* userAction) override;
0154     void SetUserAction(G4UserEventAction* userAction) override;
0155     void SetUserAction(G4UserStackingAction* userAction) override;
0156     void SetUserAction(G4UserTrackingAction* userAction) override;
0157     void SetUserAction(G4UserSteppingAction* userAction) override;
0158 
0159     // To be invoked solely from G4WorkerRunManager to merge the results
0160     void MergeScores(const G4ScoringManager* localScoringManager);
0161     void MergeRun(const G4Run* localRun);
0162 
0163     // Handling of more than one run per thread
0164     enum class WorkerActionRequest
0165     {
0166       UNDEFINED,
0167       NEXTITERATION,  // There is another set of UI commands to be executed
0168       PROCESSUI,  // Process UI commands w/o a /run/beamOn
0169       ENDWORKER  // Terminate thread, work finished
0170     };
0171 
0172     // Called to force workers to request and process the UI commands stack
0173     // This will block untill all workers have processed UI commands
0174     virtual void RequestWorkersProcessCommandsStack();
0175 
0176     // Called by workers to signal to master it has completed processing of
0177     // UI commands
0178     virtual void ThisWorkerProcessCommandsStackDone();
0179 
0180     // Worker thread barrier: this method should be used by workers' run
0181     // manager to wait, after an event loop for the next action to be
0182     // performed (for example execute a new run).
0183     // This returns the action to be performed.
0184     virtual WorkerActionRequest ThisWorkerWaitForNextAction();
0185 
0186     inline void SetEventModulo(G4int i = 1) { eventModuloDef = i; }
0187     inline G4int GetEventModulo() const { return eventModuloDef; }
0188 
0189     void AbortRun(G4bool softAbort = false) override;
0190     void AbortEvent() override;
0191 
0192     static G4int SeedOncePerCommunication();
0193     static void SetSeedOncePerCommunication(G4int val);
0194 
0195   protected:
0196     // Initialize the seeds list, if derived class does not implement this
0197     // method, a default generation will be used (nevents*2 random seeds).
0198     // Return true if initialization is done.
0199     // Adds one seed to the list of seeds.
0200     virtual G4bool InitializeSeeds(G4int /*nevts*/) { return false; };
0201 
0202     virtual void PrepareCommandsStack();
0203     void StoreRNGStatus(const G4String& filenamePrefix) override;
0204     void rndmSaveThisRun() override;
0205     void rndmSaveThisEvent() override;
0206 
0207     // Creates worker threads and signal to start
0208     virtual void CreateAndStartWorkers();
0209 
0210     // Master thread barrier: call this function to block master thread and
0211     // wait workers to be ready to process work. This function will return
0212     // only when all workers are ready to perform event loop.
0213     virtual void WaitForReadyWorkers();
0214 
0215     // Master thread barrier: call this function to block master thread and
0216     // wait workers have finished current event loop. This function will
0217     // return only when all workers have finished processing events for
0218     // this run.
0219     virtual void WaitForEndEventLoopWorkers();
0220 
0221     // Empty the workersList.
0222     virtual void TerminateWorkers();
0223 
0224     virtual void NewActionRequest(WorkerActionRequest newRequest);
0225 
0226     virtual void RefillSeeds();
0227 
0228   protected:
0229     // Number of worker threads. To be set by SetNumberOfThreads() method.
0230     G4int nworkers = 2;
0231 
0232     // Force to use this number regardless of SetNumberOfThreads() method.
0233     G4int forcedNwokers = -1;
0234 
0235     G4int numberOfEventToBeProcessed = 0;
0236 
0237     // Handling of master thread scoring worlds, access is needed by workers
0238     G4MTRUN_DLL static G4ScoringManager* masterScM;
0239     G4MTRUN_DLL static masterWorlds_t masterWorlds;
0240     // Singleton implementing master thread behavior
0241     G4MTRUN_DLL static G4MTRunManager* fMasterRM;
0242 
0243     WorkerActionRequest nextActionRequest = WorkerActionRequest::UNDEFINED;
0244 
0245     G4int eventModuloDef = 0;
0246     G4int eventModulo = 1;
0247     G4int nSeedsUsed = 0;
0248     G4int nSeedsFilled = 0;
0249     G4int nSeedsMax = 10000;
0250     G4int nSeedsPerEvent = 2;
0251     G4double* randDbl = nullptr;
0252 
0253     static G4ThreadId masterThreadId;
0254 
0255     // - If it is set to 0 (default), seeds that are centrally managed
0256     //   by G4MTRunManager are set for every event of every worker thread.
0257     //   This option guarantees event reproducibility regardless of number
0258     //   of threads.
0259     // - If it is set to 1, seeds are set only once for the first
0260     //   event of each run of each worker thread. Event reproducibility is
0261     //   guaranteed only if the same number of worker threads are used.
0262     //   On the other hand, this option offers better computing performance
0263     //   in particular for applications with relatively small primary
0264     //   particle energy and large number of events.
0265     // - If it is set to 2, seeds are set only for the first event of
0266     //   group of N events. This option is reserved for the future use when
0267     //   Geant4 will allow number of threads to be dynamically changed during
0268     //   an event loop.
0269     static G4int seedOncePerCommunication;
0270 
0271     // Barriers: synch points between master and workers
0272     G4MTBarrier beginOfEventLoopBarrier;
0273     G4MTBarrier endOfEventLoopBarrier;
0274     G4MTBarrier nextActionRequestBarrier;
0275     G4MTBarrier processUIBarrier;
0276 
0277   private:
0278     // List of workers (i.e. thread)
0279     using G4ThreadsList = std::list<G4Thread*>;
0280 
0281     // Pin Affinity parameter
0282     G4int pinAffinity = 0;
0283 
0284     // List of workers run managers
0285     // List of all workers run managers
0286     G4ThreadsList threads;
0287 
0288     // List of UI commands for workers.
0289     std::vector<G4String> uiCmdsForWorkers;
0290 
0291     // Pointer to the master thread random engine
0292     CLHEP::HepRandomEngine* masterRNGEngine = nullptr;
0293 
0294     G4MTRunManagerKernel* MTkernel = nullptr;
0295 };
0296 
0297 #endif  // G4MTRunManager_hh