I have been learning how to use JET.jl to check my code for type instabilities, and I notice that it keeps giving me a runtime dispatch after calling Julia’s built-iin sort routines. This happens even when my functions have fairly heavy type annotations, for example:
function makevector(n::Integer)::Vector{Int}
rand(1:50, n)
end
function samplemedian_inplace(n::Integer)
v = makevector(n)
sort!(v)
v[length(v)÷2]
end
function samplemedian_outofplace(n::Integer)
v = makevector(n) |> sort
v[length(v)÷2]
end
JET.jl says:
julia> using JET
julia> @report_opt samplemedian_inplace(200)
═════ 1 possible error found ═════
┌ @ /home/max/OptimalApplication.jl/sandbox2.jl:9 Main.sort!(v)
│┌ @ sort.jl:714 Base.Sort.#sort!#8(Base.Sort.defalg(v), Base.Sort.isless, Base.Sort.identity, Base.Sort.nothing, Base.Sort.Forward, #self#, v)
││┌ @ sort.jl:718 Base.Sort.extrema(v)
│││┌ @ reducedim.jl:994 Base.#extrema#782(Base.:, Base.pairs(Core.NamedTuple()), #self#, a)
││││┌ @ reducedim.jl:994 Base._extrema(a, dims)
│││││┌ @ reducedim.jl:998 Base.#_extrema#784(Base.pairs(Core.NamedTuple()), #self#, a, _3)
││││││┌ @ reducedim.jl:998 Base._extrema(Base.identity, a, Base.:)
│││││││┌ @ reducedim.jl:999 Base.#_extrema#785(Base.pairs(Core.NamedTuple()), #self#, f, a, _4)
││││││││┌ @ reducedim.jl:999 Base.mapreduce(Base.ExtremaMap(f), Base._extrema_rf, a)
│││││││││┌ @ reducedim.jl:357 Base.#mapreduce#759(Base.:, Base._InitialValue(), #self#, f, op, A)
││││││││││┌ @ reducedim.jl:357 Base._mapreduce_dim(f, op, init, A, dims)
│││││││││││┌ @ reducedim.jl:365 Base._mapreduce(f, op, Base.IndexStyle(A), A)
││││││││││││┌ @ reduce.jl:419 Base.mapreduce_empty_iter(f, op, A, Base.IteratorEltype(A))
│││││││││││││┌ @ reduce.jl:367 Base.reduce_empty_iter(Base.MappingRF(f, op), itr, ItrEltype)
││││││││││││││┌ @ reduce.jl:371 Base.reduce_empty(op, Base.eltype(itr))
│││││││││││││││┌ @ reduce.jl:348 Base.mapreduce_empty(ExtremaMap{typeof(identity)}(identity), _extrema_rf, _)
││││││││││││││││ runtime dispatch detected: Base.mapreduce_empty(ExtremaMap{typeof(identity)}(identity), _extrema_rf, _::Type{Int64})
│││││││││││││││└─────────────────
julia> @report_opt samplemedian_outofplace(200)
═════ 1 possible error found ═════
┌ @ /home/max/OptimalApplication.jl/sandbox2.jl:14 v = Main.|>(Main.makevector(n), Main.sort)
│┌ @ operators.jl:911 f(x)
││┌ @ sort.jl:773 Base.Sort.#sort#9(Base.pairs(Core.NamedTuple()), #self#, v)
│││┌ @ sort.jl:773 Base.Sort.sort!(Base.Sort.copymutable(v))
││││┌ @ sort.jl:714 Base.Sort.#sort!#8(Base.Sort.defalg(v), Base.Sort.isless, Base.Sort.identity, Base.Sort.nothing, Base.Sort.Forward, #self#, v)
│││││┌ @ sort.jl:718 Base.Sort.extrema(v)
││││││┌ @ reducedim.jl:994 Base.#extrema#782(Base.:, Base.pairs(Core.NamedTuple()), #self#, a)
│││││││┌ @ reducedim.jl:994 Base._extrema(a, dims)
││││││││┌ @ reducedim.jl:998 Base.#_extrema#784(Base.pairs(Core.NamedTuple()), #self#, a, _3)
│││││││││┌ @ reducedim.jl:998 Base._extrema(Base.identity, a, Base.:)
││││││││││┌ @ reducedim.jl:999 Base.#_extrema#785(Base.pairs(Core.NamedTuple()), #self#, f, a, _4)
│││││││││││┌ @ reducedim.jl:999 Base.mapreduce(Base.ExtremaMap(f), Base._extrema_rf, a)
││││││││││││┌ @ reducedim.jl:357 Base.#mapreduce#759(Base.:, Base._InitialValue(), #self#, f, op, A)
│││││││││││││┌ @ reducedim.jl:357 Base._mapreduce_dim(f, op, init, A, dims)
││││││││││││││┌ @ reducedim.jl:365 Base._mapreduce(f, op, Base.IndexStyle(A), A)
│││││││││││││││┌ @ reduce.jl:419 Base.mapreduce_empty_iter(f, op, A, Base.IteratorEltype(A))
││││││││││││││││┌ @ reduce.jl:367 Base.reduce_empty_iter(Base.MappingRF(f, op), itr, ItrEltype)
│││││││││││││││││┌ @ reduce.jl:371 Base.reduce_empty(op, Base.eltype(itr))
││││││││││││││││││┌ @ reduce.jl:348 Base.mapreduce_empty(ExtremaMap{typeof(identity)}(identity), _extrema_rf, _)
│││││││││││││││││││ runtime dispatch detected: Base.mapreduce_empty(ExtremaMap{typeof(identity)}(identity), _extrema_rf, _::Type{Int64})
││││││││││││││││││└─────────────────
Is there a way to prevent this runtime dispatch? Is it worth doing so?
(This is Julia v1.8.0-beta1.)