PERF STAT不计算内存加载,但计算内存存储。

5

Linux内核:4.10.0-20-generic(也尝试过4.11.3)

Ubuntu:17.04

我一直在尝试使用perf stat来收集内存访问统计信息。我能够收集内存存储的统计信息,但是内存加载的计数返回了一个0值

以下是内存存储的详细信息:

perf stat -e cpu/mem-stores/u ./libquantum_base.arnab 100
N = 100, 37 qubits required
Random seed: 33
Measured 3277 (0.200012), fractional approximation is 1/5.
Odd denominator, trying to expand by 2.
Possible period is 10.
100 = 4 * 25

 Performance counter stats for './libquantum_base.arnab 100':

       158,115,510      cpu/mem-stores/u                                            

       0.559922797 seconds time elapsed

对于内存负载,我得到了 0 计数,如下所示:

perf stat -e cpu/mem-loads/u ./libquantum_base.arnab 100
N = 100, 37 qubits required
Random seed: 33
Measured 3277 (0.200012), fractional approximation is 1/5.
Odd denominator, trying to expand by 2.
Possible period is 10.
100 = 4 * 25

 Performance counter stats for './libquantum_base.arnab 100':

                 0      cpu/mem-loads/u                                             

       0.563806170 seconds time elapsed

我不明白为什么计数不正确。我是否应该以某种方式使用不同的事件来获取正确的数据?

Stack Overflow是一个关于编程和开发问题的网站。这个问题似乎不属于编程或开发范畴。请参阅帮助中心中的我可以在这里问什么样的问题。也许超级用户Unix&Linux Stack Exchange更适合提问。另请参阅我应该在哪里发布Dev Ops相关问题? - jww
硬件性能事件是特定于您使用的 CPU 的。确切型号是什么?并非所有可能的 perf 硬件事件都映射到某个真实事件(我认为其中约一半没有;某些 CPU 可能根本没有原始 L1 加载/存储计数器)。对于英特尔 CPU,请使用 pmu-tools 的 ocperf.py https://github.com/andikleen/pmu-tools/blob/master/ocperf.py 将真正支持的事件编码为 perf_event API(perf_event_open、perf CLI 工具的 -e rXXXXX 事件说明符)的原始编码。 - osgx
嗨@osgx,这是一颗Broadwell服务器CPU。型号是E5-2620 v4。它运行在2.10GHz。我将尝试使用Andi Kleen的PMU工具,看看能否统计内存负载事件。 - Arnabjyoti Kalita
1
我有一个Skylake i7-6700HQ的同样问题,因此似乎在最近的内核上,mem-loads事件在这个硬件上是有问题的。 - BeeOnRope
1
是的,@BeeOnRope,你说得对。如果我没记错的话,我需要使用一个符号事件值来获取内存负载事件,我会尽快确定符号事件编号并更新我的答案。 - Arnabjyoti Kalita
@ArnabjyotiKalita - 很酷,我期待着它。 - BeeOnRope
2个回答

7
"mem-loads"事件在英特尔处理器上映射到"MEM_TRANS_RETIRED.LOAD_LATENCY_GT_3"性能监测单元事件。"MEM_TRANS_RETIRED.LOAD_LATENCY_*"事件是特殊的,只能使用"p"修饰符进行计数。也就是说,您必须指定"mem-loads:p"才能正确使用perf中的该事件。
"MEM_TRANS_RETIRED.LOAD_LATENCY_*"是一个精确事件,只有在精确级别上进行计数才有意义。根据这篇this英特尔文章(重点在于我): "
当用户选择对这些事件之一进行抽样时,会使用特殊的硬件来跟踪从发出到完成的数据负载。这比仅计算事件实例(如普通的基于事件的抽样)更为复杂,因此仅跟踪某些负载。这些负载是随机选择的,为每个负载确定延迟,并增加正确的事件(延迟 > 4、> 8、> 16 等)。由于对这个事件的采样方式,任何时候只能跟踪应用程序的少量数据负载。正如您所看到的,MEM_TRANS_RETIRED.LOAD_LATENCY_* 绝不会计算负载的总数,它根本就不是设计用于此目的的。
如果您想确定代码中哪些指令发出的加载请求需要超过特定数量的周期才能完成,则使用MEM_TRANS_RETIRED.LOAD_LATENCY_*是正确的性能事件。实际上,这正是perf-mem的目的,并通过使用此事件来实现其目的。
如果您想计算已退役的总装载uops数量,则应使用L1-dcache-loads,它被映射到英特尔处理器上的MEM_UOPS_RETIRED.ALL_LOADS性能事件。
另一方面,mem-storesL1-dcache-stores在所有当前英特尔处理器上都映射到完全相同的性能事件,即MEM_UOPS_RETIRED.ALL_STORES,它确实计算了所有已退役的存储uops。
总之,如果您正在使用perf-stat,您应该(几乎)总是使用L1-dcache-loadsL1-dcache-stores分别计算已退役的负载和存储。这些与您在发布的答案中使用的原始事件相对应,只是更加便携,因为它们也适用于AMD处理器。

1
我将使用Broadwell(CPU e5-2620)服务器来收集以下所有事件。
为了收集内存负载事件,我必须使用数字事件值。我基本上运行了以下命令 -
./perf record -e "r81d0:u" -c 1 -d -m 128 ../../.././libquantum_base 20

我是一名有用的助手,可以翻译文本。

这里r81d0代表计算“所有已退役指令中内存加载”的原始事件。而“u”则表示用户空间。

另一方面,下面的命令:

./perf record -e "r82d0:u" -c 1 -d -m 128 ../../.././libquantum_base 20

“r82d0:u”作为原始事件表示“用户空间中所有指令退役时的内存存储”。


什么硬件?不是所有的CPU都有相同的事件编号。此外,这是一个数字事件值,而不是符号事件值。在我的Skylake i7-6700k上,使用perf 4.15,mem-loads也是有问题的。但是ocperf.py stat -e mem_inst_retired.all_loads可以工作。(请注意,这只计算已退役的加载指令,而不是来自页面行走器或指令获取的加载,如果mem-loads应该计算其中任何一种。也不包括从未退役的错误加载指令的加载。) - Peter Cordes
嗨,Peter,这些数字事件确实计算了已退役的负载和存储器的数量。但是,“已退役存储器”事件计数与实际的“mem-stores”事件数量不匹配。我不确定这种相似性是否也适用于“mem-loads”。 - Arnabjyoti Kalita
可能 mem-loads 应该映射到 mem_inst_retired.all_loadsocperf.py 包装器使用 perf stat -e cpu/event=0xd0,umask=0x81,name=mem_inst_retired_all_loads/ 进行操作。我没有看到包括页面步骤和/或错误预测负载指令的负载事件。嗯,我也没有看到特定的 L1-dcache-loads 事件(希望不包括来自 WC 存储器的 MOVNTDQA 负载)。也许它是另一个负载 指令 计数器,而不是实际的 L1 引用总数。在 Skylake 上可能是从 mem_load_retired.l1_hit + ..._miss 综合得出的? - Peter Cordes
确切地说,彼得。我在使用数字事件编号时也有同样的担忧,我还研究了其他负载事件的来源,但没有发现任何测量它们的事件。 - Arnabjyoti Kalita
1
有关 dtlb_load_misses.miss_causes_a_walk..._store_... 的事件,但这些事件并不告诉您硬件页行走器实际执行了多少个 L1d 访问以及通过将页面目录条目缓存在内部保存了多少个访问。对于未退役的存储器,有 uops_dispatched_port.port_4(存储器数据端口)。哦,如果存储器没有达到退役状态,它们永远不会提交给 L1d,停止推测性存储器从成为全局可见的一部分是存储器缓冲区的重点之一 >.< 有一个事件来实际提交到 L1d 以测量合并存储器缓冲区中相邻存储器将是很酷的。 - Peter Cordes
但对于投机负载,uops_dispatched_port.port_2和3可能有所帮助,除了存储地址uop也在这些端口上运行。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接