Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance of threadsafe rand() #36418

Closed
mbauman opened this issue Jun 24, 2020 · 5 comments
Closed

Performance of threadsafe rand() #36418

mbauman opened this issue Jun 24, 2020 · 5 comments
Labels
domain:multithreading Base.Threads and related functionality domain:randomness Random number generation and the Random stdlib performance Must go faster

Comments

@mbauman
Copy link
Sponsor Member

mbauman commented Jun 24, 2020

I was surprised at how big a hit we suffer in looking up the THREAD_RNG — even when Julia is started with only 1 thread and without using @threads at all! Is there something we can do here?

julia> using Random, .Threads

julia> nthreads()
1

julia> function serialpi(n)
           inside = 0
           for i in 1:n
               x, y = rand(), rand()
               inside += (x^2 + y^2 <= 1)
           end
           return 4 * inside / n
       end
serialpi (generic function with 1 method)

julia> serialpi(1); @time serialpi(100_000_000);
  0.625890 seconds

julia> function serialpi2(n)
           inside = 0
           rng = Random.THREAD_RNGs[1]
           for i in 1:n
               x, y = rand(rng), rand(rng)
               inside += (x^2 + y^2 <= 1)
           end
           return 4 * inside / n
       end
serialpi2 (generic function with 1 method)

julia> serialpi2(1); @time serialpi2(100_000_000);
  0.257850 seconds
@mbauman mbauman added performance Must go faster domain:randomness Random number generation and the Random stdlib labels Jun 24, 2020
@KristofferC
Copy link
Sponsor Member

Ref #34216

@mbauman
Copy link
Sponsor Member Author

mbauman commented Jun 24, 2020

Ah, I knew we had this before — Kristoffer search is the best GitHub search.

Still, I feel like this is a slightly more constrained case; do we really need to be paying the cost of this indirection with nthreads()==1?

@tkf
Copy link
Member

tkf commented Jun 24, 2020

It'd be great if the compiler can hoist out the lookup for rng. It'd also help "context variables" as designed in #35833.

@yuyichao
Copy link
Contributor

Ah, yeah, this is the reason I had before why thread local variable can't be replaced with task local and why caching of thread local variable can't be disabled. Unless there's a way to make RNG still work equally well when many more are created and destroied on the fly. Ref #35688

@mbauman
Copy link
Sponsor Member Author

mbauman commented Jun 3, 2021

This is now fixed due to #40546 (which removes the Random.THREAD_RNGs entirely). Equivalent test code, though, is:

julia> using Random, .Threads

julia> nthreads()
1

julia> function serialpi(n)
           inside = 0
           for i in 1:n
               x, y = rand(), rand()
               inside += (x^2 + y^2 <= 1)
           end
           return 4 * inside / n
       end
serialpi (generic function with 1 method)

julia> serialpi(1); @time serialpi(100_000_000);
  0.327586 seconds

julia> function serialpi2(n)
           inside = 0
           rng = Random.default_rng(1)
           for i in 1:n
               x, y = rand(rng), rand(rng)
               inside += (x^2 + y^2 <= 1)
           end
           return 4 * inside / n
       end
serialpi2 (generic function with 1 method)

julia> serialpi2(1); @time serialpi2(100_000_000);
  0.324798 seconds

@mbauman mbauman closed this as completed Jun 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:multithreading Base.Threads and related functionality domain:randomness Random number generation and the Random stdlib performance Must go faster
Projects
None yet
Development

No branches or pull requests

4 participants