LoopVectorization.jl
LoopVectorization.jl copied to clipboard
no method matching similar in broadcasting expression
On LV v0.8.1
julia> using StaticArrays, LoopVectorization
julia> function softmin_avx(a::T, b, c, γ) where T
γ = -γ
v = SVector(a, b, c, zero(T))
v = @avx v ./ γ
maxv = maximum(v)
ve = @avx exp.(v .- maxv) #.* SVector(one(T), one(T), one(T), zero(T))
γ*(log(sum(ve)) + maxv)
end
softmin_avx (generic function with 1 method)
julia> softmin_avx(1.0, 1.0, 1.0, 1.0)
ERROR: MethodError: no method matching similar(::Base.Broadcast.Broadcasted{StaticArrays.StaticArrayStyle{1},Nothing,typeof(/),Tuple{SArray{Tuple{4},Float64,1,4},Float64}}, ::Type{Float64})
Closest candidates are:
similar(::JuliaInterpreter.Compiled, ::Any) at /home/fredrikb/.julia/packages/JuliaInterpreter/sZur5/src/types.jl:7
similar(::Array{T,1}, ::Type) where T at array.jl:358
similar(::Array{T,2}, ::Type) where T at array.jl:359
...
Stacktrace:
[1] vmaterialize at /home/fredrikb/.julia/packages/LoopVectorization/lmGAZ/src/broadcast.jl:316 [inlined]
[2] softmin_avx(::Float64, ::Float64, ::Float64, ::Float64) at ./none:4
[3] top-level scope at none:0
Trying the same thing with vmap produces another error
jjulia> function softmin_avx(a::T, b, c, γ) where T
γ = -γ
v = SVector(a, b, c, zero(T))
v = vmap(v->v / γ, v)
maxv = maximum(v)
ve = vmap(v->exp(v - maxv), v) #.* SVector(one(T), one(T), one(T), zero(T))
γ*(log(sum(ve)) + maxv)
end
softmin_avx (generic function with 1 method)
julia> softmin_avx(1.0, 1.0, 1.0, 1.0)
ERROR: Abstract type Any does not have a definite size.
Stacktrace:
[1] sizeof(::Type{T} where T) at ./essentials.jl:451
[2] #s19#58(::Any, ::Any, ::Any) at /home/fredrikb/.julia/packages/VectorizationBase/e8k1q/src/vector_width.jl:26
[3] (::Core.GeneratedFunctionStub)(::Any, ::Vararg{Any,N} where N) at ./boot.jl:526
[4] #s18#60(::Any, ::Any, ::Any) at /home/fredrikb/.julia/packages/VectorizationBase/e8k1q/src/vector_width.jl:33
[5] (::Core.GeneratedFunctionStub)(::Any, ::Vararg{Any,N} where N) at ./boot.jl:526
[6] vmap_quote(::Int64, ::Type{Any}) at /home/fredrikb/.julia/packages/LoopVectorization/lmGAZ/src/map.jl:3
[7] #s16#5(::Any, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any) at /home/fredrikb/.julia/packages/LoopVectorization/lmGAZ/src/map.jl:32
[8] (::Core.GeneratedFunctionStub)(::Any, ::Vararg{Any,N} where N) at ./boot.jl:526
[9] vmap_call at /home/fredrikb/.julia/packages/LoopVectorization/lmGAZ/src/map.jl:165 [inlined]
[10] vmap at /home/fredrikb/.julia/packages/LoopVectorization/lmGAZ/src/map.jl:175 [inlined]
[11] softmin_avx(::Float64, ::Float64, ::Float64, ::Float64) at ./none:4
[12] top-level scope at none:0
This is reminiscent of: https://github.com/chriselrod/LoopVectorization.jl/issues/7
But I'll make that one about supporting StaticArrays, and this one about not throwing an error and instead using a fallback.
The problem here is because broadcasting falls back via dispatch, and I guess it does so on the wrong level with respect to StaticArrays.
vmaterialize constructs a similar array here, and then calls vmaterialize! on it.
Fall back behavior is achieved by dispatch selecting a method that forwards to Base.Broadcast.materialize!.
The problem, of course, is that StaticArrays doesn't write into a destination, you can't materialize! into one. The error comes when trying to allocate that destination in the first place, inside vmaterialize.
So, the check for compatibility has to look at all the inputs (like @avx applied to loops does), and not just on the destination. I'll make broadcasting use the same mechanism as loops for this.