Skip to content

perf(gemm): riscv64 float32 GEMM is 1.26-1.69x slower than OpenBLAS sgemm on one X60 core #107

Open

Description

@tannevaled

The riscv64 float32 GEMM (6×16 RVV micro-kernel, go-ndarray/ndarray PR "native float32 GEMM on riscv64") is still slower than OpenBLAS sgemm on one core.

Measurement

SpacemiT X60 (cfarm95, RVV 1.0, VLEN 256), one pinned core, 1-minute load 4.1–5.2 of 8 cores, 2026-11-08/09:

float32 MatMul (n×n) 64² 256² 1024²
ndarray, RVV float32 GEMM (BenchmarkDTypeMatMul/float32, abbench median of 8) 172 µs 7.1 ms 462 ms
OpenBLAS 0.3.34 cblas_sgemm, riscv64_zvl256b, 1 thread (median of 5) 102 µs 5.4 ms 368 ms
ratio 1.69× 1.33× 1.26×

OpenBLAS is the scipy-openblas32 wheel, called through ctypes on preallocated arrays. ndarray's figure includes its allocation of the result. NumPy 2.5.4 cannot be the reference on this host: pip built it from source without a BLAS, and its fallback loop takes 1.40 ms at 64² and 169 ms at 256².

Where to look

  • The gap is largest at 64², where packing and the edge tiles weigh most. OpenBLAS's riscv64_zvl256b SGEMM kernel and its blocking are the reference to read first (kernel/riscv64/KERNEL.RISCV64_ZVL256B, sgemm_kernel_*_zvl256b.c).
  • Tile shape: OpenBLAS uses its own MR×NR for zvl256b; ours is 6×16 with LMUL=2 on E32.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions