Skip to content

feat(native): vendored NeoGPU ternary f32 LUT kernel + FFM downcall (#1137) - #1151

Merged
michalharakal merged 2 commits into
developfrom
feature/1137-vendored-neogpu-ternary-f32
Aug 26, 2026
Merged

michalharakal merged 2 commits into
developfrom
feature/1137-vendored-neogpu-ternary-f32

Conversation

@michalharakal

Copy link
Copy Markdown
Contributor

Phase 1 of #1136 — closes #1137.

What

  • Vendors hs_ml_ternary_neon.c from anjaustin/neogpu byte-identical (sha256 recorded in native/src/vendor/neogpu/README.md), MIT with REUSE .license sidecar. Agreed with upstream in Porting the ternary LUT kernel into SKaiNET (Kotlin Multiplatform ML runtime) — a few questions anjaustin/neogpu#1.
  • Adapter skainet_ternary_f32.c → skainet_kernels.h ABI: skainet_ternary_f32_gemv (exact f32 × sequential ternary payload, no scale applied) and skainet_ternary_lmhead_stage1 (fused 4-plane + FP16 row scales, stride-addressed for a future single-buffer BITNET_PLANES format). pthread_once warm-up closes the vendored LUT-init race; MSVC builds get a portable scalar mirror.
  • Build: both native trees (FFM/cinterop lib + JNI) compile the two files; on non-Apple aarch64 they are pinned to -march=armv8-a — this kernel exists for dotprod-less Cortex-A72/Pi-4, the library-wide armv8.2-a+dotprod flags must not leak in.
  • FFM downcall NativeTernaryF32GemvKernel (jvmMain) + goldens (jvmTest).

Why

Exact FP32-activation ternary matmul (no I8-absmax requantization error) on baseline NEON — the fast path where the existing bitnet_gemv falls back to vmull_s8. Upstream measured 6.78 GOPS on Pi-4. Design facts in #1136.

Tests

  • :skainet-backends:skainet-backend-native-cpu:jvmTest — green locally (macOS arm64 → NEON branch). Goldens pin the full 256-byte decode table (incl. code 3 → +2), pthread partitioning above the 512-row threshold, offsets, and edges; the same goldens cover the scalar branch on x86 CI.
  • C-level smoke (all-bytes exact, threaded-vs-per-row bitwise equality, fused lm_head vs double-precision reference) verified during development.
  • Not run locally (no NDK / aarch64 cross toolchain here): JNI Android build, linuxArm64Test -PcrossArm64 qemu lane — CI should cover both.

Kernel-support matrix intentionally untouched: the kernel joins a provider/pack in #1138 (SPI + KernelDispatch wiring), which is where it becomes dispatchable.

🤖 Generated with Claude Code

michalharakal and others added 2 commits August 26, 2026 10:04
Byte-identical copy of src/hs_ml_ternary_neon.c from anjaustin/neogpu at
0846b24 (sha256 recorded in the vendor README), with the REUSE .license
sidecar carrying the upstream copyright. Exact f32-activation ternary
matmul on baseline NEON — no dotprod, the fast path for Cortex-A72/Pi-4.
Agreed with upstream in anjaustin/neogpu#1.

Refs #1137, #1136

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pipeline

skainet_ternary_f32.c adapts the vendored file to the skainet_kernels ABI:
skainet_ternary_f32_gemv (single-plane proj, no scale applied — the caller
owns it) and skainet_ternary_lmhead_stage1 (fused 4-plane + FP16 row
scales, stride-addressed so one concatenated buffer works). A pthread_once
warm-up closes the vendored non-atomic LUT-init guard; MSVC builds compile
a portable scalar mirror instead (SKAINET_HAVE_NEOGPU_TERNARY unset).

Build: both native trees compile the two files; on non-Apple aarch64 they
are pinned back to -march=armv8-a — the library-wide v8.2+dotprod flags
would defeat a kernel that exists for dotprod-less cores.

NativeTernaryF32GemvKernel downcalls the gemv via FFM and round-trips the
output reach so row-looping callers keep previously written rows. Goldens
pin the full 256-byte decode table (code 3 → +2), the pthread partitioning
above the 512-row threshold, offsets, and edge cases — the same goldens
cover the NEON branch on arm64 and the scalar branch on x86.

The TernaryF32GemvNative SPI + KernelDispatch wiring follows in #1138;
the kernel-support matrix is untouched until the kernel joins a provider.

Refs #1137, #1136

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

[ternary-f32] Phase 1: vendor NeoGPU LUT kernel + adapter + CMake + JVM FFM downcall

1 participant