c++ generate thread safe random numbers - c++

I've read some similar questions to the one I'm asking but the answers don't seem complete or completely clear to me.
I'm trying to parallelize a parameter scan that requires the repeated generation of a set of random numbers. With only one thread I currently do something like this:
int main() {
//Get random number generators
typedef std::mt19937 MyRNG;
std::random_device rd;
//seed generator
MyRNG rng;
rng.seed(rd());
//make my uniform distributions for each parameter
std::uniform_real_distribution<> param1(-1,1);
std::uniform_real_distribution<> param2(-1,1);
double x,y;
//Do my scan
for (int i = 0; i < N; i++) {
x = param1(rng)
y = param2(rng)
//Do things with x and y*
}
In this way I get a new x and y for every scan. Now I want to utilize multiple cores to do this in parallel. So I turn define a function void scan() which essentially has the same contents as my main function. I then create multiple threads and each have them run scan(). But I'm not sure if this is thread safe using std::thread. Will my random number generation in each thread as it currently is be independent? Can I save myself time by creating my RNGs outside of my void function? Thanks.

I would probably generate the seeds in main, and pass a seed to each thread function. I wouldn't use the output of std::random_device directly either--I'd put numbers into something like an std::set or std::unordered_set until I got as many seeds as I wanted, to assure that I didn't give two threads the same seed (which would obviously be a waste of time).
Something along this general line:
int do_work(unsigned long long seed) {
//Get random number generators
typedef std::mt19937 MyRNG;
//seed generator
MyRNG rng(seed);
//make my uniform distributions for each parameter
std::uniform_real_distribution<> param1(-1,1);
std::uniform_real_distribution<> param2(-1,1);
double x,y;
//Do my scan
for (int i = 0; i < N; i++) {
x = param1(rng);
y = param2(rng);
//Do things with x and y*
}
}
static const int num_threads = 4;
int main() {
std::set<unsigned long long> seeds;
while (seeds.size() < num_threads)
seeds.insert(std::random_device()());
std::vector<std::thread> threads;
for (auto const seed: seeds)
threads.emplace_back(std::thread(do_work, seed));
for (auto &t : threads)
t.join();
}
As an aside, using a single result from random_device to seed an std::mt19937 restricts the generator quite a bit--you're giving it only 32 (or possibly 64) bits of seed, but it actually has 19937 bits of seed material. std::seed_seq attempts to ameliorate this to at least some degree (among other things, you can use a number of outputs from std::random_device to create the seed.
Oh, and given that your two instances of uniform_real_distribution use the same parameters, there's probably not a whole lot of need for two separate distribution objects either.

Related

c++ pseudo random numbers with fixed seed per thread [duplicate]

I have a function that calls srand and rand like this:
void foo() {
int seed = some_operation();
std::srand(seed);
int value = std::rand();
// Do something with random value
}
However, I don't want to change the global state of rand. Whats the easiest way to get a random number then?
Requirements:
random number must be deterministic based on seed
C++11 is fine
foo should be thread safe
the global state of rand should not be modified
Edit:
There is a stackoverflow question asking how to generate random numbers. The accepted answer however shows how to generate truly unique random numbers, using a slow std::random_device. I just needed a simple generator using a fixed seed instead.
C++11 is fine
Then use the new pseudorandom number library:
#include <random>
int foo() {
int seed = some_operation();
std::minstd_rand rand(seed);
int value = rand();
// Do something with random value
}
minstd_rand is a simple linear congruential engine, similar to that typically used by std::rand(), but with its state encapsulated in a class. Other engines are available, if you need a higher quality pseudorandom sequence. The Mersenne Twister, std::mt19937, is usually a good choice if you don't have specific requirements.
<random> defines a number of PRNG classes that you can use, which do not use global states.
For example, using a default Mersenne Twister, std::mt19937:
#include <iostream>
#include <random>
int main() {
int seed = 1234;
std::mt19937 rng(seed);
std::cout << "Random number: " << rng() << std::endl;
}
One approach is to provide your own implementation, with its own seed data. A template for doing that is provided in the manpage for rand().
static unsigned long next = 1;
/* RAND_MAX assumed to be 32767 */
int myrand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
}
void mysrand(unsigned seed) {
next = seed;
}

Generating Gaussian Noise

I created a function that is suppose to generate a set of normal random numbers from 0 to 1. Although, it seems that each time I run the function the output is the same. I am not sure what is wrong.
Here is the code:
MatrixXd generateGaussianNoise(int n, int m){
MatrixXd M(n,m);
normal_distribution<double> nd(0.0, 1.0);
random_device rd;
mt19937 gen(rd());
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
M(i,j) = nd(gen);
}
}
return M;
}
The output when n = 4 and m = 1 is
0.414089
0.225568
0.413464
2.53933
I used the Eigen library for this, I am just wondering why each time I run it produces the same numbers.
From:
http://en.cppreference.com/w/cpp/numeric/random/random_device
std::random_device may be implemented in terms of an implementation-defined pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation. In this case each std::random_device object may generate the same number sequence.
Thus, I think you should look into what library stack you are actually using here, and what's known about random_device in your specific implementation.
I realize that this then might in fact be a duplicate of "Why do I get the same sequence for every run with std::random_device with mingw gcc4.8.1?".
Furthermore, it at least used to be that initializating a new mt19937 instance would be kind of expensive. Thus, you have performance reasons in addition to quality of randomness to not re-initalize both your random_device and mt19937 instance for every function call. I would go for some kind of singleton here, unless you have very clear constraints (building in a library, unclear concurrency) that would make that an unuistable choice.

How to use std::normal_distribution

I am an experienced C programmer that is occasionally forced to use a little bit of C++.
I need to generate random numbers from a normal distribution with a variety of means and variances. If I had a C function that did this called normal(float mean, float var) then I could write the following code:
int i;
float sample;
for(i = 0;i < 1000;i++)
{
sample = normal(mean[i],variance[i]);
do_something_with_this_value(sample);
}
Note that there is a different mean and variance for each value of i.
C does not contain a function called normal, but C++ does, well actually its called std::normal_distribution. Unfortunately my C++ is not good enough to understand the syntax in the documentation. Can anyone tell me how to achieve the functionality of my C code but using std::normal_distribution.
std::normal_distribution isn't function but templated class
you can use it like this:
#include <random>
int main(int, char**)
{
// random device class instance, source of 'true' randomness for initializing random seed
std::random_device rd;
// Mersenne twister PRNG, initialized with seed from previous random device instance
std::mt19937 gen(rd());
int i;
float sample;
for(i = 0; i < 1000; ++i)
{
// instance of class std::normal_distribution with specific mean and stddev
std::normal_distribution<float> d(mean[i], stddev[i]);
// get random number with normal distribution using gen as random source
sample = d(gen);
// profit
do_something_with_this_value(sample);
}
return 0;
}

Best place to initialise random generator

In my program I use a random number generator quite a lot. I believe the general rule is that you should define things as close to the place where they're "called", but does this also hold true for random number generators?
For example, in my code I have the choice between:
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(-2147483647, 2147483646);
lots of code
for (i = 0; i < 10000; i++)
{
variable x = uni(rng);
}
Or
lots of code
for (i = 0; i < 10000; i++)
{
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(-2147483647, 2147483646);
variable x = uni(rng);
}
I would say the first method is faster, but I've gotten a bit confused due to reading many threads in which it is stated to always place everything as close to the place where it's called.
In this case, it's much better to create the RNG outside your loop:
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(-2147483647, 2147483646);
for (i = 0; i < 10000; i++)
{
variable x = uni(rng);
}
The reason for this has little to do with performance (although it will likely perform better, too). The reason is to do with correctness:
You're initialising a new random sequence each time through the loop, and reading just one value. Instead, you should be initialising the sequence just once, and consuming many values from it. Initialise outside the loop, and consume within the loop.
On the performance side, reading from a std::random_device is much slower than taking the next value from a PRNG such as std::mt19937. Doing this just once, outside the loop, will save a lot of time. Further, the std::mt19937 PRNG has a large state (624 integers). It generates this initial state from the value passed to its constructor. Again, doing this just once will give you a performance boost.
Of course, initialising outside the loop has the advantage of also being the correct usage model for the standard RNGs.
The reason is, when you located your random generator definings on top of your code, they will become global and they will be defined automatically when you first hit the "Run" button. If you are using those variables in more than one place, probably it would be the best idea. But if you are not, you don't need it. Because in some scenarios, they might not even called. Anyway, this suggestion is for class or method usages.
However, from what I see, you are going to use that number in a for loop, which will cause your computer to run below code 1000 times.
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(-2147483647, 2147483646);
That is unnecessary, and useless. I beleive your first code will work better on performance side.

Efficient random number generation with C++11 <random>

I am trying to understand how the C++11 random number generation features are meant to be used. My concern is performance.
Suppose that we need to generate a series of random integers between 0..k, but k changes at every step. What is the best way to proceed?
Example:
for (int i=0; i < n; ++i) {
int k = i; // of course this is more complicated in practice
std::uniform_int_distribution<> dist(0, k);
int random_number = dist(engine);
// do something with random number
}
The distributions that the <random> header provides are very convenient. But they are opaque to the user, so I cannot easily predict how they will perform. It is not clear for example how much (if any) runtime overhead will be caused by the construction of dist above.
Instead I could have used something like
std::uniform_real_distribution<> dist(0.0, 1.0);
for (int i=0; i < n; ++i) {
int k = i; // of course this is more complicated in practice
int random_number = std::floor( (k+1)*dist(engine) );
// do something with random number
}
which avoids constructing a new object in each iteration.
Random numbers are often used in numerical simulations where performance is important. What is the best way to use <random> in these situations?
Please do no answer "profile it". Profiling is part of effective optimization, but so is a good understanding of how a library is meant to be used and the performance characteristics of that library. If the answer is that it depends on the standard library implementation, or that the only way to know is to profile it, then I would rather not use the distributions from <random> at all. Instead I can use my own implementation which will be transparent to me and much easier to optimize if/when necessary.
One thing you can do is to have a permanent distribution object so that you only create the param_type object each time like this:
template<typename Integral>
Integral randint(Integral min, Integral max)
{
using param_type =
typename std::uniform_int_distribution<Integral>::param_type;
// only create these once (per thread)
thread_local static std::mt19937 eng {std::random_device{}()};
thread_local static std::uniform_int_distribution<Integral> dist;
// presumably a param_type is cheaper than a uniform_int_distribution
return dist(eng, param_type{min, max});
}
For maximizing performance, first of all consider different PRNG, such as xorshift128+. It has been reported being more than twice as fast as mt19937 for 64-bit random numbers; see http://xorshift.di.unimi.it/. And it can be implemented with a few lines of code.
Moreover, if you don't need "perfectly balanced" uniform distribution and your k is much less than 2^64 (which likely is), I would suggest to write simply something as:
uint64_t temp = engine_64(); // generates 0 <= temp < 2^64
int random_number = temp % (k + 1); // crop temp to 0,...,k
Note, however, that integer division/modulo operations are not cheap. For example, on an Intel Haswell processor, they take 39-103 processor cycles for 64-bit numbers, which is likely much longer than calling an MT19937 or xorshift+ engine.