Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-06 09:21:30

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