Skip to content

aarch64: add runtime i8mm expert kernel#217

Draft
RonitBStudent wants to merge 2 commits into
JustVugg:devfrom
RonitBStudent:agent/aarch64-i8mm-kernel
Draft

aarch64: add runtime i8mm expert kernel#217
RonitBStudent wants to merge 2 commits into
JustVugg:devfrom
RonitBStudent:agent/aarch64-i8mm-kernel

Conversation

@RonitBStudent

Copy link
Copy Markdown
Contributor

Summary

Add a runtime-dispatched AArch64 i8mm expert kernel for the existing int8-activation IDOT path.

  • compile SMMLA only inside per-function i8mm targets, preserving the baseline AArch64 binary
  • detect i8mm at runtime with hw.optional.arm.FEAT_I8MM on macOS and AT_HWCAP2/HWCAP2_I8MM on Linux
  • compute a 2-output × 2-activation tile so all four SMMLA lanes do useful work
  • use four independent accumulators to hide matrix-dot latency
  • support both int8 and packed-int4 weights, arbitrary tails, odd S, and odd output counts
  • keep the measured-slower int4 S=1, I<6144 case on the existing NEON path
  • add I8MM=0 for same-binary A/B measurements

This keeps the dependency-free default CPU path and file formats unchanged.

Why

The warm profile in #136 is matmul-bound on AArch64, while the current NEON IDOT path uses SDOT but not the available i8mm/SMMLA instructions. A direct instruction substitution was slower; the useful unit is a 2×2 tile with activation-pair packing and multiple independent accumulators.

Validation

Apple M2 Pro (12 cores, 32 GB), macOS arm64, Apple Clang 21.0.0. The benchmark was single-threaded because local libomp headers were unavailable. It uses the real GLM-5.2 expert shapes, one untimed call per path, 21 timed A/B pairs with alternating order, and reports medians.

$ make -C c OMPDIR= i8mm-bench
format shape              S   NEON-ms SMMLA-ms speedup  dispatch
i8   gate/up            S=1    0.867    0.526   1.648x  SMMLA
i8   down               S=1    0.652    0.529   1.233x  SMMLA
i8   gate/up            S=2    1.737    0.542   3.205x  SMMLA
i8   down               S=2    1.423    0.556   2.559x  SMMLA
i8   gate/up            S=4    3.445    1.015   3.394x  SMMLA
i8   down               S=4    2.638    0.986   2.675x  SMMLA
i4   gate/up            S=1    0.863    0.853   1.012x  SMMLA
i4   down               S=1    0.656    0.653   1.005x  NEON guard
i4   gate/up            S=2    1.725    0.850   2.029x  SMMLA
i4   down               S=2    1.305    0.853   1.530x  SMMLA
i4   gate/up            S=4    3.493    1.730   2.019x  SMMLA
i4   down               S=4    2.658    1.703   1.561x  SMMLA

Checks run:

  • make check OMPDIR= — clean CPU build, C suite, and 62 Python tests pass with zero compiler warnings
  • ./c/tests/test_idot — exact against scalar references for int8/int4 tiles, random full-range weights, -128 edges, tails, and S=1..3 / odd-output dispatch
  • x86_64 compile-only checks for glm.c, test_idot.c, and bench_i8mm.c — clean compile-out of the AArch64 path
  • git diff --check

Still needed before ready

I do not have the full model snapshot locally. Please run the token-exact oracle (32/32 TF + 20/20 greedy) and OMP_NUM_THREADS=1 make -C c i8mm-bench on an i8mm Linux machine/GB10 or Grace. I8MM=0 provides the same-binary NEON control.

Tracks the aarch64 i8mm frontier item in discussion #209.

@RonitBStudent
RonitBStudent marked this pull request as ready for review July 14, 2026 21:17
Copilot AI review requested due to automatic review settings July 14, 2026 21:17
@RonitBStudent
RonitBStudent marked this pull request as draft July 14, 2026 21:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a runtime-dispatched AArch64 i8mm/SMMLA “expert” matmul kernel for the existing int8-activation IDOT path, keeping the baseline AArch64 binary ISA unchanged while taking advantage of i8mm-capable CPUs.

Changes:

  • Add i8mm feature detection + runtime dispatch (macOS hw.optional.arm.FEAT_I8MM, Linux AT_HWCAP2/HWCAP2_I8MM) and an I8MM=0 kill-switch for same-binary A/B comparisons.
  • Implement a 2-output × 2-activation SMMLA tile (with packing + multiple accumulators) for both int8 and packed-int4 expert weights, including tail handling and an int4 S=1 short-I guard.
  • Add dedicated correctness coverage for the i8mm tile path and a same-binary microbenchmark target (i8mm-bench), plus documentation and clean integration.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
docs/ENVIRONMENT.md Documents I8MM env var and its A/B kill-switch behavior.
c/tools/clean.py Cleans new i8mm_bench build artifact.
c/tests/test_idot.c Extends IDOT exactness tests to cover i8mm tile entrypoints and dispatched matmul parity.
c/tests/bench_i8mm.c Adds same-binary NEON-vs-SMMLA microbenchmark for real expert shapes.
c/Makefile Adds build/run targets for the new i8mm benchmark and updates .PHONY.
c/glm.c Adds i8mm runtime detection, activation packing scratch, SMMLA 2×2 kernels, and dispatch integration into IDOT matmuls.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread c/tests/bench_i8mm.c Outdated
Comment on lines +25 to +28
uint8_t *w=malloc(wn); int8_t *x=malloc((size_t)S*I);
float *yn=malloc((size_t)S*O*sizeof(float)),*ym=malloc((size_t)S*O*sizeof(float));
float *sc=malloc((size_t)O*sizeof(float)),*sx=malloc((size_t)S*sizeof(float));
if(!w||!x||!yn||!ym||!sc||!sx){ fprintf(stderr,"bench_i8mm: OOM\n"); return 0; }
Comment thread c/tests/bench_i8mm.c
Comment on lines +36 to +38
if(memcmp(yn,ym,(size_t)S*O*sizeof(float))!=0){
fprintf(stderr,"bench_i8mm: numeric mismatch: %s\n",label); return 0;
}
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.

2 participants