5

我目前正在进行一些优化并比较 DSP 应用程序的矢量化可能性,这似乎是 AVX512 的理想选择,因为这些只是简单的不相关数组处理循环。但是在新的 i9 上,与 AVX2 相比,使用 AVX512 时我没有测量到任何合理的改进。任何指针?有什么好的结果吗?(顺便说一句。我试过 MSVC/CLANG/ICL,没有明显区别,很多时候 AVX512 代码实际上似乎更慢)

4

2 回答 2

10

这似乎过于笼统,但实际上有一些微架构细节值得一提。

请注意,AVX512-VL(向量长度)允许您在 128 位和 256 位向量上使用新的 AVX512 指令(如打包uint64_t<->转换、掩码寄存器等)。double在为 Skylake-AVX512(又名 Skylake-X)进行调整时,现代编译器通常使用 256 位向量进行自动向量化。例如gcc -march=nativegcc -march=skylake-avx512,除非您覆盖调整选项以将首选向量宽度设置为 512,以获取值得权衡的代码。请参阅@zam 的回答。


vpxord ymm30, ymm29, ymm10Skylake-X 上的512 位向量(不是 256 位的 AVX512 指令)的一些主要内容是:

  • 将数据与向量宽度对齐比使用 AVX2 更重要(每个未对齐的负载都跨越缓存线边界,而不是在遍历数组时每隔一个)。在实践中,它会产生更大的差异。我完全忘记了我不久前测试过的东西的确切结果,但可能是 20% 的减速与低于 5% 的失准。

  • 运行 512 位 uops 会关闭端口 1 上的向量 ALU。(但不会关闭端口 1 上的整数执行单元)。一些 Skylake-X CPU(例如 Xeon Bronze)每个时钟只有 1 个 512 位 FMA 吞吐量,但 i7 / i9 Skylake-X CPU 和更高端的 Xeon 在端口 5 上有一个额外的 512 位 FMA 单元,用于供电为AVX512“模式”。

    所以相应地计划:你不会从扩大到 AVX512 获得双倍速度,并且你的代码中的瓶颈现在可能在后端。

  • 运行 512 位微指令也会限制您的最大 Turbo,因此挂钟加速可能低于核心时钟周期加速。Turbo 降低有两个级别:任何 512 位操作,然后是重型512 位,如持续 FMA。

  • FP划分执行单元为非vsqrtps/pd zmm;它只有 128 位宽,因此 div/sqrt 与乘法吞吐量的比值差了大约 2 倍。请参阅浮点除法与浮点乘法。SKX 吞吐量为每 3/6/12 个周期一个。 -precision 是相同的比率,但吞吐量和延迟更差。vdivps/pdvsqrtps xmm/ymm/zmmdouble

    最多 256 位 YMM 向量,延迟与 XMM 相同(sqrt 为 12 个周期),但对于 512 位 ZMM,延迟高达 20 个周期,需要 3 微秒。(https://agner.org/optimize/用于指令表。)

    如果您在除法器上遇到瓶颈并且无法在混合中获得更多其他指令,VRSQRT14PS即使您需要牛顿迭代以获得足够的精度,也值得考虑。但请注意,AVX512 的近似值1/sqrt(x)确实比 AVX/SSE 具有更多的保证精度位。)


至于自动向量化,如果需要任何洗牌,编译器可能会在更宽的向量上做得更差。对于简单的纯垂直内容,编译器可以使用 AVX512 完成。

您之前的问题有一个sin函数,如果编译器/SIMD 数学库只有 256 位版本,它可能不会使用 AVX512 自动矢量化。

如果 AVX512 没有帮助,那么您可能会遇到内存带宽的瓶颈。使用性能计数器进行分析并找出答案。或者尝试更多的较小缓冲区大小的重复,看看当您的数据在缓存中很热时它是否会显着加速。如果是这样,请尝试缓存阻止您的代码,或通过在数据上一次执行更多操作来增加计算强度。

AVX512 在 i9 上的理论最大 FMA 吞吐量翻了一番(以及整数乘法,以及在同一执行单元上运行的许多其他东西),使 DRAM 和执行单元之间的不匹配增加了一倍。因此,更好地利用 L2 / L1d 缓存可以获得两倍的收益。

在数据已经加载到寄存器中时使用它是好的。

于 2018-09-26T17:59:15.937 回答
8

如果是 ICL 或 GCC,您是如何编译(启用 AVX512)代码的?AVX-512 代码有两种“操作模式”:

  1. 对于新的英特尔编译器(从 18.0 / 17.0.5 开始),如果使用[Qa]xCORE-AVX512,您将只启用AVX-512-VL,这基本上意味着 AVX512 ISA 但具有 256位宽的操作数。这似乎也是 GCC 的默认行为。
  2. 否则,如果 (a) 使用较旧的英特尔编译器,或 (b) 使用[Qa]xCOMMON-AVX512或 (c) 如果使用特殊的新标志 [Q/q]opt-zmm-usage=high,您将获得完整的 AVX -512 ISA 与512 位宽的操作数(这里描述了复杂的标志逻辑)。在 GCC8 或更高版本的情况下,也可以使用 -mprefer-vector-width=512 启用此模式。

如果您的代码是“AVX512-friendly”(您有很长的向量化代码序列,而没有标量代码“中断”向量指令序列),则模式 (2) 是可取的,您必须启用它(即默认情况下不是)。

否则,如果您的代码对 AVX512 不是很友好(向量代码之间有许多非向量化代码),那么由于 SKX“频率限制”,AVX512VL 有时可能更有益(至少在您进行更多代码向量化之前)因此,您应该确保您在模式 (1) 下运行。例如,在 Lemier 博士的博客中描述了频率与 ISA 的情况(尽管博客中给出的图片与现实相比有点过于悲观):https ://lemire.me/blog/2018/09/07/avx- 512-when-and-how-to-use-these-new-instructions/https://lemire.me/blog/2018/08/13/the-dangers-of-avx-512-throttling-myth-or -现实/

于 2018-09-27T19:04:16.217 回答