Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-07-28 22:48:38

0001 #ifndef IOMC_RandomEngine_RandomNumberGeneratorService_h
0002 #define IOMC_RandomEngine_RandomNumberGeneratorService_h
0003 
0004 /** \class edm::service::RandomNumberGeneratorService
0005 
0006  Description: Manages random number engines for modules
0007 
0008  Usage: See comments in base class, FWCore/Utilities/RandomNumberGenerator.h
0009 
0010 \author Chris Jones and W. David Dagenhart, created March 7, 2006
0011   (originally in FWCore/Services)
0012 */
0013 
0014 #include "FWCore/ServiceRegistry/interface/ServiceRegistryfwd.h"
0015 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
0016 #include "FWCore/Utilities/interface/InputTag.h"
0017 #include "FWCore/Utilities/interface/get_underlying_safe.h"
0018 
0019 #include <atomic>
0020 #include <cstdint>
0021 #include <fstream>
0022 #include <iosfwd>
0023 #include <istream>
0024 #include <limits>
0025 #include <map>
0026 #include <memory>
0027 #include <string>
0028 #include <vector>
0029 
0030 class RandomEngineState;
0031 
0032 namespace CLHEP {
0033   class HepRandomEngine;
0034 }
0035 
0036 namespace edm {
0037   class ActivityRegistry;
0038   class ConfigurationDescriptions;
0039   class ConsumesCollector;
0040   class Event;
0041   class LuminosityBlock;
0042   class LuminosityBlockIndex;
0043   class ModuleCallingContext;
0044   class ModuleDescription;
0045   class ParameterSet;
0046   class StreamContext;
0047   class StreamID;
0048 
0049   namespace service {
0050 
0051     class SystemBounds;
0052 
0053     class RandomNumberGeneratorService : public RandomNumberGenerator {
0054     public:
0055       RandomNumberGeneratorService(ParameterSet const& pset, ActivityRegistry& activityRegistry);
0056       ~RandomNumberGeneratorService() override;
0057 
0058       RandomNumberGeneratorService(RandomNumberGeneratorService const&) = delete;
0059       RandomNumberGeneratorService const& operator=(RandomNumberGeneratorService const&) = delete;
0060 
0061       /// Use the next 2 functions to get the random number engine.
0062       /// These are the only functions most modules should call.
0063 
0064       /// Use this engine in event methods
0065       CLHEP::HepRandomEngine& getEngine(StreamID const& streamID) override;
0066 
0067       /// Use this engine in the global begin luminosity block method
0068       CLHEP::HepRandomEngine& getEngine(LuminosityBlockIndex const& luminosityBlockIndex) override;
0069 
0070       std::unique_ptr<CLHEP::HepRandomEngine> cloneEngine(LuminosityBlockIndex const&) override;
0071 
0072       // This returns the seed from the configuration. In the unusual case where an
0073       // an engine type takes multiple seeds to initialize a sequence, this function
0074       // only returns the first. As a general rule, this function should not be used,
0075       // but is available for backward compatibility and debugging. It might be useful
0076       // for some types of tests. Using this to seed engines constructed in modules is
0077       // not recommended because (unless done very carefully) it will create duplicate
0078       // sequences in different threads and/or data races. Also, if engines are created
0079       // by modules the replay mechanism will be broken.
0080       // Because it is dangerous and could be misused, this function might be deleted
0081       // someday if we ever find time to delete all uses of it in CMSSW. There are of
0082       // order 10 last time I checked ...
0083       std::uint32_t mySeed() const override;
0084 
0085       static void fillDescriptions(ConfigurationDescriptions& descriptions);
0086 
0087       void preModuleConstruction(ModuleDescription const& description);
0088       void preModuleDestruction(ModuleDescription const& description);
0089       void preallocate(SystemBounds const&);
0090 
0091       void preBeginLumi(LuminosityBlock const& lumi) override;
0092       void postEventRead(Event const& event) override;
0093       void setLumiCache(LuminosityBlockIndex, std::vector<RandomEngineState> const& iStates) override;
0094       void setEventCache(StreamID, std::vector<RandomEngineState> const& iStates) override;
0095 
0096       void preBeginJob(PathsAndConsumesOfModulesBase const&, ProcessContext const&);
0097       void postBeginJob();
0098       void preEndJob();
0099       void postEndJob();
0100 
0101       /// These next 12 functions are only used to check that random numbers are not
0102       /// being generated in these methods when enable checking is configured on.
0103       void preModuleBeginStream(StreamContext const& sc, ModuleCallingContext const& mcc);
0104       void postModuleBeginStream(StreamContext const& sc, ModuleCallingContext const& mcc);
0105 
0106       void preModuleEndStream(StreamContext const& sc, ModuleCallingContext const& mcc);
0107       void postModuleEndStream(StreamContext const& sc, ModuleCallingContext const& mcc);
0108 
0109       void preModuleStreamBeginRun(StreamContext const& sc, ModuleCallingContext const& mcc);
0110       void postModuleStreamBeginRun(StreamContext const& sc, ModuleCallingContext const& mcc);
0111 
0112       void preModuleStreamEndRun(StreamContext const& sc, ModuleCallingContext const& mcc);
0113       void postModuleStreamEndRun(StreamContext const& sc, ModuleCallingContext const& mcc);
0114 
0115       void preModuleStreamBeginLumi(StreamContext const& sc, ModuleCallingContext const& mcc);
0116       void postModuleStreamBeginLumi(StreamContext const& sc, ModuleCallingContext const& mcc);
0117 
0118       void preModuleStreamEndLumi(StreamContext const& sc, ModuleCallingContext const& mcc);
0119       void postModuleStreamEndLumi(StreamContext const& sc, ModuleCallingContext const& mcc);
0120 
0121       /// These two are used by the RandomEngineStateProducer
0122       std::vector<RandomEngineState> const& getLumiCache(LuminosityBlockIndex const&) const override;
0123       std::vector<RandomEngineState> const& getEventCache(StreamID const&) const override;
0124 
0125       void consumes(ConsumesCollector&& iC) const override;
0126 
0127       /// For debugging
0128       void print(std::ostream& os) const override;
0129 
0130     private:
0131       typedef std::vector<std::uint32_t> VUint32;
0132 
0133       class LabelAndEngine {
0134       public:
0135         LabelAndEngine(std::string const& theLabel,
0136                        VUint32 const& theSeeds,
0137                        std::shared_ptr<CLHEP::HepRandomEngine> const& theEngine)
0138             : label_(theLabel), seeds_(theSeeds), engine_(theEngine) {}
0139         std::string const& label() const { return label_; }
0140         VUint32 const& seeds() const { return seeds_; }
0141         std::shared_ptr<CLHEP::HepRandomEngine const> engine() const { return get_underlying_safe(engine_); }
0142         std::shared_ptr<CLHEP::HepRandomEngine>& engine() { return get_underlying_safe(engine_); }
0143         void setSeed(std::uint32_t v, unsigned int index) { seeds_.at(index) = v; }
0144 
0145       private:
0146         std::string label_;
0147         VUint32 seeds_;
0148         edm::propagate_const<std::shared_ptr<CLHEP::HepRandomEngine>> engine_;
0149       };
0150 
0151       // This class exists because it is faster to lookup a module using
0152       // the moduleID (an integer) than the label (a string). There is a
0153       // one to one association between LabelAndEngine objects and ModuleIDToEngine objects.
0154       class ModuleIDToEngine {
0155       public:
0156         ModuleIDToEngine(LabelAndEngine* theLabelAndEngine, unsigned int theModuleID)
0157             : engineState_(), labelAndEngine_(theLabelAndEngine), moduleID_(theModuleID) {}
0158 
0159         std::vector<unsigned long> const& engineState() const { return engineState_; }
0160         LabelAndEngine const* labelAndEngine() const { return get_underlying_safe(labelAndEngine_); }
0161         LabelAndEngine*& labelAndEngine() { return get_underlying_safe(labelAndEngine_); }
0162         unsigned int moduleID() const { return moduleID_; }
0163         void setEngineState(std::vector<unsigned long> const& v) { engineState_ = v; }
0164         // Used to sort so binary lookup can be used on a container of these.
0165         bool operator<(ModuleIDToEngine const& r) const { return moduleID() < r.moduleID(); }
0166 
0167       private:
0168         std::vector<unsigned long> engineState_;  // Used only for check in stream transitions
0169         edm::propagate_const<LabelAndEngine*> labelAndEngine_;
0170         unsigned int moduleID_;
0171       };
0172 
0173       void preModuleStreamCheck(StreamContext const& sc, ModuleCallingContext const& mcc);
0174       void postModuleStreamCheck(StreamContext const& sc, ModuleCallingContext const& mcc);
0175 
0176       void readFromLuminosityBlock(LuminosityBlock const& lumi);
0177       void readFromEvent(Event const& event);
0178 
0179       void snapShot(std::vector<LabelAndEngine> const& engines, std::vector<RandomEngineState>& cache);
0180       void restoreFromCache(std::vector<RandomEngineState> const& cache, std::vector<LabelAndEngine>& engines);
0181 
0182       void checkEngineType(std::string const& typeFromConfig,
0183                            std::string const& typeFromEvent,
0184                            std::string const& engineLabel) const;
0185 
0186       void saveStatesToFile(std::string const& fileName,
0187                             StreamID const& streamID,
0188                             LuminosityBlockIndex const& lumiIndex);
0189       void writeStates(std::vector<RandomEngineState> const& v, std::ofstream& outFile);
0190       void writeVector(VUint32 const& v, std::ofstream& outFile);
0191       std::string constructSaveFileName() const;
0192 
0193       void readEventStatesFromTextFile(std::string const& fileName, std::vector<RandomEngineState>& cache);
0194       void readLumiStatesFromTextFile(std::string const& fileName, std::vector<RandomEngineState>& cache);
0195       void readStatesFromFile(std::string const& fileName,
0196                               std::vector<RandomEngineState>& cache,
0197                               std::string const& whichStates);
0198       bool readEngineState(std::istream& is,
0199                            std::vector<RandomEngineState>& cache,
0200                            std::string const& whichStates,
0201                            bool& saveToCache);
0202       void readVector(std::istream& is, unsigned numItems, std::vector<std::uint32_t>& v);
0203 
0204       void createEnginesInVector(std::vector<LabelAndEngine>& engines,
0205                                  unsigned int seedOffset,
0206                                  unsigned int eventSeedOffset,
0207                                  std::vector<ModuleIDToEngine>& moduleIDVector);
0208 
0209       void resetEngineSeeds(LabelAndEngine& labelAndEngine,
0210                             std::string const& engineName,
0211                             VUint32 const& seeds,
0212                             std::uint32_t offset1,
0213                             std::uint32_t offset2);
0214 
0215       // ---------- member data --------------------------------
0216 
0217       unsigned int nStreams_;
0218 
0219       // This exists because we can look things up faster using the moduleID
0220       // than using string comparisons with the moduleLabel
0221       std::vector<std::vector<ModuleIDToEngine>> streamModuleIDToEngine_;  // streamID, sorted by moduleID
0222       std::vector<std::vector<ModuleIDToEngine>> lumiModuleIDToEngine_;    // luminosityBlockIndex, sortedByModuleID
0223 
0224       // Holds the engines, plus the seeds and module label also
0225       std::vector<std::vector<LabelAndEngine>> streamEngines_;  // streamID, sorted by label
0226       std::vector<std::vector<LabelAndEngine>> lumiEngines_;    // luminosityBlockIndex, sorted by label
0227 
0228       // These hold the input tags needed to retrieve the states
0229       // of the random number engines stored in a previous process.
0230       // If the label in the tag is the empty string (the default),
0231       // then the service does not try to restore the random numbers.
0232       edm::InputTag restoreStateTag_;
0233       edm::InputTag restoreStateBeginLumiTag_;
0234 
0235       std::vector<std::vector<RandomEngineState>> eventCache_;  // streamID, sorted by module label
0236       std::vector<std::vector<RandomEngineState>> lumiCache_;   // luminosityBlockIndex, sorted by module label
0237 
0238       // This is used to keep track of the seeds and engine name from
0239       // the configuration. The map key is the module label.
0240       // The module ID is filled in as modules are constructed.
0241       // It is left as max unsigned if the module is never constructed and not in the process
0242       class SeedsAndName {
0243       public:
0244         static constexpr unsigned int kInvalid = std::numeric_limits<unsigned int>::max();
0245 
0246         SeedsAndName(VUint32 const& theSeeds, std::string const& theEngineName)
0247             : seeds_(theSeeds), engineName_(theEngineName), moduleID_(kInvalid) {}
0248         VUint32 const& seeds() const { return seeds_; }
0249         std::string const& engineName() const { return engineName_; }
0250         unsigned int moduleID() const { return moduleID_; }
0251         void setModuleID(unsigned int v) { moduleID_ = v; }
0252 
0253       private:
0254         VUint32 seeds_;
0255         std::string engineName_;
0256         unsigned int moduleID_;
0257       };
0258       std::map<std::string, SeedsAndName> seedsAndNameMap_;
0259 
0260       // Keep the name of the file where we want to save the state
0261       // of all declared engines at the end of each event. A blank
0262       // name means don't bother.  Also, keep a record of whether
0263       // the save file name has been recorded in the job report.
0264       std::string saveFileName_;
0265       std::atomic<bool> saveFileNameRecorded_;
0266       std::vector<edm::propagate_const<std::shared_ptr<std::ofstream>>> outFiles_;  // streamID
0267 
0268       // Keep the name of the file from which we restore the state
0269       // of all declared engines at the beginning of a run. A
0270       // blank name means there isn't one.
0271       std::string restoreFileName_;
0272 
0273       // This turns on or off the checks that ensure no random
0274       // numbers are generated in a module during stream
0275       // beginStream, beginRun, endLuminosityBlock, or endRun.
0276       bool enableChecking_;
0277 
0278       std::uint32_t eventSeedOffset_;
0279       bool beginJobEndJobActive_ = false;
0280 
0281       bool verbose_;
0282 
0283       static const std::vector<std::uint32_t>::size_type maxSeeds;
0284       static const std::vector<std::uint32_t>::size_type maxStates;
0285       static const std::uint32_t maxSeedRanecu;
0286       static const std::uint32_t maxSeedHepJames;
0287       static const std::uint32_t maxSeedTRandom3;
0288     };
0289   }  // namespace service
0290 }  // namespace edm
0291 #endif