Why does rand() in threads slowdown speed in Julia 1.3

In Julia 1.3 each thread has its own default global RNG. Calling rand() in each thread is safe. So the following code that calculates pi returns correct result:

function par_pi(n::Int)
    hits = zeros(Int, nthreads())
    @threads for i in 1:n
        x, y = rand(), rand()
        hits[threadid()] += (x^2 + y^2 <= 1)
    end

    4.0 * sum(hits) / n
end
@time par_pi(10_000_000)

But the above code runs 4x slower than the following version that uses manually allocated RNGs:

const threadsRNG = [MersenneTwister() for i in 1:nthreads()]

function par_pi2(n::Int)
    hits = zeros(Int, nthreads())
    @threads for i in 1:n
        rng = threadsRNG[threadid()]
        x, y = rand(rng), rand(rng)
        hits[threadid()] += (x^2 + y^2 <= 1)
    end

    4.0 * sum(hits) / n
end
@time par_pi2(10_000_000)

How to explain it?

1 Like

@btime instead of @time?

@jling, thanks for replying.
I used @btime and the results as follows:

25.503 ms (59 allocations: 7.00 KiB) with new RNGs
102.228 ms (59 allocations: 7.00 KiB) with default RNGs

I can confirm your finding

I see the similar results with the latest nightly. It’s strange because @code_lowered is basically the same for both functions. Maybe worth filing a bug report.

julia> @btime par_pi(10^7)
  81.293 ms (44 allocations: 5.89 KiB)
3.140466

julia> @btime par_pi2(10^7)
  27.520 ms (44 allocations: 5.89 KiB)
3.14193

julia> versioninfo()
Julia Version 1.4.0-DEV.670
Commit 032dbe33e3 (2019-12-29 22:39 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-8.0.1 (ORCJIT, skylake)
Environment:
  JULIA_NUM_THREADS = 8

EDIT:
The difference in the lowered code is the following line. I’m not sure how to read it. Do the numbers indicate a different version of the function?
Main.:(var"#19#threadsfor_fun#4")
Main.:(var"#2#threadsfor_fun#3")

it’s just the location of function in your REPL

@robsmith11, thank you for confirming the result. Indeed it is strange; Two lowered code are same except for the generated variable names. I will file a bug report.

1 Like

I’ve filed a bug report:

2 Likes