Skip to content

perf(native-cpu): run the ternary f32 GEMV on the shared row pool (+19% BitNet decode on A78C) - #1359

Merged
michalharakal merged 1 commit into
developfrom
perf/ternary-gemv-row-pool
Oct 17, 2026
Merged

michalharakal merged 1 commit into
developfrom
perf/ternary-gemv-row-pool

Conversation

@michalharakal

Copy link
Copy Markdown
Contributor

What

skainet_ternary_f32_gemv (the BitNet b1.58 / BITNET_B1_58 projection) called the vendored NeoGPU hs_ml_ternary_f32_proj directly. That function creates and joins 4 pthreads on every call once N >= 512, which is about 210 calls per BitNet 2B4T decode step. It's the create/join pattern skainet_row_threads.c documents as the slow one (#1195).

The adapter now drives the vendored kernel from the shared row pool (skainet_run_rows) in slices of < 512 rows, so each slice stays below NeoGPU's THREAD_THRESHOLD and runs inline on a pool thread.

  • Vendored file untouched: still byte-identical, "Local modifications: none", as the vendor README requires. The README's constraints section is updated to describe the adapter's threading.
  • Bit-identical results: per-row math doesn't depend on the slicing. threaded_regime_matches_single_row_calls_exactly (outputDim 2048, partial slice included) covers it; its comment is updated.
  • lm_head stage 1 unchanged: hs_ml_lmhead_stage1 always threads and has no inline entry point. Pooling it as well needs an upstream NeoGPU change; it was worth about +6 % more in my experiment below.

Measurements: Arduino Ventuno Q, 4× Cortex-A78C, taskset -c 0-3

Microbenchmark of the vendored kernel at the real 2B4T shapes, weights streamed from DRAM (harness):

op create/join (before) row pool (after)
q/o 2560×2560 654 µs 309 µs
k/v 640×2560 251 µs 84 µs
gate/up 6912×2560 1371 µs 785 µs
down 2560×6912 1430 µs 831 µs
trunk per token (210 GEMVs) 185.9 ms 93.9 ms

End to end: skainet-cli, JVM (Temurin 21), microsoft/bitnet-b1.58-2B-4T-gguf I2_S, 128 greedy tokens:

build decode tok/s greedy output
before 1.90 md5 52f57d1d…
this PR 2.26 (+19 %) md5 52f57d1d… (byte-identical)
(experiment: also pooling lm_head by editing the vendored file, not proposed) 2.40 identical

Tests

  • :skainet-backends:skainet-backend-native-cpu:jvmTest --tests '*Ternary*' on linux-x86_64 passes 13/13: NativeTernaryF32GemvKernelTest 10, TernaryPlanesFfmTest 2, TernaryF32FfmPackTest 1.
  • I cross-built libskainet_kernels.so for linux-arm64 from this branch and ran it on the board (numbers above).
  • The JNI-cpu CMake already compiles skainet_row_threads.c, so the Android AAR links unchanged.

Refs #1357

🤖 Generated with Claude Code

The vendored NeoGPU proj creates and joins 4 pthreads per call once N >= 512 —
~210 calls per BitNet 2B4T decode step. The adapter now drives the vendored kernel
from skainet_run_rows in < 512-row slices, so each slice runs inline on a pool
thread. The vendored file stays byte-identical; per-row results are unchanged.

Cortex-A78C (Ventuno Q, 4 cores): q/o 654 -> 309 us, k/v 251 -> 84 us,
gate/up/down ~1.4 -> ~0.8 ms; BitNet 2B4T JVM decode 1.90 -> 2.26 tok/s with
byte-identical greedy output.

Refs #1357

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@michalharakal
michalharakal merged commit 351b1a5 into develop Oct 17, 2026
19 of 20 checks passed
@michalharakal
michalharakal deleted the perf/ternary-gemv-row-pool branch October 17, 2026 15:56
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