Improve heuristic for choosing between matrix powering algorithms - #6293
Improve heuristic for choosing between matrix powering algorithms#6293fingolfin wants to merge 1 commit into
Conversation
|
I do not approve this pull request. This code should not be removed. But the heuristics for choosing the best method in each case can certainly be improved. Certainly in the tiny cases you mention above.
In that context typical calls are for matrices in For compressed matrices over small finite fields the matrix multiplication is quite fast, and the overhead in For non-compressed matrices the break even point is much lower, e.g., In an attempt to improve the heuristics it may also be useful to reenable the method which is currently commented out (many matrices have efficient methods for characteristic/minimal polynomial and for large exponents one can reduce to As far as I remember, after introducing |
|
@frankluebeck thanks for the additional data points. That might help coming up with a better heuristic for when to use which algorithm, |
Powering a matrix by a positive integer is handled by POW_MAT_INT, which chooses between plain repeated squaring (POW_OBJ_INT, about Log2(n) matrix multiplications) and a method based on computing x^n modulo the characteristic polynomial (a considerable fixed overhead, plus about Log2(n) much cheaper polynomial multiplications). The old rule chose the latter whenever Log2(n) >= 3d/4, which is far too eager for small matrices (up to 30x slower than repeated squaring) and at the same time too conservative for large compressed matrices. Replace it by representation dependent break even points that were determined experimentally, by measuring both algorithms over a grid of dimensions, fields resp. representations, and exponent bit lengths k = Log2(n). Since for a fixed matrix the costs of both algorithms grow linearly in k, break even points can be computed reliably from linear fits. On all measured cells the new rule is within a factor of about 1.9 of the optimal choice, compared to a factor of up to 30 for the old rule; in particular it retains the large speedups of the characteristic polynomial method for large matrices with huge exponents (e.g. powering an element of GL(200,251) by 251^200 remains ~40x faster than repeated squaring), while small matrices with moderate exponents now always use repeated squaring. The decision is based on the actual representation of the matrix (IsGF2MatrixRep, Is8BitMatrixRep, everything else), which is cheaper to test than computing DefaultFieldOfMatrix and matches what actually determines the arithmetic cost; the field is only computed (to verify the entries lie in a field, as required by the characteristic polynomial method) once the exponent is known to be large enough. This commit was prepared with assistance from the AI tool Claude Code (benchmarking, analysis and drafting of the heuristic). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
86e7c99 to
eae5041
Compare
POW_MAT_INT to speed up matrix powering
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6293 +/- ##
==========================================
- Coverage 79.08% 79.04% -0.04%
==========================================
Files 685 685
Lines 293699 293705 +6
Branches 8664 8641 -23
==========================================
- Hits 232264 232158 -106
- Misses 59635 59745 +110
- Partials 1800 1802 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
I've reworked this PR to keep both implementations but hopefully use a much better heuristic for the cross over points. |
|
(And when I write "I" then I really mean me together with Claude Code) |
frankluebeck
left a comment
There was a problem hiding this comment.
Thanks. This improment works as described.
(Replaces the original "Remove POW_MAT_INT" proposal, following the discussion below.)
Powering a matrix by a positive integer is handled by
POW_MAT_INT, which chooses betweenplain repeated squaring (
POW_OBJ_INT, aboutLog2(n)matrix multiplications) and a methodbased on computing
x^nmodulo the characteristic polynomial (considerable fixed overhead,plus about
Log2(n)much cheaper polynomial multiplications). The old rule chose the latterwhenever
Log2(n) >= 3d/4, which is far too eager for small matrices (up to 30x slower thanrepeated squaring, see the timings in the discussion) and at the same time too conservative
for large compressed matrices.
This PR replaces it by representation dependent break even points determined experimentally:
both algorithms were measured over a grid of dimensions
din 2..200, fieldsGF(2), GF(5), GF(251), GF(257), GF(3^10) plus integer matrices, and exponent bit lengths
k = Log2(n)in 8..1600. Since for a fixed matrix the costs of both algorithms grow linearlyin
k, the break even point of each cell can be computed reliably from linear fits. Findings:Is8BitMatrixRep): break even falls fromk ~ 330atd = 5to
k ~ 10atd = 200; modelled ask >= 8 + 768/dIsGF2MatrixRep): multiplication is so fast that the break evenpoint stays roughly flat at
k ~ 47..90for all measuredd; modelled ask >= 64nearly as expensive as small matrix products; the characteristic polynomial method never
wins below
d ~ 20and the break even point isk ~ 60ford >= 50; modelled ask >= Maximum(64, 8192/d)On all measured cells the new rule is within a factor of ~1.9 of the optimal choice
(and optimal on most), compared to a factor of up to 30 for the old rule. In particular:
POW_OBJ_INTspeed, e.g.powering in
GL(2,5)by3*10^7(10000 times) takes 52ms instead of 507msGL(200,251)by251^200still uses the characteristic polynomial method and remains ~40x faster thanrepeated squaring
GL(20, 3^10)withe = 10^7picks repeated squaring(~3% slower than optimal in my measurements)
The decision is based on the actual representation of the matrix, which is cheaper to test
than
DefaultFieldOfMatrix(that call alone previously dominated the runtime when poweringsmall matrices by small exponents) and matches what actually determines the arithmetic cost.
DefaultFieldOfMatrixis only computed once the exponent is known to be large enough, toverify that the entries lie in a field as required by the characteristic polynomial method;
matrices over other rings fall back to repeated squaring as before.
Not addressed here, possible follow-ups: using the minimal instead of the characteristic
polynomial (
POW_BY_MINPOLas sketched by @frankluebeck above, withPowerModCoeffs), and akernel implementation for compressed matrices.
AI disclosure: this PR was prepared with assistance from the AI tool Claude Code
(benchmarking, analysis, drafting of the heuristic and of this text); the commit carries a
corresponding
Co-authored-by:line.