performance - 简单阵列处理循环的 AVX 512 与 AVX2 性能对比

标签 performance x86 micro-optimization avx2 avx512

关闭。这个问题需要debugging details .它目前不接受答案。












想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。

3年前关闭。




Improve this question




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

最佳答案

这看起来太宽泛了,但实际上有一些微架构细节值得一提。

请注意,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 和更高端的 Xeons 在端口 5 上有一个额外的 512 位 FMA 单元来供电支持 AVX512“模式”。

    所以相应地计划:你不会从扩展到 AVX512 获得双倍的速度,你的代码中的瓶颈现在可能在后端。
  • 运行 512 位 uops 也会限制您的最大 Turbo,因此挂钟加速可能低于核心时钟周期加速。 Turbo 减少有两个级别:任何 512 位操作,然后是重型 512 位,如持续 FMA。
  • vsqrtps/pd zmm的FP除法执行单元和 vdivps/pd不是全宽;它只有 128 位宽,因此 div/sqrt 与乘法吞吐量的比率差了大约 2 倍。参见 Floating point division vs floating point multiplication . vsqrtps xmm/ymm/zmm 的 SKX 吞吐量是每 3/6/12 个周期一个。 double -precision 是相同的比率,但吞吐量和延迟更差。

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

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


  • 就自动向量化而言,如果需要任何洗牌,编译器可能会在处理更宽的向量时做得更糟。对于简单的纯垂直的东西,编译器可以用 AVX512 来做。

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

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

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

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

    关于performance - 简单阵列处理循环的 AVX 512 与 AVX2 性能对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52523349/

    相关文章:

    java - 什么是 jvm 预分配异常?

    java - 如何从长值中获取更多有效数字来打印?

    linux - .text 段大于可执行文件中的 .text 段。为什么?

    程序集 x86 : comparing strings doesn't work

    assembly - 为什么编译器不使用 ENTER 和 LEAVE 指令?

    assembly - 最快的轮询循环 - 如何修剪 1 个 CPU 周期?

    performance - 两个看似等效的汇编代码之间的性能差异

    JavaScript 性能(typeof arr[i] === "undefined"|| num < arr[i])

    python - 如果满足Python中的标准,则有效地替换元素

    javascript - 为什么 chrome 很难在 Canvas 上显示大量图像,而其他浏览器却不能?