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