File indexing completed on 2024-10-03 05:27:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 #include "DataFormats/Provenance/interface/EventAuxiliary.h"
0058 #include "DataFormats/Provenance/interface/LuminosityBlockAuxiliary.h"
0059 #include "DataFormats/Provenance/interface/ModuleDescription.h"
0060 #include "FWCore/Framework/interface/global/EDAnalyzer.h"
0061 #include "FWCore/Framework/interface/Event.h"
0062 #include "FWCore/Framework/interface/LuminosityBlock.h"
0063 #include "FWCore/Framework/interface/MakerMacros.h"
0064 #include "FWCore/ServiceRegistry/interface/Service.h"
0065 #include "FWCore/Utilities/interface/Exception.h"
0066 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
0067 #include "FWCore/Utilities/interface/propagate_const.h"
0068 #include "IOMC/RandomEngine/interface/TRandomAdaptor.h"
0069
0070 #include "CLHEP/Random/RandExponential.h"
0071 #include "CLHEP/Random/RandomEngine.h"
0072 #include "CLHEP/Random/engineIDulong.h"
0073 #include "CLHEP/Random/JamesRandom.h"
0074 #include "CLHEP/Random/RanecuEngine.h"
0075 #include "CLHEP/Random/MixMaxRng.h"
0076
0077 #include <fstream>
0078 #include <iostream>
0079 #include <memory>
0080 #include <mutex>
0081 #include <sstream>
0082 #include <string>
0083 #include <chrono>
0084
0085 namespace {
0086 std::mutex write_mutex;
0087 }
0088
0089 class TestRandomNumberServiceStreamCache {
0090 public:
0091 TestRandomNumberServiceStreamCache() : serviceEngine_(nullptr), countEvents_(0) {}
0092 edm::propagate_const<CLHEP::HepRandomEngine*> serviceEngine_;
0093 unsigned int countEvents_;
0094 std::ofstream outFile_;
0095 std::string lastEventRandomNumbers_;
0096
0097 edm::propagate_const<std::shared_ptr<CLHEP::HepRandomEngine>> referenceEngine_;
0098 std::vector<double> referenceRandomNumbers_;
0099 };
0100
0101 class TestRandomNumberServiceLumiCache {
0102 public:
0103 TestRandomNumberServiceLumiCache() {}
0104 edm::propagate_const<std::shared_ptr<CLHEP::HepRandomEngine>> referenceEngine_;
0105 std::vector<double> referenceRandomNumbers_;
0106 };
0107
0108 class TestRandomNumberServiceGlobal
0109 : public edm::global::EDAnalyzer<edm::StreamCache<TestRandomNumberServiceStreamCache>,
0110 edm::LuminosityBlockCache<TestRandomNumberServiceLumiCache>> {
0111 public:
0112 explicit TestRandomNumberServiceGlobal(edm::ParameterSet const&);
0113 ~TestRandomNumberServiceGlobal();
0114
0115 virtual void analyze(edm::StreamID, edm::Event const&, edm::EventSetup const&) const override;
0116 virtual void beginJob() override;
0117 virtual void endJob() override;
0118
0119 virtual std::shared_ptr<TestRandomNumberServiceLumiCache> globalBeginLuminosityBlock(
0120 edm::LuminosityBlock const&, edm::EventSetup const&) const override;
0121
0122 virtual void globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) const override {}
0123
0124 virtual std::unique_ptr<TestRandomNumberServiceStreamCache> beginStream(edm::StreamID) const override;
0125 virtual void endStream(edm::StreamID) const override;
0126
0127 virtual void streamBeginRun(edm::StreamID, edm::Run const&, edm::EventSetup const&) const override;
0128 virtual void streamEndRun(edm::StreamID, edm::Run const&, edm::EventSetup const&) const override;
0129
0130 virtual void streamBeginLuminosityBlock(edm::StreamID,
0131 edm::LuminosityBlock const&,
0132 edm::EventSetup const&) const override;
0133 virtual void streamEndLuminosityBlock(edm::StreamID,
0134 edm::LuminosityBlock const&,
0135 edm::EventSetup const&) const override;
0136
0137 private:
0138 std::string engineName_;
0139 std::vector<unsigned int> seeds_;
0140 unsigned int offset_;
0141 unsigned int maxEvents_;
0142 unsigned int nStreams_;
0143 std::vector<unsigned int> skippedEvents_;
0144
0145
0146
0147
0148 std::vector<unsigned int> seedByLumi_;
0149
0150 bool multiStreamReplay_;
0151
0152
0153
0154
0155 bool dump_;
0156 };
0157
0158 TestRandomNumberServiceGlobal::TestRandomNumberServiceGlobal(edm::ParameterSet const& pset)
0159 : engineName_(pset.getUntrackedParameter<std::string>("engineName")),
0160 seeds_(pset.getUntrackedParameter<std::vector<unsigned int>>("seeds")),
0161 offset_(pset.getUntrackedParameter<unsigned int>("offset")),
0162 maxEvents_(pset.getUntrackedParameter<unsigned int>("maxEvents")),
0163 nStreams_(pset.getUntrackedParameter<unsigned int>("nStreams")),
0164 skippedEvents_(
0165 pset.getUntrackedParameter<std::vector<unsigned int>>("skippedEvents", std::vector<unsigned int>(1, 0))),
0166 seedByLumi_(pset.getUntrackedParameter<std::vector<unsigned int>>("seedByLumi", std::vector<unsigned int>(1, 0))),
0167 multiStreamReplay_(pset.getUntrackedParameter<bool>("multiStreamReplay", false)),
0168 dump_(pset.getUntrackedParameter<bool>("dump", false)) {
0169 if (dump_) {
0170 edm::Service<edm::RandomNumberGenerator> rng;
0171 bool exceptionThrown = true;
0172 try {
0173 unsigned int mySeed = rng->mySeed();
0174 std::cout << "*** TestRandomNumberServiceGlobal constructor " << mySeed << "\n";
0175 exceptionThrown = false;
0176 } catch (cms::Exception const&) {
0177 }
0178 if (not exceptionThrown) {
0179 throw cms::Exception("FailedToThrow") << "RandomNunberGenerator::mySeed did not throw";
0180 }
0181 }
0182 }
0183
0184 TestRandomNumberServiceGlobal::~TestRandomNumberServiceGlobal() {}
0185
0186 void TestRandomNumberServiceGlobal::analyze(edm::StreamID streamID,
0187 edm::Event const& event,
0188 edm::EventSetup const&) const {
0189
0190 if (nStreams_ > 1) {
0191 using namespace std::chrono_literals;
0192 std::this_thread::sleep_for(25ms);
0193 }
0194
0195 if (dump_) {
0196 edm::Service<edm::RandomNumberGenerator> rng;
0197 std::cout << "*** TestRandomNumberServiceGlobal analyze " << rng->mySeed() << " "
0198 << rng->getEngine(streamID).name() << " streamID= " << streamID
0199 << " multiStreamReplay: " << multiStreamReplay_ << "\n";
0200 }
0201
0202 TestRandomNumberServiceStreamCache* cache = streamCache(streamID);
0203
0204 assert(cache->countEvents_ < maxEvents_);
0205
0206 edm::Service<edm::RandomNumberGenerator> rng;
0207 CLHEP::HepRandomEngine& engine = rng->getEngine(streamID);
0208
0209 if (cache->serviceEngine_ != &engine) {
0210 throw cms::Exception("TestRandomNumberService")
0211 << "TestRandomNumberServiceGlobal::analyze: Engines from event and beginStream are not the same";
0212 }
0213
0214
0215 double randomNumberEvent0_ = engine.flat();
0216 double randomNumberEvent1_ = engine.flat();
0217 double randomNumberEvent2_ = engine.flat();
0218
0219
0220 CLHEP::RandExponential expDist(engine);
0221 double mean = 10.0;
0222 double randomNumberEvent3_ = expDist.fire(mean);
0223
0224 if (dump_) {
0225 std::cout << " " << engine.name() << " " << randomNumberEvent0_ << " " << randomNumberEvent1_ << " "
0226 << randomNumberEvent2_ << " " << randomNumberEvent3_ << std::endl;
0227 }
0228
0229
0230 cache->outFile_ << rng->mySeed() << "\n";
0231 cache->outFile_ << randomNumberEvent0_ << "\n";
0232 cache->outFile_ << randomNumberEvent1_ << "\n";
0233 cache->outFile_ << randomNumberEvent2_ << "\n";
0234 cache->outFile_ << randomNumberEvent3_ << "\n";
0235
0236 if (!multiStreamReplay_) {
0237
0238 if (skippedEvents_.size() == 1 && skippedEvents_[0] == 0) {
0239 if (randomNumberEvent0_ != cache->referenceRandomNumbers_.at(0 + 4 * cache->countEvents_) ||
0240 randomNumberEvent1_ != cache->referenceRandomNumbers_.at(1 + 4 * cache->countEvents_) ||
0241 randomNumberEvent2_ != cache->referenceRandomNumbers_.at(2 + 4 * cache->countEvents_) ||
0242 randomNumberEvent3_ != cache->referenceRandomNumbers_.at(3 + 4 * cache->countEvents_)) {
0243 throw cms::Exception("TestRandomNumberService")
0244 << "TestRandomNumberServiceGlobal::analyze: Random sequence does not match expected sequence";
0245 }
0246
0247 } else if (cache->countEvents_ < skippedEvents_.size()) {
0248 if (randomNumberEvent0_ != cache->referenceRandomNumbers_.at(
0249 0 + 4 * (cache->countEvents_ + skippedEvents_.at(cache->countEvents_))) ||
0250 randomNumberEvent1_ != cache->referenceRandomNumbers_.at(
0251 1 + 4 * (cache->countEvents_ + skippedEvents_.at(cache->countEvents_))) ||
0252 randomNumberEvent2_ != cache->referenceRandomNumbers_.at(
0253 2 + 4 * (cache->countEvents_ + skippedEvents_.at(cache->countEvents_))) ||
0254 randomNumberEvent3_ != cache->referenceRandomNumbers_.at(
0255 3 + 4 * (cache->countEvents_ + skippedEvents_.at(cache->countEvents_)))) {
0256 throw cms::Exception("TestRandomNumberService")
0257 << "TestRandomNumberServiceGlobal::analyze: Random sequence does not match expected sequence";
0258 }
0259 }
0260 }
0261
0262
0263
0264
0265 {
0266 std::ostringstream ss;
0267 ss << moduleDescription().moduleLabel() << " ";
0268 ss << engine.name() << " ";
0269 ss << "Last event random numbers ";
0270 ss << randomNumberEvent0_ << " ";
0271 ss << randomNumberEvent1_ << " ";
0272 ss << randomNumberEvent2_ << " ";
0273 ss << randomNumberEvent3_ << "\n";
0274 cache->lastEventRandomNumbers_ = ss.str();
0275 }
0276
0277
0278 if (nStreams_ > 1) {
0279 {
0280 std::lock_guard<std::mutex> lock(write_mutex);
0281 std::ostringstream ss;
0282 if (multiStreamReplay_) {
0283 ss << "replay";
0284 }
0285 ss << "testRandomServiceL" << event.eventAuxiliary().luminosityBlock() << "E" << event.eventAuxiliary().event()
0286 << ".txt";
0287 std::string filename = ss.str();
0288
0289 std::ofstream outFile;
0290 outFile.open(filename.c_str(), std::ofstream::app);
0291
0292 outFile << moduleDescription().moduleLabel() << " ";
0293 outFile << engine.name() << " ";
0294
0295 outFile << "Event random numbers ";
0296 outFile << randomNumberEvent0_ << " ";
0297 outFile << randomNumberEvent1_ << " ";
0298 outFile << randomNumberEvent2_ << " ";
0299 outFile << randomNumberEvent3_ << "\n";
0300
0301 outFile.close();
0302 }
0303 }
0304
0305 ++cache->countEvents_;
0306 }
0307
0308 void TestRandomNumberServiceGlobal::beginJob() {
0309 if (dump_) {
0310 bool exceptionThrown = true;
0311 try {
0312 edm::Service<edm::RandomNumberGenerator> rng;
0313 unsigned int mySeed = rng->mySeed();
0314 std::cout << "*** TestRandomNumberServiceGlobal beginJob " << mySeed << "\n";
0315 exceptionThrown = false;
0316 } catch (cms::Exception const&) {
0317 }
0318 if (not exceptionThrown) {
0319 throw cms::Exception("FailedToThrow") << "RandomNunberGenerator::mySeed did not throw";
0320 }
0321 }
0322 }
0323
0324 void TestRandomNumberServiceGlobal::endJob() {
0325 if (dump_) {
0326 bool exceptionThrown = true;
0327 try {
0328 edm::Service<edm::RandomNumberGenerator> rng;
0329 unsigned int mySeed = rng->mySeed();
0330 std::cout << "*** TestRandomNumberServiceGlobal endJob " << mySeed << "\n";
0331 exceptionThrown = false;
0332 } catch (cms::Exception const&) {
0333 }
0334 if (not exceptionThrown) {
0335 throw cms::Exception("FailedToThrow") << "RandomNunberGenerator::mySeed did not throw";
0336 }
0337 }
0338 }
0339
0340 std::shared_ptr<TestRandomNumberServiceLumiCache> TestRandomNumberServiceGlobal::globalBeginLuminosityBlock(
0341 edm::LuminosityBlock const& lumi, edm::EventSetup const& iES) const {
0342 if (dump_) {
0343 edm::Service<edm::RandomNumberGenerator> rng;
0344 std::cout << "*** TestRandomNumberServiceGlobal beginLuminosityBlock " << rng->mySeed() << " "
0345 << rng->getEngine(lumi.index()).name() << "\n";
0346 }
0347
0348 auto lumiCache = std::make_shared<TestRandomNumberServiceLumiCache>();
0349
0350 unsigned int seed0 = seeds_.at(0) + nStreams_;
0351 if (lumi.luminosityBlockAuxiliary().luminosityBlock() < seedByLumi_.size()) {
0352 seed0 = seedByLumi_.at(lumi.luminosityBlockAuxiliary().luminosityBlock());
0353 }
0354
0355 if (engineName_ == "RanecuEngine") {
0356 lumiCache->referenceEngine_ = std::shared_ptr<CLHEP::HepRandomEngine>(
0357 new CLHEP::RanecuEngine());
0358 long int seedL[2];
0359 seedL[0] = static_cast<long int>(seed0);
0360 seedL[1] = static_cast<long int>(seeds_.at(1));
0361 lumiCache->referenceEngine_->setSeeds(seedL, 0);
0362 } else {
0363 long int seedL = static_cast<long int>(seed0);
0364 if (engineName_ == "HepJamesRandom") {
0365 lumiCache->referenceEngine_ = std::shared_ptr<CLHEP::HepRandomEngine>(
0366 new CLHEP::HepJamesRandom(seedL));
0367 } else if (engineName_ == "MixMaxRng") {
0368 lumiCache->referenceEngine_ = std::shared_ptr<CLHEP::HepRandomEngine>(
0369 new CLHEP::MixMaxRng(seedL));
0370 } else {
0371 lumiCache->referenceEngine_ = std::shared_ptr<CLHEP::HepRandomEngine>(
0372 new edm::TRandomAdaptor(seedL));
0373 }
0374 }
0375
0376 double y1 = lumiCache->referenceEngine_->flat();
0377 double y2 = lumiCache->referenceEngine_->flat();
0378
0379 edm::Service<edm::RandomNumberGenerator> rng;
0380 CLHEP::HepRandomEngine& engine = rng->getEngine(lumi.index());
0381 std::unique_ptr<CLHEP::HepRandomEngine> engineClone = rng->cloneEngine(lumi.index());
0382
0383 double x1 = engine.flat();
0384 double x2 = engine.flat();
0385
0386 if (x1 != y1 || x2 != y2) {
0387 throw cms::Exception("TestRandomNumberService")
0388 << "TestRandomNumberServiceGlobal::globalBeginLuminosityBlock: "
0389 << " x1= " << x1 << " y1= " << y1 << " x2= " << x2 << " y2= " << y2 << " " << engine.name() << " "
0390 << lumiCache->referenceEngine_->name() << " seed0= " << seed0 << " nStream= " << nStreams_;
0391 }
0392
0393 double z1 = engineClone->flat();
0394 double z2 = engineClone->flat();
0395 if (x1 != z1 || x2 != z2 || engine.getSeed() != engineClone->getSeed()) {
0396 throw cms::Exception("TestRandomNumberService")
0397 << "TestRandomNumberServiceGlobal::globalBeginLuminosityBlock: test of cloned engine failed "
0398 << " x1= " << x1 << " z1= " << z1 << " x2= " << x2 << " z2= " << z2 << " " << engine.name() << " "
0399 << engineClone->name() << " seed0= " << seed0 << " nStream= " << nStreams_;
0400 }
0401 return lumiCache;
0402 }
0403
0404 std::unique_ptr<TestRandomNumberServiceStreamCache> TestRandomNumberServiceGlobal::beginStream(
0405 edm::StreamID streamID) const {
0406 auto streamCache = std::make_unique<TestRandomNumberServiceStreamCache>();
0407
0408 edm::Service<edm::RandomNumberGenerator> rng;
0409 CLHEP::HepRandomEngine& engine = rng->getEngine(streamID);
0410
0411
0412
0413
0414
0415 streamCache->serviceEngine_ = &engine;
0416
0417 std::ostringstream suffix;
0418 suffix << "_" << streamID.value() << "_" << moduleDescription().moduleLabel();
0419 std::string outFileName = std::string("testRandomService") + suffix.str() + std::string(".txt");
0420 streamCache->outFile_.open(outFileName.c_str(), std::ofstream::out);
0421
0422 if (engineName_ == "RanecuEngine") {
0423 streamCache->referenceEngine_ = std::shared_ptr<CLHEP::HepRandomEngine>(
0424 new CLHEP::RanecuEngine());
0425 long int seedL[2];
0426 seedL[0] = static_cast<long int>(seeds_.at(0) + streamID.value() + offset_);
0427 seedL[1] = static_cast<long int>(seeds_.at(1));
0428 streamCache->referenceEngine_->setSeeds(seedL, 0);
0429 } else {
0430 long int seedL = static_cast<long int>(seeds_.at(0) + streamID.value() + offset_);
0431 if (engineName_ == "HepJamesRandom") {
0432 streamCache->referenceEngine_ = std::shared_ptr<CLHEP::HepRandomEngine>(
0433 new CLHEP::HepJamesRandom(seedL));
0434 } else if (engineName_ == "MixMaxRng") {
0435 streamCache->referenceEngine_ = std::shared_ptr<CLHEP::HepRandomEngine>(
0436 new CLHEP::MixMaxRng(seedL));
0437 } else {
0438 streamCache->referenceEngine_ = std::shared_ptr<CLHEP::HepRandomEngine>(
0439 new edm::TRandomAdaptor(seedL));
0440 }
0441 }
0442
0443 for (unsigned int i = 0; i < maxEvents_; ++i) {
0444 streamCache->referenceRandomNumbers_.push_back(streamCache->referenceEngine_->flat());
0445 streamCache->referenceRandomNumbers_.push_back(streamCache->referenceEngine_->flat());
0446 streamCache->referenceRandomNumbers_.push_back(streamCache->referenceEngine_->flat());
0447 CLHEP::RandExponential expDist(*streamCache->referenceEngine_);
0448 double mean = 10.0;
0449 streamCache->referenceRandomNumbers_.push_back(expDist.fire(mean));
0450 }
0451 return streamCache;
0452 }
0453
0454 void TestRandomNumberServiceGlobal::endStream(edm::StreamID streamID) const {
0455 TestRandomNumberServiceStreamCache* cache = streamCache(streamID);
0456
0457 std::ostringstream ss;
0458 if (multiStreamReplay_) {
0459 ss << "replay";
0460 }
0461 ss << "stream" << streamID.value() << "LastEvent.txt";
0462 std::string filename = ss.str();
0463
0464 std::ofstream outFile;
0465 {
0466 std::lock_guard<std::mutex> lock(write_mutex);
0467 outFile.open(filename.c_str(), std::ofstream::app);
0468 outFile << cache->lastEventRandomNumbers_;
0469 outFile.close();
0470 }
0471
0472
0473
0474
0475
0476
0477 }
0478
0479 void TestRandomNumberServiceGlobal::streamBeginRun(edm::StreamID streamID,
0480 edm::Run const&,
0481 edm::EventSetup const&) const {
0482
0483
0484
0485
0486
0487 }
0488
0489 void TestRandomNumberServiceGlobal::streamEndRun(edm::StreamID streamID,
0490 edm::Run const&,
0491 edm::EventSetup const&) const {
0492
0493
0494
0495
0496
0497 }
0498
0499 void TestRandomNumberServiceGlobal::streamBeginLuminosityBlock(edm::StreamID streamID,
0500 edm::LuminosityBlock const&,
0501 edm::EventSetup const&) const {
0502
0503
0504
0505
0506
0507 }
0508
0509 void TestRandomNumberServiceGlobal::streamEndLuminosityBlock(edm::StreamID streamID,
0510 edm::LuminosityBlock const&,
0511 edm::EventSetup const&) const {
0512
0513
0514
0515
0516
0517 }
0518
0519
0520 DEFINE_FWK_MODULE(TestRandomNumberServiceGlobal);