Deterministic random number generator tied to inst

2019-02-15 10:59发布

问题:

Random numbers have been well covered here, so I'll keep it brief.

I use srand and rand to generate some deterministic random numbers in a simulation. However, when running multiple simulations at once on separate threads, the individual sequence gets muddled up and becomes non deterministic, because all threads draw from the same pool. Is there an easy way to "bind" rand to draw from a specific instance? Or would I have to switch to something like Boost.Random?

回答1:

Your compiler most likely already has something very like Boost.Random.

C++0x includes a <random> header which is based on Boost.Random (with a few tweaks here and there).

Before then, TR1, a set of "semi-standard" libraries was available for most compilers as well, which contains nearly the same <random> header.



回答2:

On Linux, rand_r is a reentrant version of rand, but it is a rather weak PRNG, so might want to use something from the *rand48_r family of functions.

rand_s is a reentrant version of rand on Windows, but since its state is an unsigned int, it is also bound to be quite weak.

Long story short, you're probably better off with Boost.Random.



回答3:

I strongly recommend using <random> or <tr1/random> for fine-grained access to high-quality PRNG classes which you can instantiate one in each thread with full control over their seeds and thus their resulting sequence of random numbers.



回答4:

You can use this code, keeping a rnd_state struct for each of the threads. You may initialize the rnd_state with rand(). It's just an idea and this is a reasonable RNG.

From the linux kernel source code (random32.c)

the values in rnd_state should be initialized like: s1 > 1, s2 > 7, s3 > 15.

The paper claims this is a maximally equidistributed combined Tausworthe generator based on code from GNU Scientific Library 1.5 (30 Jun 2004)

struct rnd_state {
    u32 s1, s2, s3;
};

static u32 __random32(struct rnd_state *state)
{
#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)

    state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
    state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
    state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);

    return (state->s1 ^ state->s2 ^ state->s3);
}

Academia: http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps



回答5:

A bunch of PRNGs are being added to the standard library. Another option is to pregenerate a large pool of numbers for each thread and then issue them one-at-a-time.



回答6:

The documentation for my C++ random number library, RandomLib, contains an illustration of using parallel number streams in OpenMP; see http://randomlib.sourceforge.net/html/parallel.html. You might be able to adapt the ideas presented there to your application.