random numbers and multiple srand calls
Asked Answered
D

3

6

I'm writing a program that will generate numerous random numbers in loops. I'm trying to make the numbers somewhat less predictable (not only for security, but to avoid collisions on multiple threads).

I've noticed that many documents recommended calling srand only once in the program. For example: Random numbers in C, the selected answer is "As a general rule, only call srand() once in your program".

But why? Why would it be so bad to do something like this:

int THIS_THREAD_SEED;
int randomness() {
    ++THIS_THREAD_SEED;
    int i;
    for(i=0 i<1000; i++) {
        unsigned n = rand_r(&THIS_THREAD_SEED) / RAND_MAX;
        /* do something with n */
    }
    return 0;
}

int do_something() {
    int i;
    for(i=0; i<1000; i++) {
        randomness();
    }
}

As such, the seed changes once per function call, not once per program. This way, no matter how many threads are running, no two threads will every have the same random number list... Right?

UPDATE Assume I either have a unique seed for each thread, or mutex on a global SEED to prevent race conditions.

Dana answered 26/11, 2012 at 1:11 Comment(4)
"Making numerous calls to random numbers" seems to be everyone who I've spoken to on the phone recently.Phosphocreatine
Your program most likely has a race condition on SEED. Before worrying about the intricacies of random number generation, it might be more important to get the basics of multi-threading right. Your idea may well be workable, but it's probably not your biggest concern.Phosphocreatine
@KerrekSB: I know how to use a mutex just fine; I didn't want to muddy up the question with extra code about threads, because this question is really about srandDana
Related: #602811Gaffer
S
2

let's break this question into two separate ones.

  1. if you worry about race conditions when accessing random number generator, create a mutex or other synchronization primitive to avoid this.

  2. if you think about calling srand() several times, please, don't. the reason behind this is the random generator initialization routine which sets up the variables based on seed has worse random characteristics, gives worse performance than the random generator itself and should be not used as a substitute.

Seng answered 26/11, 2012 at 1:36 Comment(1)
"has worse random characteristics, gives worse performance" -- exactly what I was looking for. Thanks!Dana
F
2

srand() will reset the stream of numbers rand() will generate for you.

From the manual for srand:

   The srand() function sets its argument as the seed for a  new  sequence
   of  pseudo-random  integers  to be returned by rand().  These sequences
   are repeatable by calling srand() with the same seed value.

If you need "better" random numbers then rand() provides you should look into other sources of randomness.

Also srand() is not used for rand_r(), the argument you provide (to rand_r()) is used instead.

And if you want to use rand_r() from multiple threads all threads should have a local seed, you shouldn't use a single global variable for that.

Alternatives to rand() can be Mersenne Twister

But if you need "real" randomness you have to look hardware support.

And to answer:

As such, the seed changes once per function call, not once per program. This way, no matter how many threads are running, no two threads will every have the same random number list... Right?

No, doesn't work that way, you should have a thread-local SEED variable initialized to something unique for every thread. You could use time() for the first seed, and then use that random sequence to generate seeds for the other threads, or you read 4-8 bytes from /dev/random or /dev/urandom if you'r using *nix.

Hope that gives some insight as this is midnight rumble, good night <3

Floatplane answered 26/11, 2012 at 1:36 Comment(0)
G
0

To avoid race conditions, you need to use a separate seed variable for each thread. This means each thread will have its own separate random number sequence.

Galer answered 26/11, 2012 at 1:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.