C++ with OpenMP thread safe random numbers - c++

I am trying to draw some random points, and then calculate smth with them. I am using few threads, but my random is not so random as it supposed to be... I mean when I am using rand() I gets correct answer, but very slow(because of static rand), so I am using rand_r with seed, but the answer of my program is always wird.
double randomNumber(unsigned int seed, double a, double b) {
return a + ((float)rand_r(&seed))/(float)(RAND_MAX) * (b-a);
}
my program:
#pragma omp parallel
for(int i = 0; i < points; i++){
seedX = (i+1) * time(NULL);
seedY = (points - i) * time(NULL);
punkt.x = randomNumber(seedX, minX, maxX);
punkt.y = randomNumber(seedY, minY, maxY);
...
}
I found some solution in other topics(some mt19937 generators etc), but i cant compile anything.
I am using g++ -fopenmp for compiling.(g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2)
edit:
seed = rand();
#pragma omp parallel
for(int i = 0; i < points; i++){
punkt.x = randomNumber(seed, minX, maxX);
punkt.y = randomNumber(seed, minY, maxY);
...
}

Re-seeding your generators within each iteration of the for loop is going to ruin their statistical properties.
Also, it's likely that you'll introduce correlation between your x and y values if you extract them using two linear congruential generators.
Keep it simple; use one generator, and one seed.
Going forward, I'd recommend you use mt19937 as it will have better properties still. Linear congruential generators can fail a chi squared test for autocorrelation which is particularly important if you are using it for an x, y plot.

I believe that others are trying to say is, seed one in constructor with srand(some number), then do not seed anymore.
class someRandomNumber
{
}

Related

Setting GSL RNG seed correctly in Rcpp for model with repeat iterations

I am writing a stochastic, process driven model of transmission of infection and diagnostic testing to detect infection. The model requires repeat random samples across multiple time steps and iterations. The faster my model can run, the better. For the random sampling in the model, parameters for the random samples can change at each time step in the model. I first wrote my model in R, and then in CPP (via the great Rcpp package). In Rcpp, using the R based random number generator, the model takes about 7% of the time to run as it took in R. I was advised that using GSL within CPP for random number generation is faster again. In the CPP model, with GSL based random sampling instead of R based random sampling, I get a marginal increase in speed. However, I am not sure that I am using the GSL based random sampler correctly.
My questions are:
Is it correct to only do the seed setting procedure once for the GSL RNG based on the time of day and use this same construct for all of my random draws (as I have done in code below)? I confess I do not fully understand the seed setting procedure within CPP for GSL as I am new to both. I have compared the distributions produced using both R-based and GSL-based RNG and they are very similar, so hopefully this bit is OK.
I obtained the code for setting the GSL seed according to the time of day from this Stack Overflow post:
GSL Uniform Random Number Generator
I was expecting a greater increase in speed using the GSL RNG. Is there anything I can do to maximize the speed of the GSL RNG?
I am using a Windows machine and the RStudio interface. I am sourcing the CPP functions from R using the Rcpp package. All of the packages and programmes were recently reinstalled. Here is the session info:
R version 4.2.2 (2022-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 22000)
For context, I am a veterinary epidemiologist with R experience, but only two months into learning CPP. This is my first stack exchange query. Thanks in advance for your time!
Here is an example of what I am trying to achieve written in CPP (using Rcpp in RStudio) and using the GSL based RNG. Please can somebody tell me if this is the correct way to set the GSL RNG seed? Is it OK to do the seed setting process just once at the top of the function?
// CPP code - function GSL RNG written using Rcpp on a CPP file in RStudio
// [[Rcpp::plugins(cpp11)]]
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_blas.h>
#include <iostream>
#include <gsl/gsl_math.h>
#include <sys/time.h>
#include <RcppGSL.h>
// [[Rcpp::depends(RcppGSL)]]
// [[Rcpp::export]]
Rcpp:: NumericMatrix check_cpp_gsl_rng(int n_iters,
int min_unif,
int max_unif,
double exp_rate,
double bernoulli_prob)
{
const gsl_rng_type * T;
gsl_rng * r;
gsl_rng_env_setup();
struct timeval tv; // Seed generation based on time
gettimeofday(&tv,0);
unsigned long mySeed = tv.tv_sec + tv.tv_usec;
T = gsl_rng_default; // Generator setup
r = gsl_rng_alloc (T);
gsl_rng_set(r, mySeed);
// matrix to collect outputs
Rcpp:: NumericMatrix Output_Mat(n_iters, 7);
for (int i = 0; i < n_iters; i++) // in real model, parameters may change for each iteration
{
// random exponential draws
Output_Mat(i, 0) = gsl_ran_exponential(r , (1 / exp_rate)); // exp 1
Output_Mat(i, 1) = gsl_ran_exponential(r , (1 / exp_rate)); // exp 2
// random uniform draws
Output_Mat(i, 2) = gsl_ran_flat(r, min_unif, max_unif); // unif 1
Output_Mat(i, 3) = gsl_ran_flat(r, min_unif, max_unif); // unif 2
// random Bernoulli draws
Output_Mat(i, 4) = gsl_ran_bernoulli(r, bernoulli_prob); // Bernoulli 1
Output_Mat(i, 5) = gsl_ran_bernoulli(r, bernoulli_prob); // Bernoulli 2
Output_Mat(i, 6) = i; // record iteration number
}
return Output_Mat;
gsl_rng_free(r);
// end of function
}
The plot below shows a comparison of run speeds of the random sampling function implemented in R only, CPP using the R RNG and CPP using the GSL RNG (as in code above) based on 100 comparisons of 1000 iterations using the "microbenchmark" package.
A package you may find useful is my RcppZiggurat (github). It revives the old but fast Ziggurat RNG for normal covariates and times it. It use several other Ziggurat implementations as benchmarks -- including one from the GSL.
First, we can use its code and infrastructure to set up a simple structure (see below). I first show that 'yes indeed' we can seed a GSL RNG:
> setseedGSL(42)
> rnormGSLZig(5)
[1] -0.811264 1.092556 -1.873074 -0.146400 -1.653703
> rnormGSLZig(5) # different
[1] -1.281593 0.893496 -0.545510 -0.337940 -1.258800
> setseedGSL(42)
> rnormGSLZig(5) # as before
[1] -0.811264 1.092556 -1.873074 -0.146400 -1.653703
>
Note that we need a global variable for an instance of a GSL RNG 'state'.
Second, we can show that Rcpp is actually faster that either the standard normal GSL generator or its Ziggurat implementation. Using Rcpp vectorised is even faster:
> library(microbenchmark)
> n <- 1e5
> res <- microbenchmark(rnormGSLZig(n), rnormGSLPlain(n), rcppLoop(n), rcppDirect(n))
> res
Unit: microseconds
expr min lq mean median uq max neval cld
rnormGSLZig(n) 996.580 1151.7065 1768.500 1355.053 1424.220 18597.82 100 b
rnormGSLPlain(n) 996.316 1085.6820 1392.323 1358.696 1431.715 2929.05 100 b
rcppLoop(n) 223.221 259.2395 641.715 518.706 573.899 13779.20 100 a
rcppDirect(n) 46.224 67.2075 384.004 293.499 320.919 14883.86 100 a
>
The code is below; it is a pretty quick adaptation from my RcppZiggurat package. You can sourceCpp() it (if you have RcppGSL installed which I used to 'easily' get the compile and link instructions to the GSL) and it will run the demo code shown above.
#include <Rcpp/Lighter>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
// [[Rcpp::depends(RcppGSL)]]
class ZigguratGSL {
public:
ZigguratGSL(uint32_t seed=12345678) {
gsl_rng_env_setup() ;
r = gsl_rng_alloc (gsl_rng_default);
gsl_rng_set(r, seed);
}
~ZigguratGSL() {
gsl_rng_free(r);
}
double normZig() {
const double sigma=1.0;
return gsl_ran_gaussian_ziggurat(r, sigma);
}
double normPlain() {
const double sigma=1.0;
return gsl_ran_gaussian_ziggurat(r, sigma);
}
void setSeed(const uint32_t seed) {
gsl_rng_set(r, seed);
}
private:
gsl_rng *r;
};
static ZigguratGSL gsl;
// [[Rcpp::export]]
void setseedGSL(const uint32_t s) {
gsl.setSeed(s);
return;
}
// [[Rcpp::export]]
Rcpp::NumericVector rnormGSLZig(int n) {
Rcpp::NumericVector x(n);
for (int i=0; i<n; i++) {
x[i] = gsl.normZig();
}
return x;
}
// [[Rcpp::export]]
Rcpp::NumericVector rnormGSLPlain(int n) {
Rcpp::NumericVector x(n);
for (int i=0; i<n; i++) {
x[i] = gsl.normPlain();
}
return x;
}
// [[Rcpp::export]]
Rcpp::NumericVector rcppLoop(int n) {
Rcpp::NumericVector x(n);
for (int i=0; i<n; i++) {
x[i] = R::rnorm(1.0,0.0);
}
return x;
}
// [[Rcpp::export]]
Rcpp::NumericVector rcppDirect(int n) {
return Rcpp::rnorm(n, 1.0, 0.0);
}
/*** R
setseedGSL(42)
rnormGSLZig(5)
rnormGSLZig(5) # different
setseedGSL(42)
rnormGSLZig(5) # as before
library(microbenchmark)
n <- 1e5
res <- microbenchmark(rnormGSLZig(n), rnormGSLPlain(n), rcppLoop(n), rcppDirect(n))
res
*/
PS We write it as Rcpp. Capital R, lowercase cpp.

When is it preferable to use rand() vs a generator + a distribution? (e.g. mt19937 + uniform_real_distribution)

After going through the rabbit hole that is learning about rand() and how it's not very good at generating uniform pseudorandom data based on what I've dug into based on this post:
Random float number generation. I am stuck trying to figure out which strategy would yield better balance of performance and accuracy when iterated a significant number of times, 128*10^6 for an example of my use case.
This link is what led me to make this post, otherwise I would have just used rand(): rand() considered harmful
Anyway, my main goal is to understand whether rand() is ever preferable to use over the generator + distribution method. There doesn't seem to be very good info even on cppreference.com or cplusplus.com for performance or time complexity for either of the two strategies.
For example, between the following two random number generation strategies is it always preferable to use the 2nd approach?
rand()
std::mt19937 and uniform_real_distribution
Here is an example of what my code would be doing:
int main(){
int numIterations = 128E6;
std::vector<float> randomData;
randomData.resize(numIterations);
for(int i = 0; i < numIterations; i++){
randomData[i] = float(rand())/float(RAND_MAX);
}
}
vs.
#include<random>
int main(){
std::mt19937 mt(1729);
std::uniform_real_distribution<float> dist(0.0, 1.0);
int numIterations = 128E6;
std::vector<float> randomData;
randomData.resize(numIterations);
for(int i = 0; i < numIterations; i++){
randomData[i] = dist(mt);
}
}

Default_random_engine passed into a function gives repeatable results

I have a class Permutation that inherits from std::vector<int>. I created a constructor that makes the object filled with non-repeating numbers. Randomness is meant to be guaranteed by <random> stuff, so the declaration goes like this:
/* Creates a random permutation of a given length
* Input: n - length of permutation
* generator - engine that does the randomizing work */
Permutation(int n, default_random_engine generator);
Function itself looks like this (irrevelant details skipped):
Permutation::Permutation(int n, default_random_engine generator):
vector<int>(n, 0)
{
vector<int> someIntermediateStep(n, 0);
iota(someIntermediateStep.begin(), someIntermediateStep.end(), 0); //0, 1, 2...
shuffle(someIntermediateStep.begin(), someIntermediateStep.end(),
generator);
// etc.
}
And is called in the following context:
auto seed = std::chrono::system_clock::now().time_since_epoch().count();
static std::default_random_engine generator(seed);
for (int i = 0; i < n; i++)
Permutation test(length, generator);
Code compiles perfectly fine, but all instances of Permutation are the same. How to force regular generation of random numbers? I know that default_random_engine should be binded to a distribution object, but hey, I don't have any – I use the engine only in shuffle() (at least at the moment).
Is there any solution or a workaround that still uses the goodness of <random>?
Your Permutation constructor takes the engine in by value. So, in this loop:
for (int i = 0; i < n; i++)
Permutation test(length, generator);
You are passing a copy of the same engine, in the same state, over and over. So you are of course getting the same results. Pass the engine by reference instead
Permutation::Permutation(int n, default_random_engine& generator)
That way its state will be modified by the call to std::shuffle.
So a childish mistake, just as I supposed – I mixed various solutions to similar problems in a wrong way.
As Benjamin pointed out, I mustn't copy the same engine over and over again, because it remains, well, the same. But this alone doesn't solve the issue, since the engine is pointlessly declared static (thanks, Zereges).
For the sake of clarity, corrected code looks like this:
Permutation(int n, default_random_engine &generator);
// [...]
Permutation::Permutation(int n, default_random_engine generator):
vector<int>(n, 0)
{
vector<int> someIntermediateStep(n, 0);
iota(someIntermediateStep.begin(), someIntermediateStep.end(), 0); //0, 1, 2...
shuffle(someIntermediateStep.begin(), someIntermediateStep.end(),
generator);
// etc.
}
// [...]
// some function
auto seed = chrono::system_clock::now().time_since_epoch().count();
default_random_engine generator(seed);
for (int i = 0; i < n; i++)
Permutation test(length, generator);

openmp private/shared data in a MC simulation

I'm simulating a stochastic differential equation with a monte carlo method, which in principle is perfectly suited for openMP, as different realizations do not depend on each other. Unfortunately I'm facing some problems with my code, which produces wrong result as soon as I turn on openMP. Without it, it works perfectly fine. My 'critical' loop looks like this:
double price = 0.0
#pragma omp parallel for private(VOld, VNew)
for (long i = 0; i < NSim; ++i){
VOld = S_0;
for (long index = 0; index < Nt; ++index){
VNew = VOld + (dt * r * VOld) + (sqrdt * sig * VOld * dW());
VOld = VNew;
}
double tmp = myOption.PayOff(VNew);
price += (tmp)/double(NSim);
}
I would truly appreciate any help. Thank you in advance :-)
A common mistake is forgetting that each thread must have its own random number generator. If that's not the case, then each call to dW will be messing up with the internal state of the (shared, instead of private) random number generator.
I hope this helps.
Well one problem I see is that you have a race condition on the variable price. You should be doing a reduction
#pragma omp parallel for private(VOld, VNew) reduction(+:price)
The same goes for your variable OptionPrice
Also it looks to me like rng is still shared, not private. You should define it in the parallel block if you want it private or declare it private (for private variables I prefer to declare them int the parallel block which automatically makes them private rather than declare them private).
Ok, so based on #jmbr and #raxman answers I moved the inner loop to a separate function, and made sure that rng is now really private. Also, note the seeding trick, which turns up vital. On top of that I introduced reduction on the OptionPrice. The code below works fine.
double SimulateStockPrice(const double InitialPrize, const double dt, const long Nt, const double r, const double sig, boost::mt19937 *rng){
static unsigned long seed = 0;
boost::mt19937 *rng = new boost::mt19937();
rng -> seed((++seed) + time(NULL));
boost::normal_distribution<> nd(0.0, 1.0);
boost::variate_generator< boost::mt19937, boost::normal_distribution<> > dW(*rng, nd);
double sqrdt = sqrt(dt);
double PriceNew(0.0), PriceOld(InitialPrize);
for (long index = 0; index < Nt; ++index){
PriceNew = PriceOld + (dt * r * PriceOld) + (sqrdt * sig * PriceOld * dW());
PriceOld = PriceNew;
}
delete rng;
return PriceNew;
}
Then in the big loop I go with:
#pragma omp parallel for default(none) shared(dt, NSim, Nt, S_0, myOption) reduction(+:OptionPrice)
for (long i = 0; i < NSim; ++i){
double StockPrice = SimulateStockPrice(S_0, dt, Nt, myOption.r, myOption.sig, rng);
double PayOff = myOption.myPayOffFunction(StockPrice);
OptionPrice += PayOff;
}
And off you go :-)

Fast way to avoid modulo bias

I'm doing a shuffle and it gets done very often on a small array. Could be anything from 1 - 10 elements.
I've tried the accepted answer in this question:
Is this C implementation of Fisher-Yates shuffle correct?
Unfortunately it's extremely slow.
I need a faster way of doing this and avoiding modulo bias which I'm seeing. Any suggestions?
EDIT:
Sorry I should point out that it's not the shuffle that's slow, it's the method used to generate a random int range. i.e. rand_int(). I'm using a Mersenne twister algorithm and RAND_MAX in my case is UINT_MAX to help out. This of course makes it slower when n is much smaller than RAND_MAX
I've also found 2 implementations of a rand_int type function.
static int rand_int(int n) {
int limit = RAND_MAX - RAND_MAX % n;
int rnd;
do {
rnd = rand();
} while (rnd >= limit);
return rnd % n;
}
The following is much much faster. But, does it avoid the modulo bias problem?
int rand_int(int limit) {
int divisor = RAND_MAX/(limit);
int retval;
do {
retval = rand() / divisor;
} while (retval > limit);
return retval;
}
Edit
To address the basic question on avoiding the modulo bias with rand() see http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx.
In short, you can't get truly uniform other than skipping non-domain random numbers1; The article lists some formulae to get a smaller bias (int r = rand() / ( RAND_MAX / N + 1 ) eg) without sacrificing more performance.
1 See Java's implementation of Random.nextInt(int):
http://download.oracle.com/javase/1.4.2/docs/api/java/util/Random.html#nextInt(int)
Using C++
You should be able to use std::random_shuffle (from <algorithm> header);
If you must roll your own shuffle implementation, I suggest using std::random (TR1, C++0x or Boost). It comes with a number of generators and distributions, with varying performance characteristics.
#include <random>
std::mt19937 rng(seed);
std::uniform_int_distribution<int> gen(0, N); // uniform, unbiased
int r = gen(rng);
Refer to the boost documentation for a good overview of Boost Random generator and distribution characteristics:
http://www.boost.org/doc/libs/1_47_0/doc/html/boost_random/reference.html#boost_random.reference.generators
Here is a sample of doing std::random_shuffle using Boost Random, directly:
#include <algorithm>
#include <functional>
#include <vector>
#include <boost/random.hpp>
struct Rng
{
Rng(boost::mt19937 &rng) : _rng(rng) {}
unsigned operator()(unsigned i)
{
boost::uniform_int<> dist(0, i - 1);
return dist(_rng);
}
private:
boost::mt19937 &_rng;
};
boost::mt19937 state;
std::random_shuffle(v.begin(), v.end(), Rng(state));