【问题标题】:Perf shows L1-dcache-load-misses in a block with no memory accessPerf 在没有内存访问的块中显示 L1-dcache-load-misses
【发布时间】:2020-11-24 19:32:49
【问题描述】:

下面是一个代码块,它记录标记为所有 L1-dcache 未命中的 10%,但该块完全是 zmm 寄存器之间的移动。这是 perf 命令字符串:

perf record -e L1-dcache-load-misses -c 10000 -a -- ./Program_to_Test.exe

代码块:

Round:
vmulpd zmm1,zmm0,zmm28
VCVTTPD2QQ zmm0{k7},zmm1
VCVTUQQ2PD zmm2{k7},zmm0
vsubpd zmm3,zmm1,zmm2
vmulpd zmm4,zmm3,zmm27
VCVTTPD2QQ zmm5{k7}{z},zmm4

VPCMPGTQ k2,zmm5,zmm26
VPCMPEQQ k3 {k7},zmm5,zmm26
KADDQ k1,k2,k3

VCVTQQ2PD zmm2{k7},zmm0
VDIVPD zmm1{k7},zmm2,zmm28 ; Divide by 100
VPXORQ zmm2{k7},zmm2,zmm2
vmovupd zmm2,zmm1
VADDPD zmm2{k1},zmm1,zmm25

对于该代码块,我使用其他 L1 度量(例如 l1d.replacement)得到了类似的结果。

我的问题是,只有 zmm 寄存器移动的块如何产生 L1 缓存未命中?我认为寄存器根本不会进入内存。实际上,最后一次内存访问是在这块代码之上的 10 条指令;其他 9 条指令都是寄存器到寄存器指令。

【问题讨论】:

  • 无论硬件事件性能使用什么,它可能都不是“精确”事件。您可能想查看mem_load_retired.l1_miss 以将 L1 未命中归因于特定的加载 uops。
  • 另外,你不能使用1./100 作为倒数吗?它不能完全表示为双精度,但 div 比乘法慢很多。也许我遗漏了一些东西,但vmovupd zmm2, zmm1 会覆盖前面vpxorq-zeroing 的合并屏蔽结果。如果这应该将某些元素归零,您是否可以简单地使用归零或混合?
  • 感谢您使用倒数的评论。我注意到当我发布这个时我仍然有一个 div 指令。此外,再次检查此代码 vpxorq 指令看起来没有必要。我测试一下看看。
  • How does Linux perf calculate the cache-references and cache-misses events 显示了perf 实际用于L1-dcache-load-misses - L1D.REPLACEMENT 的硬件事件!因此,这会将同一行的多次未命中计数为仅 1 次未命中,但它与指令不同步(例如,硬件预取可能会导致它)。 Can perf account for all cache misses? 是相关的。
  • 我怀疑是硬件预取,因为在下一次迭代中,我们将再次从内存中读取 64 个字节。 L1 缓存未命中可能会从上面延迟。正如你所提到的,计数器不是 100% 精确的。

标签: linux performance profiling x86-64 perf


【解决方案1】:

事件 L1-dcache-load-misses 映射到 Sandy Bridge 和更高版本微架构上的 L1D.REPLACEMENT(或映射到旧微架构上的类似事件)。此事件不支持精确采样,这意味着样本可以指向无法生成被采样事件的指令。 (注意L1-dcache-load-misses 不支持任何当前的 Atom。)

从在 Haswell+ 或 Silvermont+ 微架构上运行的 Linux 3.11 开始,通过指定满足以下两个条件的采样事件,可以使用事件指令指针捕获样本:

  • 事件支持精确采样。例如,您可以使用任何表示内存 uop 或指令退出的事件。事件的确切名称和含义取决于微架构。有关详细信息,请参阅英特尔 SDM 第 3 卷。没有事件支持精确采样并且与L1D.REPLACEMENT具有相同的确切含义。在支持扩展 PEBS 的处理器上,只有一部分 PEBS 事件支持精确采样。
  • 对事件启用精确采样级别。在 Linux perf 中,这可以通过在事件名称或原始事件编码后附加“:pp”来完成,或者在 PMU 语法中指定的原始事件的终止斜杠之后附加“pp”。例如,在 Haswell 上,可以将事件 mem_load_uops_retired.l1_miss:pp 指定给 Linux perf。

对于这样的事件,当事件计数器溢出时,PEBS 硬件将被启用,这意味着它现在正在寻找尽可能早的机会来收集精确的样本。当在此时间窗口内至少有一条指令将导致事件时,PEBS 硬件最终将由这些指令之一触发,并偏向于高延迟指令。当触发 PEBS 的指令退出时,PEBS 微码例程将执行并捕获一条 PEBS 记录,其中包含触发 PEBS 的指令的 IP(不同于架构 IP)。 perf 用来显示结果的指令指针 (IP) 就是这个事件 IP。 (我注意到指向不可能导致事件的指令的样本数量可以忽略不计。)

在较旧的微架构(Haswell 和 Silvermont 之前)上,还支持“pp”精确采样级别。这些处理器上的 PEBS 将仅捕获体系结构事件,该事件指向按程序顺序紧跟在 PEBS 触发指令之后的静态指令。如果可能,Linux perf 使用 LBR,它包含源-目标 IP 对来确定捕获的 IP 是否是跳转的目标。如果是这种情况,它会将源 IP 作为事件 IP 添加到示例记录中。

一些微架构支持一个或多个具有更好采样分布的事件(好多少取决于微架构、事件、计数器以及计数器即将溢出时正在执行的指令)。在 Linux perf 中,如果支持,可以通过指定精确级别“ppp”来启用精确分发。

【讨论】:

  • 所以perf 不默认使用PEBS,即使它可用于活动?我认为 PEBS 通常更好、更高效(至少用于记录,如果不是 stat),因为它可以将样本记录到缓冲区中而不会中断执行。 (虽然默认可能与更好是分开的)。
  • @PeterCordes - 通常缓冲区的大小为 1,因此效率不高,除非满足“大型 PEBS”的特定条件。没有 :p[p...] 后缀的 AFAIK 不会获得精确的事件(尽管在未明确指定事件时,perf record 之类的某些内容可能默认为精确事件)。
  • @Hadi - 你的最后一段我不清楚。有一些指令会导致计数器溢出(这必然是导致相关事件的指令),有与硬件 PEBS 样本相关的指令,还有与非硬件性能样本相关的指令(例如, . 当堆栈跟踪被捕获时),也许更多,也许其中一些在某些或所有场景中是相同的。目前尚不清楚您在该段落的哪个位置谈论的是其中的哪一个。
  • @BeeOnRope 我希望现在更好。这是我临睡前写的:)
  • @HadiBrais - 谢谢,我认为它更清楚了。我会说我不完全理解它,但也许这只是我。我不明白的一件事是“在这个时间窗口内” - 哪个时间窗口(这个窗口的起点/终点是什么)?我也搞不懂“和架构IP有什么区别”这个意义上的架构IP是什么?
猜你喜欢
  • 2023-03-28
  • 2020-05-17
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 2021-07-04
  • 1970-01-01
  • 2016-12-14
相关资源
最近更新 更多