NuRandomService_service.cc
Go to the documentation of this file.
1 /**
2  * @file NuRandomService_service.cc
3  * @brief Assists in the distribution of guaranteed unique seeds to all engines within a job.
4  * @author Rob Kutschke (kutschke@fnal.gov)
5  * @see NuRandomService.h SeedMaster.h
6  */
7 
8 // NuRandomService header
9 #include "nutools/RandomUtils/NuRandomService.h"
10 
11 // Art include files
20 
21 // Supporting library include files
23 
24 // CLHEP libraries
25 #include "CLHEP/Random/RandomEngine.h" // CLHEP::HepRandomEngine
26 
27 // C++ include files
28 #include <iostream>
29 #include <iomanip>
30 
31 namespace rndm {
32 
33  //----------------------------------------------------------------------------
35  (fhicl::ParameterSet const& paramSet, art::ActivityRegistry& iRegistry)
36  : seeds(paramSet)
37  , state()
38  , verbosity(paramSet.get<int>("verbosity", 0))
39  , bPrintEndOfJobSummary(paramSet.get<bool>("endOfJobSummary",false))
40  {
42 
43  // Register callbacks.
48  iRegistry.sPreProcessEvent.watch (this, &NuRandomService::preProcessEvent );
49  iRegistry.sPreModule.watch (this, &NuRandomService::preModule );
50  iRegistry.sPostModule.watch (this, &NuRandomService::postModule );
51  iRegistry.sPostProcessEvent.watch (this, &NuRandomService::postProcessEvent );
52  iRegistry.sPreModuleEndJob.watch (this, &NuRandomService::preModuleEndJob );
53  iRegistry.sPostModuleEndJob.watch (this, &NuRandomService::postModuleEndJob );
54  iRegistry.sPostEndJob.watch (this, &NuRandomService::postEndJob );
55 
56  } // NuRandomService::NuRandomService()
57 
58 
59 
60  //----------------------------------------------------------------------------
62  (std::string moduleLabel, std::string instanceName) const
63  { return { moduleLabel, instanceName }; }
64 
66  (std::string instanceName /* = "" */) const
67  { return qualify_engine_label( state.moduleLabel(), instanceName); }
68 
69  //----------------------------------------------------------------------------
71  return getSeed(qualify_engine_label());
72  } // NuRandomService::getSeed()
73 
74 
75  //----------------------------------------------------------------------------
77  return getSeed(qualify_engine_label(instanceName));
78  } // NuRandomService::getSeed(string)
79 
80 
81  //----------------------------------------------------------------------------
83  EngineId ID(instanceName, EngineId::global);
84  MF_LOG_DEBUG("NuRandomService")
85  << "NuRandomService::getGlobalSeed(\"" << instanceName << "\")";
86  return getSeed(ID);
87  } // NuRandomService::getGlobalSeed()
88 
89 
90  //----------------------------------------------------------------------------
92 
93  // We require an engine to have been registered before we yield seeds;
94  // this should minimise unexpected conflicts.
95  if (hasEngine(id)) return querySeed(id); // ask the seed to seed master
96 
97  // if it hasn't been declared, we declare it now
98  // (this is for backward compatibility with the previous behaviour).
99  // registerEngineID() will eventually call this function again to get the
100  // seed... so we return it directly.
101  // Also note that this effectively "freezes" the engine since no seeder
102  // is specified.
103  return registerEngineID(id);
104 
105  } // NuRandomService::getSeed(EngineId)
106 
107 
109  return seeds.getSeed(id); // ask the seed to seed master
110  } // NuRandomService::querySeed()
111 
112 
113  std::pair<NuRandomService::seed_t, bool> NuRandomService::findSeed(
114  EngineId const& id,
115  fhicl::ParameterSet const& pset, std::initializer_list<std::string> pnames
116  ) {
117  seed_t seed = InvalidSeed;
118  // try and read the seed from configuration; if succeed, it's "frozen"
119  bool const bFrozen = readSeedParameter(seed, pset, pnames);
120 
121  // if we got a valid seed, use it as frozen
122  if (bFrozen && (seed != InvalidSeed))
123  return { seed, true };
124 
125  // seed was not good enough; get the seed from the master
126  return { querySeed(id), false };
127 
128  } // NuRandomService::findSeed()
129 
130 
133  {
134  return registerEngineID(qualify_engine_label(instance), seeder);
135  } // NuRandomService::registerEngine(Seeder_t, string)
136 
137 
139  SeedMaster_t::Seeder_t seeder, std::string instance,
140  fhicl::ParameterSet const& pset, std::initializer_list<std::string> pnames
141  ) {
142  EngineId id = qualify_engine_label(instance);
143  registerEngineAndSeeder(id, seeder);
144  std::pair<seed_t, bool> seedInfo = findSeed(id, pset, pnames);
145  seedEngine(id); // seed it before freezing
146  if (seedInfo.second) freezeSeed(id, seedInfo.first);
147  seed_t const seed = seedInfo.first;
148  return seed;
149  } // NuRandomService::registerEngine(Seeder_t, string, ParameterSet, init list)
150 
151 
153  return registerEngine(SeedMaster_t::Seeder_t(), instance);
154  } // NuRandomService::declareEngine(string)
155 
156 
158  std::string instance,
159  fhicl::ParameterSet const& pset, std::initializer_list<std::string> pnames
160  ) {
161  return registerEngine(SeedMaster_t::Seeder_t(), instance, pset, pnames);
162  } // NuRandomService::declareEngine(string, ParameterSet, init list)
163 
164 
166  (SeedMaster_t::Seeder_t seeder, std::string instance /* = {} */)
167  {
168  return defineEngineID(qualify_engine_label(instance), seeder);
169  } // NuRandomService::defineEngine(string, Seeder_t)
170 
171 
172  //----------------------------------------------------------------------------
174  EngineId const& id,
175  SeedMaster_t::Seeder_t seeder /* = SeedMaster_t::Seeder_t() */
176  ) {
177  prepareEngine(id, seeder);
178  return seedEngine(id);
179  } // NuRandomService::registerEngine()
180 
181 
183  (EngineId const& id, SeedMaster_t::Seeder_t seeder)
184  {
185  if (!hasEngine(id)) {
187  << "Attempted to define engine '" << id.artName()
188  << "', that was not declared\n";
189  }
190 
191  if (seeds.hasSeeder(id)) {
193  << "Attempted to redefine engine '" << id.artName()
194  << "', that has already been defined\n";
195  }
196 
198 
199  seeds.registerSeeder(id, seeder);
200  seed_t const seed = seedEngine(id);
201  return seed;
202  } // NuRandomService::defineEngineID()
203 
204 
205  //----------------------------------------------------------------------------
206  void NuRandomService::ensureValidState(bool bGlobal /* = false */) const {
207  if (bGlobal) {
208  // registering engines may only happen in a service c'tor
209  // In all other cases, throw.
211  {
213  << "NuRandomService: not in a service constructor."
214  << " May not register \"global\" engines.\n";
215  }
216  }
217  else { // context-aware engine
218  // registering engines may only happen in a c'tor
219  // (disabling the ability to do that or from a beginRun method)
220  // In all other cases, throw.
222  // && (state.state() != NuRandomServiceHelper::ArtState::inModuleBeginRun)
223  )
224  {
226  << "NuRandomService: not in a module constructor."
227  << " May not register engines.\n";
228  }
229  } // if
230  } // NuRandomService::ensureValidState()
231 
232 
233  //----------------------------------------------------------------------------
235  // get all the information on the current process, event and module from
236  // ArtState:
238  seed_t const seed = seeds.reseedEvent(id, data);
239  if (seed == InvalidSeed) {
240  mf::LogDebug("NuRandomService")
241  << "No random seed specific to this event for engine '" << id << "'";
242  }
243  else {
244  mf::LogInfo("NuRandomService") << "Random seed for this event, engine '"
245  << id << "': " << seed;
246  }
247  return seed;
248  } // NuRandomService::reseedInstance()
249 
250 
252  for (EngineId const& ID: seeds.engineIDsRange()) {
253  if (ID.moduleLabel != currentModule) continue; // not our module? neeext!!
255  } // for
256  } // NuRandomService::reseedModule(string)
257 
259 
260 
262  for (EngineId const& ID: seeds.engineIDsRange()) {
263  if (!ID.isGlobal()) continue; // not global? neeext!!
265  } // for
266  } // NuRandomService::reseedGlobal()
267 
268 
269  //----------------------------------------------------------------------------
271  (EngineId const& id, SeedMaster_t::Seeder_t seeder)
272  {
273  // Are we being called from the right place?
274  ensureValidState(id.isGlobal());
275 
276  if (hasEngine(id)) {
278  << "NuRandomService: an engine with ID '" << id.artName()
279  << "' has already been created!\n";
280  }
281  seeds.registerNewSeeder(id, seeder);
282  } // NuRandomService::registerEngineAndSeeder()
283 
284 
285  //----------------------------------------------------------------------------
286  void NuRandomService::freezeSeed(EngineId const& id, seed_t frozen_seed)
287  { seeds.freezeSeed(id, frozen_seed); }
288 
289 
290  //----------------------------------------------------------------------------
292  (EngineId const& id, SeedMaster_t::Seeder_t seeder)
293  {
294  registerEngineAndSeeder(id, seeder);
295  return querySeed(id);
296  } // NuRandomService::prepareEngine()
297 
298 
299  //----------------------------------------------------------------------------
301  seed_t& seed, fhicl::ParameterSet const& pset,
302  std::initializer_list<std::string> pnames
303  ) {
304  for (std::string const& key: pnames)
305  if (pset.get_if_present(key, seed)) return true;
306  seed = InvalidSeed;
307  return false;
308  } // NuRandomService::readSeedParameter()
309 
310 
311  //----------------------------------------------------------------------------
312  // Callbacks called by art. Used to maintain information about state.
315  state.set_module(md);
316  } // NuRandomService::preModuleConstruction()
317 
319  state.reset_state();
320  } // NuRandomService::postModuleConstruction()
321 
325  } // NuRandomService::preModuleBeginRun()
326 
328  state.reset_state();
329  } // NuRandomService::postModuleBeginRun()
330 
333  state.set_event(evt);
334  seeds.onNewEvent(); // inform the seed master that a new event has come
335 
336  MF_LOG_DEBUG("NuRandomService") << "preProcessEvent(): will reseed global engines";
337  reseedGlobal(); // why don't we do them all?!?
338 
339  } // NuRandomService::preProcessEvent()
340 
344 
345  // Reseed all the engine of this module... maybe
346  // (that is, if the current policy alows it).
347  MF_LOG_DEBUG("NuRandomService") << "preModule(): will reseed engines for module '"
348  << mc.moduleLabel() << "'";
350  } // NuRandomService::preModule()
351 
354  state.reset_state();
355  } // NuRandomService::postModule()
356 
358  state.reset_event();
359  state.reset_state();
360  } // NuRandomService::postProcessEvent()
361 
364  state.set_module(md);
365  } // NuRandomService::preModuleBeginRun()
366 
368  state.reset_state();
369  } // NuRandomService::preModuleBeginRun()
370 
372  if ((verbosity > 0) || bPrintEndOfJobSummary)
373  print(); // framework logger decides whether and where it shows up
374  } // NuRandomService::postEndJob()
375 
376  //----------------------------------------------------------------------------
377 
378 } // end namespace rndm
379 
state_type transit_to(state_type astate)
Records the new status of ART and returns the old one.
Definition: ArtState.h:63
seed_t querySeed(EngineId const &id)
Query a seed from the seed master.
bool bPrintEndOfJobSummary
print a summary at the end of job
GlobalSignal< detail::SignalResponseType::FIFO, void(ModuleContext const &)> sPreModuleBeginRun
void reset_state()
Resets the status to "something else" (inOther)
Definition: ArtState.h:74
seed_t getGlobalSeed(std::string instanceName)
Returns a seed for the global engine with specified instance name.
int verbosity
Control the level of information messages.
std::string string
Definition: nybbler.cc:12
unsigned int ID
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
#define DEFINE_ART_SERVICE(svc)
Definition: ServiceMacros.h:88
GlobalSignal< detail::SignalResponseType::FIFO, void(ModuleDescription const &)> sPreModuleConstruction
bool hasSeeder(EngineId const &id) const
Returns whether the specified engine has a valid seeder.
Definition: SeedMaster.h:281
GlobalSignal< detail::SignalResponseType::LIFO, void()> sPostEndJob
EventSeedInputData getEventSeedInputData() const
Definition: ArtState.h:128
void set_event(art::Event const &evt)
Records the specified event ID.
Definition: ArtState.h:77
static bool readSeedParameter(seed_t &seed, fhicl::ParameterSet const &pset, std::string pname)
seed_t defineEngineID(EngineId const &id, SeedMaster_t::Seeder_t seeder)
Set the seeder of an existing engine.
void preProcessEvent(art::Event const &evt, art::ScheduleContext)
GlobalSignal< detail::SignalResponseType::FIFO, void(ModuleContext const &)> sPreModule
void postModuleBeginRun(art::ModuleContext const &)
std::string moduleLabel() const
Definition: ArtState.h:122
const std::string instance
seed_t getSeed()
Returns a seed for the engine with default instance name.
seed_t seedEngine(EngineId const &id)
Calls the seeder with the specified seed and engine ID.
NuRandomService(const fhicl::ParameterSet &, art::ActivityRegistry &)
GlobalSignal< detail::SignalResponseType::LIFO, void(ModuleDescription const &)> sPostModuleConstruction
void freezeSeed(EngineId const &id, seed_t frozen_seed)
Forces NuRandomService not to change the seed of the specified engine.
void registerEngineAndSeeder(EngineId const &id, SeedMaster_t::Seeder_t seeder)
Registers an engine and its seeder.
EngineId qualify_engine_label(std::string moduleLabel, std::string instanceName) const
Returns a fully qualified EngineId.
void postModuleConstruction(art::ModuleDescription const &)
seed_t registerEngineID(EngineId const &id, SeedMaster_t::Seeder_t seeder=SeedMaster_t::Seeder_t())
Register an engine and seeds it with the seed from the master.
SeedMaster_t::EngineId EngineId
type of random engine ID
void registerNewSeeder(EngineId const &id, Seeder_t seeder)
Register the specified function to reseed the engine id.
Definition: SeedMaster.h:536
void ensureValidState(bool bGlobal=false) const
void print() const
Prints to the framework Info logger.
std::function< void(EngineId const &, seed_t)> Seeder_t
type of a function setting a seed
Definition: SeedMaster.h:216
def key(type, name=None)
Definition: graph.py:13
typename PolicyImpl_t::EventData_t EventData_t
type of data used for event seeds
Definition: SeedMaster.h:255
void freezeSeed(EngineId const &id, seed_t seed)
Forces SeedMaster not to change the seed of a registered engine.
Definition: SeedMaster.h:548
NuRandomServiceHelper::ArtState state
in event processing by a module
Definition: ArtState.h:41
void preModuleConstruction(art::ModuleDescription const &md)
Identifier for a engine, made of module name and optional instance name.
Definition: EngineId.h:22
bool get_if_present(std::string const &key, T &value) const
Definition: ParameterSet.h:208
GlobalSignal< detail::SignalResponseType::LIFO, void(ModuleContext const &)> sPostModuleBeginRun
static constexpr seed_t InvalidSeed
An invalid seed.
void postModule(art::ModuleContext const &)
seed_t defineEngine(SeedMaster_t::Seeder_t seeder, std::string instance={})
Defines a seeder for a previously declared engine.
std::pair< seed_t, bool > findSeed(EngineId const &id, fhicl::ParameterSet const &pset, std::initializer_list< std::string > pnames)
GlobalSignal< detail::SignalResponseType::FIFO, void(Event const &, ScheduleContext)> sPreProcessEvent
GlobalSignal< detail::SignalResponseType::FIFO, void(ModuleDescription const &)> sPreModuleEndJob
void preModule(art::ModuleContext const &mc)
GlobalSignal< detail::SignalResponseType::LIFO, void(Event const &, ScheduleContext)> sPostProcessEvent
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::vector< TrajPoint > seeds
Definition: DataStructs.cxx:13
void preModuleBeginRun(art::ModuleContext const &mc)
seed_t reseedInstance(EngineId const &id)
Reseeds the specified engine instance in the current module.
GlobalSignal< detail::SignalResponseType::LIFO, void(ModuleContext const &)> sPostModule
static QCString currentModule
name of the current enclosing module
state_type state() const
Getters.
Definition: ArtState.h:112
seed_t reseedEvent(EngineId const &id, EventData_t const &data)
Reseeds the specified engine with an event seed (if any)
Definition: SeedMaster.h:572
seed_t getSeed(std::string moduleLabel)
Returns the seed value for this module label.
Definition: SeedMaster.h:509
static Global_t global
A constant to select a "global" flavour constructor.
Definition: EngineId.h:28
void onNewEvent()
Prepares for a new event.
Definition: SeedMaster.h:726
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
void reseedGlobal()
Reseed all the global engines.
auto const & moduleDescription() const
Definition: ModuleContext.h:38
#define MF_LOG_DEBUG(id)
auto const & moduleLabel() const
Definition: ModuleContext.h:43
GlobalSignal< detail::SignalResponseType::LIFO, void(ModuleDescription const &)> sPostModuleEndJob
bool hasEngine(EngineId const &id) const
Returns whether the specified engine is already registered.
EngineInfoIteratorBox engineIDsRange() const
Returns an object to iterate in range-for through configured engine IDs.
Definition: SeedMaster.h:365
void registerSeeder(EngineId const &id, Seeder_t seeder)
Register the specified function to reseed the engine id.
Definition: SeedMaster.h:527
void postProcessEvent(art::Event const &, art::ScheduleContext)
TCEvent evt
Definition: DataStructs.cxx:7
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
seed_t declareEngine(std::string instance="")
Declares the presence of an engine with a given instance name.
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
void preModuleEndJob(art::ModuleDescription const &md)
void postModuleEndJob(art::ModuleDescription const &)
int bool
Definition: qglobal.h:345
void set_module(art::ModuleDescription const &desc)
Records the specified module description.
Definition: ArtState.h:86
seed_t registerEngine(SeedMaster_t::Seeder_t seeder, std::string instance="")
Registers an existing engine with NuRandomService.
seed_t prepareEngine(EngineId const &id, SeedMaster_t::Seeder_t seeder)
Registers the engine ID into SeedMaster.
SeedMaster_t seeds
Class managing the seeds.
art::detail::EngineCreator::seed_t seed_t