Why is rand() not so random after fork?

Solution 1:

The outputs must be the same. If two processes each seed the random number with the same seed and each call rand once, they must get the same result. That's the whole point of having a seed. All of your processes call srand with the same seed (because you only call srand once) and they all call rand once, so they must get the same result.

Uncommenting the srand won't make a difference because unless the number of seconds has changed, they will still give the same seed. You could do:

srand(time(NULL) ^ (getpid()<<16));

Solution 2:

The rand() function is a pseudo-random number generator. This means that the sequence of numbers generated is deterministic, depending only upon the seed provided.

Because you are forking the same process 10 times, the state of the random number generator is the same for each child. The next time you call rand() you will get the same value.

By calling srand(time(NULL)) inside the child process, you are potentially helping but the granularity of time() is only 1 second, so all your children probably start inside the same second. Seeding with the same value generates the same pseudo-random sequence.

You could try seeding with a value that depends on the child number:

srand(time(NULL) - i*2);

(I used i*2 in the event that time() advances by 1 second during the fork loop.)

Solution 3:

If your code is running fast enough, srand() might be seeded with the exact same time for each fork. time() only changes every second.

Solution 4:

The reason that even adding srand(time(NULL)); (the line inside the if block that you have commented) inside the loop isn't making a difference is because modern computers can execute that whole block extremely fast, and time counts in seconds. From the man pages:

time() returns the time as the number of seconds since the Epoch...

If you add a sleep(1); after the if statement in the while loop and uncomment the srand call, the results will be different, since time would now return a different value because a second has elapsed.

It would however be more appropriate to use a different seed value, rather than waiting. Something like i would be a good idea since it'll be unique for each iteration of the loop.

Solution 5:

You're not reseeding when you make a child process. The state of the random number generator is exactly the same.

Even if you seed again in your child, you're seeding with the time with a +/- 1 second granularity. When you fork, it all happens in less than a second.

Try seeding it with something different and more random.