Skip to content

perf(lu): floor the blocked partial-pivoting recursion's trailing update - #14

Merged
shinaoka merged 1 commit into
mainfrom
perf/lu-trailing-update-floor
Oct 14, 2026
Merged

shinaoka merged 1 commit into
mainfrom
perf/lu-trailing-update-floor

Conversation

@shinaoka

Copy link
Copy Markdown
Member

The blocked partial-pivoting LU ran its per-level panel solve and trailing product
at the caller's par whatever the trailing update's size, so at 512 x 512 it
opened ~60 rayon regions around a few thousand flops each. Both now take Par::Seq
while A11.nrows() * A11.ncols() is not above params.par_threshold — the same
128 * 128 the swap stage below already reads — and the recursion still forwards the
caller's par, so each level decides for its own trailing update.

The floor is a sweep over 256 x 256, 512 x 512 and 1024 x 1024, not one shape:
16384 is the best of nine values on all three, 8192 and 24576 are within 3%.

Parent -> child, best of 4 calls, smallest over 14 interleaved repetitions, f64,
four threads (CPUs 0-3, four physical cores):

n parent child
128 0.0980 0.0582 (1.68x)
192 0.1597 0.1120 (1.43x)
256 0.3108 0.2550 (1.22x)
384 0.6046 0.4806 (1.26x)
512 1.2799 1.1673 (1.10x)
1024 5.2400 5.1188 (1.02x)

At one thread the two builds are the same code path and measure the same
(512 x 512: 1.8818 -> 1.8724). Instrumenting the phases puts the whole win in the
trailing product and panel solve buckets below 16384 output elements.

Test: linalg::lu::partial_pivoting::factor::tests::threaded_lu_matches_the_sequential_one
(96, 128, 192 below the floor at the top level, 256 and 512 above it).
Gate: cargo test -p t4a-faer --lib, 205 passed, 0 failed, 2 ignored.

Record: docs/worklogs/2026-10-14-lu-trailing-update-floor.md.

Limits: four physical cores only, so the campaign's 8T row is not reproduced and the
four-thread crossover is not the eight-thread one. This does not close the vendor gap
at 512 x 512; the sequential leaf kernel and the level-0 products remain.

The recursion halves its panel every level and ran the level's panel solve and
trailing product at the caller's `par` whatever their size, so at 512x512 it
opened about sixty rayon regions, most of them a few thousand flops. They now
take `Par::Seq` while the trailing update is not above `par_threshold` -- the
same 128*128 the swap stage already reads -- and the recursion keeps forwarding
the caller's `par`, so each level decides for its own trailing update.

The floor comes from a sweep over 256x256, 512x512 and 1024x1024, not from one
shape: 16384 is the best of nine values on all three. Parent -> child, best of
4, smallest over 14 interleaved repetitions, f64, four threads (CPUs 0-3):
128x128 0.0980 -> 0.0582, 192x192 0.1597 -> 0.1120, 256x256 0.3108 -> 0.2550,
384x384 0.6046 -> 0.4806, 512x512 1.2799 -> 1.1673, 1024x1024 5.2400 -> 5.1188.
At one thread the two builds are the same code path and measure the same.

Test: threaded_lu_matches_the_sequential_one (96, 128, 192, 256, 512).
Gate: cargo test -p t4a-faer --lib, 205 passed, 0 failed, 2 ignored.

Record: docs/worklogs/2026-10-14-lu-trailing-update-floor.md
@shinaoka
shinaoka force-pushed the perf/lu-trailing-update-floor branch from b4efac0 to 28bc13b Compare October 14, 2026 04:53
@shinaoka
shinaoka merged commit 88fec8d into main Oct 14, 2026
7 checks passed
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.

1 participant