5

我正在查看 x86-64 中的以下虚拟方法调用:

mov     rcx, qword ptr [x]   
mov     rax, qword ptr [rcx]
call    qword ptr [rax+8]

还有 Agner Fog 的延迟表:

http://www.agner.org/optimize/instruction_tables.pdf

当我使用 Ivy Bridge CPU 时,我正在查看第 175 页。

  1. 我是否正确,前两个 MOV 指令都只需要 2 个(它们都是将内存移动到寄存器)CPU 周期?我认为对虚拟方法的调用比这慢?

  2. 在第 178 页的指令延迟表中,它说这个调用的延迟是 2 个 CPU 周期(我认为?)。与“r”(寄存器)和“m”(内存)CALL相反,“near”是什么意思?CALLCALL

  3. 所以根据 Fog 手册,上面的 ASM 确实需要 6 个 CPU 周期,我没有误解任何东西吗?

编辑:我将虚函数调用更改为 vtable 中的第二个。

4

1 回答 1

4

我是否正确,前两个 MOV 指令都只需要 2 个(它们都是将内存移动到寄存器)CPU 周期?我认为对虚拟方法的调用比这慢?在第 178 页的指令延迟表中,它说这个调用的延迟是 2 个 CPU 周期(我认为?)。

不,只有最小延迟的 2 个 CPU 周期。

让我们检查一下 Agner 的表格http://www.agner.org/optimize/instruction_tables.pdf

整数指令。

指令 操作数 uops 融合域 uops 未融合域 (p015 p0 p1 p5 p23 p4) 延迟 倒数吞吐量 注释

Inst   Oper        fus p23 p4  Latency Rec.
MOV r32/64,m32/64   1   1        2     0.5

要找到时间,什么时候指令会产生结果,你应该使用“延迟”列。并且每个 mov 的延迟为 2 个周期,并且仅列出最小值(检查“列标题说明”中的文本 - “延迟 - 这是指令在依赖链中生成的延迟。数字是最小值。缓存未命中,未对准,...可能会显着增加时钟计数。”)

如果您有很多不同的多态调用,它们所需的内存可能不会被缓存。我们从不同的评论中知道缓存和内存延迟,并且所有这些都是通过长链的依赖MOV项来衡量mov eax, [eax]; mov eax, [eax]; mov eax, [eax]; ...。Ivy 的值是:在 L1 中命中 = 4 个周期,在 L2 中命中 = 11 个周期,在 L3 中命中 = 30-40 个周期,在高速缓存和访问内存中未命中 = 32 个周期 + 60 ns(在 3 GHz 时,每 ns 3 个周期 > 200循环)。甚至没有容易获得 2 个周期延迟的情况(什么比 L1 更接近 ALU?只有 72 条目加载缓冲区用于重新排序加载?),并且第二个周期没有机会有 2 个周期延迟mov(它的操作数是第一个 mov 的结果,因此在第一个 mov 退休之前没有什么可以乱序执行)。

在从Agner's Links 链接的表格http://instlatx64.atw.hu/中,有报告为 Ivy InstLatX64 for Intel Core i7-3770K, 3700 MHz made with aida_bench64.dll

27 AMD64 :MOV r64, [m64] L: 1.14ns= 4.0c T: 0.14ns= 0.50c

该表显示L了 L1 缓存中命中的实际延迟 ( ),4 个周期。

64-ia-32-architectures-optimization-manual.pdf第 46 页“2.2.5.1 加载和存储操作概述”部分中的相同数据(L1 为 4c,L2 为 ~12c,L3 为 26-31c) ,表“2- 10 查找顺序和加载延迟"

所以根据 Fog 手册,上面的 ASM 确实需要 6 个 CPU 周期,我没有误解任何东西吗?

在最好的情况下,当第一次加载在关键路径上以乱序 = 2 个周期提前执行时;L1 中的第二次负载命中 = 关键路径上的 4 个周期;2个执行周期call;BTB(分支目标预测/间接分支目标)成功,当您从单个调用地址总是跳转到同一个目标(或具有周期性模式的少量目标)时更有可能 - 您将有 8 个周期来确认该分支被预测正确,它可能被目标函数的 OoO 执行部分隐藏。

如果 L1/L2 中的任何加载未命中,则应添加相应的缓存延迟。如果 L3 未命中,则添加 200 个循环。

如果 BTB 未命中,您将受到至少 15 个周期的惩罚(查看Agner 的 microarchitecture.pdf,第 27 页“3.7 Intel Sandy Bridge 和 Ivy Brindge 中的分支预测;错误预测惩罚”) - 对于缓存的微指令;更多用于 L1i 中的目标。您可以在相同的 microarchitecture.pdf 第 25 页“3.5 PM 和 Core2 中的分支预测;间接跳转和调用的模式识别”和“BTB 组织......用于间接跳转和间接调用”中阅读有关旧 BTB 的信息。

非常有用的文档来自英特尔:“英特尔® 64 和 IA-32 架构优化参考手册” 64-ia-32-architectures-optimization-manual.pdf。它具有调优建议和有关性能计数器的信息,这将帮助您获得代码的实际延迟和未命中率(请查看 B.6.3.2 部分“虚拟表和间接调用”)。

于 2014-03-15T07:19:43.800 回答