Repository navigation
matmul: overwrite a MaybeUninit destination (#136) - #153
Merged
Merged
Conversation
matmul_with_conj_uninit(dst: MatUninitMut, lhs, conj_lhs, rhs, conj_rhs, alpha, par) computes alpha * op(lhs) * op(rhs) into storage whose elements may be uninitialized and returns it as an initialized MatMut, for callers (strided-rs#198) that otherwise fill the output before an overwriting product. Requested upstream as sarah-quinones#269; the view type and the first tests follow the same author's upstream PR sarah-quinones#270. The destination's prior contents are never read and no reference to an unwritten element is formed. The native types on x86_64 with AVX2 or AVX-512 go to t4a-private-gemm-x86 with Accum::Replace (on a team, through gemm_team); other scalars write each dot product through ptr::write; an empty depth writes zeros. The gemm and nano-gemm crates never see uninitialized storage (gemm's GEMV forms a slice of the destination, its AMX kernel copies partial tiles, nano-gemm scales by beta), so elsewhere the native types are zero-filled first. Existing MatMut APIs are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Closes #136.
Summary
This adds
faer::linalg::matmul::matmul_with_conj_uninit, an overwrite-only matrix product whose destination may be uninitialized storage:It was requested upstream as sarah-quinones#269 and is needed by strided-rs#198. The view type
MatUninitMut(mat::UninitMut) and the first tests come from shinaoka's upstream PR sarah-quinones#270 (branchfeat/maybe-uninit-matmul, same author, MIT). The product routing is new and uses this fork's kernels. Nothing was posted upstream.Requirements → implementation
t4a-private-gemm-x86withAccum::Replace, which writes every element in the first depth block and loads the destination only when accumulating; on aPar::Teamthey go throughgemm_team, which takes the same kernel. Other scalars write each dot product withptr::write. An empty depth writes zeros. Thegemmandnano-gemmcrates never see uninitialized storage (see the review below), so on other targets the native types are zero-filled through raw writes and then multiplied by the ordinary path.&T/&mut Tto unwritten elementsUninitMutexposes only metadata and the raw pointer; every write goes through a raw pointer (ptr::writeon the generic path). TheMatMutis formed from the raw parts only after the call has written every element.MatUninitMutper slot (from_raw_parts_mutat the batch offset), as in the test.MatMutreturnedMaybeUninit<T>storage; no element is exposed as initialized unless the call returns.Parparargument;Par::Teamreachesgemm_team, and the generic path is split by columns on the team.MatMutAPIs unchangedUninitMut,MatUninitMut,matmul_with_conj_uninit.Tests
All tests are in
linalg::matmul::tests.fx128. The upstream PR's Rayon test is replaced by a team test, sincePar::Rayonno longer exists here.test_matmul_with_conj_uninit_native_never_reads_destination:1x1x1to130x70x90, plus5x300x7and9x600x7, which crosses the kernel's 512 depth block, row- and column-major, and the conjugation pairs;matmul_with_conj, and the padding must still be NaN afterwards._team: f64130x70x90andfx128on a team of 3._matrix_vector:2x3 · 3x1intouninit()storage, the shape where thegemmcrate takes its GEMV._batched: three row-major slots in one buffer; the padding between slots stays untouched.cargo +nightly miri test) runs the seven small tests, six of them onMaybeUninit::uninit()storage, and reports no uninitialized read. Under Miri the native types take the zero-fill route, because Miri cannot run the SIMD kernel. The NaN and team tests are too large for Miri.Performance (indicative)
On primerose, a shared host, I timed one shape:
2048x64x2048, f64,Par::Seq, into existing storage, best of 30, three runs. The new call took 0.89 to 0.93 of a zero fill followed byAccum::Replace. The saving is the output-sized fill, so it shrinks askgrows. This is not a quiet-host measurement.Verification
cargo test -p t4a-faer --lib uninit: 9 passed after the review fixes. Before them,--lib linalg::matmulgave 16 passed (1 ignored, as onmain), and the new doctest passes.docs/worklogs/2026-10-29-matmul-uninit.md.cargo check -p t4a-faer --no-default-featuresand--no-default-features --features stdcompile with no warning from this change.gemm-common0.19'smixed_gemv_colmajorbuilds a&mut [T]over the destination before writing it. The first version sent the non-x86 fallback through thegemmcrate.alpha.gemmcrate no longer receives uninitialized storage; those targets zero-fill first.🤖 Generated with Claude Code