![]() |
|
|||
File indexing completed on 2025-04-04 01:26:34
0001 #ifndef FWCore_AbstractServices_RandomNumberGenerator_h 0002 #define FWCore_AbstractServices_RandomNumberGenerator_h 0003 0004 /** \class edm::RandomNumberGenerator 0005 0006 Description: Interface for obtaining random number engines. 0007 0008 Usage: This class is the abstract interface to a Service 0009 which provides access to the random number engines which are 0010 used to generate random numbers. One accesses the service using 0011 the Service system. 0012 0013 edm::Service<edm::RandomNumberGenerator> rng; 0014 CLHEP::HepRandomEngine& engine = rng->getEngine(streamID); 0015 or 0016 CLHEP::HepRandomEngine& engine = rng->getEngine(luminosityBlockIndex); 0017 0018 The RandomNumberGenerator automatically knows what module is 0019 requesting an engine and will return the proper one for that 0020 module. 0021 0022 For each module the service will hold one engine per stream. 0023 In addition, for each module the service will hold a number 0024 of engines equal to the number of LuminosityBlocks that can 0025 be processed concurrently. When running a multithreaded 0026 process the correct engine for the current module and 0027 streamID/luminosityBlockIndex must be used to avoid 0028 data races. This is also important for replay. 0029 0030 A source cannot use this service and sources should not generate 0031 random numbers (otherwise replay will fail). 0032 0033 Random numbers should only be generated in two functions of a 0034 module, the function used to process the Event and also the 0035 global beginLuminosityBlock function. Random numbers should 0036 not be generated at any other time, not in the constructor, 0037 not at beginJob, not at beginRun ... Note that this restriction 0038 applies to generating the random numbers. If one is only calling 0039 the function getEngine that takes a streamID argument then it is 0040 also OK to call it in the beginStream method, but only to get 0041 the reference to the engine and save it or save a pointer to 0042 it (but not to generate any random numbers in beginStream). 0043 0044 The service owns the engines and handles memory management 0045 for them. 0046 0047 The service does a lot of work behind the scenes to allow one 0048 to replay specific events of a prior process. There are two 0049 different mechanisms. 0050 0051 First, if the parameter named "saveFileName" is set the 0052 state of the random engines will be written to a text file 0053 before each event is processed. This text file is overwritten 0054 at each event. If a job crashes while processing an event, 0055 then one can replay the processing of the event where the 0056 crash occurred and get the same random number sequences. 0057 For jobs with more than 1 thread or forked processes, the 0058 text files are named by appending "_" and a number 0059 to the "saveFileName" parameter, where the number is either 0060 the child index of the forked process or the streamID of 0061 the stream which processed the event. 0062 0063 Second, if the RandomEngineStateProducer module is executed 0064 the state of all the engines managed by this service 0065 can be saved to both the Event and LuminosityBlock. Then in a 0066 later process, the RandomNumberGenerator is capable of restoring 0067 the state of the engines in order to be able to exactly replay 0068 the earlier process starting at any event without having to 0069 replay the entire process. 0070 0071 This service performs its tasks so that the random sequences 0072 are independent sequences with different seeds for two cases: 0073 0074 1. Multiprocess jobs where processes are forked 0075 2. Multithread jobs where multiple threads are used 0076 0077 It is assumed that we will never run jobs that are both 0078 multiprocess and multithread. The service seeding algorithm 0079 will fail to produce independent sequences if that is 0080 attempted. 0081 0082 Three warnings. 0083 0084 1. When there is more than one LuminosityBlock in a single 0085 process, the random number engines used in global begin 0086 luminosity block are reset to the same starting state 0087 before each call to that function (except in replay mode). 0088 This allows the initialization performed in all of them 0089 to be identical. Don't expect unique sequences in different 0090 calls to beginLuminosityBlock. 0091 0092 2. In multiprocess jobs, the engines are reinitialized 0093 after the processes are forked with new seeds equal to 0094 the original seed plus the child index. In multithread 0095 jobs, the stream sequences are initialized in a similar way 0096 by adding the streamID to the seed to form a new 0097 seed for each stream. The seeds for the engines for 0098 the luminosity blocks are all the same and the original 0099 seed plus the number of streams or the number of forked 0100 child processes is used. In existing work management schemes 0101 this works well, because the initial configured seed is 0102 derived randomly and the seeds in different jobs should 0103 not be close to one another. If not using one of these 0104 work management schemes, one has to be careful to not 0105 configure seeds in multiple jobs that are close enough 0106 together to overlap (closer than the number of forked 0107 processes or streams). For example, if one generated 0108 the original configured seed for a job using the previous 0109 jobs seed and adding one, then there would be a problem. 0110 0111 3. This service properly handles modules running concurrently 0112 and generating random numbers, but not concurrent submodule tasks. 0113 If a module creates its own subtasks that are run concurrently 0114 and generate numbers, then using the engines from the service 0115 will result in data races. If this design if ever needed, 0116 one possible approach would be for each submodule task that 0117 needs random numbers to create its own engine and seed it 0118 using a random number from the module random engine. There 0119 might be better ways. 0120 0121 There are more details explaining this service on a TWIKI page 0122 which can be accessed through a link on the Framework TWIKI page 0123 of the SWGuide. 0124 0125 \author Chris Jones and W. David Dagenhart, created March 7, 2006 0126 */ 0127 0128 #include <cstdint> 0129 #include <iosfwd> 0130 #include <memory> 0131 #include <vector> 0132 0133 class RandomEngineState; 0134 0135 namespace CLHEP { 0136 class HepRandomEngine; 0137 } 0138 0139 namespace edm { 0140 0141 class ConsumesCollector; 0142 class Event; 0143 class LuminosityBlock; 0144 class LuminosityBlockIndex; 0145 class StreamID; 0146 0147 class RandomNumberGenerator { 0148 public: 0149 RandomNumberGenerator() = default; 0150 RandomNumberGenerator(RandomNumberGenerator const&) = delete; 0151 RandomNumberGenerator& operator=(RandomNumberGenerator const&) = delete; 0152 RandomNumberGenerator(RandomNumberGenerator&&) = delete; 0153 RandomNumberGenerator& operator=(RandomNumberGenerator&&) = delete; 0154 virtual ~RandomNumberGenerator(); 0155 0156 /// Use the next 2 functions to get the random number engine. 0157 /// These are the only functions most modules should call. 0158 0159 /// Use this engine in event methods 0160 virtual CLHEP::HepRandomEngine& getEngine(StreamID const&) = 0; 0161 0162 /// Use this engine in the global begin luminosity block method 0163 virtual CLHEP::HepRandomEngine& getEngine(LuminosityBlockIndex const&) = 0; 0164 0165 /// This function is not intended for general use. It is intended for 0166 /// the special case where multiple instances of Pythia 8 will 0167 /// be run concurrently and we want them to be initialized exactly 0168 /// the same. In this special case, the luminosity block engine(s) 0169 /// owned by the service should not be used to generate random numbers 0170 /// in between calls to cloneEngine, because the clone will be in 0171 /// the state that existed at the moment of cloning. 0172 /// Before initializing Pythia, this function should be used to clone 0173 /// the engine owned by the service and the cloned random engine should be 0174 /// used to generate numbers for initialization so that all initializations 0175 /// in the process get identical sequences of random numbers. 0176 virtual std::unique_ptr<CLHEP::HepRandomEngine> cloneEngine(LuminosityBlockIndex const&) = 0; 0177 0178 /// This returns the seed from the configuration. In the unusual case where an 0179 /// an engine type takes multiple seeds to initialize a sequence, this function 0180 /// only returns the first. As a general rule, this function should not be used, 0181 /// but is available for backward compatibility and debugging. It might be useful 0182 /// for some types of tests. Using this to seed engines constructed in modules is 0183 /// not recommended because (unless done very carefully) it will create duplicate 0184 /// sequences in different threads and/or data races. Also, if engines are created 0185 /// by modules the replay mechanism will be broken. 0186 /// Because it is dangerous and could be misused, this function might be deleted 0187 /// someday if we ever find time to delete all uses of it in CMSSW. There are of 0188 /// order 10 last time I checked ... 0189 virtual std::uint32_t mySeed() const = 0; 0190 0191 // The following functions should not be used by general users. They 0192 // should only be called by Framework code designed to work with the 0193 // service while it is saving the engine states or restoring them. 0194 // The first two are called by the EventProcessor at special times. 0195 // The next two are called by a dedicated producer module (RandomEngineStateProducer). 0196 0197 virtual void preBeginLumi(LuminosityBlock const& lumi) = 0; 0198 virtual void postEventRead(Event const& event) = 0; 0199 0200 virtual void setLumiCache(LuminosityBlockIndex, std::vector<RandomEngineState> const& iStates) = 0; 0201 virtual void setEventCache(StreamID, std::vector<RandomEngineState> const& iStates) = 0; 0202 0203 virtual std::vector<RandomEngineState> const& getEventCache(StreamID const&) const = 0; 0204 virtual std::vector<RandomEngineState> const& getLumiCache(LuminosityBlockIndex const&) const = 0; 0205 0206 virtual void consumes(ConsumesCollector&& iC) const = 0; 0207 0208 /// For debugging purposes only. 0209 virtual void print(std::ostream& os) const = 0; 0210 }; 0211 } // namespace edm 0212 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.2.1 LXR engine. The LXR team |
![]() ![]() |