Skip to content

test(linalg): benchmark per-block transpose naive vs HPTT - #456

Merged
ultimatile merged 2 commits into
mainfrom
perf/311-block-sparse-transpose-hptt
Jul 7, 2026
Merged

test(linalg): benchmark per-block transpose naive vs HPTT#456
ultimatile merged 2 commits into
mainfrom
perf/311-block-sparse-transpose-hptt

Conversation

@ultimatile

@ultimatile ultimatile commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Summary

The block-sparse contract and permute paths transpose each block with a naive per-element kernel that bypasses HPTT. Whether HPTT would win is block-shape dependent and was not measurable: rank-2 permuted contraction takes the GEMM trans-flag path, so no existing benchmark drives the physical per-block transpose.

This adds an isolating micro-benchmark that times ComputeBackend::transpose across representative block shapes, so the native naive kernel (default build) and HPTT (--features hptt) can be compared per shape via criterion baselines.

Refs #311 — this satisfies that issue's "needs a benchmark" prerequisite; routing the block-sparse sites through the backend is a separate follow-up (see Notes).

Changes

  • crates/ariadnetor-linalg/benches/block_sparse_ops.rs: add a block_transpose group sweeping rank-3 (d, 2, d) and rank-4 (d, 2, 2, d) folds over per-sector degeneracy d in {16, 32, 64, 128}, each perm chosen to reach the physical transpose rather than the GEMM trans-flag fast path. Sequential across the whole sweep, plus a parallel variant at the largest d.

Test plan

  • cargo clippy --benches -- -D warnings: clean.

  • Both configs compile and run; measured with --save-baseline naive (default build) then --features hptt --baseline naive.

  • Result: HPTT beats the naive kernel at every representative shape, the margin growing with block size. Times are single-machine criterion medians; the load-bearing result is the relative naive-vs-HPTT ratio, not the absolute values.

    shape naive HPTT improvement
    rank-3, d=16 1.5-1.6 us 1.0-1.1 us -28 to -37%
    rank-3, d=64 23-25 us 2.4-3.2 us -87 to -91%
    rank-4, d=128 ~284 us 12 us -96%
  • Parallel at d=128 is far slower than sequential (~55 us vs ~6-12 us): Rayon overhead dominates at these block sizes, so the per-block transpose should stay sequential.

Notes

  • The benchmark times ComputeBackend::transpose (native naive vs HPTT), not the in-tree transpose_block_data the block-sparse paths call today. The two are the same cost class (both O(n), output-driven, stride-indexed), so the native-vs-HPTT ratio stands in for the payoff of routing those sites through the backend; it is not a measurement of the current call path.
  • Follow-up, warranted by the numbers above: route the transpose_block_data sites through ComputeBackend::transpose and hoist the redundant rhs re-transpose out of the contraction's inner loop, keeping the per-block transpose sequential.

Summary by CodeRabbit

  • Chores
    • Added a new benchmark suite to measure block-wise transpose performance more accurately.
    • Included a wider range of block shapes and permutation patterns to better reflect real-world workloads.
    • Added both sequential and parallel benchmark runs for larger cases to compare scaling behavior.

The block-sparse contract and permute paths transpose each block with a
naive per-element kernel that bypasses HPTT. Whether HPTT wins is
block-shape dependent and was not measurable: rank-2 permuted contraction
takes the GEMM trans-flag path, so no existing bench drives the physical
per-block transpose.

Add a block_transpose group sweeping representative block shapes (rank-3
and rank-4 folds over per-sector degeneracy d) through the public
ComputeBackend::transpose, so the naive kernel (default build) and HPTT
(--features hptt) can be compared per shape via criterion baselines.
State on the benchmark that it times ComputeBackend::transpose (native
naive vs HPTT), not the in-tree transpose_block_data the block-sparse
paths currently call, and why the native-vs-HPTT ratio still stands in
for the routing payoff (same cost class). Prevents a reader from taking
the numbers as the current call path's cost.
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 94259fa3-b152-4a4c-8c0e-3aab8bfda0df

📥 Commits

Reviewing files that changed from the base of the PR and between 088ea3f and 684bfdf.

📒 Files selected for processing (1)
  • crates/ariadnetor-linalg/benches/block_sparse_ops.rs

📝 Walkthrough

Walkthrough

Adds a new Criterion benchmark file section introducing a block_transpose benchmark group. It defines TransposeCase cases via a degeneracy sweep, a bench_transpose_case() timing helper calling NativeBackend::transpose through a TransposeDescriptor, and registers the new group alongside existing benchmarks.

Changes

Block Transpose Benchmark

Layer / File(s) Summary
Transpose case generation and imports
crates/ariadnetor-linalg/benches/block_sparse_ops.rs
Imports TransposeDescriptor and defines TransposeCase, D_SWEEP, and transpose_cases() to generate representative block shapes/permutations forcing the physical transpose fallback.
Benchmark execution and registration
crates/ariadnetor-linalg/benches/block_sparse_ops.rs
Adds bench_transpose_case() to time NativeBackend::transpose calls with deterministic buffers and black_box, bench_block_transpose() to run sequential and parallel (max d) cases in a Criterion group, and registers it in criterion_group!.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

Possibly related PRs

  • ultimatile/ariadnetor#433: The new transpose benchmarks exercise the physical fallback path that becomes default once this PR flips hptt to opt-in.

Poem

A rabbit hops with stopwatch in paw,
Timing each transpose without a flaw,
Blocks flip and swap, sequential then parallel race,
Criterion charts the fastest pace,
🐇⏱️ Benchmarks bloom, hop hop, hooray!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the new linalg benchmark comparing naive per-block transpose with HPTT.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/311-block-sparse-transpose-hptt

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a Criterion micro-benchmark to isolate and measure the cost of per-block tensor transposes via ComputeBackend::transpose, enabling direct comparison of the native naive transpose kernel vs the HPTT implementation (--features hptt) across representative block shapes and permutations.

Changes:

  • Introduces a block_transpose benchmark group that sweeps representative rank-3 and rank-4 block shapes over d ∈ {16, 32, 64, 128}.
  • Benchmarks sequential transpose for all cases and adds a parallel-policy variant only for the largest d to limit total benchmark runtime.
  • Reuses per-benchmark input/output buffers to avoid measuring allocation overhead instead of transpose cost.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ultimatile
ultimatile merged commit 08eeb3e into main Jul 7, 2026
2 checks passed
@ultimatile
ultimatile deleted the perf/311-block-sparse-transpose-hptt branch July 8, 2026 10:16
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