-
-
Notifications
You must be signed in to change notification settings - Fork 660
Faster determinant for matrices over gf2e (M4RIE) #40773
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
base: develop
Are you sure you want to change the base?
Conversation
Documentation preview for this PR (built with commit 8ee83ca; changes) is ready! 🎉 |
|
||
sig_on() | ||
cdef int r = mzed_ple(A, P, Q) | ||
sig_off() |
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.
My impression is it would make the code much easier to maintain if you just make a single method that compute the PLE decomposition, then in determinant you return prod(self.ple_decomposition()[0].diagonal())
or something. If one can accept the overhead (which is likely negligible compared to the likely O(n^3) PLE decomposition).
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.
Yes, I agree (including about the negligible overhead), however this requires a bit more work: already for doing it for this specific class, but also and mostly because I think there is some rewriting to do so that the general LU
method calls this kind of fast PLE/PLUQ/... when available. For example matrices in modn_dense
or mod2
or gf2e
should be able to do LU by a direct call to FFLAS-FFPACK/M4RI/M4RIE functions for PLE/PLUQ. For the moment, Sage's LU is a naive algorithm for these classes. So I preferred to simply accelerate the determinant for now, and keep the LU improvements for a moment when I have time to do them properly.
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.
not necessarily so, you can just expose an additional method .ple_decomposition()
and explain what it does. Making LU
call it is an optional extra improvement.
But either way, this is optional.
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.
To remember about this comment and handle it when time permits (if no one does it before then), I have created #40791
|
||
cdef Cache_base cache = <Cache_base> self._base_ring._cache | ||
|
||
# characteristic 2, so det(P) == det(Q) == 1 |
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.
PLE decomposition has P and Q being a permutation matrix in whatever characteristic right? (plus, here P and Q aren't really matrix either, they're represented by permutations which can be converted to permutation matrix if necessary)
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.
Yes, well in case of PLUQ yes, for PLE (which has no Q in its definition) it depends what we mean by Q and how pivots are chosen, but here for M4RIE both are indeed permutation matrices. The comment is here because if the characteristic was not 2, the determinant of P and Q would need to be computed.
sagemathgh-40773: Faster determinant for matrices over gf2e (M4RIE) This computes the determinant for matrices over `GF(2**e)` by directly relying on the PLE decomposition of M4RIE. This provides a significant speed-up over the generic implementation used until now for this class. Before: ``` sage: mat = matrix.random(GF(2**4), 200, 200) sage: %time dd = mat.det() CPU times: user 706 ms, sys: 2.26 ms, total: 708 ms Wall time: 705 ms sage: mat = matrix.random(GF(2**8), 200, 200) sage: %time dd = mat.det() CPU times: user 746 ms, sys: 890 µs, total: 747 ms Wall time: 744 ms sage: mat = matrix.random(GF(2**15), 200, 200) sage: %time dd = mat.det() CPU times: user 1.37 s, sys: 4.74 ms, total: 1.38 s Wall time: 1.37 s sage: mat = matrix.random(GF(2**4), 500, 500) sage: %time dd = mat.det() CPU times: user 10.8 s, sys: 23.8 ms, total: 10.8 s Wall time: 10.7 s sage: mat = matrix.random(GF(2**8), 500, 500) sage: %time dd = mat.det() CPU times: user 11.6 s, sys: 22.1 ms, total: 11.6 s Wall time: 11.6 s sage: mat = matrix.random(GF(2**15), 500, 500) sage: %time dd = mat.det() CPU times: user 21.7 s, sys: 37 ms, total: 21.7 s Wall time: 21.7 s ``` After: ``` sage: mat = matrix.random(GF(2**4), 200, 200) sage: %time dd = mat.det() CPU times: user 275 µs, sys: 68 µs, total: 343 µs Wall time: 356 µs sage: mat = matrix.random(GF(2**8), 200, 200) sage: %time dd = mat.det() CPU times: user 1.1 ms, sys: 21 µs, total: 1.12 ms Wall time: 1.13 ms sage: mat = matrix.random(GF(2**15), 200, 200) sage: %time dd = mat.det() CPU times: user 81.2 ms, sys: 8.98 ms, total: 90.1 ms Wall time: 89.7 ms sage: mat = matrix.random(GF(2**4), 500, 500) sage: %time dd = mat.det() CPU times: user 1.84 ms, sys: 0 ns, total: 1.84 ms Wall time: 1.86 ms sage: mat = matrix.random(GF(2**8), 500, 500) sage: %time dd = mat.det() CPU times: user 5.23 ms, sys: 39 µs, total: 5.27 ms Wall time: 5.44 ms sage: mat = matrix.random(GF(2**15), 500, 500) sage: %time dd = mat.det() CPU times: user 719 ms, sys: 17.6 ms, total: 737 ms Wall time: 732 ms ``` URL: sagemath#40773 Reported by: Vincent Neiger Reviewer(s): user202729, Vincent Neiger
This computes the determinant for matrices over
GF(2**e)
by directly relying on the PLE decomposition of M4RIE. This provides a significant speed-up over the generic implementation used until now for this class.Before:
After: