feat(native): vendored NeoGPU ternary f32 LUT kernel + FFM downcall (#1137) - #1151
Merged
Merged
Conversation
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>
This was referenced Aug 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1 of #1136 — closes #1137.
What
hs_ml_ternary_neon.cfrom anjaustin/neogpu byte-identical (sha256 recorded innative/src/vendor/neogpu/README.md), MIT with REUSE.licensesidecar. Agreed with upstream in Porting the ternary LUT kernel into SKaiNET (Kotlin Multiplatform ML runtime) — a few questions anjaustin/neogpu#1.skainet_ternary_f32.c→skainet_kernels.hABI:skainet_ternary_f32_gemv(exact f32 × sequential ternary payload, no scale applied) andskainet_ternary_lmhead_stage1(fused 4-plane + FP16 row scales, stride-addressed for a future single-bufferBITNET_PLANESformat).pthread_oncewarm-up closes the vendored LUT-init race; MSVC builds get a portable scalar mirror.-march=armv8-a— this kernel exists for dotprod-less Cortex-A72/Pi-4, the library-widearmv8.2-a+dotprodflags must not leak in.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_gemvfalls back tovmull_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.linuxArm64Test -PcrossArm64qemu lane — CI should cover both.Kernel-support matrix intentionally untouched: the kernel joins a provider/pack in #1138 (SPI +
KernelDispatchwiring), which is where it becomes dispatchable.🤖 Generated with Claude Code