Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:58:57

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