【问题标题】:AVX 512 vs AVX2 performance for simple array processing loops [closed]简单阵列处理循环的 AVX 512 与 AVX2 性能 [关闭]
【发布时间】:2018-09-26 17:38:44
【问题描述】:

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

【问题讨论】:

    标签: performance x86 micro-optimization avx2 avx512


    【解决方案1】:

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

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


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

    • 将数据与向量宽度对齐比使用 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 位操作,然后是 heavy 512 位,如持续 FMA。

    • vsqrtps/pd zmmvdivps/pd 的 FP 除法执行单元不是全宽;它只有 128 位宽,因此 div/sqrt 与乘法吞吐量的比值要差大约 2 倍。请参阅Floating point division vs floating point multiplicationvsqrtps xmm/ymm/zmm 的 SKX 吞吐量为每 3/6/12 个周期一个。 double-precision 的比率相同,但吞吐量和延迟更差。

      最多 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 缓存可以获得两倍的收益。

    在数据已经加载到寄存器时处理数据是好的。

    【讨论】:

    • @BeeOnRope:缓存行交叉的额外延迟降低了 OoO exec 通过保持多次迭代来隐藏长 dep 链的能力。这是我在log(x) 的多项式近似代码中看到的真实效果,它是asinh(x) 的一部分。即使 L1d 带宽远未达到饱和,您也能获得效果。
    • @PeterCordes - 有道理。我意识到我对拆分负载延迟了解不多,所以我added some tests。您可以像以前一样在same gist 中查看 SKL 和 SKX 上的结果。在 Intel 的 L1 中,拆分负载看起来有 11 个周期延迟。在这种情况下,AMD on the other hand 似乎只是 1 个周期惩罚(总共 5 个周期)。
    • 对于其他缓存级别仍然有很大的损失,例如 L2 (Intel) 的总周期为 22-24 个,而对于仅适合内存的较大尺寸,在 SKX 和在 SKL 上也很大!这有点奇怪,因为您希望两条线都以并行方式获取,并且这样可以隐藏大部分惩罚,但情况似乎并非如此。在 AMD Zen 上,大区域损失要小得多,但整体时间与英特尔的拆分情况一样慢,因此英特尔在非拆分负载方面非常出色,或者测试可能有问题。
    • 是的,看起来英特尔可能是背靠背地执行拆分负载,至少到 L2,不是并行执行,而是 AMD 并行执行。 AMD 也有吞吐量损失,与 Intel 或多或少的负载相同,只是它适用于 32B 边界,而不仅仅是 64B(高速缓存行)边界。 256 位负载当然是不同的,因为 AMD 拆分了 256 位操作,但其余部分大致相同(每个交叉负载 1 个周期)。商店在 AMD 上的表现更差。
    • FWIW 自Haswell 以来,L1D 拆分负载延迟损失似乎有所增加,我在那里获得了大约 9 个周期(实际上在这个特定的测试中始终测量为 9.36,我无法真正解释)。这与 Skylake 客户端中 L1D 加载路径中发生的各种变化一致,可能是为 SKX 中的 64 字节加载做准备。我还看到,在拆分情况下,每个负载发出 2 个 p23 微指令,因此处理整个事情的不仅仅是一个微指令:所以也许调度程序像往常一样发送拆分负载,然后拆分负载回来并说...
    【解决方案2】:

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

    1. 对于新的 Intel 编译器(从 18.0 / 17.0.5 开始),如果使用 [Qa]xCORE-AVX512,您将只启用 AVX-512-VL,这基本上意味着 AVX512 ISA 但带有 256 位宽的操作数。这似乎也是 GCC 的默认行为。
    2. 否则,如果 (a) 使用旧版 Intel 编译器,或 (b) 使用 [Qa]xCOMMON-AVX512 或 (c) 如果使用特殊的新标志 [Q/q]opt-zmm- usage=high,您将获得具有 512 位宽操作数的完整 AVX-512 ISA。 (给定复杂的标志逻辑描述here)。在 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-reality/

    【讨论】:

    • 好点,更新了我的答案,明确表示微架构效果仅适用于使用 512 位向量,不适用于 EVEX 编码的 512 位指令。
    • 我找到了一个更新的链接-xCore-AVX512 -qopt-zmm-usage=highcolfaxresearch.com/skl-avx512
    • 来自godbolt,如果您查看程序集,除了-qopt-zmm-usage=high 之外,ICC 不会生成聚集。但是 GCC 使用 256 位聚集,除了 -mprefer-vector-width=512 在这种情况下它使用 512 位聚集。至少在这种情况下,ICC 甚至没有使用 256 位 AVX512 操作。
    • 给定的 colfax 文档应该是过时的(并且可能在 ICC 18 版本之前生成)。 GCC 和 ICC 应该是相对一致的,这就是你部分确认的。驱动最大频率使用的不是 512 位本身,因此低与高(以及继承的 CORE 与 COMMON 等)差异可能比简单的 512 与 256 更细。
    猜你喜欢
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 2013-08-19
    • 2022-08-18
    • 2018-01-20
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多