gpt4 book ai didi

assembly - 缺少uop缓存的粒度

转载 作者:行者123 更新时间:2023-12-02 09:03:09 24 4
gpt4 key购买 nike

英特尔优化手册/ B.5.7.3

There are no partial hits in the Decoded ICache. If any micro-op that is part of that lookup on the 32-byte chunk is missing, a Decoded ICache miss occurs on all micro-ops for that transaction



uop缓存未命中是否真的以32字节粒度发生?

最佳答案

KbL i7-8550U上,其行为就像每个高速缓存行没有部分命中,而不是32字节的区域。

实际上,我进行了下面描述的更多不同的实验,但是不可能在这里进行全部拟合。

英特尔优化手册记录了uop缓存包含L1i:

The Decoded ICache is virtually included in the Instruction cache and ITLB.



考虑以下

示例1.
;edi = 1 << 31
align 32
test_uop_cache_hit:
nop ax
nop ax
nop ax
nop ax
nop ax
nop ax
nop ax
nop ax

;More 8 * nop ax blocks

dec edi
jnz test_uop_cache_hit
ret

收集计数器 icache_64b.iftag_hitidq.dsb_uopsidq.mite_uops我们有以下图表

enter image description here

uops图是合理的。所有uops都是从dsb交付的。

第一张图显示,每个L1i高速缓存行只有一个标签查找,大小为64字节。标签查找对于找到uop缓存条目是必需的。

示例2.

在同一缓存行的8 * nop ax块中间添加jmp。
;edi = 1 << 31
align 64
test_uop_cache_hit:
nop ax
nop ax
nop ax
nop ax
nop ax
nop ax
nop ax
jmp test_uop_cache_hit_1

align 32
test_uop_cache_hit_1:
nop ax
nop ax
nop ax
nop ax
nop ax
nop ax
nop ax
nop ax

dec edi
jnz test_uop_cache_hit
ret

我们有以下情节:

enter image description here

uop图再次是合理的。从 icache_64b.iftag_hit得出的结论是,预测要采取的分支会引起li1标签查找,以便在uop缓存中找到相应的条目(即使分支源和目标属于同一行)。有了这个观察, Intel Optimization Manual/2.5.5.2

Once micro-ops are delivered from the legacy pipeline, fetching micro-ops from the Decoded ICache can resume only after the next branch micro-op.



对我来说看起来很合理。

现在考虑一点更有趣

示例3.

我将使用汇编程序伪代码来节省空间
align 64
test_uop_cache_hit:
8 * nop ax

19 * nop
jmp test_uop_cache_hit_1
align 32:
test_uop_cache_hit_1: ;new line starts here
;more 8 * nop ax 19 * nop jmp blocks
dec edi
jnz test_uop_cache_hit
ret

我们得到以下结果

enter image description here
enter image description here

这里有趣的是,即使插入了已插入的分支微操作,并且 8 * nop ax完全适合uop缓存 ,它们也不会从uop缓存传递。从图 可以看出,从uop缓存传递的唯一微操作是宏融合的dec-jnz

结果让我觉得,如果某些32字节区域不适合uop缓存,则整个缓存行都标记为不包含在uop缓存中,并且下次要求它的任何32字节部分将从旧版解码管道。

从旧版解码管道切换是否需要分支微型操作?为了检查它考虑

示例4.
align 32
test_uop_cache_hit:
32 * nop
test_uop_cache_hit_0: ;new line start here
16 * nop ax
;more 16 * nop ax
dec edi ;new line start here
jnz test_uop_cache_hit
ret

这是dsb的结果

enter image description here

显然,所有的指令都是从旧版解码管道中传递的。

考虑一些更复杂的示例,以检查在 Example 3.下进行的假设是否在此处起作用:

I.
align 32
test_uop_cache_hit:
6 * nop ax
test edi, 0x1
;ends 64 byte region, misses due to erratum
;does not matter for the example
jnz test_uop_cache_hit_1

32 * nop
test_uop_cache_hit_1:
dec edi
jnz test_uop_cache_hit
ret

结果是
 1 075 981 881       idq.dsb_uops
50 341 922 587 idq.mite_uops

结果是完全合理的。当不使用分支并传递 32 * nop时,很明显它们不能容纳uop缓存。在 32 * nop之后,从旧版解码管道中传递了已融合的 dec-jnz宏。它适合uop缓存,因此,下次采用该分支时,它将从dsb传递。

结果非常接近预期:(1 << 31)/2 = 1073741824

II。

比以前更复杂的示例
align 32
test_uop_cache_hit:
test edi, 0x1
jnz test_uop_cache_hit_2
jmp test_uop_cache_hit_1

;starts new cache line
align 32
test_uop_cache_hit_1:
8 * nop ax
; 32 byte aligned
test_uop_cache_hit_2:
6 * nop ax
nop dword [eax + 1 * eax + 0x1]
;End of 32 bytes region
;misses due to erratum
;Important here
jmp test_uop_cache_hit_3
test_uop_cache_hit_3:
dec edi
jnz test_uop_cache_hit
ret

结果如下:
 5 385 033 285      idq.dsb_uops
25 815 684 426 idq.mite_uops

结果是预期的。每次采用 dec edi - jnz test_uop_cache_hit_2时,它都会跳转到末尾包含 jmp的32字节区域。因此它将错过dsb。下次不使用 dec edi - jnz test_uop_cache_hit_2时,将采用 jmp test_uop_cache_hit_1。通常,它会命中dsb,因为 8 * nop ax非常适合它,但请记住,在上一个循环迭代中,32字节区域末尾的 jmp会导致未命中。它们都属于同一高速缓存行,因此dsb丢失会在每次迭代中发生。

结果接近预期:(1 << 31) + (1 << 31)/2 + (1 << 31) = 5368709120

从32字节区域中仅删除一个nop ax,最后添加jmp,而保留test_uop_cache_hit_3 32字节对齐会导致所有uops从dsb传递:
29 081 868 658       idq.dsb_uops
8 887 726 idq.mite_uops

注意:如果每个高速缓存行预测有2个分支,结果将是非常不可预测的,因此很难给出合理的估计。我不清楚为什么。

关于assembly - 缺少uop缓存的粒度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61567672/

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