How one can approach multithreading simulations, which uses random numbers generators? Especially if one wants to use non Base generators, like StableRNGs.jl
, RandomNumbers.jl
and others.
Here is a simple example of a random walk, which I want to make parallel
using Random
using StableRNGs
function randomwalk!(tbl, i, rng)
len = size(tbl, 1)
tbl[1, i] = rand(rng)
@inbounds for j in 2:len
tbl[j, i] = (tbl[j - 1, i]) + rand(rng)
end
end
function randomwalk(nparticles, t, rng)
tbl = Array{Float64, 2}(undef, t, nparticles)
map(i -> randomwalk!(tbl, i, rng), 1:nparticles)
return tbl
end
rng = StableRNG(2020)
randomwalk(10, 1000, rng)
Here is what I want to achieve
- I want to be able to use different number generators (MersenneTwister, StableRNG, etc)
- I want calculations to be run on multiple threads
- Calculations should be random in a sense, that there shouldn’t be a correlation between random numbers on different threads. Well, as much as we can talk of non-correlation of pseudo-random numbers anyway.
- It would be good for this algorithm to be not too complicated, so it can be easily used in other similar calculations.
- As a bonus it would be good to have these calculations reproducible. But this is not a very strict requirement, i.e. if one thread is running ahead of another and grab RNG first, it’s ok, as long as the random sequence is not correlated with other threads.
I guess I can do some bookkeeping in randomwalk
function and generate some amount of RNGs, but which way is more appropriate;
- Generate new RNG on-the-fly for each new index
i
, where RNG seed should be generate from the main generator. - Pregenerate RNGs for all elements, and then feed them to
randomwalk!
function.
rngs = StableRNG.(rand(rng, 1:typemax(Int), length(nparticles))
map(i -> randomwalk!(tbl, i, rngs[i]), 1:nparticles)
by the way, is it correct to use 1:typemax(Int)
or range should be made even larger?
3. Generate only Threads.nthreads()
number of new RNGs and determine which one should be used inside randomwalk!
function?
In this discussion Reproducible multithreaded monte-carlo / Task local random if I understand it correctly, it is claimed, that MersenneTwister
is thread-safe now. Is it possible to somehow “upgrade” other RNG to make them thread-safe too? And on the other hand, wouldn’t thread safety of RNG slow down multithreading calculations?