了解 lfence 对具有两个长依赖链的循环的影响,以增加长度

2024-03-02

我正在玩代码这个答案 https://stackoverflow.com/a/50496379/5801661,稍微修改一下:

BITS 64

GLOBAL _start

SECTION .text

_start:
 mov ecx, 1000000

.loop:

 ;T is a symbol defined with the CLI (-DT=...)

 TIMES T imul eax, eax
 lfence
 TIMES T imul edx, edx


 dec ecx
jnz .loop

 mov eax, 60           ;sys_exit
 xor edi, edi
 syscall

如果没有lfence我得到的结果与该答案中的静态分析一致。

当我介绍一个single lfence我希望CPU执行imul edx, edx的序列k-th并行迭代imul eax, eax下一个序列(k+1-th)迭代。
像这样的东西(调用A the imul eax, eax序列和D the imul edx, edx one):

|
| A
| D A
| D A
| D A
| ...
| D A
| D
|
V time

采取或多或少相同数量的周期,但对于一个不成对的并行执行。

当我测量原始版本和修改版本的周期数时,taskset -c 2 ocperf.py stat -r 5 -e cycles:u '-x ' ./main-$T for T在下面的范围内我得到

T   Cycles:u    Cycles:u    Delta
    lfence      no lfence

10  42047564    30039060    12008504
15  58561018    45058832    13502186
20  75096403    60078056    15018347
25  91397069    75116661    16280408
30  108032041   90103844    17928197
35  124663013   105155678   19507335
40  140145764   120146110   19999654
45  156721111   135158434   21562677
50  172001996   150181473   21820523
55  191229173   165196260   26032913
60  221881438   180170249   41711189
65  250983063   195306576   55676487
70  281102683   210255704   70846979
75  312319626   225314892   87004734
80  339836648   240320162   99516486
85  372344426   255358484   116985942
90  401630332   270320076   131310256
95  431465386   285955731   145509655
100 460786274   305050719   155735555

的价值观如何Cycles:u lfence需要解释一下吗?
我本以为它们会与Cycles:u no lfence自从单身以来lfence应仅防止两个块并行执行第一次迭代。
我不认为这是因为lfence开销,因为我相信这对所有人来说都应该是恒定的Ts.

我想修复我的问题脑膜在处理代码的静态分析时。


支持带有源文件的存储库 https://github.com/margaretbloom/interleaved-cycle/tree/master.


我认为您测量得很准确,并且解释是微架构的,而不是任何类型的测量错误。


我认为你的中低 T 结果支持以下结论:lfence阻止前端甚至发出过去的lfence直到所有先前的指令失效,而不是让两个链中的所有微指令都已发出并等待lfence打开开关并让每个链中的乘法开始按交替周期进行调度。

(port1 将立即获得 edx,eax,empty,edx,eax,empty,... 对于 Skylake 的 3c 延迟/1c 吞吐量乘数,如果lfence不会阻塞前端,并且开销不会随 T 缩放。)

你输了imul当只有来自第一条链的微指令在调度程序中时的吞吐量,因为前端尚未咀嚼imul edx,edx并循环分支。对于窗口末尾的相同数量的周期,管道大部分已耗尽,仅剩下来自第二条链的微指令。


开销增量看起来呈线性,直到 T=60 左右。我没有计算数字,但到那里的坡度看起来是合理的T * 0.25发出第一条链的时钟与 3c 延迟执行瓶颈。 IE。增量增长速度可能是无围栏周期总数的 1/12.

所以(鉴于lfence我在下面测量了开销),T

no_lfence cycles/iter ~= 3T                  # OoO exec finds all the parallelism
lfence    cycles/iter ~= 3T + T/4 + 9.3      # lfence constant + front-end delay
                delta ~=      T/4 + 9.3

@Margaret 报道说T/4比更适合2*T / 4,但我预计在开始和结束时都为 T/4,三角洲的斜率总共为 2T/4。


大约 T=60 后,delta 增长得更快(但仍然是线性的),斜率大约等于总无栅栏周期,因此每 T 大约 3c。我认为在这一点上,调度程序(预订站)的大小限制了无序窗口。您可能在 Haswell 或 Sandybridge/IvyBridge 上进行了测试,(分别有 60 个条目或 54 个条目的调度程序 https://www.realworldtech.com/haswell-cpu/4/。 Skylake 的条目有 97 个(但并未完全统一;IIRC BeeOnRope 的测试表明并非所有条目都可用于任何类型的 uop。例如,有些条目特定于加载和/或存储。)

The RS tracks un-executed uops. Each RS entry holds 1 unfused-domain uop that's waiting for its inputs to be ready, and its execution port, before it can dispatch and leave the RS1.

After an lfence, the front-end issues at 4 per clock while the back-end executes at 1 per 3 clocks, issuing 60 uops in ~15 cycles, during which time only 5 imul instructions from the edx chain have executed. (There's no load or store micro-fusion here, so every fused-domain uop from the front-end is still only 1 unfused-domain uop in the RS2.)

对于大T,RS很快就被填满,此时前端只能以后端的速度前进。 (对于小 T,我们进行下一次迭代lfence在此之前,这就是前端停滞的原因)。当 T > RS_size 时,后端看不到任何来自eaximul 链,直到后端有足够的进展edx链条在RS中腾出了空间。就在这时,一imul每个链可以每 3 个周期调度一次,而不仅仅是第 1 条或第 2 条链。

记得从第一部分开始,就在之后花费的时间lfence只执行第一个链=之前的时间lfence仅执行第二条链。这也适用于这里。

即使没有,我们也能得到一些这种效果lfence,对于 T > RS_size,但是长链的两侧都有可能重叠。 ROB 至少是 RS 大小的两倍,因此当不因以下原因而停滞时,乱序窗口lfence即使 T 略大于调度程序容量,也应该能够保持两条链持续运行。 (请记住,uop 在执行后立即离开 RS。我不确定这是否意味着他们必须finish执行并转发结果,或者只是开始执行,但这对于短 ALU 指令来说是一个微小的区别。一旦完成,只有 ROB 会按照程序顺序保留它们,直到他们退休。)

ROB 和寄存器文件不应限制无序窗口大小(http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/)在这个假设的情况下,或者在你的真实情况下。它们都应该很大。


阻塞前端是一个实现细节lfence关于英特尔的 uarches。说明书上只说了后面的说明不能execute。该措辞将允许前端将它们全部发布/重命名到调度程序(预订站)和 ROB 中,同时lfence仍在等待,只要没有人被分派到执行单元。

所以较弱lfence可能会有平坦的开销,直到 T=RS_size,然后与您现在看到的 T>60 的斜率相同。(开销的恒定部分可能会更低。)

请注意,保证了条件/间接分支的推测执行lfence适用于执行,而不是(据我所知)代码获取。仅仅触发代码获取对于 Spectre 或 Meltdown 攻击来说没有(据我所知)有用。可能用于检测其解码方式的定时侧通道可以告诉您有关获取的代码的一些信息......

我认为当相关 MSR 启用时,AMD 的 LFENCE 在实际 AMD CPU 上至少同样强大。 (LFENCE 是否在 AMD 处理器上进行序列化? https://stackoverflow.com/questions/51844886/is-lfence-serializing-on-amd-processors).


Extra lfence高架:

你的结果很有趣,但我一点也不惊讶,因为有大量的持续开销lfence本身(对于小 T),以及随 T 缩放的组件。

请记住lfence不允许稍后的指令开始,直到较早的指令完成retired。这可能比其结果准备好旁路转发到其他执行单元(即正常延迟)至少晚几个周期/管道阶段。

因此,对于小 T 来说,通过要求结果不仅准备好,而且还写回寄存器文件,在链中添加额外的延迟绝对是很重要的。

可能需要一个额外的周期左右lfence允许发出/重命名阶段在检测到其之前的最后一条指令退出后再次开始操作。问题/重命名过程需要多个阶段(周期),并且可能 lfence 会在start这样做,而不是在将微指令添加到核心的 OoO 部分之前的最后一步。

甚至背靠背lfence根据 Agner Fog 的测试,SnB 系列本身具有 4 个周期吞吐量。阿格纳·福格报道 https://agner.org/optimize/2 个融合域微指令(没有未融合的),但在 Skylake 上,如果我只有 1 个融合域,我会以 6 个融合域(仍然没有未融合)来测量它lfence。但随着更多lfence背靠背,uop 更少了!下降至约 2 uop/lfence有很多背靠背,这就是阿格纳的衡量标准。

lfence/dec/jnz(没有工作的紧密循环)在 SKL 上每约 10 个周期运行 1 次迭代,因此这可能会让我们了解真正的额外延迟lfence即使没有前端和 RS-full 瓶颈,也会添加到 dep 链中。

测量lfence开销仅one配送链, OoO exec 不相关:

.loop:
    ;mfence                  ; mfence here:  ~62.3c (with no lfence)
    lfence                   ; lfence here:  ~39.3c
    times 10 imul eax,eax    ; with no lfence: 30.0c
    ; lfence                 ; lfence here:  ~39.6c
    dec   ecx
    jnz   .loop

Without lfence,以预期的每迭代 30.0c 运行。和lfence,每迭代运行温度约为 39.3c,因此lfence有效地为关键路径 dep 链增加了约 9.3c 的“额外延迟”。 (还有 6 个额外的融合域微指令)。

With lfence在 imul 链之后、循环分支之前,它的速度稍微慢一些。但并不是整个周期变慢,因此这表明前端在单个问题组中发出循环分支 + 和 imullfence允许恢复执行。既然如此,我不知道为什么它会慢。这不是来自分支未命中。


获得您期望的行为:

按照程序顺序交错链,就像 @BeeOnRope 在注释中建议的那样,不需要乱序执行来利用 ILP,所以它非常简单:

.loop:
    lfence      ; at the top of the loop is the lowest-overhead place.

%rep T
    imul   eax,eax
    imul   edx,edx
%endrep

    dec     ecx
    jnz    .loop

你可以放一对短的times 8 imula 内的链%rep让OoO exec 过得轻松。


脚注1:前端/RS/ROB如何交互

我的思维模型是前端的问题/重命名/分配阶段向两个 RS 添加新的 uopsandROB 同时。

Uop 执行后离开 RS,但保留在 ROB 中直到按顺序退出。 ROB 可能很大,因为它永远不会无序扫描以查找第一个就绪的微指令,而只会按顺序扫描以检查最旧的微指令是否已完成执行并准备好退出。

(我假设 ROB 实际上是一个具有开始/结束索引的循环缓冲区,而不是一个实际上每个周期都将微指令复制到右侧的队列。但只需将其视为具有固定最大大小的队列/列表,其中前端在前面添加 uops,并且只要完全执行完毕,退休逻辑就会从末尾退休/提交 uops,直到某个每个周期每个超线程的退休限制,这通常不是瓶颈。Skylake 确实增加了它以获得更好的效果超线程,每个逻辑线程每个时钟可能有 8 个。也许退休还意味着释放物理寄存器,这有助于 HT,因为当两个线程都处于活动状态时,ROB 本身是静态分区的。这就是每个逻辑线程的退休限制的原因。)

哎呀喜欢nop, xor eax,eax, or lfence,在前端处理(不需要任何端口上的任何执行单元)添加only到 ROB,处于已执行状态。 (ROB 条目大概有一个位将其标记为准备退出与仍在等待执行完成。这就是我正在谈论的状态。对于 uopsdid需要一个执行端口,我假设 ROB 位是通过完成端口 https://stackoverflow.com/questions/791798/what-is-the-eu-in-x86-architecture-calculates-effective-address#comment64889806_11389785来自执行单元。并且相同的完成端口信号释放其 RS 条目。)

Uops 从问题到问题都保留在 ROB 中退休.

从发行到发行,Uops 一直保留在 RS 中执行. RS 在少数情况下可以重放微指令, e.g. 用于缓存行分割负载的另一半 https://stackoverflow.com/questions/45128763/how-can-i-accurately-benchmark-unaligned-access-speed-on-x86-64,或者如果它是在预期负载数据到达时进行调度的,但实际上它没有到达。 (缓存未命中或其他冲突,例如IvyBridge 上的指针追逐循环中附近的依赖存储对性能产生奇怪的影响。添加额外的负载会加快速度吗? https://stackoverflow.com/questions/54084992/weird-performance-effects-from-nearby-dependent-stores-in-a-pointer-chasing-loop.) 或者当加载端口推测它可以在开始 TLB 查找之前绕过 AGU 以缩短小偏移量的指针追逐延迟时 -当基址+偏移量与基址位于不同页面时是否会受到惩罚? https://stackoverflow.com/questions/52351397/is-there-a-penalty-when-baseoffset-is-in-a-different-page-than-the-base

所以我们知道 RS 无法在调度时立即删除 uop,因为它可能需要重播。 (甚至可能发生在消耗负载数据的非负载微指令上。)但是任何需要重放的推测都是短程的,而不是通过微指令链,因此一旦结果从执行单元的另一端出来,微指令就可以从 RS 中删除。这可能是完成端口所做的一部分,同时将结果放在旁路转发网络上。


脚注 2:微融合 uop 需要多少个 RS 条目?

TL:DR:P6 系列:RS 已熔合,SnB 系列:RS 未熔合。

微融合 uop 被发送到 Sandybridge 系列中的两个独立的 RS 条目,但只有 1 个 ROB 条目。 (假设发行前没有未层压,请参阅 Intel 优化手册的 HSW 2.3.5 节或 SnB 2.4.2.4 节,以及微融合和寻址模式 https://stackoverflow.com/questions/26046634/micro-fusion-and-addressing-modes。 Sandybridge 系列更紧凑的 uop 格式在所有情况下都无法表示 ROB 中的索引寻址模式。)

负载可以在 ALU uop 的其他操作数准备就绪之前独立分派。 (或者对于微融合存储,存储地址或存储数据微指令可以在其输入准备好时进行调度,而无需等待两者。)

我使用问题中的两深度链方法在 Skylake 上进行实验测试(RS 大小 = 97), 带有微熔or edi, [rdi] vs. mov+or,以及另一个部门链rsi. (完整测试代码,Godbolt 上的 NASM 语法 https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAKxAEZSAbAQwDtQmBnDzAWwCMGAT1IdUAV2LJMIAOQBSAMwAhRUoDUBRQBECmDgQapUAB1VrOPALQM8LANZq5AJicASAgDoLzp46cA2Z381fA5OPzdNFz9AgI1OO24CNUtkNQU1VGRjTGIAMw9jQTV9JmTLTAIE1MNkO1I0Fl0ADwJLDgB3QmQEPQbjMUsePGBiMrxUFg5SYyZgTEs8pjEGAmnkQWQGPtt9YjFkAgmp0jETDgB9PC4xTHQvFmEz40vMZsxkMV17ggRiTCY6EYHHuzw4ag8AHofO4fHIAAwAQQRiKwSxWyX%2BDBRzgArHg8mi1BcLgBNREAZQAshcAGrYABKJJRalZjmUbM5agAwgAFACqOI5bL5/LUtl0DBYJhZIoFPMmxFQmDUiKpWllrNFagpdkEzDsKrVGqReMwDG4OKcuLE3BKPCYxCqNmALBRTBdLB4GBVxn8pDU/gALFbcZgWPg8jjTdaCUSAJKI7mIi5UxEMgDSFNDDuQStZieTF1KTrU8M1rO9ADc1Jg%2BM0A7QmxWQnwy81gwH4R2AOxd5oATnLMbDEdzSpzTDzqALSZT4fQZZb1dr9YDLicLfQbe7nfb/j77aHoYX49QJ4tmFDaNsKsLKZLmhHN5Yd7nFwXJ4jBOjiOAhj4D1iUfFFiyqJ0QF/TkzDZVhFy5NliA4YwA0sYNQwJNRaArbYmAQ1liHwAM5FxJQ%2BDEKNcRNRFOVw/C1CQvBiNI8i8g4SQSOos1vyjJFORXNkSKUQi8E4gMRKgtkBLZOsUKw%2BEFMU4dkRHTDsKRD0RhYdJN1NYVWWQHhjFZAEG3bWgnAUINcWCdl1G3dsFC0VkODsPBjN%2BFU8jwJDkiDNQ%2BEEXRwUmDRejUbzfPFXQxiOUKUXvMDHSfREPEMExINNPT1DZI4eD0dJ4TUFcROY4T8E41kzCIZ01GYXQWA2NQg2QAMODwIztnMdB0H%2BLhbGAYqfQizg2lmX4hRy1k8oKhQisBRdGLKxjKrsjRUFq%2Brwya/xkEUAAxMAwAOo7WRakb9EscaEEyFghAikg6tQQFLEUbBDEBB7iA6R18DYA7Js5GbwTmzJiAIojHFIiSqKqjkaqA3a6rKbbBBO46FH2xxsqBjrZqKx6GMhoSJKcYT62cJQnHhdDYbWj1REDNItsa4Q1CrDgPCGmsul%2BMLrm63rvSwNQOnEBhFz4FVcV/PF/mMgAVDC8jUfb%2BQpbAK0eu4mKh8rRKoi9LT4qTUBrWsmDMkmKsNk3WUJ2tIdMr9Ixd%2BXZeteW1CV1SVbVjWtfBvRdZJ9rOKNq87e5kzLeWsPbZotkHeDgNnZHBcf3TiN3ayxO4aUATTLK1jw6j1RDOMi2zKK%2Bja7W3wwXW2q8ke6tIQryEqFfNQIAblg8ltO4AEpJPztQK5CMXCL1rEAoosSywQswMkbhGGC%2B8ejM7lVeZujqeAADnE9zLFniAV/7wf0BHsv4b0ZJ0CnxcSfNOfKK0fs8hVtaV/OJugJbuDYKBBt6i0IHvHgPAFBOGWifLElVz5qDEJfbg18KzVXvpPEgz9oavxLlRVO%2BAx4NxMP/degCND31AbvGemBgAL3%2BINHuF8B6oJvipPOa1gFYOnkJJgfBwT4I/u2L%2BxCkF/zXhvYB1DwHikgdAgM/DwSIOQaw4e6C776B4Tg/WC9uyiPruIl4ZCpFUKoDvWRL96EELkVA3wKiUHqNvuobhj9sEzxtsInWY9aBGJMRQ6R5iwF8ysQwuhrJe5IMcWg5xrin56yUW/Be3i1q%2BOeP4x6gSLEhNwdY4RjCIl9zUTEzhqgu4qg8J%2BWJeNwS4jUM0bWyAGwfGaLLHGbIOBiDbMQPgcl1KcKwGkWSgMOldNXH0isVBBppSMKYdpLkxktMbLLfSm9jKETMrQJS2yzCSFafMtQVA2wzJlEiRKVTkTWgzrxVKC5MocNUKoAAcpSKklhJhCADNKZI5JqQgEErGFWJIlDxgVhSEk7INROR0srPA6BtIkgAPL8gVgKBWFx9qIoZGmdFFxU4MDyNAisK4i79M5A0oOa46z7M4RKdsB8a6CQ5BwQQrxmiEAgPCIeOlLB8EIKqEFEcKwUsdkxHWxKzZV1IJZXxY8SRPKZG8QgFxRjiErnkJUPA1CQltMQSEtgthiCwJCCwOqWDXAIOgC4wYPAIArCyjgyAPTryXsy1lH52UEBVUqMQxhOXsO4q7XOv5uCHGOBCJU6AyhMHdJ6LCgQkQcAdAwBgFwWBiH4Lkf500anNRCIueEHhtkKX6ZMaQdcc35XBP5HqWEi0ho%2BHFbSHgBEcFjVpQMIYkSsWzYhPQbYgzwgHAmjhrF2LIGzX1AdQ6R0yCHowWQuIZCkBYLIeEy7UCyERFwXgAhiiiAkFIPwChaDLoIGuud867AgFxE4DwDKezUwUAoA%2BA4D5zVxPCXEC6ZBBmXaumQ67SCbpkMujgIB4SkHPYBudpA4CwBgIgFAqAjJ4G2GQCgEA0CofQyAFgFgnC0DmgoUg3lVi5HAxAPgF7SB8vw8QQQshT0NBQ/lJoiK7qMZg6QLADo2DbBo/gf4Yaqx6Bo28D4XxpAyGYxKc0TGz3EA6gp%2BdzA2AgE4NwfgnybACPgPOkwTbwMyEWOaPIwYUhaCVk5fwRVLBaH9prJyQGD2SGkLQVTi7/00ZAy86kag71EaLRkCAuBCCPWcCegM3IUPGDQ7kY9HnVQ7u04IM9F6h5XpvZBhgsg/2kB4DegcRb/C4gHFZGmZWKv%2BH9ABoDIGwMQagxluDiGIBIHEAQAYBByCUGw3F3D9AdZEGIHQUgHQxjGBUz%2BpdK6fOyEi74mhfmqQBY8EF%2BECh0swcy6QXogIs0QE87%2B5dhXB0eHK4O0rl3KuXbm9xhrIgmvQfXbt69QYezrYHE4Hsw7/BbNoP4AcQYBzftyzILbBW6AKSLcW4t9A6sbtkNt17x2nDeYe8j5rO352icYpMEAQYgA)

; loop body
%rep T
%if FUSE
    or edi, [rdi]    ; static buffers are in the low 32 bits of address space, in non-PIE
%else
    mov  eax, [rdi]
    or   edi, eax
%endif
%endrep

%rep T
%if FUSE
    or esi, [rsi]
%else
    mov  eax, [rsi]
    or   esi, eax
%endif
%endrep

看着uops_executed.thread(未融合域)每个周期(或每秒)perf为我们计算),我们可以看到不依赖于单独负载与折叠负载的吞吐量数字。

使用较小的 T (T=30),可以利用所有 ILP,无论有或没有微融合,我们每个时钟都能获得约 0.67 uop。 (我忽略了来自 dec/jnz 的每个循环迭代 1 个额外 uop 的小偏差。与我们看到的微融合 uop 仅使用 1 个 RS 条目所看到的效果相比,它可以忽略不计)

记住负载+or是 2 uop,并且我们有 2 个飞行中的 dep 链,所以这是 4/6,因为or edi, [rdi]有6个周期的延迟。 (不是 5,这令人惊讶,见下文。)

在 T=60 时,对于 FUSE=0,我们仍然每个时钟执行约 0.66 个未融合的微指令,对于 FUSE=1,每个时钟执行约 0.64 个未融合微指令。我们仍然可以找到基本上所有的 ILP,但它才刚刚开始下降,因为两个 dep 链的长度为 120 uops(相对于 RS 大小为 97)。

在 T=120 时,对于 FUSE=0,每个时钟有 0.45 个未融合的微指令,对于 FUSE=1,每个时钟有 0.44 个未融合的微指令。我们肯定已经过了膝盖了,但仍然发现someILP 的。

如果微融合 uop 仅占用 1 个 RS 条目,则 FUSE=1 T=120 的速度应与 FUSE=0 T=60 大致相同,但事实并非如此。相反,FUSE=0 或 1 在任何 T 上几乎没有区别。(包括较大的 T=200:FUSE=0:0.395 uops/时钟,FUSE=1:0.391 uops/时钟)。我们必须去very在我们开始 1 个深度链在飞行中的时间之前,T 大 T 完全控制了 2 个在飞行中的时间,并下降到 0.33 uops/时钟 (2/6)。

奇怪的是:融合与非融合的吞吐量差异如此之小,但仍然可测量,并且单独的mov加载速度更快。

其他奇怪之处:总计uops_executed.thread is slightly在任何给定 T 下,FUSE=0 的值较低。例如 T=60 时为 2,418,826,591 与 2,419,020,155。这种差异可重复至 2.4G 中的 +- 60k,足够精确。 FUSE=1 的总时钟周期较慢,但大部分差异来自于每个时钟的微指令数较低,而不是更多的微指令数。

简单的寻址模式如[rdi]假设只有 4 个周期延迟,因此负载 + ALU 应该只有 5 个周期。但我测量了 6 个周期的加载使用延迟or rdi, [rdi],或者使用单独的 MOV 加载,或者使用任何其他 ALU 指令,我永远无法将加载部分设为 4c。

复杂的寻址模式如[rdi + rbx + 2064]当 dep 链中有 ALU 指令时,具有相同的延迟,因此看来 Intel 的 4c 延迟适用于简单寻址模式only当一个负载转发到另一个负载的基址寄存器时适用(最多 +0..2047 位移且无索引)。

指针追逐很常见,因此这是一种有用的优化,但我们需要将其视为特殊的负载-负载转发快速路径,而不是更快准备好供 ALU 指令使用的一般数据。


P6 系列不同:RS 条目保存融合域 uop。

@哈迪发现2002 年英特尔专利 https://patents.google.com/patent/US20040034757A1/en,其中图 12 显示了融合域中的 RS。

在 Conroe(第一代 Core 2 Duo,E6600)上进行的实验测试表明,对于 T=50,FUSE=0 和 FUSE=1 之间存在很大差异。 (RS大小为32个条目 https://www.realworldtech.com/merom/6/).

  • T=50 FUSE=1:2.346G周期总时间(0.44IPC)

  • T=50 FUSE=0:3.272G 周期的总时间(0.62IPC = 0.31 负载+OR 每个时钟)。 (perf / ocperf.py没有活动uops_executed在 Nehalem 之前的 uarches 上,我没有oprofile安装在该机器上。)

  • T=24 FUSE=0 和 FUSE=1 之间的差异可以忽略不计,大约为 0.47 IPC 与 0.9 IPC(每个时钟约 0.45 负载+OR)。

T=24 仍然是循环中超过 96 字节的代码,对于 Core 2 的 64 字节(预解码)循环缓冲区来说太大,因此由于适合循环缓冲区,它的速度并没有更快。如果没有 uop 缓存,我们必须担心前端,但我认为我们很好,因为我专门使用 2 字节单 uop 指令,这些指令应该可以轻松地以每个时钟 4 个融合域 uop 进行解码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

了解 lfence 对具有两个长依赖链的循环的影响,以增加长度 的相关文章

  • 记录 Google Cloud SQL PostgreSQL 实例上的慢速查询

    我工作的公司使用 Google Cloud SQL 来管理生产中的 SQL 数据库 我们遇到了性能问题 我认为查看 监控高于特定阈值 例如 250 毫秒 的所有查询是一个好主意 除其他外 通过查看PostgreSQL 文档 https ww
  • Android:了解 OnDrawFrame、FPS 和 VSync (OpenGL ES 2.0)

    一段时间以来 我在 Android 游戏中遇到了运动精灵间歇性 卡顿 的情况 这是一个非常简单的 2D OpenGL ES 2 0 游戏 这是一个持续存在的问题 我已经多次重新访问过 在我的游戏循环中 我有 2 个 计时器 一个用于记录前一
  • _mm_max_ss 在 clang 和 gcc 之间有不同的行为

    我正在尝试使用 clang 和 gcc 交叉编译一个项目 但在使用时发现一些奇怪的差异 mm max ss e g m128 a mm set ss std numeric limits
  • SQL Azure 和 READ_COMMITTED_SNAPSHOT

    我想在 SQL Azure 数据库上将 READ COMMITTED SNAPSHOT 设置为 ON 但 Azure 不支持以下适用于其他版本的 SQL Server 的代码 ALTER DATABASE database name SET
  • IDA pro asm 指令更改

    我只是想知道我怎样才能 更改IDA视图A中的asm指令 如何编辑指令 对于 实例 jnz 到 jmp 如何插入新指令 call func1 调用 func2 插入到现有的 代码 我知道如何制作 diff 文件 我知道如何在我的 DLL 上应
  • 具有单个成员的结构是否具有与成员类型相同的性能?

    Does struct单个成员是否具有与成员类型相同的性能 内存使用和速度 Example 这段代码是一个struct与单个成员 struct my int int value 是的表现my int与 一样int 同意 harper htt
  • 如何在WinMobile6上启用ARMv6非对齐访问?

    ARMv6 引入了一个很棒的功能 未对齐的内存访问 这使得代码中的某些事情变得更加简单和更快 但微软只在winCE6中提供了API 现在大多数 PDA 都基于 WinMobile6 基于 CE 5 x 默认情况下禁用未对齐访问 我尝试在 C
  • 为什么反射会减慢Android手机的速度

    我多次读到反射会降低手机性能 这有多真实 例如 在我的例子中 我从 Web 服务获取一些参数 这些参数与我在 Android 应用程序中的类的参数同名 所以我只是使用java字段和反射设置这些参数的值 它似乎并没有降低性能 有人可以向我解释
  • LEFT JOIN 比 INNER JOIN 快得多

    我有一张桌子 MainTable 有超过 600 000 条记录 它通过第二个表连接到自身 JoinTable 在父 子类型关系中 SELECT Child ID Parent ID FROM MainTable AS Child JOIN
  • long double(GCC 特定)和 __float128

    我正在寻找有关的详细信息long double and float128在 GCC x86 中 更多是出于好奇而不是因为实际问题 可能很少有人需要这些 我只是有史以来第一次 truly需要一个double 但我想知道你的工具箱里有什么以及它
  • 学习 (N)ASM 的最佳资源是什么? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想学习汇编已经有一段时间了 尽管我之前尝试过几次 但我还没有真正能够超越 Hello world 有
  • 在哪里可以找到Python内置序列类型的时间和空间复杂度

    我一直无法找到此信息的来源 无法亲自查看 Python 源代码来确定这些对象是如何工作的 有谁知道我可以在网上找到这个吗 结帐时间复杂度 http wiki python org moin TimeComplexitypy dot org
  • ICC 中的 -O3 会扰乱内在函数,使用 -O1 或 -O2 或相应的手动汇编即可

    这是后续这个问题 http stackoverflow com questions 49791664 o2 in icc messes up assembler fine with o1 in icc and all optimizatio
  • 如何在 MacOS 上使用 nasm 进行编译

    我正在尝试在汇编器上编译并链接我的第一个程序 我尝试编译以下代码 include stud io inc global main section text main xor eax eax again PRINT Hello PUTCHAR
  • 在 Chrome 18 中检测 SwiftShader WebGL 渲染器

    我有一个 2D HTML5 游戏引擎 www scirra com http www scirra com 并且确实想检测 WebGL 是否将使用 Chrome 18 的 Swiftshader 软件渲染器进行渲染 如果是这样我们会much
  • VirtualStringTree 正确/推荐使用

    我已经使用 virtualstringtree 一段时间了 我将它用于两个不同的用途 第一个是用于选择 显示数据的普通树 第二个是作为网格来显示 SQL 语句的输出 我加载到树中的所有数据都来自数据库 对于树示例 我有一个 ParentId
  • php 日期函数和 Carbon 哪个更快?

    Carbon 是 DateTime 的简单 PHP API 扩展 我想知道我们可以通过 Composer 安装 Carbon 来使用日期时间函数 php 日期时间函数和 Carbon 哪个更快 我对您的评论做了一些测试 比较了 DateTi
  • 如何证明2条sql语句是等价的

    我开始用连接和子语句重写一个复杂的 SQL 语句 并获得一个看起来更简单的语句 我通过在相同的数据集上运行并获得相同的结果集来测试它 一般来说 我如何 概念上 证明这两个陈述在任何给定数据集中都是相同的 我建议学习关系代数 正如 Mchl
  • gcc 删除内联汇编代码

    看起来 gcc 4 6 2 删除了它认为函数中未使用的代码 test c int main void goto exit handler asm volatile jmp 0x0 exit return 0 拆解main 0x0804840
  • 应用程序中 GC 长时间暂停

    我当前运行的应用程序需要最大堆大小为 16GB 目前我使用以下标志来处理垃圾收集 XX UseParNewGC XX UseConcMarkSweepGC XX CMSInitiatingOccupancyFraction 50 XX Di

随机推荐