Skip to content

perf(kernels): SIMD128 bodies for K-quants, Q5_0/Q5_1 and dense FP32/BF16/FP16; threaded dense kernels - #1364

Merged
michalharakal merged 2 commits into
SKaiNET-developers:developfrom
michalharakal:feature/wasm-simd128-kernel-bodies
Oct 19, 2026
Merged

michalharakal merged 2 commits into
SKaiNET-developers:developfrom
michalharakal:feature/wasm-simd128-kernel-bodies

Conversation

@michalharakal

Copy link
Copy Markdown
Contributor

Summary

Second step of the wasm ↔ JVM parity series (first: #1363, which this branch is stacked on — the BF16/FP16 provider binding from there is what exercises the new 16-bit bodies on wasm). All C changes are in the shared skainet-backend-native-cpu/native/src tree, so the JVM FFM, Android JNI and Kotlin/Native packs build from the same files.

  • Explicit SIMD128 bodies for every matmul kernel in the sidecar. Q4_K, Q5_K, Q6_K, Q5_0 and Q5_1 join Q8_0 and Q4_0. The K-quant int8 dots use i32x4.dot_i16x8_s over widened lanes (the SIMD128 stand-in for vdotq_s32), the Q6_K unpack is one lane vector per sub-code, the Q5_0/Q5_1 fifth-bit plane is expanded with a byte swizzle and a per-lane bit test. Helpers live in skainet_simd.h next to the NEON ones.
  • Dense FP32 GEMM micro-kernel. The SIMD128 body is a 4×8 register-blocked, k-blocked tile (eight accumulators carried in C between k-blocks). Every output still accumulates in ascending p, so the result is bit-identical to the portable body. The portable and NEON bodies are unchanged.
  • BF16 / FP16. Eight weights widen per step on SIMD128 (the branch-free binary16 decode on i32x4 lanes, bit-for-bit the scalar sequence) and on NEON (vcvt_f32_f16); the stream (m == 1) and tile (m > 1) paths both use it. These are the first NEON bodies for the two formats on any tier; the macOS arm64 CI leg runs the FFM parity tests against them.
  • Threads for the dense kernels. skainet_fp32_matmul splits C over its longer side, the 16-bit kernels over columns, through skainet_row_threads.h like the packed kernels — the mt sidecar's pthreads in a browser, the native pool on the JVM. Workers own disjoint outputs, so no accumulation order changes.
  • WasmCpuOps.matmul. A dense 2-D A · B on heap FP32 operands runs the sidecar GEMM. The common [k, n] loop served that shape before the registry, so it was the one dense path that never reached the sidecar (measured at scalar speed in feat(wasm): BF16/FP16 provider kernels, common KernelStrictness, matrix rows, sidecar features, aligned wasm-bench scenarios #1363's bench).
  • Sidecar rebuilt (build-wasm.sh, emsdk 4.0.14): 29 KB st / 44 KB mt.

Measurements (wasm-bench, Node, 12-core laptop; engine-* ids as in jvm-cpu-publish)

Scenario simd128-st before → after simd128-mt before → after
engine-fp32-gemm (ops layer, 1024³) GFLOPS 0.74 → 13.83 0.74 → 39.14
engine-kernel-matmul GFLOPS 10.76 → 13.99 7.36 → 40.36
engine-bf16-matmul GFLOPS 6.96 → 7.01 4.42 → 11.88
engine-q4-gemm (Q4_K 4096²) Gops 4.42 → 7.62 14.26 → 24.03
engine-q8-matmul Gops 8.39 → 8.18 24.03 → 27.55

JVM Panama on the same machine: fp32 gemm 15.9, kernel 24.5, bf16 1.5, q4_k 19.3.

Verification

  • :skainet-backends:skainet-backend-wasm-simd:wasmJsNodeTest — 7 tests: all seven packed formats against the scalar kernels (K-quant int8 paths on the aggregate relative-RMS gate the JVM tests use, the rest at lane-sum tolerance), the ops-layer GEMM over full tiles, row/column remainders and a k past one 256-block, BF16/FP16 contiguous and windowed, strict mode, features.
  • :skainet-backends:skainet-backend-native-cpu:jvmTest — FFM parity for the threaded portable bodies (x86 host); NEON bodies via the macOS arm64 CI leg.
  • scripts/pr-gate.sh --quick and the full gate.

…ix rows, sidecar features, aligned wasm-bench scenarios

- WasmKernelProvider binds the existing skainet_bf16_matmul / skainet_fp16_matmul
  sidecar exports (resident contiguous weight, staged strided window).
- WasmSimd.features() and a one-line install banner mirroring the JVM factory.
- KernelStrictness moves to commonMain with a programmatic overrideEnabled switch;
  JVM/Android keep the system property. KernelDispatch and DefaultCpuOps.matmul
  fail fast in strict mode before their reference fallbacks.
- Kernel support matrix: Float16 row, BF16/FP16 on wasm-simd128, Q6_K on
  native-ffm, new "Resident serving" table; drift gate covers Panama and FFM
  tiers when available.
- wasm-bench runs the engine-* scenarios of jvm-cpu-publish on every tier;
  the ternary gemv is skipped where no ternary kernel is registered.
- Docs: eager-execution wasm column and FP16 row, corrected gaps; dtype-model
  strict-mode section; CHANGELOG.
…BF16/FP16; threaded dense kernels

- Explicit __wasm_simd128__ bodies for q4k, q5k, q6k, q5_0 and q5_1 (K-quant
  int8 dots on i32x4.dot_i16x8_s, Q5 fifth-bit plane via byte swizzle);
  helpers in skainet_simd.h next to the NEON ones.
- Dense FP32 GEMM: 4x8 register-blocked, k-blocked SIMD128 micro-kernel;
  BF16/FP16 widen eight weights per step on SIMD128 and NEON (first NEON
  bodies for those formats). Accumulation order unchanged on every path.
- skainet_fp32_matmul, skainet_bf16_matmul and skainet_fp16_matmul split the
  output over the shared row-thread pool like the packed kernels.
- WasmCpuOps.matmul routes dense 2-D heap FP32 A·B to the sidecar GEMM.
- Sidecar rebuilt; wasm parity tests for all seven packed formats and the
  ops-layer GEMM tile shapes; CHANGELOG and eager-execution docs.
@michalharakal
michalharakal merged commit 4393a7b into SKaiNET-developers:develop Oct 19, 2026
22 checks passed
@michalharakal
michalharakal deleted the feature/wasm-simd128-kernel-bodies branch October 19, 2026 10:15
michalharakal added a commit that referenced this pull request Oct 21, 2026
CHANGELOG [0.62.0] - 2026-10-21 with the parity headline over #1363, #1364,
#1368, #1369, #1426, #1427, #1428 and #1430, plus entries for the operator
coverage matrix (#1370), the BitNet decode allocation and threading fixes
(#1359, #1360, #1361, #1362), the ClassificationSupport extraction (#1429)
and the toolchain bumps (Kotlin 2.4.21, kotest 6.2.6, Gradle 9.8.1).
VERSION_NAME, CITATION, Antora version, README bom coordinate, What's New
and contributors, Android tutorial coordinates; regenerated operator and
kernel-support matrices; SKEEP-007 rollout step 3 marked shipped.
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