PLease see the whole question
I know that srand()
should be called only once, but my 2nd code segment shows that that does not solve the issue!!!!
The program I have written is giving me outputs which I can't quite make out why is it so. Different alterations of code segments give different outputs.
Objective of code:
The code uses omp
to simply run a piece of code for 3 threads. Each thread has to print 3 random values using the rand()
function. So, a total of 9 outputs would come. Thread 0
is the main thread/ the main program's run flow. Thread 1
and Thread 2
are the fellow new threads created at the start of code for the threads.
The code:
#include<omp.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
#pragma omp parallel num_threads(3)
{
srand(time(NULL));
int i=0;
for(i=0;i<3;i++)
{
printf("\nRandom number: %d by thread %d", rand(), omp_get_thread_num());
}
}
return 0;
}
The output:
Random number: 17105 by thread 0
Random number: 30076 by thread 0
Random number: 21481 by thread 0
Random number: 17105 by thread 1
Random number: 30076 by thread 1
Random number: 21481 by thread 1
Random number: 17105 by thread 2
Random number: 30076 by thread 2
Random number: 21481 by thread 2
But if I make keep the srand(time(NULL))
before the code for thread like,
srand(time(NULL));
#pragma omp parallel num_threads(3)
{
int i=0;
......
......(rest is same)
The output is,
The output:
Random number: 16582 by thread 0
Random number: 14267 by thread 0
Random number: 14030 by thread 0
Random number: 41 by thread 1
Random number: 18467 by thread 1
Random number: 6334 by thread 1
Random number: 41 by thread 2
Random number: 18467 by thread 2
Random number: 6334 by thread 2
The Problem, and my doubts:
So,
Please help me understand this whole thing..
Updated: Inserted direct answers to the OP's enumerated questions.
What is actually happening here?
Although some versions of the rand()
function may be "thread safe" in some sense, there is no reason to believe or expect that without any external memory synchronization, the set of values returned by multiple rand()
calls executed by different threads will be the same as the set of values returned by the same number of calls all executed by one thread. In particular, rand()
maintains internal state that is modified on each call, and without any memory synchronization, it is entirely plausible that one thread will not see updates to that internal state that are performed by other threads. In that case, two or more threads may generate partially or wholly the same sequence of numbers.
How come the placement of the
srand()
function make a difference only to the main thread (thread0
)?
The only thing that can be said for certain is that if the srand()
is outside the parallel block then it is executed only by the main thread, whereas if it is inside then it is executed separately by each thread. Inasmuch as your code is not properly synchronized, the effects of each case are not predictable from the source code, so my next comments are mostly speculative.
Supposing that time()
, with its (only) one-second precision, returns the same value in each thread, placing srand()
inside the parallel region ensures that every thread sees the same initial random number seed. If they then do not see each other's updates then they will generate the same sequences of pseudo-random numbers. Note, however, that you can neither safely rely on the threads seeing each other's updates nor safely rely on them not seeing each others updates.
If you put the srand()
outside the parallel region, however, so that it is executed only by the main thread, then there are additional possibilities. If OMP maintains a thread pool whose members are already started before you enter the parallel section, then it may be that threads 1 and 2 fail to see the effect of thread 0's srand()
call at all, and therefore both proceed with the default seed. There are other possibilities.
Why is it that either ways the the other 2 new threads always output same random number for the respective call to
rand()
?
It's impossible to say with any certainty. I'm inclined to guess, however, that none of the threads involved see each other's updates to rand()
's internal state.
How is this
srand()
andrand()
even linked, to cause this abnormality?
The two functions are intimately linked. The purpose of srand()
is to modify rand()
's internal state (to "seed" it, hence the "s" in "srand"), so as to start the psuedo-random number sequence it generates at a different (but still deterministic) point.
This problem can be solved in the same way that any problem involving multi-threaded access to shared variables can be solved: by applying synchronization. In this case, the most straightforward form of synchronization would probably be to protect rand()
calls with a mutex. Since this is OMP code, your best bet might be to use OMP locks to implement a mutex, as it seems dicey to mix explicit pthreads objects with OMP declarations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With