Skip to content

Add Mooncake and Enzyme tests for Diagonal#179

Open
kshyatt wants to merge 1 commit intomainfrom
ksh/diag
Open

Add Mooncake and Enzyme tests for Diagonal#179
kshyatt wants to merge 1 commit intomainfrom
ksh/diag

Conversation

@kshyatt
Copy link
Copy Markdown
Member

@kshyatt kshyatt commented Feb 27, 2026

No description provided.

@kshyatt kshyatt requested a review from lkdvos February 27, 2026 10:24
@codecov
Copy link
Copy Markdown

codecov bot commented Feb 27, 2026

Codecov Report

❌ Patch coverage is 42.71845% with 59 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ixAlgebraKitEnzymeExt/MatrixAlgebraKitEnzymeExt.jl 0.00% 43 Missing ⚠️
...gebraKitMooncakeExt/MatrixAlgebraKitMooncakeExt.jl 73.33% 16 Missing ⚠️
Files with missing lines Coverage Δ
...gebraKitMooncakeExt/MatrixAlgebraKitMooncakeExt.jl 64.20% <73.33%> (-0.11%) ⬇️
...ixAlgebraKitEnzymeExt/MatrixAlgebraKitEnzymeExt.jl 1.12% <0.00%> (-0.17%) ⬇️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@kshyatt kshyatt changed the title Add Mooncake tests for Diagonal Add Mooncake and Enzyme tests for Diagonal Mar 26, 2026
@kshyatt
Copy link
Copy Markdown
Member Author

kshyatt commented Mar 26, 2026

Went a little crazy with this one after figuring out some of the rules needed modification for the Diagonal case where the output is by default the same as the input

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 26, 2026

Your PR no longer requires formatting changes. Thank you for your contribution!

@kshyatt kshyatt marked this pull request as ready for review March 27, 2026 16:59
@kshyatt
Copy link
Copy Markdown
Member Author

kshyatt commented Mar 27, 2026

This was a fun one, as a bunch of rules had to be modified to account for the case where one of the arguments === the input. Seems to all be working now, at least!

Copy link
Copy Markdown
Member

@lkdvos lkdvos left a comment

Choose a reason for hiding this comment

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

Good catch, that does indeed sound like an absolute misery to debug/find and solve!

I left some small suggestions around code organization, mostly to reduce the amount of code and/or improve readability, but otherwise this looks great (I absolutely understand that the complexity might just be unavoidable, again, impressive catch on this!)

I'll go through the remainder afterwards if you like, but I will already leave this here to not get lost in a wall of questions :)

if A_is_arg
ΔA = make_zero(A.dval)
$pb(ΔA, Aval, argval, darg)
A.dval .= ΔA
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
A.dval .= ΔA
A.dval .+= ΔA

I'm guessing this has to be accumulating, but I'm not entirely sure I follow the logic of this branch, why can't we immediately in-place accumulate?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We can't do it inplace because you'll modify dA which is the same as darg, I think. I think we should not do a + because A is overwritten in the primal step (but this is confusing, I'm open to being convinced otherwise)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think I'm following now.
Would it help if instead of allocating a new dA and then doing the copy afterwards, we instead copy the darg if we need to?
Also, does that mean that we could in principle be checking that dA is zero, since nothing is allowed to depend on the value of A after the decomposition?
Or would that be too strict of a check in the case where A is secretly not overwritten by the specific implementation of the decomposition.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Let me think about this a bit... btw this whole hornet's nest would be much easier to handle if we finally implemented the qr_full!! stuff we had discussed at one point 😛

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I thought Jutho wasn't a big fan of that 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Then the hornets are sticking around!

# use A (so that whoever does this is forced to handle caching A
# appropriately here)
Aval = nothing
A_is_arg = !isa(A, Const) && TA <: Diagonal && diagview(A.dval) === D.dval
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Code-organization-wise, I am not a huge fan of this hardcoded special case for different types.
Why do you need the specific specialization here? Could it not just be A.dval === D.dval?

That being said, we should probably just add an implementation of isalias(A, arg).
Maybe something like Base.mightalias could be a more generic solution, or even a fallback definition, but that function is technically internal, and similar problems hold for checking Base.dataids.
I might actually be okay with depending on that though, that has been quite stable and does seem to me like a good way of going at this. ( and we already secretly use this in TensorOperations! )

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

For the _vals methods we can't do A.dval === D.dval because D is a Vector, and A is a Diagonal, whose diag field points to D

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ah you are right, my bad! I think then I would even more think an isalias(A, arg) = Base.mightalias(A, arg) is the right abstraction (I would leave in the hook since Base.mightalias is internal, and this allows us to overload without piracy)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, that sounds good to me. We could do it as part of this PR or separately?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There are a lot of goofy special cases running around here haha

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It might be reasonable to include it in this PR, as this does seem to be the primary change that is needed to solve the issue? Happy to defer it if you prefer though.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

TBH this PR is complex enough, I might do the isalias as a followup?

Comment on lines +47 to +54
if !(A === arg1 || A === arg2)
copy!(A, Ac)
$pb(dA, A, (arg1, arg2), (darg1, darg2))
else
ΔA = zero(A)
$pb(ΔA, A, (arg1, arg2), (darg1, darg2))
dA .= ΔA
end
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
if !(A === arg1 || A === arg2)
copy!(A, Ac)
$pb(dA, A, (arg1, arg2), (darg1, darg2))
else
ΔA = zero(A)
$pb(ΔA, A, (arg1, arg2), (darg1, darg2))
dA .= ΔA
end
# compute pullback of A and restore input
# order is important - A might alias `args`!
$pb(dA, Ac, (arg1, arg2), (darg1, darg2))
copy!(A, Ac)
# compute pullbacks and restore other inputs if they don't alias
if A !== arg1
copy!(arg1, arg1c)
zero!(darg1)
end
if A !== arg2
copy!(arg2, arg2c)
zero!(darg2)
end

Again mostly a readability suggestion. (Note that I might again be missing something about the use of dA vs Delta A here)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

See comment above about Delta A

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

suggestion for the bottom part still stands though :)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

NB that if A !== arg, we MUST copy Ac -> A before the pullback

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Pushed a small cleanup here at least...

elseif A_is_arg2
make_zero!(arg.dval[1])
end
A.dval === arg.dval[1] || make_zero!(arg.dval[1])
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think this is actually not correct...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Or at least seems to be causing test failures now?

@kshyatt
Copy link
Copy Markdown
Member Author

kshyatt commented Mar 31, 2026

CUDA fail is unrelated, it's the CUSOLVER memory thing again

Fix stupid typos

Diagonal + eig(h) working

SVD working for diag

LQ/QR working

Polar and orthnull

Some Mooncake progress

Formatter

Working Mooncake eig

Remove comment

No diag for orthnull

Diag tests working for Mooncake

Formatter

Update ext/MatrixAlgebraKitEnzymeExt/MatrixAlgebraKitEnzymeExt.jl

Co-authored-by: Lukas Devos <ldevos98@gmail.com>

A bit of Enzyme cleanup

A little Mooncake cleanup
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.

2 participants