Skip to content

tools/parakeet: x86_64 AVX2 kernel tier for the five-value GEMM - #75

Merged
lalalune merged 1 commit into
eliza/develop-pin-ea8b3f2from
claude/parakeet-x86-avx2
Oct 14, 2026
Merged

lalalune merged 1 commit into
eliza/develop-pin-ea8b3f2from
claude/parakeet-x86-avx2

Conversation

@lalalune

Copy link
Copy Markdown
Member

What

Adds an x86_64 AVX2 tier to the Parakeet five-value int8 kernels in tools/parakeet. Until now x86_64 had only the scalar tier, which runs the encoder below real time. That makes ASR on x86_64 Android emulator images unusable.

  • src/pk-kernels-avx2.cpp provides three kernels:
    • fv5 decode, using a PSHUFB nibble lookup.
    • The 8-row x 2·np-token tile. It uses VPMADDWD on int16-widened straight and half-swapped token pairs, the same scheme as the dotprod tier.
    • The decoder int8 matvec.
  • Widening to int16 keeps every int8 product exact, so the tier is bit-identical to the scalar reference for any input. There is no VPMADDUBSW saturation and no -128 corner case.
  • Runtime dispatch: CPUID leaf 7 AVX2, plus OSXSAVE/AVX and an XGETBV check that the OS saves YMM state. The file is compiled with -mavx2 (/arch:AVX2 on MSVC), so the baseline stays x86-64. PK_KERNEL=avx2 or --kernel avx2 forces the tier, and pk_params.kernel = 4 selects it.
  • ARM i8mm and dotprod code is unchanged. CMake also no longer passes the ARM -march flags to an x86_64 build on an Apple silicon host (CMAKE_OSX_ARCHITECTURES=x86_64).
  • tests/test_parakeet_kernels.cpp now also runs 200 random full-range int8 tile and matvec cases against scalar for every tier present, including the all -128 corner.

AVX-512 VNNI is not included. I had no way to execute it here, because Rosetta 2 has no AVX-512, and I did not want to ship an unexecuted tier.

Validation

All runs were on an Apple M4 Max. The x86_64 binaries were cross-compiled and run under Rosetta 2 with arch -x86_64 -e ROSETTA_ADVERTISE_AVX=1. Rosetta executes AVX2 but only reports it in CPUID when that variable is set. Linux x86_64 CI runs test-parakeet-kernels (label main) on real hardware.

  • Kernel tests. test-parakeet-kernels (x86_64, Rosetta) found scalar, avx2 and all checks passed: decode, tile for np 1-4, gemm driver at 1 and 3 threads, matvec, and the 200 random full-range cases. Native arm64 (scalar, dotprod, i8mm) also passed, including the new random cases.
  • Fixture parity, ref-cmd (20 utterances). I ran test-parakeet-parity with phonon-2-fv5.gguf (sha256 dc552eb7…) on x86_64 with PK_KERNEL=avx2 and with PK_KERNEL=scalar. The two report logs are line-for-line identical apart from the tier name. Text and token ids are identical on 20/20, and WER against the reference transcripts is 0.
  • Fixture parity, ref-ls (6 utterances, avx2). PARITY OK, 6/6 text and token ids identical, WER 0.
  • Encoder cosine on x86_64 (gate failure, both tiers). On ref-cmd, the x86_64 build fails the encoder cosine gate with both tiers: utterance c11 has a mean frame cosine of 0.978 against the 0.98 gate. The scalar tier gives exactly the same numbers, so the AVX2 tier did not cause this; it comes from the non-NEON fp32 code paths in pk-ops/parakeet.cpp. The native arm64 build passes the same fixtures (worst 0.9895). I did not loosen the gate.
  • Android NDK r29 builds. The x86_64 build compiles the avx2 file with -mavx2. The arm64-v8a build has no -mavx2.
  • Rosetta speed (sanity check only, not x86 performance evidence). 8 command utterances, 11.8 s of audio, 1 thread, busy host. avx2 ran at 1.18x real time by CPU time, scalar at 0.58x, and native arm64 i8mm at 15.7x.

This PR was prepared with AI assistance (Claude Code), which wrote and tested the change.

🤖 Generated with Claude Code

x86_64 only had the scalar tier, which runs the encoder below real time
and leaves ASR on x86_64 Android emulator images unusable.

pk-kernels-avx2.cpp adds decode (PSHUFB nibble lookup), the 8-row tile
(VPMADDWD on int16-widened straight and half-swapped token pairs, the same
scheme as the dotprod tier) and the decoder matvec. Widening to int16 keeps
every int8 product exact, so the tier is bit-identical to scalar for any
input. The file is built with -mavx2 (/arch:AVX2) and entered only after
CPUID AVX2 plus XGETBV YMM state; PK_KERNEL=avx2 / --kernel avx2 force it.

The kernel test now also runs 200 random full-range int8 tile and matvec
cases (including the all -128 corner) against scalar for every tier.
CMake no longer passes the ARM -march flags to an x86_64 build on an
Apple silicon host (CMAKE_OSX_ARCHITECTURES=x86_64).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation examples labels Oct 14, 2026
@lalalune

Copy link
Copy Markdown
Member Author

I'm merging with failing checks. Every failure on this PR also fails on the base branch head (51b38ee), for the same reason: misaki-g2p does not build under GCC -Werror (maybe_unused, -Wcast-qual) or on clang/Windows (missing <algorithm> for std::all_of). The build stops there, before it reaches tools/parakeet. The one difference is ubuntu-cpu (arm64): it is cancelled on base and fails here, on the same misaki -Wcast-qual error. #74 fixes these.

To get a real CI signal on this change, I opened #76, a draft CI probe that merges this PR on top of #74:

  • The build succeeds on Linux GCC x64 and arm64, Windows clang x64 and arm64, Windows MSVC (vulkan-x64, which compiles pk-kernels-avx2.cpp with /arch:AVX2) and android-arm64.
  • test-parakeet-kernels passes on ggml-ci x64 high-perf and low-perf and on Windows cpu-x64, openblas-x64 and vulkan-x64.
  • The only test failure on [CI probe, do not merge] #75 on top of #74 #76 is test-kokoro-layer-options, which is unrelated to this change.

ctest output is not verbose, so the CI logs do not show which tiers were selected. Locally under Rosetta 2 with AVX reporting enabled, the test selects scalar, avx2 and all checks pass.

🤖 Generated with Claude Code

@lalalune
lalalune merged commit cc45e94 into eliza/develop-pin-ea8b3f2 Oct 14, 2026
9 of 38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation examples

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant