JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.9k stars 5.49k forks source link

Regression in rand due to inlining behavior #37030

Closed haampie closed 3 years ago

haampie commented 4 years ago

This came up in the julia slack channel, via https://twitter.com/genkuroki/status/1293558651588767750. Disregarding the type instability from their benchmark, there seems to be a true regression

julia> using BenchmarkTools; using Random: default_rng
julia> function sim!(a, N)
         n = length(a)
         rng = default_rng()
         @inbounds for iter in 1:N
           i = rand(rng, 1:n)
           j = rand(rng, 1:n-1)
           j = ifelse(j == i, n, j)
           Δ = 0.05 * a[i]
           a[i] -= Δ
           a[j] += Δ
         end
       end
sim! (generic function with 1 method)

Julia 1.4.1:

@btime sim!($(rand(1000)), 10^5)
  991.752 μs (0 allocations: 0 bytes)

Julia 1.5.0:

julia> @btime sim!($(rand(1000)), 10^5)
  1.107 ms (0 allocations: 0 bytes)

around 10% difference.

Finally, it does seem like rand is actually faster on Julia 1.5.0:

harmen-desktop ~ $ ./julia-1.4.1/bin/julia -e 'using BenchmarkTools; println(@benchmark rand($(1:10)))'
Trial(11.964 ns)
harmen-desktop ~ $ ./julia-1.5.0/bin/julia -e 'using BenchmarkTools; println(@benchmark rand($(1:10)))'
Trial(7.411 ns)

so it's a bit confusing why sim! is slower on Julia 1.5.0.

mbauman commented 4 years ago

The hoisting of the default RNG is #36418.

haampie commented 4 years ago

Ah. So let me remove the bit about sim_simpler!, since that's handled elsewhere already :)

mbauman commented 3 years ago

Looks like this improved in 1.6 and yet again on 1.7-DEV (likely due to xoroshiro #40546 in the second case):

Common set up ```Julia julia> using BenchmarkTools; using Random: default_rng julia> function sim!(a, N) n = length(a) rng = default_rng() @inbounds for iter in 1:N i = rand(rng, 1:n) j = rand(rng, 1:n-1) j = ifelse(j == i, n, j) Δ = 0.05 * a[i] a[i] -= Δ a[j] += Δ end end sim! (generic function with 1 method) ```
julia-1.4> @btime sim!($(rand(1000)), 10^5)
  1.171 ms (0 allocations: 0 bytes)

julia-1.5> @btime sim!($(rand(1000)), 10^5)
  1.361 ms (0 allocations: 0 bytes)

julia-1.6> @btime sim!($(rand(1000)), 10^5)
  827.056 μs (0 allocations: 0 bytes)

julia-1.7> @btime sim!($(rand(1000)), 10^5)
  697.995 μs (0 allocations: 0 bytes)