StaticArrays.jl icon indicating copy to clipboard operation
StaticArrays.jl copied to clipboard

inconsistent MArray allocation behavior with @inbounds, loop order

Open jlchan opened this issue 4 years ago • 2 comments

Allocations for MArray in an accumulation loop are inconsistent (depend on @inbounds and loop order)

function accum1(L, ::Val{N}) where {N}
    acc = zero(MVector{N,Float64})
    for i ∈ 1:L
        for n ∈ 1:N
            acc[n] += n
        end
    end
    sum(acc) # no allocs if sum(acc) is removed
end

function accum2(L, ::Val{N}) where {N}
    acc = zero(MVector{N,Float64})
    for i ∈ 1:L
        @inbounds for n ∈ 1:N
            acc[n] += n
        end
    end
    sum(acc)
end

function accum3(L, ::Val{N}) where {N}
    acc = zero(MVector{N,Float64})
    for n ∈ 1:N # switch loop order - slower, but no allocs
        for i ∈ 1:L
            acc[n] += n
        end
    end
    sum(acc)
end

@btime accum1($10,$(Val(4)))   #  21.393 ns (1 allocation: 48 bytes)
@btime accum2($10,$(Val(4)))  #  7.710 ns (0 allocations: 0 bytes)
@btime accum3($10,$(Val(4)))  #  21.731 ns (0 allocations: 0 bytes)

jlchan avatar Jan 23 '21 21:01 jlchan

I think it's a general Julia problem with allocation of mutable variables on stack: sometimes Julia can do that, and sometimes it can't, it's not reliable.

mateuszbaran avatar Jan 26 '21 11:01 mateuszbaran

I discovered the same problem.

Yes, but why does this depend on @inbounds and access order ?

j-fu avatar Apr 19 '23 20:04 j-fu