KbL i7-8550U
我正在研究 uops-cache 的行为并遇到了关于它的误解。
如英特尔优化手册2.5.2.2(我的)中所述:
解码的 ICache 由 32 组组成。每组包含八种方式。 每路最多可容纳六个微操作。
——
Way 中的所有微操作表示在代码中静态连续的指令,并且它们的 EIP 位于相同的对齐 32 字节区域内。
——
最多三种方式可以专用于相同的 32 字节对齐块,从而允许在原始 IA 程序的每个 32 字节区域中缓存总共 18 个微操作。
——
无条件分支是 Way 中的最后一个微操作。
情况1:
考虑以下例程:
uop.h
void inhibit_uops_cache(size_t);
Run Code Online (Sandbox Code Playgroud)
uop.S
align 32
inhibit_uops_cache:
mov edx, esi
mov edx, esi
mov edx, esi
mov edx, esi
mov edx, esi
mov edx, esi
jmp decrement_jmp_tgt
decrement_jmp_tgt:
dec rdi
ja inhibit_uops_cache ;ja is intentional to avoid Macro-fusion
ret
Run Code Online (Sandbox Code Playgroud)
为了确保例程的代码实际上是 32 字节对齐的,这里是 asm …
作为我的问题的后续问题在x86-64中使用32位寄存器/指令的优点,我开始测量指令的成本.我知道这已经多次完成了(例如Agner Fog),但我这样做是为了娱乐和自我教育.
我的测试代码非常简单(为简单起见,这里是伪代码,实际上是汇编程序):
for(outer_loop=0; outer_loop<NO;outer_loop++){
operation #first
operation #second
...
operation #NI-th
}
Run Code Online (Sandbox Code Playgroud)
但是应该考虑一些事情.
NI>10^7),则循环的整个内容不适合指令高速缓存,因此必须一遍又一遍地加载,使得RAM的速度定义执行所需的时间.例如,对于大的内部部分,xorl %eax, %eax(2个字节)比xorq %rax, %rax(3个字节)快33%.NI是小,整个循环可轻松放入指令缓存,比xorl %eax, %eax和xorq %rax, %rax同样快速,可以执行每时钟周期的4倍.然而,这个简单的模型并没有为jmp建筑提供水.对于jmp-instruction,我的测试代码如下所示:
for(outer_loop=0; outer_loop<NO;outer_loop++){
jmp .L0
.L0: jmp .L1
L1: jmp L2
....
}
Run Code Online (Sandbox Code Playgroud)
结果是:
NI>10^4),我测量4.2 ns/ - jmp指令(相当于从RAM加载的42个字节或在我的机器上大约12个时钟周期).NI<10^3),我测量1 ns/jmp-指令(大约3个时钟周期,听起来似乎合理--Agner Fog的表显示了2个时钟周期的成本).该指令jmp LX使用2字节eb 00 …
我了解的是,指令融合有两种类型:
微操作是指可以在1个时钟周期内执行的操作。如果几个微操作融合在一起,我们将获得一个“指令”。
如果融合了多条指令,我们将获得宏操作。
如果几个宏操作融合在一起,我们将获得宏操作融合。
我对么?