Skip to content

riscv64: 2 of 4: 16 RVV matmul kernels behind Zvfh - #2600

Open
czoli1976 wants to merge 3 commits into
sonos:mainfrom
czoli1976:riscv64-rvv-f16
Open

riscv64: 2 of 4: 16 RVV matmul kernels behind Zvfh#2600
czoli1976 wants to merge 3 commits into
sonos:mainfrom
czoli1976:riscv64-rvv-f16

Conversation

@czoli1976

@czoli1976 czoli1976 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Stacked on #2599. GitHub cannot base a pull request on a fork branch, so this
targets main and its diff carries that PR's commits too. The only new commit here
is 80a800f5 — everything else belongs to #2599 and is reviewed there.

Stacked on the f32 tier. Adds four f16 mmm kernels — 16x8 and 32x8 GEMM, 64x1
and 128x1 GEMV — from the same template at SEW=16, where VLMAX doubles and so
does every tile height for a given LMUL and VLEN.

No template change was needed: the f32 PR already parameterised element size,
so this is a kernel table, a probe, and a predicate.

Why this is not speculative

Zvfh is optional in RVA23, so it has to be detected rather than assumed — but
it is not hypothetical hardware. The SpacemiT X60 in the K1 reports zvfh and
zvfhmin in its /proc/cpuinfo isa string, which covers the Banana Pi BPI-F3,
Orange Pi RV2 and Milk-V Jupiter. llama.cpp's RISC-V build enables zvfh
alongside v for exactly this hardware.

The C920v2 in the SG2044 has scalar zfh only, so this is a VLEN=256-class
feature in practice, and the predicates fall back cleanly on parts without it.

Zvfhmin is not sufficient: it provides only f16<->f32 conversion and so cannot
carry an f16 accumulator, which is why the detection looks for Zvfh
specifically.

Testing

No CI change needed — the -cpu max models the f32 PR added already enable
Zvfh, so both existing riscv64 entries exercise this tier. Locally, tract-linalg
passes at VLEN 128 and 256 with Zvfh on and off, and dispatch_matches_vlen
covers the f16 predicates alongside the f32 ones.

Same caveat as the f32 PR: correctness under emulation, no hardware numbers.

🍍

@czoli1976 czoli1976 changed the title riscv64: f16 RVV matmul kernels behind Zvfh riscv64: 2 of 4: 16 RVV matmul kernels behind Zvfh Aug 7, 2026
ckristian added 2 commits August 12, 2026 07:23
tract had no RISC-V backend, so rv64gc ran the generic Rust kernels for every
matmul. Add an RVV 1.0 f32 mmm tier, detecting V from the AT_HWCAP bit that
Linux never sets for the incompatible 0.7.1 draft and VLEN from the vlenb CSR.
Because VLEN is a runtime property while MR must be a const generic, each
kernel fixes (MR, NR, LMUL) and pins vl to MR, which is correct wherever
VLMAX >= MR and short below it, so dispatch is gated on the hart's VLMAX
reaching MR and the kernel re-checks the granted vl before running. An
assembler probe keeps toolchains predating RVV 1.0 on the generic fallback.
The RVV kernels are gated on the hart's vector length, so a single emulated
width would leave half the kernel set untested. Add riscv64gc to the qemu
cross-test platforms twice, at VLEN 256 and 128, which select disjoint halves.
-cpu max rather than a profile model because the generic rv64 model cannot run
Debian's riscv64 glibc at all.
The riscv64 tier covered f32 only, so f16 matmul fell back to the generic
kernels even on parts with native half-precision vectors, which includes the
SpacemiT X60 in the K1. Add an f16 mmm tier from the same template at SEW=16,
where VLMAX doubles and so does every tile height for a given LMUL and VLEN.
Zvfh is read from the /proc/cpuinfo isa line, since RVA23 mandates only
Zvfhmin and that cannot hold an f16 accumulator, and a second assembler probe
keeps toolchains predating Zvfh on the f32 tier alone.
@czoli1976

Copy link
Copy Markdown
Contributor Author

Rebased onto current main; merge conflict resolved.

This was downstream of #2599, whose conflict was a duplicate of fb4bf2f (the hwbench fallback, since landed upstream). Dropping that one commit cleared this PR too — everything else cherry-picked onto current main with no conflicts. The only new commit here is now 80a800f5.

Re-verified on the new base under qemu-riscv64 11.0.3: the full stack passes 2709 tract-linalg tests at VLEN 128, 256 and 512, on stock rva23u64, and with V absent. cargo fmt --all clean.

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