.NET8支持Vector512,但为什么Vector达不到512位?

zyl*_*910 13 c# simd intrinsics avx512 .net-8.0

我的CPU是AMD Ryzen 7 7840H,支持AVX-512指令集。当我运行.NET8程序时, 的值为Vector512.IsHardwareAcceleratedtrue。但System.Numerics.Vector<T>仍然是256位,并没有达到512位。Vector<T>为什么类型长度没有达到 512 位?目前是否不支持,或者我需要调整配置吗?

示例代码:

TextWriter writer = Console.Out;
writer.WriteLine(string.Format("Vector512.IsHardwareAccelerated:\t{0}", Vector512.IsHardwareAccelerated));
writer.WriteLine(string.Format("Vector.IsHardwareAccelerated:\t{0}", Vector.IsHardwareAccelerated));
writer.WriteLine(string.Format("Vector<byte>.Count:\t{0}\t# {1}bit", Vector<byte>.Count, Vector<byte>.Count * 8));
Run Code Online (Sandbox Code Playgroud)

检测结果:

Vector512.IsHardwareAccelerated:        True
Vector.IsHardwareAccelerated:   True
Vector<byte>.Count:     32      # 256bit
Run Code Online (Sandbox Code Playgroud)

Pet*_*des 18

请参阅https://github.com/dotnet/runtime/issues/92189 - 出于与 C 编译器在自动向量化大型循环时默认的硬件原因相同的原因-mprefer-vector-width=256,C# 不会自动使所有向量化代码使用 512 位,即使它是可用的。

此外,对于小问题,例如 9 个浮点数,这可能意味着不会发生矢量化迭代,而只是标量后备代码。

另外,显然某些代码库(希望是偶然的)依赖于 Vector 的宽度不超过 32 字节,因此这对这些代码库来说将是一个重大更改。

@stephentoub 写道: 在 .NET 8 中,可变宽度Vector<T>不会自动支持大于 256 位的宽度。在 .NET 9 中您可能可以选择启用此功能,但目前尚不清楚它是否会默认启用,


我在 dotnet github 问题上发表了评论,其中包含一些有关 CPU 硬件原因的详细信息;我将在这里重现其中的一些内容:

  • 请参阅降低 CPU 频率的 SIMD 指令
  • 另外https://reviews.llvm.org/D111029包括一些英特尔测试结果,发现 SPEC2017 的 clang 自动矢量化实际上比-mprefer-vector-width=512Ice 256Lake Xeon 上的速度慢了 1%。但同样,这是标量代码的 LLVM 自动矢量化,与 C# 不同,这只会影响手动矢量化循环,因此调整考虑因素与-mprefer-vector-width=256.

在频繁唤醒短突发计算的程序中,使用 AVX-512 仍会降低核心的睿频频率,从而影响其他程序。

Zen 4 的情况有所不同;它们通过在执行单元中占用额外的周期来处理 512 位向量,因此只要 512 位向量不需要更多的洗牌工作或其他会增加开销的效果,512 位向量对于前端来说是一个很好的胜利最终吞吐量以及乱序执行器在元素或标量迭代方面可以看到的领先程度。(因为对于前端来说,512 位 uop 仍然只有 1 uop。)GCC 和 Clang 默认为-mprefer-vector-width=512for -march=znver4.

Zen 4 上的 512 位向量没有涡轮惩罚或其他固有缺点(AFAIK;我不知道未对齐的负载如何执行)。这只是软件是否可以有效地使用它们的问题(不需要更多臃肿的循环序言/尾声代码,例如,如果屏蔽的最终迭代不起作用,则进行标量清理。)AVX-512 屏蔽存储在 Zen 4 上是高效的,尽管事实上 AVX1/2 vmaskmovps/vpmaskmovd不是。(https://uops.info/

对于恰好有 32 字节内容的代码,如果 32 字节向量不再是一个选项,那么那就是一种损失。C# 的可扩展向量长度模型对于这些情况并不理想。ARM SVE 或 RISC-V 矢量扩展,其中硬件 ISA 围绕可变矢量长度设计,并带有掩码来处理比硬件本机长度短的矢量,但对 C# 执行相同的操作Vector<>可能效果不佳,因为大量硬件 (具有 AVX2 的 x86 或不具有 SVE 的 AArch64)无法有效支持任意长度内容的屏蔽。


我在 github 问题上写了更多有关英特尔的内容,我不会在这里复制/粘贴所有内容。

对于 Intel CPU 上的某些工作负载,512 位向量可以显着提高总体吞吐量。但它也有缺点,比如更昂贵的未对齐内存访问。