Repository navigation
Conversation
The sum/sum! rules did not accept the init keyword that the Base methods accept, so calls matching a rule's positional types but passing init threw a MethodError instead of applying the rule. This adds init (non-differentiable, no tangent, as in the foldl rule) to all sum/sum! rules, and tests.
Member
|
I think this will give silently wrong answers to this: instead of a MethodError. That might be why this never got written in the first place. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #870 +/- ##
=======================================
Coverage 96.65% 96.66%
=======================================
Files 28 28
Lines 3615 3625 +10
=======================================
+ Hits 3494 3504 +10
Misses 121 121 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Member
|
Yes, that's the general problem of non-differentiable keyword arguments: JuliaDiff/ChainRulesCore.jl#384 Also makes me realize that #868 was already discussed in #656 |
Member
|
At least in case of the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #868
Problem
The
sum/sum!rules did not accept theinitkeyword that thecorresponding
Basemethods accept, so a call matching a rule'spositional types but passing
initthrew aMethodErrorinstead ofapplying the rule (or falling back to AD). For example, on
main:Fix
Add
initto everysum/sum!rule insrc/rulesets/Base/mapreduce.jl(10 sites:
frule/rruleforsum(::Tuple),sum(x; dims),sum!,sum(f, ::Tuple),sum(f, ::AbstractArray)incl. the fast and generalpaths,
sum(abs2, …)and its config-dispatched wrapper).initisnon-differentiable — it gets no tangent, as the
foldlrule alreadydoes. For
sum!, the keyword is passed through to the tangent too,so
init=falseaccumulates intoẏexactly as it does intoy.One subtlety: the internal
_InitialValue()sentinel (used when noinitis given) must never reach the@non_differentiableBoolrules, which forward all keywords into
Base.sum. Thesum(f, ::Tuple)rrule and the config
sum(abs2, …)wrapper therefore only passinitwhen a real one was given; regression tests cover the
Bool-valuedcase both with and without
init.No new rules for generic iterables (
Generator,Dict, …) — thosekeep falling back to AD, as the issue specifies.
Proof
Base commit:
30cf1f6b4c4f19c191b7a734c0d0369357c83860(main).Before/after on Julia 1.13.3 (repro script exercising all listed
sites, incl. the exact examples from the issue):
MethodError, 3 casesnothingvia fallback.frule((NoTangent(), ones(3)), sum, [1.0, 2.0, 3.0]; init=0.0) == (6.0, 3.0),rrule(sum, [1.0, 2.0, 3.0]; init=10.0)[1] == 16.0,sum!withinit=falsegives primal[13.0, 27.0]and tangent[3.0, 4.0].All no-
initcontrol cases unchanged.Focused test suite (
Pkg.test(; test_args=["rulesets/Base/mapreduce"]),Julia 1.13.3): 2050 passed, 0 failed, 22 broken (pre-existing
@test_broken), 2072 total. The fullPkg.testsuite was not runlocally (very heavy); CI covers it, including Julia 1.10.
Tests added in
test/rulesets/Base/mapreduce.jl:initvariants forsum(::Tuple),sum(x; dims),sum!(init=true/false),sum(abs2, …),sum(f, ::Tuple),sum(f, xs)(fast and general paths, incl.dims+init), a"sum with init (#868)"testset with the issue's exactexamples, and
Bool-valued regression tests for the sentinel fix.Note: plain tests use a Float64
init(finite differences are onlyaccurate to
1e-9in one precision —Base.sum(x; dims=2, init::Float32)returns Float32), while the
@gpucomparisons use a Float32init.Notes for reviewers
src/rulesets/Base/mapreduce.jl(+52/−18),test/rulesets/Base/mapreduce.jl(+52),Project.tomlversion bump 1.74.12 → 1.74.13.git diff --checkclean,JuliaFormatter ("blue") clean on both changed files.
fruleforsumdoesn't work forGenerator#768"): it restricts the same genericsumfrule toAbstractArray; this PR does not subsume it and has nosemantic overlap — if Restrict the sum forward rule to AbstractArray #867 merges first, this needs a one-line rebase.
sum!(f, r, A; init=true)has aBasemethod but no rule, so itstill falls back to AD; adding a rule for it is out of scope here.