Hi, I just realised that my solution below for multithreaded random number generators works only in Julia >= 1.5. In particular the test of “CASE A” fails, i.e. the two repetitions issue the same number.
Is there a way to get the same framework working on Julia <= 1.4 ?
using Random, Test, Future, Statistics
FIXEDRNG = MersenneTwister(123)
function generateParallelRngs(rng::AbstractRNG, n::Integer)
step = rand(rng,big(10)^20:big(10)^40) # making the step random too !
rngs = Vector{Union{MersenneTwister,Random._GLOBAL_RNG}}(undef, n) # Vector{typeof(rng)}(undef, n)
rngs[1] = copy(rng)
for i = 2:n
rngs[i] = Future.randjump(rngs[i-1], step)
end
return rngs
end
# ==================================
# New test
println("** Testing generateParallelRngs()...")
x = rand(100)
function innerFunction(bootstrappedx; rng=Random.GLOBAL_RNG)
sum(bootstrappedx .* rand(rng) ./ 0.5)
end
function outerFunction(x;rng = Random.GLOBAL_RNG)
rngs = generateParallelRngs(rng,Threads.nthreads()) # make new copy instances
results = Array{Float64,1}(undef,30)
Threads.@threads for i in 1:30
tsrng = rngs[Threads.threadid()] # Thread safe random number generator
toSample = rand(tsrng, 1:100,100)
bootstrappedx = x[toSample]
innerResult = innerFunction(bootstrappedx, rng=tsrng)
results[i] = innerResult
end
overallResult = mean(results)
return overallResult
end
# Case A - Different sequences..
@test outerFunction(x) != outerFunction(x)
# Case B - Different values, but same sequence..
mainRng = copy(FIXEDRNG)
a = outerFunction(x, rng=mainRng)
b = outerFunction(x, rng=mainRng)
mainRng = copy(FIXEDRNG)
A = outerFunction(x, rng=mainRng)
B = outerFunction(x, rng=mainRng)
@test a != b && a == A && b == B
# Case C - Same value at each call
a = outerFunction(x,rng=copy(FIXEDRNG))
b = outerFunction(x,rng=copy(FIXEDRNG))
@test a == b