Repository navigation
[MLAS] Add RVV LinearAttention and ReduceMinimumMaximumF32 kernels for riscv64 - #32710
Conversation
β¦ment through it on riscv64
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Copilot review overview
π΅ Needs a closer look
The large architecture-specific vector kernel requires final review and validation on supported RVV hardware.
Review effort: Balanced
Findings: None
What changed in this PR
Adds riscv64 RVV acceleration for linear attention and FP32 min/max reduction.
Changes:
- Implements fused RVV linear-attention kernels and dispatch.
- Adds RVV minimum/maximum reduction.
- Registers kernels with runtime dispatch and CMake.
| File | Description |
|---|---|
riscv64/βsoftmax_kernel_rvv.cpp |
Adds RVV min/max reduction. |
riscv64/βlinear_attention_kernel_rvv.cpp |
Implements RVV linear attention. |
quantize.cpp |
Enables riscv64 RVV min/max dispatch. |
platform.cpp |
Registers scalar and RVV kernels. |
mlasi.h |
Declares new RVV entry points. |
onnxruntime_mlas.cmake |
Builds the RVV attention source. |
π‘ Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Copilot review overview
π‘ Changes recommended
The new kernels lack coverage for important multi-vector and exact-buffer-boundary paths.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (2)
β¦eave partial tails
β¦oss-token buffers, including eight readout heads
There was a problem hiding this comment.
Copilot review overview
π΅ Needs a closer look
The large architecture-specific RVV kernel remains hardware- and compiler-sensitive despite comprehensive static review and reported testing.
Review effort: Balanced
Findings: None


Description
Two RVV kernels for riscv64, closing the remaining fp32 gaps between the RVV and SVE dispatch tables:
MlasLinearAttentionDispatchRvv (riscv64/linear_attention_kernel_rvv.cpp) β the fused recurrence for all four rules (linear / gated / delta / gated-delta), 1/2/4/8 readout heads, any d_v, d_k β€ 256. Other shapes and head counts fall back to the portable kernel as on NEON/SVE.
Where this differs from the fixed-width kernels: a column panel is a single LMUL register group with vl from vsetvl, so there is no per-lane macro grid and the trailing partial panel is an ordinary iteration rather than a predicated copy of the body. LMUL is chosen per head from a register budget (NOUT+2, NOUT+3 or 2Β·NOUT+3 groups, one kept spare) and narrowed to cover d_v. Two further reductions in S traffic, both bit-exact with the unfused form:
The decayed update is evaluated as (decΒ·S_old) + kΒ·upd, multiplying the loaded row in place β the other association holds a product live alongside the row and spills at LMUL 4. Inner loops are verified spill-free.
MlasReduceMinimumMaximumF32KernelRvv (riscv64/softmax_kernel_rvv.cpp) β LMUL 4, tail-undisturbed accumulators, one reduction per extremum at the end, matching the existing RVV max kernel. MlasFindMinMaxElement only consulted the platform slot under MLAS_TARGET_AMD64 || MLAS_USE_SVE; the guard now includes RVV builds, and the riscv64 default block initializes the slot so ORT_MLAS_RISCV_FORCE_SCALAR=1 no longer dereferences a null kernel.
Motivation and Context
LinearAttention gained fused kernels for AVX-512 (#31674), NEON (#32178) and SVE (#32356); riscv64 was still on the scalar portable path. ReduceMinimumMaximumF32 feeds DynamicQuantizeLinear and was the last F32 compute kernel with an SVE implementation but no RVV one.
Test
Measured on a SpacemiT K3 (onnxruntime_mlas_benchmark, BM_LinearAttention, 8 threads), against the portable dispatch on the same build:
X100 cores, VLEN=256. The single-thread gated-delta case runs at β96% of the core's vector-issue bound. On the board's A100 cores (VLEN=1024) the same shapes are 5β14Γ.
MlasFindMinMaxElement: 1024 floats 1677 β 172 ns (9.7Γ), 64K floats 8.1Γ, 4M floats 2.4Γ (DRAM-bound).
LinearAttention and MinMaxElement unit tests pass at VLEN=256 and VLEN=1024 (which take different LMUL paths) and with ORT_MLAS_RISCV_FORCE_SCALAR=1.