Belle II Software  release-05-02-19
RandomNumbers.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2010-2015 Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Thomas Kuhr, Martin Ritter *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include <boost/python.hpp>
12 #include <random>
13 #include <sstream>
14 
15 #include <framework/core/RandomNumbers.h>
16 #include <framework/pcore/ProcHandler.h>
17 #include <framework/pcore/ProcHelper.h>
18 #include <framework/logging/Logger.h>
19 
20 
21 using namespace Belle2;
22 
23 
33 
35 {
36  //use std::random_device to get non deterministic initial seed to be used if
37  //user doesn't set one
38  std::random_device random_device;
39  std::stringstream seed;
40  for (int i = 0; i < 8; ++i) {
41  seed << std::hex << random_device();
42  }
43  initialize(seed.str());
44 }
45 
46 void RandomNumbers::initialize(const std::string& seed)
47 {
48  s_initialSeed = seed;
49  if (!s_evtRng) {
50  s_evtRng = new RandomGenerator("event generator");
51  }
52  if (!s_runRng) {
53  s_runRng = new RandomGenerator("independent generator");
54  }
55  auto* gen = dynamic_cast<RandomGenerator*>(gRandom);
56  if (!gen) {
57  delete gRandom;
58  B2DEBUG(100, "Replacing gRandom from " << gRandom << " to " << gen);
59  }
60  gRandom = s_evtRng;
62  s_evtRng->setSeed((const unsigned char*)seed.c_str(), seed.size());
63  s_runRng->setSeed((const unsigned char*)seed.c_str(), seed.size());
64 }
65 
67 {
68  return (s_evtRng != nullptr);
69 }
70 
72 {
73  auto* gen = dynamic_cast<RandomGenerator*>(gRandom);
74  if (!gen) {
75  B2ERROR("Random Generator gRandom is not Belle2::RandomGenerator, cannot increase barrier");
76  } else {
77  gen->barrier();
78  }
79 }
80 
81 void RandomNumbers::setSeed(const std::string& seed)
82 {
83  initialize(seed);
84  B2INFO("The random number seed is set to \"" << seed << '"');
85 }
86 
88 {
89  gRandom = s_runRng;
91  //This might be called in in main or output process. In that case we don't
92  //know how many random barriers came before but we can look at the s_evtRng
93  //as this was passed from the previous process and contains the current
94  //barrier number in the event flow. We save it in intializeEvent so let's use
95  //it now.
97 };
98 
100 {
101  gRandom = s_runRng;
103  //We set the barrier index to it's minimum possible value: usually barrier
104  //index starts at 0 but for endRun we set it to a negative number large
105  //enough that there is no realistic chance that beginRun had the same barrier
106  //index.
107  s_runRng->setBarrier(INT_MIN + s_barrierOffset);
108 }
109 
111 {
113  //we pass the random generator to other processes in multiprocessing so we only
114  //want to initialize it in the input process (or if there is no multi processing)a
115  //However on HLT we do things differently and so we need to initialize on all
116  //worker processes. So the HLT event processor can request initialization in
117  //all cases.
119  // when in event loop we want an error if there is no EventMetaData
121  s_evtRng->initialize();
122  }
123  //Ok, now we either have reset the barrier to 0 if we are an input process or
124  //have decided to keep the state from the previous process. In any case, this
125  //is the start barrier we want to use for begin/end of run processing so we
126  //keep it.
128 }
129 
131 {
132  gRandom = s_evtRng;
133 }
134 
135 //=====================================================================
136 // Python API
137 //=====================================================================
138 
139 namespace {
141  std::string pythonObjectToString(const boost::python::object& obj)
142  {
143  return boost::python::extract<std::string>(obj.attr("__str__")());
144  }
146  void setPythonSeed(const boost::python::object& obj)
147  {
148  RandomNumbers::setSeed(pythonObjectToString(obj));
149  }
150 }
151 
153 {
154  using namespace boost::python;
155 
156  //don't show c++ signature in python doc to keep it simple
157  docstring_options options(true, true, false);
158  //Expose RandomNumbers class
159  def("set_random_seed", &setPythonSeed, args("seed"), R"DOCSTRING(
160 Set the random seed. The argument can be any object and will be converted to a
161 string using the builtin str() function and will be used to initialize the
162 random generator.)DOCSTRING");
163  def("get_random_seed", &RandomNumbers::getSeed, "Return the current random seed");
164 }
Belle2::RandomGenerator::c_independent
@ c_independent
Don't use event info to generate state.
Definition: RandomGenerator.h:53
Belle2::RandomGenerator::c_runDependent
@ c_runDependent
Use experiment and run number to generate state.
Definition: RandomGenerator.h:55
Belle2::RandomNumbers::s_initialSeed
static std::string s_initialSeed
The random number generator seed set by the user.
Definition: RandomNumbers.h:121
Belle2::RandomNumbers::useEventDependent
static void useEventDependent()
Set Event dependent Random Generator as current one.
Definition: RandomNumbers.cc:130
Belle2::RandomNumbers::barrier
static void barrier()
Increase random barrier.
Definition: RandomNumbers.cc:71
Belle2::RandomNumbers::s_runRng
static RandomGenerator * s_runRng
event independent random generator to be used for begin/end run processing
Definition: RandomNumbers.h:118
Belle2::RandomGenerator::c_eventDependent
@ c_eventDependent
Use experiment, run and event number to generate state.
Definition: RandomGenerator.h:57
Belle2::RandomGenerator
Fast Random number Generator using on xorshift1024* [arXiv:1402.6246].
Definition: RandomGenerator.h:47
Belle2::RandomGenerator::setBarrier
void setBarrier(int barrierIndex)
manually set the barrier index to a fixed value
Definition: RandomGenerator.h:99
Belle2::RandomNumbers::initializeEndRun
static void initializeEndRun()
Initialize run independent random generator for end run.
Definition: RandomNumbers.cc:99
Belle2::RandomNumbers::initialize
static void initialize()
Initialize the random number generator with a unique random seed;.
Definition: RandomNumbers.cc:34
Belle2::RandomNumbers::exposePythonAPI
static void exposePythonAPI()
Exposes methods of the RandomNumbers class to Python.
Definition: RandomNumbers.cc:152
Belle2::RandomNumbers::setSeed
static void setSeed(const std::string &seed)
Sets the seed for the random number generator.
Definition: RandomNumbers.cc:81
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::RandomNumbers::initializeEvent
static void initializeEvent(bool force=false)
Initialize event information.
Definition: RandomNumbers.cc:110
Belle2::RandomNumbers::s_evtRng
static RandomGenerator * s_evtRng
event dependent random generator to be used for event processing
Definition: RandomNumbers.h:116
Belle2::RandomGenerator::setSeed
void setSeed(const unsigned char *seed, unsigned int n)
Set the seed information.
Definition: RandomGenerator.cc:44
Belle2::RandomNumbers::isInitialized
static bool isInitialized()
Truth that the random number generator has been initialized.
Definition: RandomNumbers.cc:66
Belle2::RandomNumbers::getSeed
static std::string getSeed()
Get the random number generator seed.
Definition: RandomNumbers.h:102
Belle2::ProcHandler::isInputProcess
static bool isInputProcess()
Return true if the process is an input process.
Definition: ProcHandler.cc:223
Belle2::RandomNumbers::s_barrierOffset
static int s_barrierOffset
barrier index offset to be used in begin/endRun.
Definition: RandomNumbers.h:123
Belle2::ProcHandler::parallelProcessingUsed
static bool parallelProcessingUsed()
Returns true if multiple processes have been spawned, false in single-core mode.
Definition: ProcHandler.cc:221
Belle2::RandomNumbers::initializeBeginRun
static void initializeBeginRun()
Initialize run independent random generator for begin run.
Definition: RandomNumbers.cc:87
Belle2::RandomGenerator::setMode
void setMode(EGeneratorMode mode)
Set the generator mode.
Definition: RandomGenerator.h:78
Belle2::RandomGenerator::initialize
void initialize()
set the State from event meta information like experiment, run, and event number.
Definition: RandomGenerator.h:90
Belle2::RandomGenerator::getBarrier
int getBarrier() const
obtain the currently active barrier id
Definition: RandomGenerator.h:102