首页 >后端开发 >C++ >为什么在 Intel CPU 上用 64 位替换 32 位循环计数器会导致'_mm_popcnt_u64”性能下降?

为什么在 Intel CPU 上用 64 位替换 32 位循环计数器会导致'_mm_popcnt_u64”性能下降?

Patricia Arquette
Patricia Arquette原创
2024-12-03 15:04:10777浏览

Why Does Replacing a 32-bit Loop Counter with 64-bit Cause Performance Degradation with `_mm_popcnt_u64` on Intel CPUs?

用 64 位替换 32 位循环计数器会在 Intel CPU 上使用 mm_popcnt_u64 引入疯狂的性能偏差

摘要

文章调查了更换 32 位循环计数器时遇到的性能偏差使用 _mm_popcnt_u64 内在函数在性能关键循环中使用 64 位计数器。该问题导致 Intel CPU 的性能显着下降,从而导致执行速度不同。作者探讨了这种行为背后的原因并提供了潜在的解决方案。

详细信息

相关代码涉及一个迭代数据数组并执行 popcount 的循环使用 x86 内部指令进行操作。循环计数器变量最初是一个无符号整数,但将其替换为 64 位无符号整数(uint64_t)导致性能下降约 50%。

为了调查原因,作者编译了代码:各种优化标志并分析了生成的汇编代码。他们观察到32位和64位版本生成了不同的程序集,导致他们怀疑编译器存在错误。

但是,在使用不同的编译器测试代码后,作者得出的结论是问题不在于由编译器错误引起,而不是由硬件中的错误数据依赖性引起。 _mm_popcnt_u64 指令在 Intel Sandy/Ivy Bridge 和 Haswell 处理器上使用时,会表现出对目标寄存器的错误依赖性,其中指令会等到目标准备好后再执行。这种错误的依赖关系可能会跨循环迭代,从而阻止处理器并行化不同的迭代并导致性能损失。

作者提出了内联汇编测试,通过隔离 popcount 操作并打破错误依赖关系来演示性能差异链。这些测试表明,错误的依赖关系对性能有显着影响,导致速度从 18.6195 GB/s 降低至 8.49272 GB/s。

文章还强调该问题影响 Intel CPU,而 AMD 处理器似乎没有这个假

解决方案

为了缓解此性能问题,作者建议了几种解决方案:

  • 改用 32 位循环计数器用于此特定循环的 64 位计数器。
  • 如果使用 64 位循环计数器必要时,在 popcount 操作中使用目标寄存器之前,通过显式清零目标寄存器来打破错误依赖链。
  • 使用能够识别此错误依赖关系并生成代码来补偿它的编译器。

以上是为什么在 Intel CPU 上用 64 位替换 32 位循环计数器会导致'_mm_popcnt_u64”性能下降?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn