From 8556d3137045af6a137cc8f865ede3849b2cc924 Mon Sep 17 00:00:00 2001 From: Lisa Goodenough Date: Thu, 17 Dec 2020 09:59:03 -0600 Subject: [PATCH] RNs seeds in G4MT are now handled by us. We use Crypto++ to create hashes for seeds based on art::event ID (Run#, Subrun#, Event#). --- Mu2eG4/inc/Mu2eG4Config.hh | 2 + Mu2eG4/inc/Mu2eG4MTRunManager.hh | 5 +- Mu2eG4/inc/Mu2eG4WorkerRunManager.hh | 7 +- Mu2eG4/src/Mu2eG4MTRunManager.cc | 62 +------------- Mu2eG4/src/Mu2eG4MT_module.cc | 8 +- Mu2eG4/src/Mu2eG4WorkerRunManager.cc | 122 +++++++++++++-------------- Mu2eG4/src/SConscript | 7 +- setup.sh | 9 +- 8 files changed, 87 insertions(+), 135 deletions(-) diff --git a/Mu2eG4/inc/Mu2eG4Config.hh b/Mu2eG4/inc/Mu2eG4Config.hh index ac0e616b8c..3957680977 100644 --- a/Mu2eG4/inc/Mu2eG4Config.hh +++ b/Mu2eG4/inc/Mu2eG4Config.hh @@ -203,6 +203,8 @@ namespace mu2e { fhicl::Atom generatorModuleLabel {Name("generatorModuleLabel"), ""}; + fhicl::Atom salt {Name("salt"), ""}; + fhicl::Atom G4InteralFiltering {Name("G4InteralFiltering"), false}; }; } diff --git a/Mu2eG4/inc/Mu2eG4MTRunManager.hh b/Mu2eG4/inc/Mu2eG4MTRunManager.hh index 3b2a5446a3..6e206f77ae 100644 --- a/Mu2eG4/inc/Mu2eG4MTRunManager.hh +++ b/Mu2eG4/inc/Mu2eG4MTRunManager.hh @@ -37,10 +37,7 @@ namespace mu2e { void initializeMasterRunAction(); void stopG4(); void terminateRun(); - - G4bool SetUpAnEvent(G4Event* evt, - long& s1, long& s2, long& s3, - G4bool reseedRequired); + G4bool SetUpEvent(); inline G4VUserPhysicsList* getMasterPhysicsList() {return physicsList_;} diff --git a/Mu2eG4/inc/Mu2eG4WorkerRunManager.hh b/Mu2eG4/inc/Mu2eG4WorkerRunManager.hh index 05000f39ad..32a747a68e 100644 --- a/Mu2eG4/inc/Mu2eG4WorkerRunManager.hh +++ b/Mu2eG4/inc/Mu2eG4WorkerRunManager.hh @@ -49,9 +49,9 @@ namespace mu2e { void initializeThread(Mu2eG4MTRunManager* mRM, const G4ThreeVector& origin_in_world); void initializeUserActions(const G4ThreeVector& origin_in_world); - void initializeRun(art::Event* art_event); - void processEvent(art::Event*); - G4Event* generateEvt(G4int i_event); + void initializeRun(art::Event* const art_event); + void processEvent(art::EventID); + G4Event* generateEvt(art::EventID); inline bool workerRMInitialized() const { return m_managerInitialized; } @@ -67,6 +67,7 @@ namespace mu2e { bool m_steppingVerbose; int m_mtDebugOutput; int rmvlevel_; + std::string salt_; std::unique_ptr perThreadObjects_; diff --git a/Mu2eG4/src/Mu2eG4MTRunManager.cc b/Mu2eG4/src/Mu2eG4MTRunManager.cc index adb2b5d9e4..f0c2d54d0d 100644 --- a/Mu2eG4/src/Mu2eG4MTRunManager.cc +++ b/Mu2eG4/src/Mu2eG4MTRunManager.cc @@ -116,49 +116,13 @@ namespace mu2e { StoreRNGStatus(fileN); } - ///////////////////////////////////////////////////////////////////////////////////// - //RANDOM NUMBER SEEDING SetEventModulo(1);//this sets eventModuloDef - int seedbunchsize = 10000; - int numworkers = 1; numberOfEventToBeProcessed = std::numeric_limits::max(); numberOfEventProcessed = 0; - nSeedsUsed = 0; - nSeedsFilled = 0; - if(verboseLevel>0) { timer->Start(); } - //if we are using G4's seed filling scheme - if ( InitializeSeeds(seedbunchsize) == false && seedbunchsize>0 ) { - - G4RNGHelper* helper = G4RNGHelper::GetInstance(); - switch(seedOncePerCommunication) - { - case 0://default value - nSeedsFilled = seedbunchsize; - break; - case 1: - nSeedsFilled = numworkers; - break; - case 2: - nSeedsFilled = seedbunchsize/eventModulo + 1; - break; - default: - G4ExceptionDescription msgd; - msgd << "Parameter value <" << seedOncePerCommunication - << "> of seedOncePerCommunication is invalid. It is reset to 0." ; - G4Exception("G4MTRunManager::InitializeEventLoop()", "Run10036", JustWarning, msgd); - seedOncePerCommunication = 0; - nSeedsFilled = seedbunchsize; - } - - // Generates up to nSeedsMax seed pairs only. - if(nSeedsFilled>nSeedsMax) nSeedsFilled=nSeedsMax; - const_cast(getMasterRandomEngine())->flatArray(nSeedsPerEvent*nSeedsFilled,randDbl); - helper->Fill(randDbl,nSeedsFilled,seedbunchsize,nSeedsPerEvent); - } }//Mu2eG4MTRunManager::initializeG4 @@ -167,8 +131,7 @@ namespace mu2e { void Mu2eG4MTRunManager::initializeKernelAndRM() { G4RunManager::Initialize(); - G4MTRunManager::GetMTMasterRunManagerKernel()->SetUpDecayChannels();//note, this is usually done in - //InitializeEventLoop + G4MTRunManager::GetMTMasterRunManagerKernel()->SetUpDecayChannels();//usually done in //InitializeEventLoop if ( userWorkerThreadInitialization == 0 ) { userWorkerThreadInitialization = new G4UserWorkerThreadInitialization(); } @@ -248,30 +211,13 @@ namespace mu2e { m_runTerminated = true; } - G4bool Mu2eG4MTRunManager::SetUpAnEvent(G4Event* evt, long& s1, long& s2, long& s3, - G4bool reseedRequired) { - - G4AutoLock l(&setUpEventMutex); - + G4bool Mu2eG4MTRunManager::SetUpEvent() { + if( numberOfEventProcessed < numberOfEventToBeProcessed ) { - - if(reseedRequired) { - G4RNGHelper* helper = G4RNGHelper::GetInstance(); - G4int idx_rndm = nSeedsPerEvent*(evt->GetEventID()-1); - s1 = helper->GetSeed(idx_rndm); - s2 = helper->GetSeed(idx_rndm+1); - if(nSeedsPerEvent==3) s3 = helper->GetSeed(idx_rndm+2); - nSeedsUsed++; - //G4cout << "nSeedsUsed = " << nSeedsUsed << ", nSeedsFilled = " << nSeedsFilled << "\n"; - if(nSeedsUsed==nSeedsFilled) { - RefillSeeds(); - //G4cout << "Refilling Seeds\n"; - } - } numberOfEventProcessed++; return true; } - + return false; } diff --git a/Mu2eG4/src/Mu2eG4MT_module.cc b/Mu2eG4/src/Mu2eG4MT_module.cc index 16bc64d46f..a157c4efe6 100644 --- a/Mu2eG4/src/Mu2eG4MT_module.cc +++ b/Mu2eG4/src/Mu2eG4MT_module.cc @@ -361,7 +361,7 @@ namespace mu2e { Mu2eG4WorkerRunManager* scheduleWorkerRM = (access_workerMap->second).get(); access_workerMap.release(); - if (_mtDebugOutput > 0){ + if (_mtDebugOutput > 1){ G4cout << "FOR SchedID: " << schedID << ", TID=" << tid << ", workerRunManagers[schedID].get() is:" << scheduleWorkerRM << "\n"; } @@ -373,9 +373,9 @@ namespace mu2e { Mu2eG4PerThreadStorage* perThreadStore = scheduleWorkerRM->getMu2eG4PerThreadStorage(); perThreadStore->initializeEventInfo(&event, &spHelper, &parentHelper, &genInputHits, _generatorModuleLabel); - scheduleWorkerRM->processEvent(&event); + scheduleWorkerRM->processEvent(event.id()); - if (_mtDebugOutput > 0){ + if (_mtDebugOutput > 2){ G4cout << "Current Event in RM is: " << scheduleWorkerRM->GetCurrentEvent()->GetEventID() << "\n"; } @@ -418,7 +418,7 @@ namespace mu2e { // Tell G4 that this run is over. void Mu2eG4MT::endRun(art::Run & run, art::ProcessingFrame const& procFrame) { - if (_mtDebugOutput > 1){ + if (_mtDebugOutput > 0){ G4cout << "At endRun pt1, we have " << myworkerRunManagerMap.size() << " members in the map " << "and are running " << num_threads << " threads.\n" ; } diff --git a/Mu2eG4/src/Mu2eG4WorkerRunManager.cc b/Mu2eG4/src/Mu2eG4WorkerRunManager.cc index 65ebf652ef..04d66726b0 100644 --- a/Mu2eG4/src/Mu2eG4WorkerRunManager.cc +++ b/Mu2eG4/src/Mu2eG4WorkerRunManager.cc @@ -40,22 +40,37 @@ #include "G4HadronicProcessStore.hh" //Other includes -#include "CLHEP/Random/JamesRandom.h" +#include #include +#include "CLHEP/Random/JamesRandom.h" +//Crypto++ includes +#include "sha3.h" +#include "hex.h" +#include "files.h" using namespace std; namespace { - std::atomic thread_counter{0}; - + atomic thread_counter{0}; int get_new_thread_index() { return thread_counter++; } - thread_local int s_thread_index = get_new_thread_index(); - int getThreadIndex() { return s_thread_index; } - - + + + string CryptoPP_Hash(const string msg){ + + CryptoPP::SHA3_224 hash; + string digest, str_hex; + + //digest is 56 hex numbers, or 28 pairs of hex numbers = 28 bytes + //compute the digest and keep 8 bytes of it + CryptoPP::StringSource(msg, true, new CryptoPP::HashFilter(hash, new CryptoPP::StringSink(digest), false, 8)); + CryptoPP::CRYPTOPP_DLL HexEncoder encoder_out(new CryptoPP::StringSink(str_hex)); + CryptoPP::StringSource(digest, true, new CryptoPP::Redirector(encoder_out)); + return str_hex; + } + } namespace mu2e { @@ -63,14 +78,15 @@ namespace mu2e { // If the c'tor is called a second time, the c'tor of base will // generate an exception. - Mu2eG4WorkerRunManager::Mu2eG4WorkerRunManager(const Mu2eG4Config::Top& conf, std::thread::id worker_ID): + Mu2eG4WorkerRunManager::Mu2eG4WorkerRunManager(const Mu2eG4Config::Top& conf, thread::id worker_ID): G4WorkerRunManager(), conf_(conf), m_managerInitialized(false), m_steppingVerbose(true), m_mtDebugOutput(conf.debug().mtDebugOutput()), rmvlevel_(conf.debug().diagLevel()), - perThreadObjects_(std::make_unique()), + salt_(conf.salt()), + perThreadObjects_(make_unique()), masterRM(nullptr), workerID_(worker_ID), mu2elimits_(conf.ResourceLimits()), @@ -84,15 +100,15 @@ namespace mu2e { steppingCuts_(createMu2eG4Cuts(conf.Mu2eG4SteppingOnlyCut.get(), mu2elimits_)), commonCuts_(createMu2eG4Cuts(conf.Mu2eG4CommonCut.get(), mu2elimits_)) { + if (m_mtDebugOutput > 0) { G4cout << "WorkerRM on thread " << workerID_ << " is being created\n!"; - //to see random number seeds for each event and other verbosity, uncomment this - SetPrintProgress(1); } } // Destructor of base is called automatically. No need to do anything. Mu2eG4WorkerRunManager::~Mu2eG4WorkerRunManager(){ + if (m_mtDebugOutput > 0) { G4cout << "WorkerRM on thread " << workerID_ << " is being destroyed\n!"; } @@ -112,22 +128,6 @@ namespace mu2e { const CLHEP::HepRandomEngine* masterEngine = masterRM->getMasterRandomEngine(); masterRM->GetUserWorkerThreadInitialization()->SetupRNGEngine(masterEngine); - //perThreadObjects_->UserActionInit->InitializeSteppingVerbose() - if(m_steppingVerbose) { - - //if(masterRM->GetUserActionInitialization()) - //{ - // G4VSteppingVerbose* sv = masterRM->GetUserActionInitialization()->InitializeSteppingVerbose(); - // if ( sv ) { G4VSteppingVerbose::SetInstance(sv); } - //} - - //WE CANNOT INSTANTIATE THIS ONE RIGHT NOW SINCE WE ALREADY HAVE ONE - //perThreadObjects_->steppingVerbose = new SteppingVerbose(); - //SteppingVerbose* sv = perThreadObjects_->steppingVerbose; - //if (sv) - // SteppingVerbose::SetInstance(sv); - } - // Initialize worker part of shared resources (geometry, physics) G4WorkerThread::BuildGeometryAndPhysicsVector(); @@ -217,7 +217,8 @@ namespace mu2e { } - void Mu2eG4WorkerRunManager::initializeRun(art::Event* art_event){ + + void Mu2eG4WorkerRunManager::initializeRun(art::Event* const art_event){ perThreadObjects_->currentRunNumber = art_event->id().run(); @@ -243,7 +244,7 @@ namespace mu2e { if(fSDM) currentRun->SetHCtable(fSDM->GetHCtable()); - std::ostringstream oss; + ostringstream oss; G4Random::saveFullState(oss); randomNumberStatusForThisRun = oss.str(); currentRun->SetRandomNumberStatus(randomNumberStatusForThisRun); @@ -261,7 +262,7 @@ namespace mu2e { if(storeRandomNumberStatus) { G4String fileN = "currentRun"; if ( rngStatusEventsFlag ) { - std::ostringstream os; + ostringstream os; os << "run" << currentRun->GetRunID(); fileN = os.str(); } @@ -275,34 +276,29 @@ namespace mu2e { } - void Mu2eG4WorkerRunManager::processEvent(art::Event* event){ + void Mu2eG4WorkerRunManager::processEvent(art::EventID evtID){ numberOfEventToBeProcessed = 1; - runIsSeeded = false; eventLoopOnGoing = true; - G4int i_event = event->id().event(); - - // below code is from ProcessOneEvent(i_event); - currentEvent = generateEvt(i_event); - if(eventLoopOnGoing) { - eventManager->ProcessOneEvent(currentEvent); - AnalyzeEvent(currentEvent); - UpdateScoring(); - } + //below code is from ProcessOneEvent(i_event); + currentEvent = generateEvt(evtID); + + if(eventLoopOnGoing) { + eventManager->ProcessOneEvent(currentEvent); + AnalyzeEvent(currentEvent); + UpdateScoring(); + } } - G4Event* Mu2eG4WorkerRunManager::generateEvt(G4int i_event){ + G4Event* Mu2eG4WorkerRunManager::generateEvt(art::EventID evtID){ - G4Event* anEvent = new G4Event(i_event); - long s1 = 0; - long s2 = 0; - long s3 = 0; + G4Event* anEvent = new G4Event(evtID.event()); G4bool eventHasToBeSeeded = true; - eventLoopOnGoing = G4MTRunManager::GetMasterRunManager()->SetUpAnEvent(anEvent,s1,s2,s3,eventHasToBeSeeded); + eventLoopOnGoing = masterRM->SetUpEvent(); runIsSeeded = true; if(!eventLoopOnGoing) @@ -313,14 +309,26 @@ namespace mu2e { if(eventHasToBeSeeded) { - long seeds[3] = { s1, s2, 0 }; + string msg = "r" + to_string(evtID.run()) + "s" + to_string(evtID.subRun()) + "e" + to_string(evtID.event()) + salt_; + string hash_out = CryptoPP_Hash(msg); + vector randnumstrings = {hash_out.substr(0,8), hash_out.substr(8,8)}; + + long rn1 = stol(randnumstrings[0],nullptr,16); + long rn2 = stol(randnumstrings[1],nullptr,16); + long seeds[3] = { rn1, rn2, 0 }; G4Random::setTheSeeds(seeds,-1); runIsSeeded = true; + + if(m_mtDebugOutput > 1) { + G4cout << "--> Event " << anEvent->GetEventID() << " starts with initial seeds (" + << rn1 << "," << rn2 << ")." << G4endl; + } + } //This is the filename base constructed from run and event const auto filename = [&] { - std::ostringstream os; + ostringstream os; os << "run" << currentRun->GetRunID() << "evt" << anEvent->GetEventID(); return os.str(); }; @@ -328,10 +336,10 @@ namespace mu2e { G4bool RNGstatusReadFromFile = false; if ( readStatusFromFile ) { //Build full path of RNG status file for this event - std::ostringstream os; + ostringstream os; os << filename() << ".rndm"; const G4String& randomStatusFile = os.str(); - std::ifstream ifile(randomStatusFile.c_str()); + ifstream ifile(randomStatusFile.c_str()); if ( ifile ) { //File valid and readable RNGstatusReadFromFile = true; G4Random::restoreEngineStatus(randomStatusFile.c_str()); @@ -340,7 +348,7 @@ namespace mu2e { if(storeRandomNumberStatusToG4Event==1 || storeRandomNumberStatusToG4Event==3) { - std::ostringstream oss; + ostringstream oss; G4Random::saveFullState(oss); randomNumberStatusForThisEvent = oss.str(); anEvent->SetRandomNumberStatus(randomNumberStatusForThisEvent); @@ -353,15 +361,7 @@ namespace mu2e { } StoreRNGStatus(fileN); } - - if(printModulo > 0 && anEvent->GetEventID()%printModulo == 0 ) { - G4cout << "--> Event " << anEvent->GetEventID() << " starts"; - if(eventHasToBeSeeded) { - G4cout << " with initial seeds (" << s1 << "," << s2 << ")"; - } - G4cout << "." << G4endl; - } - + userPrimaryGeneratorAction->GeneratePrimaries(anEvent); return anEvent; diff --git a/Mu2eG4/src/SConscript b/Mu2eG4/src/SConscript index 6bdc846175..1b30248e38 100644 --- a/Mu2eG4/src/SConscript +++ b/Mu2eG4/src/SConscript @@ -19,7 +19,10 @@ helper=mu2e_helper(env) g4inc = os.environ['G4INCLUDE'] + '/Geant4' g4libdir = os.environ['G4LIB'] -g4LibInc = [ '-L'+g4libdir, '-I'+g4inc ] +g4LibInc = [ '-L'+g4libdir, '-I'+g4inc] +cryptoppinc = os.environ['CRYPTOPP_INC'] +cryptopplibdir = os.environ['CRYPTOPP_LIB'] +g4LibInc = [ '-L'+g4libdir, '-I'+g4inc, '-L'+cryptopplibdir, '-I'+cryptoppinc ] g4_version = os.environ['GEANT4_VERSION'] g4_version=g4_version.replace('_','') if g4_version[2] == '9': @@ -255,6 +258,7 @@ mainlib = helper.make_mainlib ( [ 'boost_system', 'tbb', 'pthread', + 'libcryptopp', ], [ G4CPPFLAGS, G4GS_CPPFLAGS, G4GV_CPPFLAGS ], [ g4LibInc, vgcLibInc ] @@ -293,6 +297,7 @@ helper.make_plugins( [ 'boost_system', 'tbb', 'pthread', + 'libcryptopp', ], [], [ G4CPPFLAGS, G4GS_CPPFLAGS, G4GV_CPPFLAGS ], diff --git a/setup.sh b/setup.sh index d28b41b617..b89441474d 100755 --- a/setup.sh +++ b/setup.sh @@ -103,7 +103,7 @@ build=$($MU2E_BASE_RELEASE/buildopts --build) # and is therefore different from the value shown in # SETUP_ environment vars, or by the "ups active" command. export MU2E_UPS_QUALIFIERS=+e20:+${build} -export MU2E_ART_SQUALIFIER=s104 +export MU2E_ART_SQUALIFIER=s101 MU2E_G4_GRAPHICS_QUALIFIER='' if [[ $($MU2E_BASE_RELEASE/buildopts --g4vis) == qt ]]; then @@ -124,7 +124,7 @@ export MU2E_G4_EXTRA_QUALIFIER='' # Setup the framework and its dependent products setup -B art v3_06_03 -q${MU2E_UPS_QUALIFIERS} -setup -B art_root_io v1_05_00 -q${MU2E_UPS_QUALIFIERS} +setup -B art_root_io v1_04_03 -q${MU2E_UPS_QUALIFIERS} # Geant4 and its cross-section files. if [[ $($MU2E_BASE_RELEASE/buildopts --trigger) == "off" ]]; then @@ -134,13 +134,14 @@ else fi # Get access to raw data formats. -setup -B mu2e_artdaq_core v1_05_03 -q${MU2E_UPS_QUALIFIERS}:+${MU2E_ART_SQUALIFIER}:offline +setup -B mu2e_artdaq_core v1_05_00 -q${MU2E_UPS_QUALIFIERS}:+${MU2E_ART_SQUALIFIER}:offline setup -B heppdt v03_04_02 -q${MU2E_UPS_QUALIFIERS} -setup -B BTrk v1_02_29 -q${MU2E_UPS_QUALIFIERS}:p383b +setup -B BTrk v1_02_28 -q${MU2E_UPS_QUALIFIERS}:p383b setup -B cry v1_7n -q${MU2E_UPS_QUALIFIERS} setup -B gsl v2_6a setup curl v7_64_1 +setup cryptopp v08_02_00 -q${MU2E_UPS_QUALIFIERS} # The build system. setup -B scons v3_1_2 -q +p383b