-
-
Notifications
You must be signed in to change notification settings - Fork 396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove convert methods which cause method invalidations #2278
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2278 +/- ##
==========================================
+ Coverage 91.54% 91.71% +0.16%
==========================================
Files 42 42
Lines 4448 4440 -8
==========================================
Hits 4072 4072
+ Misses 376 368 -8
Continue to review full report at Codecov.
|
IIRC, it was replaced by JuMP.jl/src/mutable_arithmetics.jl Lines 80 to 93 in 1129e58
|
What's the effect on compile time, if any? |
Virtually none. From what I understand from reading the blogpost, the main issue is
So to fix these, we can either remove the methods from JuMP (as above), or fix the type instability in the lower-level package. For example, the The next three worst ones caused by JuMP are: julia> trees[end - 1]
inserting collect_to_with_first!(dest::Union{JuMP.Containers.DenseAxisArray{T,N,Ax,L} where L<:Tuple{Vararg{Dict,N}} where Ax where N, JuMP.Containers.SparseAxisArray{T,N,K} where K<:Tuple{Vararg{Any,N}} where N}, first_value::T, iterator, state) where T in JuMP.Containers at /Users/oscar/.julia/dev/JuMP/src/Containers/Containers.jl:33 invalidated:
backedges: 1: superseding collect_to_with_first!(dest::AbstractArray, v1, itr, st) in Base at array.jl:709 with MethodInstance for collect_to_with_first!(::AbstractArray, ::Any, ::Base.Generator{_A,MacroTools.var"#1#2"{Vector{Any}}} where _A, ::Any) (1 children)
2: superseding collect_to_with_first!(dest, v1, itr, st) in Base at array.jl:715 with MethodInstance for collect_to_with_first!(::Any, ::Any, ::Base.Generator{_A,MacroTools.var"#1#2"{Vector{Any}}} where _A, ::Any) (3 children)
3: superseding collect_to_with_first!(dest, v1, itr, st) in Base at array.jl:715 with MethodInstance for collect_to_with_first!(::Any, ::Dict{String,Any}, ::Base.Generator{_A,typeof(Pkg.TOML.table2dict)} where _A, ::Any) (126 children)
julia> trees[end - 2]
inserting +(α::T, arg::Union{MathOptInterface.ScalarAffineFunction{T}, MathOptInterface.ScalarQuadraticFunction{T}}, args::Union{MathOptInterface.SingleVariable, MathOptInterface.ScalarAffineFunction{T}, MathOptInterface.ScalarQuadraticFunction{T}}...) where T in MathOptInterface.Utilities at /Users/oscar/.julia/packages/MathOptInterface/bygN7/src/Utilities/functions.jl:1121 invalidated:
backedges: 1: superseding +(a, b, c, xs...) in Base at operators.jl:538 with MethodInstance for +(::Int64, ::Any, ::Any) (98 children)
julia> trees[end - 6]
inserting eachindex(A::JuMP.Containers.DenseAxisArray) in JuMP.Containers at /Users/oscar/.julia/dev/JuMP/src/Containers/DenseAxisArray.jl:137 invalidated:
backedges: 1: superseding eachindex(A::AbstractVector{T} where T) in Base at abstractarray.jl:212 with MethodInstance for eachindex(::AbstractVector{var"#s57"} where var"#s57"<:Symbol) (1 children)
2: superseding eachindex(A::AbstractVector{T} where T) in Base at abstractarray.jl:212 with MethodInstance for eachindex(::AbstractVector{var"#s70"} where var"#s70"<:AbstractString) (1 children)
3: superseding eachindex(A::AbstractVector{T} where T) in Base at abstractarray.jl:212 with MethodInstance for eachindex(::AbstractVector{var"#s71"} where var"#s71"<:Real) (1 children)
4: superseding eachindex(A::AbstractVector{T} where T) in Base at abstractarray.jl:212 with MethodInstance for eachindex(::AbstractVector{T} where T) (2 children)
5: superseding eachindex(A::AbstractVector{T} where T) in Base at abstractarray.jl:212 with MethodInstance for eachindex(::AbstractVector{var"#s843"} where var"#s843"<:Integer) (13 children) |
Quite impressive, @odow! With As I explained elsewhere (JuliaLang/www.julialang.org#794 (comment)) fixing invalidations triggered by JuMP itself is mostly you being a good citizen for your users, not for direct usage of JuMP itself. (There are some exceptions, e.g., if you need methods you invalidate.) So you should already see some speedups on Julia 1.6 from changes that prevent your predecessors from triggering invalidations. But don't have exceptional hopes that eliminating invalidations caused by JuMP itself will massively decrease your own latency, unless you're explicitly using methods that you're invalidating. |
I should mention that the invalidation work has a "secret" subtext: if we eliminate invalidations, then in addition to its direct benefits it will also eliminate one big obstacle to caching native code in It will still take someone knowledgeable and enthusiastic to implement that feature, and I'm not sure how Jeff/Jameson feel about it. But until recently the invalidations were so rampant that it was basically pointless to even try. We're almost to a spot where it's no longer pointless. |
Yeah, we seem to be invalidating very generic fallback methods or ones in Pkg. I'm coming round to the idea that our compilation issue when testing stems from the fact that almost all tests are unique enough that they are all touching different code paths. We test lots of different functions with different typed inputs, rather than testing lots of edge cases of the same input types. I've also found a few inference failures in the JuMP source and various tests, but fixing them has no noticeable impact on the overall runtime.
Cthulhu and SnoopCompile are incredible... |
…ions. These methods appear to be used from before we switched to MutableArithmetics. In the future, instead of overloading Base.convert, we should use a new function like `to_constant(::AffExpr)` which avoids the invalidation. Alternatively, future versions of Julia may be clever enough to avoid the invalidations.
575154d
to
68b25c8
Compare
To update this: Current julia> using SnoopCompile
julia> invalidations = @snoopr using JuMP;
[ Info: Precompiling JuMP [4076af6c-e467-56ae-b986-b466b2749572]
julia> length(invalidations)
5778 This PR julia> using SnoopCompile
julia> invalidations = @snoopr using JuMP;
julia> length(invalidations)
1650 So better than before, but this PR should be merged. |
They were replaced by JuMP.jl/src/mutable_arithmetics.jl Lines 80 to 93 in e9b2bf3
|
TODO:
x-ref #2273
These methods appear to be used from before we switched to MutableArithmetics.
In the future, instead of overloading Base.convert, we should use a new function
like
to_constant(::AffExpr)
which avoids the invalidation. Alternatively,future versions of Julia may be clever enough to avoid the invalidations.
Background
@snoopr
docs: https://timholy.github.io/SnoopCompile.jl/stable/snoopr/master
This PR