Mysterious Core.Box

please help. In the following, using a @boundscheck would cause a mysterious Core.Box. How to solve it??? using 1.1.0, thanks.

function fun1()
    nthreads = Threads.nthreads()

    x = zeros(200)
    Threads.@threads for t in Base.OneTo(nthreads)
        for i in t:nthreads:200
            x[i] = t + i
        end
    end

    return Statistics.mean(x)
end

function fun2()
    @boundscheck 2 >= 1 || error()      # the ONLY difference

    nthreads = Threads.nthreads()

    x = zeros(200)
    Threads.@threads for t in Base.OneTo(nthreads)
        for i in t:nthreads:200
            x[i] = t + i
        end
    end

    return Statistics.mean(x)
end

julia> @code_warntype fun1()    # fine

julia> @code_warntype fun2()
Body::Any
1 ── %1  = %new(Core.Box)::Core.Box

This is performance of captured variables in closures · Issue #15276 · JuliaLang/julia · GitHub once again (note that the @threads macro creates a closure). The let-block workaround works in this case:

import Statistics
function fun2()
    @boundscheck 2 >= 1 || error()      # the ONLY difference

    nthreads = Threads.nthreads()

    x = zeros(200)
    let x = x, nthreads = nthreads
        Threads.@threads for t in 1
            for i in t:nthreads:200
                x[i] = t + i
            end
        end
    end

    return Statistics.mean(x)
end
2 Likes

It works. thanks.