Skip to content
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

Fix and test promote_rule definitions #207

Merged
merged 3 commits into from
Oct 3, 2022
Merged

Fix and test promote_rule definitions #207

merged 3 commits into from
Oct 3, 2022

Conversation

devmotion
Copy link
Member

This PR fixes the promote_rule definitions by using basically the same implementation as ForwardDiff (https://github.com/JuliaDiff/ForwardDiff.jl/blob/6a6443b754b0fcfb4d671c9a3d01776df801f498/src/dual.jl#L440-L452).

Currently, abstract types (such as Real, AbstractFloat etc.) are not handled properly as promote_rule should be defined for Type{<:T} for these types instead of Type{T}. Moreover, currently only one order of arguments is defined which can lead to issues (usually stackoverflow errors when calling promote_type: JuliaLang/julia#13193) if some other package (such as ForwardDiff) defines a promote_rule with reversed order of arguments and different result.

Fixes #206. Closes #203.

@@ -24,7 +24,7 @@ using ChainRulesCore
# Not all operations will be valid over all of these types, but that's okay; such cases
# will simply error when they hit the original operation in the overloaded definition.
const ARRAY_TYPES = (:AbstractArray, :AbstractVector, :AbstractMatrix, :Array, :Vector, :Matrix)
const REAL_TYPES = (:Bool, :Integer, :(Irrational{:e}), :(Irrational{:π}), :Rational, :BigFloat, :BigInt, :AbstractFloat, :Real, :Dual)
const REAL_TYPES = (:Bool, :Integer, :(Irrational{:}), :(Irrational{:π}), :Rational, :BigFloat, :BigInt, :AbstractFloat, :Real, :Dual)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a bug it seems:

julia> typeof(ℯ)
Irrational{:ℯ}

julia> typeof(MathConstants.e)
Irrational{:ℯ}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was it never tested? Would be nice to add a test.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already added a test (I only noticed the bug since it failed without the fix).

@@ -270,10 +270,22 @@ Base.convert(::Type{T}, t::T) where {T<:TrackedReal} = t
Base.convert(::Type{T}, t::T) where {T<:TrackedArray} = t

for R in REAL_TYPES
@eval Base.promote_rule(::Type{$R}, ::Type{TrackedReal{V,D,O}}) where {V,D,O} = TrackedReal{promote_type($R,V),D,O}
R === :Dual && continue # ForwardDiff.Dual is handled below
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only defining promote_rule for Type{<:Dual} leads to method ambiguity issues; hence it is skipped here and defined below for Type{Dual{T,V,N}}.

end

Base.promote_rule(::Type{R}, ::Type{TrackedReal{V,D,O}}) where {R<:Real,V,D,O} = TrackedReal{promote_type(R,V),D,O}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is covered by the loop above (:Real is part of REAL_TYPES).

@devmotion
Copy link
Member Author

devmotion commented Sep 24, 2022

It seems DiffTests 0.1.2 (recently released) broke the ReverseDiff tests 😢 Promotion tests passed.

R === :Dual && continue # ForwardDiff.Dual is handled below
@eval begin
if isconcretetype($R) # issue ForwardDiff#322
Base.promote_rule(::Type{TrackedReal{V,D,O}}, ::Type{$R}) where {V,D,O} = TrackedReal{promote_type(V,$R),D,O}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are implementing both methods, do we know if they are all covered by tests? Might be worth adding a test checking that switching arguments gives the same result.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both are tested since promote_type calls both promote_rule definitions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should add that actually tests fail when one of the definitions is removed due to eg stackoverflow errors when calling promote_type as mentioned in the OP.

@mohamed82008
Copy link
Member

I left some comments. It would also be nice to run some downstream tests to make sure this doesn't break anything. DiffEqSensitivity, DistributionsAD and GalacticOptim would be good to test.

@devmotion
Copy link
Member Author

DiffEqSensitivity, DistributionsAD and GalacticOptim would be good to test.

I ran tests of SciMLSensitivity, DistributionsAD (with `ENV["AD"] = "ReverseDiff"), and Optimization locally. Optimization and DistributionsAD succeeded, SciMLSensitivity tests did not finish before my laptop ran out of battery. I can retry tomorrow.

@devmotion
Copy link
Member Author

devmotion commented Sep 26, 2022

Took forever but tests passed with this PR in the end:

10702.904078 seconds (22.35 G allocations: 1.929 TiB, 8.78% gc time, 87.66% compilation time: 0% of which was recompilation)
     Testing SciMLSensitivity tests passed

@mohamed82008 is this good to go? All test failures seem unrelated (also exist on the master branch, due to the new DiffTests release and some changes in Julia base that also broke Tracker tests a while ago) but the promote_type tests succeed and downstream tests pass.

@mohamed82008
Copy link
Member

Looks good. Let's wait for CI to pass before we merge this PR though.

@devmotion
Copy link
Member Author

There's no response yet in DiffTests to my issue and PR, and I'm not sure when I will have time to dig more into other unrelated test errors on the master branch. So it might take a while until CI is fixed on the master branch.

@mohamed82008
Copy link
Member

Can we rebase this one now that DiffTests is upper bounded?

@codecov-commenter
Copy link

codecov-commenter commented Oct 3, 2022

Codecov Report

Base: 82.19% // Head: 81.98% // Decreases project coverage by -0.21% ⚠️

Coverage data is based on head (287de26) compared to base (ac44511).
Patch coverage: 0.00% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #207      +/-   ##
==========================================
- Coverage   82.19%   81.98%   -0.22%     
==========================================
  Files          18       18              
  Lines        1528     1532       +4     
==========================================
  Hits         1256     1256              
- Misses        272      276       +4     
Impacted Files Coverage Δ
src/ReverseDiff.jl 100.00% <ø> (ø)
src/tracked.jl 86.81% <0.00%> (-1.61%) ⬇️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@devmotion
Copy link
Member Author

CI passed.

@devmotion devmotion merged commit 8ac1f7d into master Oct 3, 2022
@devmotion devmotion deleted the dw/promote_rule branch October 3, 2022 10:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Missing Promotion Rule
4 participants