我正在查看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页。
我是否正确,前两个 MOV 指令都只需要 2(它们都是移动内存以寄存器)CPU 周期?我以为调用虚拟方法比这慢?
在指令延迟表第 178 页中,它说此调用的延迟为 2 个 CPU 周期(我认为?
CALL
"近"是什么意思,而不是CALL
"r"(寄存器)和CALL
"m"(内存)?所以根据 Fog 小册子,上面的 ASM 确实需要 6 个 CPU 周期,我没有误解什么?
编辑:我将虚拟函数调用更改为 vtable 中的第二个。
我是否正确,前两条 MOV 指令都只需要 2 个(它们都是要寄存器的移动内存)CPU 周期?我以为调用虚拟方法比这慢? 在指令延迟表第 178 页中,它说此调用的延迟为 2 个 CPU 周期(我认为?
不,只有最小的延迟 2 个 CPU 周期。
让我们检查一下阿格纳的表格 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 eax, [eax]; mov eax, [eax]; mov eax, [eax]; ...
这样的依赖MOV
长链来测量的。常春藤的值为:L1 = 4 个周期命中,L2 = 11 个周期命中,L3 = 30-40 个周期命中,缓存和存取存储器未命中 = 32 个周期 + 60 ns(在 3 GHz 时,每 ns 3 个周期> 200 个周期)。甚至没有简单的案例可以获得 2 个周期的延迟(什么比 L1 更接近 ALU?只有 72 个条目的负载缓冲区用于重新排序的负载?),并且在第二个mov
上不会有 2 个周期延迟(其操作数是第一个 mov 的结果,因此在第一个 mov 停用之前没有什么可以无序执行的)。
在从Agner's Links链接 http://instlatx64.atw.hu/表中,有Ivy InstLatX64的报告,用于Intel Core i7-3770K,3700 MHz
,由aida_bench64.dll27 AMD64 :MOV r64, [m64] 长: 1.14ns= 4.0c T: 0.14ns= 0.50c
此表显示了 L1 缓存中命中的实际延迟 (L
),4 个周期。
64-ia-32 架构优化手册中的相同数据(L1 为 4c,L2 为 ~12c,L3 为 26-31c.pdf第 46 页"2.2.5.1 加载和存储操作概述"部分,表 "2-10 查找顺序和加载延迟">
所以根据 Fog 小册子,上面的 ASM 确实需要 6 个 CPU 周期,我没有误解什么?
在最好的情况下,当第一次加载提前执行时,乱序 = 关键路径上的 2 个周期; L1 中的第二个负载命中 = 关键路径上的 4 个周期; 执行call
2 个周期;BTB(分支目标预测/间接分支目标)成功,当从调用的单个地址跳转到同一目标(或具有周期模式的少量目标)时,可能性更大——您将有 8 个周期来确认分支被预测正确,这可能被目标函数的 OoO 执行部分隐藏。
如果 L1/L2 中有任何负载未命中,则应添加相应的缓存延迟。如果 L3 未命中,请添加 200 个周期。
如果 BTB 未命中,您将受到至少 15 个周期的惩罚(检查 Agner 的微架构.pdf,第 27 页"英特尔桑迪桥和常春藤布林奇的 3.7 分支预测;错误预测惩罚") - 用于缓存的 uops;更多关于 L1i 中的目标。您可能会在同一微架构中阅读有关较旧 BTB 的信息.pdf第 25 页"3.5 PM 和 Core2 中的分支预测;间接跳转和呼叫的模式识别"和"BTB 组织......用于间接跳转和间接呼叫"。
非常有用的文档来自英特尔:"英特尔® 64 和 IA-32 架构 优化参考手册" 64-ia-32-架构-优化-手册.pdf.它包含有关性能计数器的优化建议和信息,这将帮助您获取代码的实际延迟和未命中率(请查看 B.6.3.2 部分"虚拟表和间接调用")。