-
Notifications
You must be signed in to change notification settings - Fork 57
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
Add rule for triangular solves #1264
Conversation
Actually, EnzymeTestUtils is doing the right thing. You don't want to end up pulling back a nonzero cotangent on the unused triangle, which is what you're doing here, since next Enzyme will pull back the cotangent through the constructor of the triangular matrix, and this pullback just extracts the |
I think it relates to my question above, but if I'm assigning to the shadow with the A = UpperTriangular([1 2; 3 4])
B = UpperTriangular([0 0; 1 0])
A .+= B
A.data == [1 2; 3 4] # true So I'm not sure where the non-zero entries come from. So your suggestion is to add a call to |
Ah, I see now you're wrapping in We can show this by pirating this method. This overload causes tests to pass for me: function FiniteDifferences.to_vec(x::T) where {T<:LinearAlgebra.AbstractTriangular}
x_vec, back = FiniteDifferences.to_vec(parent(x))
function AbstractTriangular_from_vec(x_vec)
return T(reshape(back(x_vec), size(x)))
end
return x_vec, AbstractTriangular_from_vec
end We could pirate this method here, but it's not the ideal way of handling this. An alternative is to manually create the tangents (i.e. construct the A long-term solution would be for EnzymeTestUtils to roll its own |
Sorry, but who is writing to that unused triangle? If I understand your explanation correctly, it is not FiniteDifferences. |
No-one's writing to it. I'll explain. We want to test that a given rule only overwrites the shadow of an argument if that argument is itself overwritten by the primal. In all other cases, it should just increment the shadow. The way to test this is to start with a shadow filled with random numbers. There's then some complexity with how we get FiniteDifferences to work with this, since it doesn't support mutating functions. In short, we replace the mutating function with one that copies all arguments first, and then all arguments are also returned as outputs. Then for these returned arguments we pull back as cotangents the exact same random shadows we use with Enzyme. This causes FD to increment these random cotangents in the same way Enzyme should. It's a little complicated and happens here: Enzyme.jl/lib/EnzymeTestUtils/src/finite_difference_calls.jl Lines 126 to 177 in a511e4e
But in this case, FD is intentionally ignoring the unused triangle stored by the triangular matrix, which is a problem for us, because a user need not ignore it, and Enzyme won't either. So FD is not pulling back the random values in the unused triangle, and that causes Enzyme and FD to disagree. This is why either modifying FD to pull back these values as I did above or using zeros instead of random values will work just fine. |
Ok but it sounds like if we want to test both aspects we need to keep the random vectors. Looks like FD is providing the wrong abstractions for this. Instead of pirating |
I think I got it wrong. You meant to initialize randomly but only on the used triangle? |
If we initialize the shadow of the used diagonal randomly, then we still test this for the used diagonal at least, just not the unused one. 🤷♂️
Yes, this is what I meant by the final sentence in #1264 (comment) . It just takes more time than I have right now to work on. |
What if we add a test that ADs through the constructor as well? |
Yeah I think that's a good way to go, but for some reason Enzyme errored. But sure, if you can get it working, it's probably best. |
What is the API for injecting a custom cotangent into |
Instead of passing a tuple Enzyme.jl/lib/EnzymeTestUtils/src/test_reverse.jl Lines 35 to 38 in a511e4e
|
The tests should now pass, maybe we can trigger the CI. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## main #1264 +/- ##
===========================================
+ Coverage 75.93% 93.54% +17.61%
===========================================
Files 35 7 -28
Lines 10543 248 -10295
===========================================
- Hits 8006 232 -7774
+ Misses 2537 16 -2521 ☔ View full report in Codecov by Sentry. |
I only ran the tests in a local script, so I forgot to include EnzymeTestUtils. Should be fine now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If \
is under the hood just calling ldiv!
, and all other function calls are differentiable by Enzyme, then I agree it makes more sense to target ldiv!
.
I will try to re-write the rule in terms of |
22f0389
to
403e816
Compare
Maybe I should add some tests for batched inputs? Otherwise feel free to merge. |
Let's trigger CI to get a full picture of the additional tests. |
95e5401
to
0f88a94
Compare
I've stared at the errors for a while but I cannot make sense of them. They are mostly inside the EnzymeTestUtils logic for calling FiniteDifferences for |
test/internal_rules.jl
Outdated
for Tret in (Const, Active), | ||
TY in (Const, Duplicated, BatchDuplicated), | ||
TA in (Const, Duplicated, BatchDuplicated), | ||
TB in (Const, Duplicated, BatchDuplicated) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wsmoses in the past, mixing and matching Duplicated and BatchDuplicated caused errors. Is this no longer the case? I'm surprised this succeeds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, looking at the CI logs, it seems it doesn't succeed.
Co-authored-by: Seth Axen <seth@sethaxen.com>
Co-authored-by: Seth Axen <seth@sethaxen.com>
Co-authored-by: Seth Axen <seth@sethaxen.com>
Despite the check for compatibility of activities, I still get some failures. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
So this is a first attempt by a complete beginner at this.
One issue is that the tests using EnzymeTestUtils fail because they seem to compare the
data
field of the cotangents:The remaining tests currently pass, but they are not covering all cases.