<p dir="auto">This 3x regression from Julia 1.2 to Julia 1.3 / 1.5 on the simplest random walk simulation is not good:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function walk(T)
    x = 0
    
    for i in 1:T        
        if rand() &lt; 0.5
            x += 1
        else
            x -= 1
        end
    end
    
    return x
end

function run(T, N)
    sumsq = 0.0
    
    for i in 1:N
        w = walk(T)
        sumsq += w^2
    end
    
    return sumsq / N
end"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">walk</span>(T)
    x <span class="pl-k">=</span> <span class="pl-c1">0</span>
    
    <span class="pl-k">for</span> i <span class="pl-k">in</span> <span class="pl-c1">1</span><span class="pl-k">:</span>T        
        <span class="pl-k">if</span> <span class="pl-c1">rand</span>() <span class="pl-k">&lt;</span> <span class="pl-c1">0.5</span>
            x <span class="pl-k">+=</span> <span class="pl-c1">1</span>
        <span class="pl-k">else</span>
            x <span class="pl-k">-=</span> <span class="pl-c1">1</span>
        <span class="pl-k">end</span>
    <span class="pl-k">end</span>
    
    <span class="pl-k">return</span> x
<span class="pl-k">end</span>

<span class="pl-k">function</span> <span class="pl-en">run</span>(T, N)
    sumsq <span class="pl-k">=</span> <span class="pl-c1">0.0</span>
    
    <span class="pl-k">for</span> i <span class="pl-k">in</span> <span class="pl-c1">1</span><span class="pl-k">:</span>N
        w <span class="pl-k">=</span> <span class="pl-c1">walk</span>(T)
        sumsq <span class="pl-k">+=</span> w<span class="pl-k">^</span><span class="pl-c1">2</span>
    <span class="pl-k">end</span>
    
    <span class="pl-k">return</span> sumsq <span class="pl-k">/</span> N
<span class="pl-k">end</span></pre></div>
<p dir="auto">Timings after warm-up:<br>
Julia 1.2:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; @time run(10^4, 10^5)
  1.467660 seconds (7 allocations: 208 bytes)
9997.0888 "><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">@time</span> <span class="pl-c1">run</span>(<span class="pl-c1">10</span><span class="pl-k">^</span><span class="pl-c1">4</span>, <span class="pl-c1">10</span><span class="pl-k">^</span><span class="pl-c1">5</span>)
  <span class="pl-c1">1.467660</span> seconds (<span class="pl-c1">7</span> allocations<span class="pl-k">:</span> <span class="pl-c1">208</span> bytes)
<span class="pl-c1">9997.0888</span> </pre></div>
<p dir="auto">Julia 1.3.1:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; @time run(10^4, 10^5);
  5.518198 seconds (7 allocations: 208 bytes)"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">@time</span> <span class="pl-c1">run</span>(<span class="pl-c1">10</span><span class="pl-k">^</span><span class="pl-c1">4</span>, <span class="pl-c1">10</span><span class="pl-k">^</span><span class="pl-c1">5</span>);
  <span class="pl-c1">5.518198</span> seconds (<span class="pl-c1">7</span> allocations<span class="pl-k">:</span> <span class="pl-c1">208</span> bytes)</pre></div>
<p dir="auto">Julia 1.5-DEV.0:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="julia&gt; @time run(10^4, 10^5);
  4.891881 seconds"><pre class="notranslate">julia<span class="pl-k">&gt;</span> <span class="pl-c1">@time</span> <span class="pl-c1">run</span>(<span class="pl-c1">10</span><span class="pl-k">^</span><span class="pl-c1">4</span>, <span class="pl-c1">10</span><span class="pl-k">^</span><span class="pl-c1">5</span>);
  <span class="pl-c1">4.891881</span> seconds</pre></div>
<p dir="auto">Default RNGs in threads slowdown performance in Julia 1.3.</p>
<p dir="auto">Here is my environment:</p>
<blockquote>
<p dir="auto">julia&gt; versioninfo(verbose=true)<br>
Julia Version 1.3.0<br>
Commit <a class="commit-link" data-hovercard-type="commit" data-hovercard-url="https://github.com/JuliaLang/julia/commit/46ce4d79337bdd257ee2e3d2f4bb1c55ff0a5030/hovercard" href="https://github.com/JuliaLang/julia/commit/46ce4d79337bdd257ee2e3d2f4bb1c55ff0a5030"><tt>46ce4d7</tt></a> (2019-11-26 06:09 UTC)<br>
Platform Info:<br>
OS: Windows (x86_64-w64-mingw32)<br>
Microsoft Windows [Version 10.0.18362.535]<br>
CPU: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz:<br>
speed         user         nice          sys         idle          irq<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="817954" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/1" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/1/hovercard" href="https://github.com/JuliaLang/julia/issues/1">#1</a>  4008 MHz     633296            0       811953     12463687       195718  ticks<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="817959" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/2" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/2/hovercard" href="https://github.com/JuliaLang/julia/issues/2">#2</a>  4008 MHz     423671            0       328500     13156765         6218  ticks<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="818013" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/3" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/3/hovercard" href="https://github.com/JuliaLang/julia/issues/3">#3</a>  4008 MHz     935390            0       638296     12335250         6562  ticks<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="818058" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/4" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/4/hovercard" href="https://github.com/JuliaLang/julia/issues/4">#4</a>  4008 MHz     436546            0       558328     12913859         2953  ticks<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="818144" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/5" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/5/hovercard" href="https://github.com/JuliaLang/julia/issues/5">#5</a>  4008 MHz     772937            0       654812     12480984         5468  ticks<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="818224" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/6" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/6/hovercard" href="https://github.com/JuliaLang/julia/issues/6">#6</a>  4008 MHz     499781            0       503546     12905406         3000  ticks<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="818235" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/7" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/7/hovercard" href="https://github.com/JuliaLang/julia/issues/7">#7</a>  4008 MHz     721312            0       661609     12525812         3750  ticks<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="818245" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/8" data-hovercard-type="issue" data-hovercard-url="/JuliaLang/julia/issues/8/hovercard" href="https://github.com/JuliaLang/julia/issues/8">#8</a>  4008 MHz     578609            0       338343     12991781         2156  ticks</p>
<p dir="auto">Memory: 15.953498840332031 GB (8580.15625 MB free)<br>
Uptime: 13908.0 sec<br>
Load Avg:  0.0  0.0  0.0<br>
WORD_SIZE: 64<br>
LIBM: libopenlibm<br>
LLVM: libLLVM-6.0.1 (ORCJIT, skylake)<br>
Environment:<br>
JULIA_EDITOR = "C:\Users\Earth\AppData\Local\atom\app-1.42.0\atom.exe"  -a<br>
JULIA_NUM_THREADS = 8</p>
</blockquote>
<p dir="auto">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:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="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 &lt;= 1)
    end

    4.0 * sum(hits) / n
end
@btime par_pi(10_000_000) #102.228 ms (59 allocations: 7.00 KiB)"><pre class="notranslate"><code class="notranslate">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 &lt;= 1)
    end

    4.0 * sum(hits) / n
end
@btime par_pi(10_000_000) #102.228 ms (59 allocations: 7.00 KiB)
</code></pre></div>
<p dir="auto">But the above code runs 4x slower than the following version that uses manually allocated RNGs:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="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 &lt;= 1)
    end

    4.0 * sum(hits) / n
end
@time par_pi2(10_000_000) #25.503 ms (59 allocations: 7.00 KiB)"><pre class="notranslate"><code class="notranslate">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 &lt;= 1)
    end

    4.0 * sum(hits) / n
end
@time par_pi2(10_000_000) #25.503 ms (59 allocations: 7.00 KiB)
</code></pre></div>
<p dir="auto">What's strange is that lowered versions are identical to each other except for one generated variable name:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="julia&gt; @code_lowered par_pi(10^7)
CodeInfo(
1 ─ %1  = Main.nthreads()
│         hits = Main.zeros(Main.Int, %1)
│         range = 1:n
│   %4  = Main.:(var&quot;#390#threadsfor_fun#31&quot;)
│   %5  = Core.typeof(hits)
│   %6  = Core.typeof(range)
│   %7  = Core.apply_type(%4, %5, %6)
│   %8  = hits
│         threadsfor_fun = %new(%7, %8, range)
│   %10 = Base.Threads.threadid()
│   %11 = %10 != 1
└──       goto #3 if not %11
2 ─ %13 = Base.invokelatest
│   %14 = threadsfor_fun
│         (%13)(%14, true)
└──       goto #4
3 ─ %17 = Base.cconvert(Base.Threads.Any, threadsfor_fun)
│   %18 = Base.unsafe_convert(Base.Threads.Any, %17)
└──       $(Expr(:foreigncall, :(:jl_threading_run), Nothing, svec(Any), 0, :(:ccall), :(%18), :(%17)))
4 ┄       Base.Threads.nothing
│   %21 = Main.sum(hits)
│   %22 = 4.0 * %21
│   %23 = %22 / n
└──       return %23
)"><pre class="notranslate"><code class="notranslate">julia&gt; @code_lowered par_pi(10^7)
CodeInfo(
1 ─ %1  = Main.nthreads()
│         hits = Main.zeros(Main.Int, %1)
│         range = 1:n
│   %4  = Main.:(var"#390#threadsfor_fun#31")
│   %5  = Core.typeof(hits)
│   %6  = Core.typeof(range)
│   %7  = Core.apply_type(%4, %5, %6)
│   %8  = hits
│         threadsfor_fun = %new(%7, %8, range)
│   %10 = Base.Threads.threadid()
│   %11 = %10 != 1
└──       goto #3 if not %11
2 ─ %13 = Base.invokelatest
│   %14 = threadsfor_fun
│         (%13)(%14, true)
└──       goto #4
3 ─ %17 = Base.cconvert(Base.Threads.Any, threadsfor_fun)
│   %18 = Base.unsafe_convert(Base.Threads.Any, %17)
└──       $(Expr(:foreigncall, :(:jl_threading_run), Nothing, svec(Any), 0, :(:ccall), :(%18), :(%17)))
4 ┄       Base.Threads.nothing
│   %21 = Main.sum(hits)
│   %22 = 4.0 * %21
│   %23 = %22 / n
└──       return %23
)
</code></pre></div>
<p dir="auto">and</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="julia&gt; @code_lowered par_pi2(10^7)
CodeInfo(
1 ─ %1  = Main.nthreads()
│         hits = Main.zeros(Main.Int, %1)
│         range = 1:n
│   %4  = Main.:(var&quot;#372#threadsfor_fun#30&quot;)
│   %5  = Core.typeof(hits)
│   %6  = Core.typeof(range)
│   %7  = Core.apply_type(%4, %5, %6)
│   %8  = hits
│         threadsfor_fun = %new(%7, %8, range)
│   %10 = Base.Threads.threadid()
│   %11 = %10 != 1
└──       goto #3 if not %11
2 ─ %13 = Base.invokelatest
│   %14 = threadsfor_fun
│         (%13)(%14, true)
└──       goto #4
3 ─ %17 = Base.cconvert(Base.Threads.Any, threadsfor_fun)
│   %18 = Base.unsafe_convert(Base.Threads.Any, %17)
└──       $(Expr(:foreigncall, :(:jl_threading_run), Nothing, svec(Any), 0, :(:ccall), :(%18), :(%17)))
4 ┄       Base.Threads.nothing
│   %21 = Main.sum(hits)
│   %22 = 4.0 * %21
│   %23 = %22 / n
└──       return %23
)"><pre class="notranslate"><code class="notranslate">julia&gt; @code_lowered par_pi2(10^7)
CodeInfo(
1 ─ %1  = Main.nthreads()
│         hits = Main.zeros(Main.Int, %1)
│         range = 1:n
│   %4  = Main.:(var"#372#threadsfor_fun#30")
│   %5  = Core.typeof(hits)
│   %6  = Core.typeof(range)
│   %7  = Core.apply_type(%4, %5, %6)
│   %8  = hits
│         threadsfor_fun = %new(%7, %8, range)
│   %10 = Base.Threads.threadid()
│   %11 = %10 != 1
└──       goto #3 if not %11
2 ─ %13 = Base.invokelatest
│   %14 = threadsfor_fun
│         (%13)(%14, true)
└──       goto #4
3 ─ %17 = Base.cconvert(Base.Threads.Any, threadsfor_fun)
│   %18 = Base.unsafe_convert(Base.Threads.Any, %17)
└──       $(Expr(:foreigncall, :(:jl_threading_run), Nothing, svec(Any), 0, :(:ccall), :(%18), :(%17)))
4 ┄       Base.Threads.nothing
│   %21 = Main.sum(hits)
│   %22 = 4.0 * %21
│   %23 = %22 / n
└──       return %23
)
</code></pre></div>