perf(linalg): route block-sparse per-block transpose through the backend - #457
Merged
Conversation
Route the four per-block transpose sites (permute, contract-to-scalar, and the contract-to-tensor lhs/rhs branches) through ComputeBackend::transpose instead of the hand-written naive transpose_block_data, so builds with HPTT use it per block. The benchmark showed HPTT beats the naive kernel at every representative block shape. Memoize each rhs block's physical transpose by block index so a block shared across multiple lhs blocks is transposed at most once per contraction, and transpose permute blocks straight into the output block to drop an intermediate buffer and copy. The per-block transpose stays sequential: Rayon dispatch loses at these block sizes. Remove transpose_block_data and its compute_strides helper (the native backend already provides the naive path as its non-HPTT fallback); compute_strides moves into the contract test module as a test-only helper. Add a ground-truth block-sparse permute test, since the site was previously only round-trip-tested. Closes #311
There was a problem hiding this comment.
Pull request overview
This PR improves block-sparse linalg performance by routing per-block transposes through ComputeBackend::transpose, enabling HPTT (when built with --features hptt) and removing the previous hand-written per-element transpose path that bypassed the backend. It also reduces redundant work in block-sparse contraction by caching RHS block transposes, and strengthens permutation correctness testing with a ground-truth mapping assertion.
Changes:
- Route block-sparse per-block transpose in both contraction and permutation through
ComputeBackend::transpose(HPTT-enabled), removing the in-tree naivetranspose_block_data. - Cache each RHS block’s physical transpose during contraction so a shared RHS block is transposed at most once per contraction.
- Add a rank-3 ground-truth permute test that asserts exact element mapping; update the transpose benchmark doc comment to reflect the new production path.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| crates/ariadnetor-linalg/src/block_sparse_permute/tests.rs | Adds a ground-truth rank-3 permutation test with explicit element mapping checks. |
| crates/ariadnetor-linalg/src/block_sparse_permute.rs | Uses ComputeBackend::transpose directly into the output block to avoid an intermediate buffer/copy. |
| crates/ariadnetor-linalg/src/block_sparse_contract/tests/mod.rs | Moves stride computation into tests as a test-only helper for index math assertions. |
| crates/ariadnetor-linalg/src/block_sparse_contract.rs | Routes per-block transpose through the backend and adds RHS transpose memoization; removes the in-tree transpose kernel. |
| crates/ariadnetor-linalg/benches/block_sparse_ops.rs | Updates benchmark documentation to state it measures the production per-block transpose path. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The existing contraction benchmarks all take the GEMM trans-flag fast path and never exercise the physical per-block transpose, so the win from routing that path through the backend was untracked end to end. `permute_bsp` permutes a rank-3 block-sparse tensor by a cyclic perm, which physically transposes every block, giving a benchmark that moves with the routed transpose (and with HPTT under `--features hptt`).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Block-sparse per-block transpose was a hand-written naive per-element kernel (
transpose_block_data) that bypassed the backend's transpose, so HPTT was never used per block even when the build enabled it. This routes all four per-block transpose sites throughComputeBackend::transpose, which selects HPTT or the native naive kernel at compile time. The benchmark in #456 showed HPTT beats the naive kernel at every representative block shape, so the routing is a measured win.Closes #311
Changes
block_sparse_contract.rs: route thecontract_to_scalarandcontract_to_tensor(lhs / rhs) transposes through a newtranspose_blockhelper overComputeBackend::transpose; memoize each rhs block's transpose by block index so a block shared across several lhs blocks is transposed at most once per contraction; removetranspose_block_dataand itscompute_strideshelper.block_sparse_permute.rs: transpose each block straight into its freshly-zeroed output block, dropping an intermediate buffer and copy.block_sparse_contract/tests/mod.rs:compute_stridesmoves here as a test-only helper — its only remaining consumers are tests.block_sparse_permute/tests.rs: add a ground-truth permute test asserting the exact element mapping, closing a gap where the site was only round-trip-tested.benches/block_sparse_ops.rs: add an end-to-endpermute_bspbenchmark — the existing contraction groups all take the GEMM trans-flag fast path and never exercise the physical transpose, so nothing tracked the changed path end to end; also update thebench_block_transposedoc comment, which now measures the production per-block transpose path.Impact
contract_to_scalarandcontract_to_tensorare file-private; the only signature change (contract_to_scalargainsbackend, returnsResult) is matched at its sole in-file caller. No public API changes; net removal of twopub(crate)internals.Test plan
ExecPolicy::Sequential): theblock_transposebenchmark's parallel variant is slower at these block sizes, where Rayon dispatch overhead dominates.cargo test -p ariadnetor-linalgandcargo test -p ariadnetor-linalg --features hptt: 292 pass each, so the ground-truth tests certify the HPTT kernel as well as the naive one.cargo make clippy(all targets, deny warnings) clean.Benchmark
End-to-end
permute_bsp(rank-3, cyclic perm, physical transpose per block), native naive kernel vs HPTT (--features hptt), single-machine criterion medians — the relative ratio is the load-bearing figure:The default build keeps the native naive kernel, so the routing is performance-neutral there; the roughly 4-5x speedup is realized when building with
--features hptt.Notes
The rhs transpose cache trades memory for recomputation: at most one transposed copy per distinct rhs block lives for the contraction's duration.
@coderabbitai ignore