Skip to content

perf(gemm): native float32 GEMM on riscv64 (RVV 6x16) - #108

Merged
tannevaled merged 2 commits into
mainfrom
perf/gemm32-riscv64-rebased
Nov 9, 2026
Merged

tannevaled merged 2 commits into
mainfrom
perf/gemm32-riscv64-rebased

Conversation

@tannevaled

@tannevaled tannevaled commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Native float32 GEMM on riscv64: a 6×16 RVV micro-kernel (gemmMicro6x16RVV, go-asmgen), accumulating in float32 like NumPy's sgemm. It runs behind the same AT_HWCAP V check as the float64 RVV GEMM; without V, float32 products still go through the float64 GEMM.

This is the kernel of #80, rebased onto today's main (97aaaa7, after the K1 moves and the refbench page), plus the measurement #80 was waiting for. A force-push of #80's branch was refused, so the rebase lives on a new branch; #80 will be closed with a pointer here. GEMM stays in ndarray, as the K1 tracking issue says ("GEMM stays here"; Refs #98, which stays open for the kernels that do move).

Measured on the SpacemiT X60 (cfarm95, VLEN 256): one pinned core, abbench 8 interleaved rounds, load 4.1–4.9 of 8, BenchmarkDTypeMatMul/float32.

float32 MatMul 64² 256² 1024²
main (float64 GEMM path) 546 µs 15.9 ms 944 ms
this PR 172 µs 7.1 ms 462 ms
OpenBLAS 0.3.34 cblas_sgemm, 1 thread 102 µs 5.4 ms 368 ms

That is −69%, −55% and −51% (p = 0.000). It is still 1.26–1.69× slower than OpenBLAS, filed as Refs #107. NumPy is no reference on that host: its 2.5.4 build has no BLAS.

Verified:

  • TestGemm32Accuracy and TestGemm32Specials pass on the X60, as does the whole kernels and root suite there.
  • Locally, go vet passes for linux/riscv64 and the full suite passes.
  • Regenerating the assembly leaves no diff.

Docs: README (riscv64 joins the native float32 GEMMs; the roadmap keeps only loong64) and docs/perf-history.md.

🤖 Generated with Claude Code

tannevaled and others added 2 commits November 8, 2026 13:45
gemmMicro6x16RVV is the float64 6x8 RVV kernel in float32: with E32,
a group of four registers (LMUL=4) holds at least sixteen floats on any
VLEN >= 128, so vl = 16 everywhere and the same six accumulator groups,
B group and C group fit. Each A value is fused in with vfmacc.vf. Gated
on useRVV; without V, float32 products widen to the float64 GEMM.

Correct on a real Spacemit X60 (cfarm95), kernel and root suites. Not
yet measured: the host was 98.9% busy and abbench refused to run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README: riscv64 (RVV 1.0) joins the native float32 GEMMs; the roadmap
keeps only loong64. perf-history.md: on the SpacemiT X60, one core,
abbench 8 rounds, -69%/-55%/-51% at 64/256/1024 against the float64
path, and still 1.69x/1.33x/1.26x slower than OpenBLAS 0.3.34
(riscv64_zvl256b, one thread), an open defect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 32aaf74 into main Nov 9, 2026
13 checks passed
@tannevaled
tannevaled deleted the perf/gemm32-riscv64-rebased branch November 9, 2026 10:11
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