Skip to content

Add a WASM SIMD128 SAXPY/DAXPY kernel - #5984

Open
jjerphan wants to merge 1 commit into
OpenMathLib:developfrom
jjerphan:wasm128-axpy
Open

Add a WASM SIMD128 SAXPY/DAXPY kernel#5984
jjerphan wants to merge 1 commit into
OpenMathLib:developfrom
jjerphan:wasm128-axpy

Conversation

@jjerphan

@jjerphan jjerphan commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #5983 / #5680 / #4023: replace the RISC-V scalar SAXPY/DAXPY kernels used by WASM128_GENERIC with a WASM SIMD128 unit-stride kernel.

  • kernel/wasm/KERNEL is included after KERNEL.WASM128_GENERIC and previously overwrote S/D AXPY with kernel/riscv64/axpy.c, so the x86_64 V_SIMD sources listed in the target file never ran.
  • SAXPY/DAXPY now use kernel/wasm/axpy.c. Unit-stride y += da * x is eight independent v128 lanes (32 floats / 16 doubles) with IEEE mul+add; remainder is one vector then scalar.
  • Relaxed madd stays out of AXPY: L1 is checked to machine epsilon, and putting it in the generic V_SIMD path previously slowed Level 1. Non-unit stride stays scalar (no WASM gather); inc == 0 uses that path so y[0] += n * da * x[0].
  • SAXPYKERNEL / DAXPYKERNEL in KERNEL are wrapped in ifndef so the target file wins (same include-order fix as TRMM in Add a 4x4 WASM SIMD128 GEMM microkernel #5983). CAXPY/ZAXPY stay RISC-V scalar.

Benchmarks

Node / Emscripten, TARGET=WASM128_GENERIC, USE_THREAD=0, COMMON_OPT=-O2. Same machine, 5 warmup + 10 timed samples (median). Speedup > 1 means this branch is faster than develop.

Geomean vs develop: SAXPY 1.63x, DAXPY 1.53x.

op n develop MFLOPS SIMD MFLOPS speedup
saxpy 256 13612.1 18614.5 1.367
saxpy 512 12526.7 18872.2 1.507
saxpy 1024 7845.5 19280.2 2.457
saxpy 2048 10572.4 22151.7 2.095
saxpy 4096 12152.2 17183.2 1.414
saxpy 8192 12721.4 15785.8 1.241
daxpy 256 6002.4 9422.7 1.570
daxpy 512 4949.5 10745.0 2.171
daxpy 1024 5293.2 8661.3 1.636
daxpy 2048 6056.4 8628.7 1.425
daxpy 4096 6432.5 8139.7 1.265
daxpy 8192 6308.6 7882.8 1.250

Test plan

  • Node CBLAS odd-size GEMM/TRSM/TRMM check
  • utest under node (including saxpy/daxpy inc==0; 106/106)
  • CBLAS ctest L1 (x{s,d,c,z}cblat1) under node, including SAXPY/DAXPY

kernel/wasm/KERNEL is included after KERNEL.WASM128_GENERIC and
unconditionally pointed S/D AXPY at RISC-V scalar axpy.c, so the
x86_64 V_SIMD sources listed in the target file never ran.

Add kernel/wasm/axpy.c for both precisions. Unit-stride y += da * x
uses eight independent v128 lanes (32 floats / 16 doubles) with IEEE
mul+add; remainder is one vector then scalar. Skip relaxed madd:
AXPY is checked to machine epsilon, and putting it in the generic
V_SIMD path previously slowed Level 1. Non-unit stride stays scalar
(no WASM gather); inc==0 uses that path so y[0] += n * da * x[0].

Guard SAXPYKERNEL/DAXPYKERNEL with ifndef in KERNEL so the target
file wins. CAXPY/ZAXPY stay RISC-V scalar.

On n=512..8192 vs the RISC-V champion, SAXPY is about 1.4–3.0x and
DAXPY about 1.4–2.2x. test.sh is green.

Signed-off-by: Julien Jerphanion <git@jjerphan.xyz>
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