Slow `convert` for arrays. Use multiple dispatch instead?

I was wondering why something like

x = rand(10)
convert(Vector{Float64}, x)

is relatively slow, when x does not even need to be converted.

I noticed that in Julia base the convert method is defined as

convert(::Type{T}, a::AbstractArray) where {T<:Array} = a isa T ? a : T(a)

At least for converting some a :: Array I would rather do something like

convert(::Type{T}, a :: T) where T<:Array = a

I am sure that I’m overlooking some subtleties concerning the type hierarchy here.
But taking

std_convert(::Type{T}, a::AbstractArray) where {T<:Array} = a isa T ? a : T(a)

new_convert(::Type{T}, a::T) where{T<:Array} = a
new_convert(::Type{T}, a::F) where{T<:Array, F<:AbstractArray} = T(a)

x = rand(10)

leads to a significant speedup when no conversion has to be done

julia> @btime std_convert( Vector{Float64}, x )
  115.684 ns
julia> @btime new_convert( Vector{Float64}, x )
  3.851 ns

… and equal performance otherwise:

julia >@btime std_convert( Vector{Float32}, x )
  162.644 ns (1 allocation: 128 bytes)
julia> @btime new_convert( Vector{Float32}, x )
  152.948 ns

I would appreciate any comment on whether the new_convert way is sensible :slight_smile:

Use const x = ... and there is no difference (see Performance Tips - Avoid (non-constant) global variables).

1 Like

Or simply interpolate global variables when benchmarking to avoid the dynamic-dispatch overhead, i.e. use @btime std_convert( Vector{Float64}, $x )

3 Likes

Thank you both!
I totally forgot that I was operating in global scope. Silly me.

When actually testing functions using either method there is no difference.