gpt4 book ai didi

pointers - 为什么这个跳转指令在执行指针追逐时如此昂贵?

转载 作者:行者123 更新时间:2023-12-04 16:38:26 76 4
gpt4 key购买 nike

我有一个程序可以执行 pointer chasing我正在尝试尽可能地优化指针追踪循环。我注意到 perf record 检测到函数 myFunction() 中约 20% 的执行时间用于执行跳转指令(用于在特定值后退出循环已阅读)。

一些注意事项:

  • 指针追逐路径可以轻松地放入 L1 数据缓存
  • 使用 __builtin_expect 来避免分支预测错误的成本没有明显效果

perf record 具有以下输出:

Samples: 153K of event 'cycles', 10000 Hz, Event count (approx.): 35559166926                                                                                                                                                               
myFunction /tmp/foobar [Percent: local hits]
Percent│ endbr64
...
80.09 │20: mov (%rdx,%rbx,1),%ebx
0.07 │ add $0x1,%rax
│ cmp $0xffffffff,%ebx
19.84 │ ↑ jne 20
...

我希望此循环中花费的大部分周期用于从内存中读取值,这已由 perf 确认。我还希望剩余的周期能够均匀地用于执行循环中的剩余指令。取而代之的是,perf 报告剩余周期中有很大一部分用于执行跳跃。

我怀疑我可以通过理解用于执行这些指令的微操作来更好地理解这些成本,但我有点不知道从哪里开始。

最佳答案

请记住,cycles 事件必须选择一个指令来指责,即使 mov-load 和宏融合的 cmp- and-branch 微指令正在等待结果。在运行时,这不是一个或另一个“成本计算周期”的问题; 他们都在并行等待。 (Modern MicroprocessorsA 90-Minute Guide!https://agner.org/optimize/)

但是当“循环”事件计数器溢出时,它必须选择一个特定的指令来“责备”,因为您正在使用统计抽样。这是一个不准确的现实图片必须由一个有数百个 uop 的 CPU 在飞行中发明的地方。通常它是等待缓慢输入的那个,我认为是因为它通常是 ROB 或 RS 中最旧的并且阻止前端分配新的微指令。

具体选择哪条指令的细节可能会告诉我们一些关于 CPU 内部的信息,但只是非常间接的。可能与它如何退出 4(?)微指令组有关,而这个循环有 3 个微指令,所以当出现性能事件异常时,哪个微指令最旧。

由于某些原因,4:1 拆分可能很重要,可能是因为 4+1 = 5 周期延迟的负载具有非简单寻址模式。 (我假设这是一个 Intel Sandybridge 系列 CPU,也许是 Skylake 派生的?)就像如果数据在 perf 事件溢出(并选择采样)的同一周期从缓存到达,mov不会受到指责,因为它实际上可以执行并摆脱困境?

IIRC、BeeOnRope 或其他人通过实验发现,Skylake CPU 倾向于让最旧的未退休指令在异常到达后退休,至少在它不是缓存未命中的情况下。在您的情况下,这将是循环底部的 cmp/jne,它按程序顺序出现在下一次迭代顶部的加载之前。

关于pointers - 为什么这个跳转指令在执行指针追逐时如此昂贵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65707155/

76 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com