LoopVectorization.jl
LoopVectorization.jl copied to clipboard
`@turbo` and destructuring assignments
Discussed in https://github.com/JuliaSIMD/LoopVectorization.jl/discussions/421
Originally posted by matthias314 August 16, 2022 It seems that destructuring assignments inside a loop may lead to wrong results. The example
function swap(v, w)
@turbo for i in axes(v, 1)
v[i], w[i] = w[i], v[i]
end
end
gives
julia> v = [0, 0];
julia> w = [1, 1];
julia> swap(v, w);
julia> v[1], w[1]
(1, 1) # wrong
I don't know if this is a bug or part of the "don't rely on a specific execution order" rule. In the latter case, would it make sense to mention this case explicitly in the documentation? After all, it's formally a single statement.
This may be a good first issue for someone who wants to give this a try.
julia> using LoopVectorization
julia> function swap_debug(v, w)
LoopVectorization.@turbo_debug for i in axes(v, 1)
v[i], w[i] = w[i], v[i]
end
end
swap_debug (generic function with 1 method)
julia> v = [0, 0];
julia> w = [1, 1];
julia> ls = swap_debug(v, w);
julia> ls.operations
5-element Vector{LoopVectorization.Operation}:
var"##op#226" = w[i]
var"##op#227" = LoopVectorization.identity(var"##op#226")
v[i] = var"##op#227"
var"##op#229" = LoopVectorization.identity(var"##op#227")
w[i] = var"##op#229"
The problem is in parsing. Basically, LV is reading this expression as (look at the operations)
temp0 = w[i]
temp1 = identity(temp0)
v[i] = temp1
temp2 = identity(temp1)
w[i] = temp2
What may be happening is that it's getting parsed in the wrong order.
It sees the store into v[i]
and that we load from v[i]
, and then thinks that we're reloading the same value that we stored.
Something like this:
function swap_debug_sa(v, w)
LoopVectorization.@turbo_debug for i in axes(v, 1)
wi = w[i]
w[i] = v[i]
v[i] = wi
end
end
ls_sa = swap_debug_sa(v, w);
With this, we get
julia> ls_sa.operations
6-element Vector{LoopVectorization.Operation}:
var"##op#234" = w[i]
var"##op#235" = v[i]
var"##op#236" = LoopVectorization.identity(var"##op#235")
w[i] = var"##op#236"
var"##op#238" = LoopVectorization.identity(var"##op#234")
v[i] = var"##op#238"
So the fix is probably just to make sure things get parsed in the right order.