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)
- Bump
Directory.Build.props TFM → net11.0, global.json SDK pin.
- 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.
- Gate on
AvxVnni.V512.IsSupported; keep the maddubs-on-256-halves path as the AVX-512-without-VNNI fallback.
- Parity tests vs scalar (discriminating shapes), guarded by
AvxVnni.V512.IsSupported — run on Zen5 / AVX-512 CI.
- 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
The AVX-512 VNNI path for Q8_0 requires .NET 11
The Q8_0 outer-product kernel's AVX-512 path (
OuterProductQ8_0Avx512_4x6→ helperAvx512DualBlockFma, plus the single-dotVecDotQ8_0Avx512andProcessAvx512DualBlock) currently reduces int8 withAvx2.Sign+MultiplyAddAdjacent(maddubs) +MultiplyAddAdjacent(prod, ones256)on two 256-bit halves, then assemblesVector512<float>for the accumulate. It does not use VNNI. Replacing that with a single 512-bitVPDPBUSD(dropones256+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.Avx512Vnnidoes not exist in this SDK (clean-projectCS0246; reflection onSystem.Private.CoreLibreturnsnull; the only*Vnni*types areAvxVnni,AvxVnniInt8,AvxVnniInt16). The BCL deliberately did not ship a standaloneAvx512Vnniclass.VPDPBUSDavailable in net10.0 isAvxVnniInt8.V512.MultiplyWideningAndAdd, but it is gated on AVX_VNNI_INT8 (Granite Rapids / Sierra Forest / AVX10.2-era) — a different flag from AVX512-VNNI. It returnsIsSupported == falseon 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 theAVX512v3instruction-set group (BITALG+VBMI2+VPOPCNTDQ+VNNI), i.e. standard AVX512-VNNI (CPUID leaf 7 ECX bit 11) — soAvxVnni.V512.IsSupportedis 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)
Directory.Build.propsTFM →net11.0,global.jsonSDK pin.AvxVnni.V512.MultiplyWideningAndAdd(Vector512<int>.Zero, absX512.AsByte(), adjW512)overVector512— 64 int8 → 16 int32. The dual-block scale mapping (lanes 0–7 → block0, 8–15 → block1) is unchanged. Dropones256.AvxVnni.V512.IsSupported; keep the maddubs-on-256-halves path as the AVX-512-without-VNNI fallback.AvxVnni.V512.IsSupported— run on Zen5 / AVX-512 CI.Until then
The net10.0 deliverable is #321 / PR #323 (the V256
AvxVnnipath 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
AvxVnni.V512(AVX512-VNNI / AVX512v3, .NET 11)