如何解释 Xeon 处理器在具有顺序复制和分散存储的循环中性能不佳?

Jon*_*ert 14 performance intel cpu-architecture cpu-cache amd-processor

c++在某些英特尔至强处理器上运行以下代码时,我偶然发现了一个特殊的性能问题:

// array_a contains permutation of [0, n - 1]
// array_b and inverse are initialized arrays
for (int i = 0; i < n; ++i) {
  array_b[i] = array_a[i];
  inverse[array_b[i]] = i;
}
Run Code Online (Sandbox Code Playgroud)

循环的第一行按顺序复制array_aarray_b(预期很少有缓存未命中)。第二行计算array_b(许多缓存未命中,因为array_b是随机排列)的倒数。我们也可以将代码分成两个单独的循环:

for (int i = 0; i < n; ++i)
  array_b[i] = array_a[i];
for (int i = 0; i < n; ++i)
  inverse[array_b[i]] = i;
Run Code Online (Sandbox Code Playgroud)

我原以为这两个版本(单循环与双循环)在相对现代的硬件上的性能几乎相同。但是,在执行单循环版本时,某些 Xeon 处理器似乎非常慢。

您可以在下方看到以纳秒为单位n的挂机时间除以在一系列不同处理器上运行代码段的时间。出于测试目的,代码是使用 GCC 7.5.0 编译的,并-O3 -funroll-loops -march=native在具有 Xeon E5-4620v4 的系统上带有标志。然后,在所有系统上使用相同的二进制文件numactl -m 0 -N 0在具有多个 NUMA 域的系统上使用。

使用的代码可在github 上找到。有趣的东西在文件runner.cpp 中

[编辑:] 程序集在此处提供。

[编辑:] 包括 AMD EPYC 在内的新结果。

阴谋

在各种 i7 型号上,结果大多符合预期。使用单循环仅比双循环稍慢。这也适用于至强 E3-1271v3,它与 i7-4790 的硬件基本相同。到目前为止,AMC EPYC 7452 的表现最好,单环路和双环路实施之间几乎没有区别。但是,在使用单循环的至强 E5-2690v4 和 E5-4620v4 系统上速度非常慢。

在之前的测试中,我还在至强 E5-2640 和 E5-2640v4 系统上观察到了这个奇怪的性能问题。相比之下,在几个 AMD EPYC 和 Opteron 系统上没有性能问题,在 Intel i5 和 i7 移动处理器上也没有问题。

因此,我向 CPU 专家提出的问题是:为什么英特尔最高端的产品线与其他 CPU 相比性能如此差?我目前还不是 CPU 架构方面的专家,因此非常感谢您的知识和想法!

小智 0

也许这与Intel 处理器上的 avx-512 频率限制有关。这些指令会产生大量热量,如果在某些情况下使用,处理器会降低工作频率。

以下是一些显示效果的OpenSSL基准测试。Linus Torvalds 对这个话题有一个咆哮。

如果 avx-512 指令是使用“-march=native”生成的,您可能会受到这种影响。尝试使用以下命令禁用 avx-512

gcc -mno-avx512f
Run Code Online (Sandbox Code Playgroud)