Skip to content

perf(linalg): route cross-order reorder through the backend transpose - #458

Merged
ultimatile merged 2 commits into
mainfrom
perf/310-reorder-hptt-bench
Jul 8, 2026
Merged

perf(linalg): route cross-order reorder through the backend transpose#458
ultimatile merged 2 commits into
mainfrom
perf/310-reorder-hptt-bench

Conversation

@ultimatile

@ultimatile ultimatile commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Summary

The linalg row-major sandwich (decomposition, contract, expm, solve, eigen, einsum) normalizes rank>2 operands across memory order with reorder_data, a backend-less per-element loop that never reaches HPTT. A cross-order reorder at fixed logical shape is a physical axis-reversal permutation, byte-identical to ComputeBackend::transpose with the reverse permutation under the source order. This routes those reorders through the transpose, so builds with --features hptt use HPTT and the default build uses the parallelizable native kernel.

Closes #310

Changes

  • Add reorder_via_backend (reorder_route.rs): a reverse-perm transpose under the source order, re-wrapped at the original logical shape; early exits for from == to, rank <= 1, and empty tensors.
  • Route the dense sandwich sites (decomposition, contract, expm, solve, eigen, einsum) and the block-sparse trace result reorder through the helper; reshape_for_backend / prepare_for_gemm gain a backend argument and become fallible.
  • Add the reorder_sandwich criterion bench: a per-shape micro comparison of naive reorder_data vs the routed transpose, plus a rank-3 SVD end-to-end probe.
  • Clarify that ComputeBackend::transpose honors desc.order per call (transpose is layout-parametric), sanctioning the source-order transpose.
  • Collapse a redundant normalize-then-RowMajor step in batched einsum.

Impact

  • No public API change: the routed behavior is byte-identical, and the two touched helpers are crate-internal.
  • Default build (no HPTT): the routed reorder uses the native transpose kernel; its auto-parallelism speeds large reorders while small reorders stay roughly neutral (see Performance).
  • to_vec_in_order stays on reorder_data; its callers pass a no-op order, so routing would only add setup to a clone.

Test plan

  • A new byte-identity test asserts reorder_via_backend == reorder_data across ranks 1-4 (including an empty shape), both order directions, and all four scalars, under both the default and --features hptt builds.
  • Existing linalg suites pass unchanged under both builds; cargo test --workspace is green (73 binaries, 0 failures).

Performance

Criterion medians (f64; absolute times are hardware-dependent, the ratios less so). Speedup is relative to the always-sequential reorder_data; the routed path follows par_for_transpose (parallel for large shapes, sequential for small).

Reorder kernel, --features hptt (microseconds):

shape elems reorder_data HPTT (routed) speedup
[256, 8] 2,048 6.6 1.6 4.2x
[512, 512] 262,144 679 101 6.7x
[128, 16, 128] 262,144 739 132 5.6x
[64, 8, 8, 64] 262,144 764 136 5.6x

f32 reaches about 8.5x; complex is about 1.5x to 2.5x. No shape regresses.

Reorder kernel, default build (no HPTT) — the native kernel's auto-parallelism vs the sequential loop (microseconds):

shape elems reorder_data routed speedup
[512, 512] 262,144 662 229 2.9x
[128, 16, 128] 262,144 737 304 2.4x
[64, 8, 8, 64] 262,144 758 339 2.2x

Small reorders below the parallel threshold stay roughly neutral.

End-to-end rank-3 SVD, default vs --features hptt (milliseconds):

tensor elems default hptt speedup
[64, 8, 64] 32,768 1.42 1.22 1.17x
[128, 4, 128] 65,536 4.24 4.06 1.04x

The operation-level gain is diluted by the faer SVD; reorder-dominated operations (large rank>2 contract or permute) benefit more.

@coderabbitai ignore

A cross-order reorder at fixed logical shape (RowMajor<->ColumnMajor) is a
physical axis-reversal permutation, byte-identical to backend.transpose with
the reverse perm under the source order. The naive reorder_data is a
backend-less sequential element loop that never reaches HPTT; routing the
conversion through the transpose uses HPTT for f64/f32/complex under
--features hptt and the parallelizable native kernel otherwise.

Add reorder_via_backend and route the dense row-major-sandwich sites
(decomposition, contract, expm, solve, eigen, einsum) and the block-sparse
trace result reorder through it. A criterion bench (reorder_sandwich) shows
HPTT beats the naive loop at every representative shape (1.5-8.5x, no
small-2D regression), the native kernel parallelizes large reorders even
without HPTT, and a rank-3 SVD moves 4-14% end to end under --features hptt.

Clarify that ComputeBackend::transpose honors desc.order per call (transpose
is layout-parametric), sanctioning the source-order transpose. Collapse a
redundant normalize-then-RowMajor step in batched einsum. to_vec_in_order
stays on reorder_data (its callers pass a no-op order).

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 improves linalg “row-major sandwich” performance by routing cross-memory-order reorders through ComputeBackend::transpose, enabling HPTT acceleration when built with --features hptt, and using the backend’s native transpose kernel otherwise.

Changes:

  • Introduces reorder_via_backend (new reorder_route module) and routes multiple linalg sites (decomposition/contract/expm/solve/eigen/einsum and a block-sparse trace reorder) through it.
  • Makes reshape_for_backend / prepare_for_gemm backend-aware and fallible to propagate backend transpose errors.
  • Adds a Criterion benchmark (reorder_sandwich) and clarifies ComputeBackend::transpose’s per-call layout contract.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
crates/ariadnetor-linalg/src/solve.rs Switches solve/inverse reorders to reorder_via_backend and propagates errors.
crates/ariadnetor-linalg/src/reorder_route.rs Adds the reorder-via-transpose helper and byte-identity tests.
crates/ariadnetor-linalg/src/lib.rs Registers the new reorder_route module.
crates/ariadnetor-linalg/src/expm/mod.rs Routes expm’s reorder steps through the backend transpose path.
crates/ariadnetor-linalg/src/einsum.rs Removes redundant normalization and routes batch/slice reorders through the backend.
crates/ariadnetor-linalg/src/eigen.rs Routes eigen decomposition reorders through reorder_via_backend.
crates/ariadnetor-linalg/src/decomposition/mod.rs Makes reshape helper backend-aware/fallible and updates decomposition callers.
crates/ariadnetor-linalg/src/decomposition/lq.rs Updates LQ path to the fallible backend-aware reshape helper.
crates/ariadnetor-linalg/src/contract.rs Routes GEMM prep and result reconstruction reorders through the backend transpose path.
crates/ariadnetor-linalg/src/block_sparse_trace.rs Routes per-block trace-result reorder through reorder_via_backend.
crates/ariadnetor-linalg/Cargo.toml Registers the new reorder_sandwich benchmark target.
crates/ariadnetor-linalg/benches/reorder_sandwich.rs Adds microbench + end-to-end SVD probe to measure naive vs routed reorder.
crates/ariadnetor-core/src/backend.rs Documents that transpose must honor desc.order per call (layout-parametric).

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

Comment thread crates/ariadnetor-linalg/src/reorder_route.rs Outdated
The rank<=1 fast path in reorder_via_backend copied the whole buffer via
to_vec. DenseStorage is Arc-backed, so re-tag the order by cloning the
storage Arc and rebuilding the layout instead of moving the data.

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

@ultimatile
ultimatile merged commit 5fdb8d3 into main Jul 8, 2026
2 checks passed
@ultimatile
ultimatile deleted the perf/310-reorder-hptt-bench branch July 8, 2026 15:14
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.

perf: linalg cross-order reorder bypasses HPTT; needs a benchmark

2 participants