Ocean
Loading...
Searching...
No Matches
RandomGenerator.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_BASE_RANDOM_GENERATOR_H
9#define META_OCEAN_BASE_RANDOM_GENERATOR_H
10
11#include "ocean/base/Base.h"
12#include "ocean/base/Lock.h"
13
14#include <cstdlib>
15
16namespace Ocean
17{
18
19/**
20 * This class implements a generator for random numbers.
21 * A random generator object can be used to improve the performance of code (needing random numbers) which is applied on several CPU cores in parallel.<br>
22 * The default random number functions of the standard library are thread-safe but may apply expensive locks to synchronize the individual seed parameters of the individual threads.<br>
23 * Therefore, this class can be used to improve the code performance significantly in multi-threaded environments.<br>
24 * The following code example shows the correct application of this class for multi-core functions (which can be invoked e.g., by the Worker class):<br>
25 * @code
26 * void multiCoreFunction(RandomGenerator& randomGenerator, unsigned int* data, unsigned int firstObject, unsigned int numberObjects)
27 * {
28 * /// create a local random generator object which uses the function's random generator to create a new seed value
29 * RandomGenerator localRandomGenerator(randomGenerator);
30 *
31 * for (unsigned int n = firstObject; n <= firstObject + numberObjects; ++n)
32 * {
33 * /// we create random values and use the local random generator (not the function's random generator)
34 * data[n] = RandomI::random(localRandomGenerator, 100u);
35 * }
36 * }
37 * @endcode
38 * @see RandomI, Worker.
39 * @ingroup base
40 */
41class OCEAN_BASE_EXPORT RandomGenerator
42{
43 public:
44
45 /**
46 * Creates a new random generator and initializes the internal parameter with the random value of the standard random function.
47 * Ensure that RandomI::initialize() has been called before using this constructor.
48 * @see RandomI::initialize().
49 */
51
52 /**
53 * Creates a new random generator and initializes the internal parameter by a random value provided by the locked random function of the given generator.
54 * @param generator Random number generator used for initialization, the generator's seed will be changed during the initialization
55 */
56 explicit inline RandomGenerator(RandomGenerator& generator);
57
58 /**
59 * Creates a new random generator and optional initializes the internal parameter by a random value provided by the locked random function of the given generator, if no generator is provided the standard random function will be used for initialization.
60 * @param optionalGenerator The random number generator used for initialization (the generator's seed will be changed during the initialization), nullptr to use the standard random function for initialization
61 */
62 explicit RandomGenerator(RandomGenerator* optionalGenerator);
63
64 /**
65 * Move constructor.
66 * @param randomGenerator The random generator object to be moved
67 */
68 inline RandomGenerator(RandomGenerator&& randomGenerator) noexcept;
69
70 /**
71 * Creates a new random generator and initializes the internal parameter by the given value.
72 * @param seed The seed initialization value, with range [0, infinity)
73 */
74 explicit inline RandomGenerator(const unsigned int seed);
75
76 /**
77 * Returns the next random number.
78 * Beware: This function is not thread safe.
79 * @return Random number with range [0, 4294967294] == [0, 2^32-2]
80 * @see lockedRand().
81 */
82 inline unsigned int rand();
83
84 /**
85 * Returns the next random number.
86 * This function is thread safe.
87 * @return Random number with range [0, 4294967294] == [0, 2^32-2]
88 * @see rand().
89 */
90 inline unsigned int lockedRand();
91
92 /**
93 * Returns the current seed value of this object.
94 * This seed value changes whenever a new random number is generated.
95 * @return Current seed value
96 */
97 inline unsigned int seed() const;
98
99 /**
100 * Returns the initial seed value which was used to initialize this random generator.
101 * The initial seed value will not change during the lifetime of the generator.
102 * @return The random generator's initial seed value
103 */
104 inline unsigned int initialSeed() const;
105
106 /**
107 * Move operator.
108 * @param randomGenerator The random generator object to be moved
109 * @return Reference to this object
110 */
112
113 /**
114 * Generates a new random number using the xorshift32 algorithm.
115 * This function updates the seed in place and returns the new random value.
116 * The xorshift32 algorithm produces values in the range [1, 2^32-1], so we subtract 1 to get [0, 2^32-2].
117 * @param seed The seed value to update, with range [1, infinity)
118 * @return The new random number in range [0, 4294967294] == [0, 2^32-2]
119 */
120 static inline unsigned int nextRandomNumber(unsigned int& seed);
121
122 /**
123 * Returns the maximal random value of this generator.
124 * @return Maximal random value of this generator
125 */
126 static constexpr unsigned int randMax();
127
128 private:
129
130 /**
131 * Returns a seed value based on the current time, the thread id, and a random value from RandomI.
132 * @return The combined seed value, with range [1, infinity)
133 */
134 static unsigned int threadAndTimeBasedSeed();
135
136 private:
137
138 /// The seed value which was used to initialize this random generator.
139 unsigned int initialSeed_ = (unsigned int)(-1);
140
141 /// Internal seed parameter used for random number generation, changes whenever a new random number is generated.
142 unsigned int seed_ = (unsigned int)(-1);
143
144 /// Generator lock.
146};
147
149{
150 initialSeed_ = generator.lockedRand();
151
152 if (initialSeed_ == 0u)
153 {
154 initialSeed_ = 1u; // Xorshift32 requires non-zero seed, ensure it's not zero
155 }
156
158
159 // doing first randomization step
161}
162
163inline RandomGenerator::RandomGenerator(const unsigned int seed) :
164 initialSeed_(seed != 0u ? seed : 1u) // Xorshift32 requires non-zero seed, ensure it's not zero
165{
166
168}
169
170inline RandomGenerator::RandomGenerator(RandomGenerator&& randomGenerator) noexcept
171{
172 *this = std::move(randomGenerator);
173}
174
175inline unsigned int RandomGenerator::rand()
176{
177 return nextRandomNumber(seed_);
178}
179
180inline unsigned int RandomGenerator::lockedRand()
181{
182 const ScopedLock scopedLock(lock_);
183
184 return nextRandomNumber(seed_);
185}
186
187inline unsigned int RandomGenerator::seed() const
188{
189 return seed_;
190}
191
192inline unsigned int RandomGenerator::initialSeed() const
193{
194 return initialSeed_;
195}
196
197inline unsigned int RandomGenerator::nextRandomNumber(unsigned int& seed)
198{
199 // Xorshift32 algorithm - generates full 32-bit random numbers
200 // The seed must not be zero, otherwise the algorithm will produce infinite zeros
201 ocean_assert(seed != 0u);
202
203 seed ^= seed << 13u;
204 seed ^= seed >> 17u;
205 seed ^= seed << 5u;
206
207 // Xorshift32 produces values in [1, 2^32-1], subtract 1 to get [0, 2^32-2]
208 return seed - 1u;
209}
210
211constexpr unsigned int RandomGenerator::randMax()
212{
213 return 0xFFFFFFFEu; // 4294967294 (2^32 - 2), as xorshift32 never produces 0 or 2^32-1
214}
215
216}
217
218#endif // META_OCEAN_BASE_RANDOM_GENERATOR_H
This class implements a recursive lock object.
Definition Lock.h:31
This class implements a generator for random numbers.
Definition RandomGenerator.h:42
Lock lock_
Generator lock.
Definition RandomGenerator.h:145
static unsigned int threadAndTimeBasedSeed()
Returns a seed value based on the current time, the thread id, and a random value from RandomI.
unsigned int lockedRand()
Returns the next random number.
Definition RandomGenerator.h:180
unsigned int rand()
Returns the next random number.
Definition RandomGenerator.h:175
static constexpr unsigned int randMax()
Returns the maximal random value of this generator.
Definition RandomGenerator.h:211
unsigned int initialSeed_
The seed value which was used to initialize this random generator.
Definition RandomGenerator.h:139
unsigned int seed() const
Returns the current seed value of this object.
Definition RandomGenerator.h:187
unsigned int initialSeed() const
Returns the initial seed value which was used to initialize this random generator.
Definition RandomGenerator.h:192
RandomGenerator & operator=(RandomGenerator &&randomGenerator)
Move operator.
unsigned int seed_
Internal seed parameter used for random number generation, changes whenever a new random number is ge...
Definition RandomGenerator.h:142
RandomGenerator(RandomGenerator *optionalGenerator)
Creates a new random generator and optional initializes the internal parameter by a random value prov...
RandomGenerator()
Creates a new random generator and initializes the internal parameter with the random value of the st...
static unsigned int nextRandomNumber(unsigned int &seed)
Generates a new random number using the xorshift32 algorithm.
Definition RandomGenerator.h:197
This class implements a scoped lock object for recursive lock objects.
Definition Lock.h:147
The namespace covering the entire Ocean framework.
Definition Accessor.h:15