Skip to content

perf(cpu/matmul): AVX-512 VNNI for Q8_0 outer-product (AvxVnni.V512 / VPDPBUSD-512) — requires .NET 11 bump #322

Description

@jamesburton

The AVX-512 VNNI path for Q8_0 requires .NET 11

The Q8_0 outer-product kernel's AVX-512 path (OuterProductQ8_0Avx512_4x6 → helper Avx512DualBlockFma, plus the single-dot VecDotQ8_0Avx512 and ProcessAvx512DualBlock) currently reduces int8 with Avx2.Sign + MultiplyAddAdjacent (maddubs) + MultiplyAddAdjacent(prod, ones256) on two 256-bit halves, then assembles Vector512<float> for the accumulate. It does not use VNNI. Replacing that with a single 512-bit VPDPBUSD (drop ones256 + prod) is the win — but it cannot be expressed on the current target.

Why not on net10.0 (SDK 10.0.300) — verified empirically

  • System.Runtime.Intrinsics.X86.Avx512Vnni does not exist in this SDK (clean-project CS0246; reflection on System.Private.CoreLib returns null; the only *Vnni* types are AvxVnni, AvxVnniInt8, AvxVnniInt16). The BCL deliberately did not ship a standalone Avx512Vnni class.
  • The only 512-bit VPDPBUSD available in net10.0 is AvxVnniInt8.V512.MultiplyWideningAndAdd, but it is gated on AVX_VNNI_INT8 (Granite Rapids / Sierra Forest / AVX10.2-era) — a different flag from AVX512-VNNI. It returns IsSupported == false on Zen4, Zen5, Ice Lake-SP, Sapphire Rapids, so it would silently fall back to maddubs on every intended target (and skip its own parity test even on a Zen5 box).

The route — AvxVnni.V512 (.NET 11)

dotnet/runtime#128365 (merged 2026-06-09) adds AvxVnni.V512.MultiplyWideningAndAdd(Vector512<int>, Vector512<byte>, Vector512<sbyte>) -> Vector512<int>. It maps to the AVX512v3 instruction-set group (BITALG+VBMI2+VPOPCNTDQ+VNNI), i.e. standard AVX512-VNNI (CPUID leaf 7 ECX bit 11) — so AvxVnni.V512.IsSupported is true on AMD Zen5 / Strix Halo and on Intel Cascade/Ice/Sapphire. It ships in .NET 11 and is absent from net10.0.

Scope (gated on the .NET 11 bump)

  1. Bump Directory.Build.props TFM → net11.0, global.json SDK pin.
  2. Rewrite the AVX-512 Q8_0 int8 reduction (the three sites above) to a single AvxVnni.V512.MultiplyWideningAndAdd(Vector512<int>.Zero, absX512.AsByte(), adjW512) over Vector512 — 64 int8 → 16 int32. The dual-block scale mapping (lanes 0–7 → block0, 8–15 → block1) is unchanged. Drop ones256.
  3. Gate on AvxVnni.V512.IsSupported; keep the maddubs-on-256-halves path as the AVX-512-without-VNNI fallback.
  4. Parity tests vs scalar (discriminating shapes), guarded by AvxVnni.V512.IsSupported — run on Zen5 / AVX-512 CI.
  5. Benchmark V512-VNNI vs the current AVX-512 maddubs path on Strix Halo (Zen5).

Until then

The net10.0 deliverable is #321 / PR #323 (the V256 AvxVnni path for AVX2+VNNI-without-AVX512 CPUs — benchmarked ~1.3–1.6× on Meteor Lake). On AVX-512 CPUs the existing 512-bit maddubs path remains in use until this lands.

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