Skip to content

perf(cpu/matmul): Q8_0 outer-product GEMM via AVX2 VNNI (VPDPBUSD-256) — unblock #61 register pressure #321

Description

@jamesburton

Summary

Implement the Q8_0 outer-product GEMM kernel using AVX2 VNNI (AvxVnni.MultiplyWideningAndAddVPDPBUSD-256), completing the Q8_0 half of ROADMAP Phase 3 Step 26 (the F32 half is #312 / PR #315).

Background

PR #61 landed the Q8_0 outer-product family but left it register-pressure-bound: the AVX2 microkernel holds only 3 live accumulators (one weight row at a time) to stay under the 16-YMM ceiling, because the s8×s8 reduction needs a maddubs + madd(ones) pair plus a ones mask and a prod temporary.

AVX2 VNNI (AvxVnni, shipped since .NET 5) fuses multiply + widen + accumulate into a single VPDPBUSD, eliminating the ones register and the prod temporary. That lifts safe accumulator residency from 3 → 6 rows and clears the ~23-YMM problem that blocked #61's dispatch.

Scope

  • OuterProductQ8_0Vnni_4x3 in src/DotLLM.Cpu/Kernels/MatMul.cs: acc = AvxVnni.MultiplyWideningAndAdd(Vector256<int>.Zero, absX.AsByte(), adjW), replacing the AVX2 integer-reduction pair. Same 4-row × 3-token output tile, abs/sign idiom and per-block dw·dx float fold preserved → bit-identical per cell to the AVX2 path (same FMA order).
  • Dispatch: VNNI branch ahead of AVX2 in OuterProductGemmQ8_0 (single-threaded) + OuterProductGemmQ8_0Worker (parallel); not taken on AVX512BW CPUs (they keep the 4×6 AVX512 path) — targets AVX2+VNNI-without-AVX512.
  • Register budget: 4-row R4 group processed as two 2-row sub-passes → 6 float acc + 3 token vectors + ~4-5 transients ≈ 13-14 YMM ≤ 16.

Acceptance criteria

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions