我通过perf stat -d
运行我的程序,输出包括以下结果:
3,527,202,599 instructions # 3.70 insn per cycle
578,724,753 branches # 2.679 G/sec
3,816,842 branch-misses # 0.66% of all branches
4,764,220,185 slots # 22.058 G/sec
3,441,864,146 topdown-retiring # 72.2% Retiring
597,862,925 topdown-bad-spec # 12.5% Bad Speculation
467,080,410 topdown-fe-bound # 9.8% Frontend Bound
261,565,029 topdown-be-bound # 5.5% Backend Bound
811,364,274 L1-dcache-loads # 3.756 G/sec
396,558 L1-dcache-load-misses # 0.05% of all L1-dcache accesses
字符串
由此看来,分支预测错误是主要的性能瓶颈,topdown-bad-spec
为12.5%,branch-misses
为0.66%。
很高兴我知道这一点,但我需要知道错误预测的 * 位置 *,以尝试改善这些统计数据。当我运行perf record
和perf report
时,我没有找到此信息。-e branch-misses
的记录不会产生非常有意义的结果。
如何找到这些分支预测错误的位置?
1条答案
按热度按时间2nbm6dog1#
perf record -e branch-misses
应该只显示分支指令,这些指令有分支错误预测的样本。默认情况下,它不使用英特尔的PEBS(基于处理器事件的采样)或AMD的IBS(基于指令的采样),因此可能会有一些打滑(skid aka skew)效应,归咎于后面的指令,而不是jcc
或宏融合cmp/test/whatever/jcc
本身。使用
event:pp
请求PEBS。或者在Skylake上,有一个br_misp_retired.all_branches_pebs
别名。字符串
相关:
p
s越多,你要求的就越精确。:pp
请求0 skid,:ppp
must have 0 skid(如果不可能,则失败)。:p
是“must have constant skid”。在现代Intel上,它会使用PEBS,它也会给出0 skid,和:pp
一样。我不知道为什么它在默认情况下不使用PEBS;我认为它是一样有效的。我听说PEBS缓冲区通常很小,可能只有一个样本,所以你不需要像你期望的那样从更少的中断中获得任何效率上的提高。
如果这仍然是相当均匀的分布,也许你没有任何分支具有高的未命中率。0.66%的总体未命中率不是很高,但如果有一些有问题的分支,他们值得一看。根据每个分支之间有多少非分支指令,0.66%的总体分支未命中率可能是一个相当不错的uop数。
看看
uops_issued.any
和uops_retired.retire_slots
,你会发现有多少来自错误执行路径的指令实际上进入了后端,但是错误预测的主要代价是获得正确路径的延迟。**分支不是CPU推测的东西。**在我的机器上的
perf
6.5中,perf list
显示自顶向下的坏推测(tma_bad_speculation_group
)包括tma_machine_clears
和tma_branch_mispredicts
。machine_clears.memory_ordering
很容易在多线程代码中发生,但在单线程代码中也可能发生,如果加载有时会重新加载最近的存储,但有时不会。(CPU动态预测加载是否需要等待先前存储的地址已知,或者是否可以假设没有存储转发并从L1 d缓存读取。https://blog.stuffedcow.net/2014/01/x86-memory-disambiguation/)CPU也会推测加载/存储不会发生页面错误,但是错误推测意味着错误确实发生了,所以它没有太多用处。
page-faults
事件存在,所以你可以检查它。大多数其他错误默认情况下是致命的,所以它们不会在正常操作期间发生。所以推测FP指令不会陷阱总是正确的推测,例如。