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

no method matching similar in broadcasting expression

Open baggepinnen opened this issue 4 years ago • 1 comments

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

baggepinnen avatar May 25 '20 12:05 baggepinnen

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.

chriselrod avatar May 25 '20 20:05 chriselrod