Suppose I run the following code:
newstate=123; threadFor i(1,1000,1); {e,newstate}=rndn(100,5,newstate} threadEndFor;
Then GAUSS 15 will generate an error message indicating something wrong with LHS of threadFor. Alternatives are of course to replace "threadFor-threadEndFor" with "for-endfor", or "ThreadBegin-ThreadEnd-ThreadJoin". Or I could use:
threadFor i(1,1000,1); e=rndn(100,5}; threadEndFor;
But each time I run the code, the results will be different as the random numbers are different.
So is there a decent way to use directly "threadFor" to generate thread-safe random numbers?
1 Answer
0
Inside of threadFor loops, there are two kinds of assignments you can make. The first type of assignment is to an index (using the threadFor counter. The second type of assignment in a threadFor loop is to a temporary variable. If the entire variable is assigned to inside of a threadFor loop, it must be to a temporary variable. Temporary variables must be assigned to before they can be used inside of a threadFor loop.
The reason that temporary variables must be first assigned to in a loop before they are used is to make the code more explicit, so that some subtle programming bugs are harder to make. The code below is a good example.
newstate=123; threadFor i(1,1000,1); {e,newstate}=rndn(100,5,newstate); threadEndFor;
It might at first appear that the code above will create 1000 different sets of 100x5 random normal numbers, each created from a different state variable. When passing in a state variable to the rndn function, rndn will create random normal numbers based upon the incoming state or seed variable and then return a new state variable so that the next call to rndn can begin at the point in the sequence just after the last call left off.
However, since many iterations of a threadFor loop are run at the same time, there will not always be a new state variable available to use. So either each iteration would have to wait for the previous iteration to run, or some iterations would have to use the same state variable. It is to prevent these problems, that threadFor temporary variables must be assigned to when first used in a threadFor statement. Here is the more explicit version of the code above:
newstate=123; threadFor i(1,1000,1); tmp_newstate = newstate; { e, tmp_newstate } = rndn(100, 5, tmp_newstate); threadEndFor;
In this code snippet, (which GAUSS will allow you to run) it is much more clear what is happening. At the start of each iteration, tmp_newstate is being set to equal 123 and then that is passed into the rndn function. Each iteration of the loop is producing the same random numbers which is probably not what you want.
To create different random numbers in each iteration of the loop, we need to give the rndn function a different seed or state variable. The simplest way to do that is to use the threadFor loop counter as the seed. For example:
threadFor i(1,1000,1); { e, tmp_state } = rndn(100, 5, i); threadEndFor;
The code above will create repeatable random numbers where every iteration of the loop has a different set of random numbers. Some other options that would also work are:
1. Create a vector of states and use an index into the vector as the starting seed, like this:
//set seed below to make 'rndu' call repeatable rndseed 45234452; num_iters = 1000; my_states = trunc(1e5 .* rndu(num_iters, 1)); threadFor i(1,num_iters,1); { e, tmp_state } = rndn(100, 5, my_states[i]); threadEndFor;
2. Perform some operation like multiplication on the threadFor loop counter to use as the starting seed variable, like this:
mult_var = 2350; threadFor i(1,1000,1); { e, tmp_state } = rndn(100, 5, i * mult_var); threadEndFor;
Your Answer
1 Answer
Inside of threadFor loops, there are two kinds of assignments you can make. The first type of assignment is to an index (using the threadFor counter. The second type of assignment in a threadFor loop is to a temporary variable. If the entire variable is assigned to inside of a threadFor loop, it must be to a temporary variable. Temporary variables must be assigned to before they can be used inside of a threadFor loop.
The reason that temporary variables must be first assigned to in a loop before they are used is to make the code more explicit, so that some subtle programming bugs are harder to make. The code below is a good example.
newstate=123; threadFor i(1,1000,1); {e,newstate}=rndn(100,5,newstate); threadEndFor;
It might at first appear that the code above will create 1000 different sets of 100x5 random normal numbers, each created from a different state variable. When passing in a state variable to the rndn function, rndn will create random normal numbers based upon the incoming state or seed variable and then return a new state variable so that the next call to rndn can begin at the point in the sequence just after the last call left off.
However, since many iterations of a threadFor loop are run at the same time, there will not always be a new state variable available to use. So either each iteration would have to wait for the previous iteration to run, or some iterations would have to use the same state variable. It is to prevent these problems, that threadFor temporary variables must be assigned to when first used in a threadFor statement. Here is the more explicit version of the code above:
newstate=123; threadFor i(1,1000,1); tmp_newstate = newstate; { e, tmp_newstate } = rndn(100, 5, tmp_newstate); threadEndFor;
In this code snippet, (which GAUSS will allow you to run) it is much more clear what is happening. At the start of each iteration, tmp_newstate is being set to equal 123 and then that is passed into the rndn function. Each iteration of the loop is producing the same random numbers which is probably not what you want.
To create different random numbers in each iteration of the loop, we need to give the rndn function a different seed or state variable. The simplest way to do that is to use the threadFor loop counter as the seed. For example:
threadFor i(1,1000,1); { e, tmp_state } = rndn(100, 5, i); threadEndFor;
The code above will create repeatable random numbers where every iteration of the loop has a different set of random numbers. Some other options that would also work are:
1. Create a vector of states and use an index into the vector as the starting seed, like this:
//set seed below to make 'rndu' call repeatable rndseed 45234452; num_iters = 1000; my_states = trunc(1e5 .* rndu(num_iters, 1)); threadFor i(1,num_iters,1); { e, tmp_state } = rndn(100, 5, my_states[i]); threadEndFor;
2. Perform some operation like multiplication on the threadFor loop counter to use as the starting seed variable, like this:
mult_var = 2350; threadFor i(1,1000,1); { e, tmp_state } = rndn(100, 5, i * mult_var); threadEndFor;