gpt4 book ai didi

loops - x86_64 - 汇编 - 循环条件和乱序

转载 作者:行者123 更新时间:2023-12-04 23:19:30 26 4
gpt4 key购买 nike

我不是在要求一个基准。
(如果是这样的话,我会自己做的。)

我的问题:
为了方便起见,我倾向于避免使用间接/索引寻址模式。
作为替代,我经常使用立即寻址、绝对寻址或寄存器寻址。
编码:

; %esi has the array address. Say we iterate a doubleword (4bytes) array.
; %ecx is the array elements count
(0x98767) myloop:
... ;do whatever with %esi
add $4, %esi
dec %ecx
jnz 0x98767;
在这里,我们有一个序列化的组合(dec 和 jnz),可以防止正确的乱序执行(依赖)。
有没有办法避免/打破dep? (我不是 assembly 专家)。

最佳答案

在针对 Intel CPU 进行优化时,始终将标志设置指令放在条件跳转指令之前(如果它是下表中列出的简单指令之一),以便它们可以在解码器中宏融合为一个 uop。
对于不进行宏融合的旧 CPU,这样做并没有显着恶化。提前设置标志可能会将此类 CPU 的分支错误预测惩罚缩短 1,但乱序执行意味着移动 dec之前的几条指令不会产生真正的影响。另见 Avoid stalling pipeline by calculating conditional early .为了真正发挥作用,您可以在一些可以更简单地计算的东西上展开循环和/或分支,理想情况下不依赖于缓慢的输入,因此 OoO exec 可以在处理较旧的迭代时已经解决分支循环体。即循环计数器 dep-chain 可以在主要工作之前运行。
我没有基准测试,但我不认为越来越稀有的 CPU 的小缺点证明错失了进行融合的 CPU 的前端吞吐量优势(解码和发布)。总 uop 吞吐量通常是一个瓶颈。
AMD推土机/打桩机/ Steam 压路机可熔断test/cmp与任何 jcc ,但只有 test/cmp , 不是任何其他 ALU 指令。所以绝对把与分支进行比较。如果英特尔 CPU 可以在 Sandybridge 系列上进行宏融合,那么将其他东西与分支放在一起仍然很有值(value)。
来自 Agner Fog's微拱指南,表 9.2(适用于 Sandybridge/Ivybridge):

First       | can pair with these  |  cannot pair with
instruction | (and the inverse) |
---------------------------------------------
cmp |jz, jc, jb, ja, jl, jg| js, jp, jo
add, sub |jz, jc, jb, ja, jl, jg| js, jp, jo
adc, sbb |none |
inc, dec |jz, jl, jg | jc, jb, ja, js, jp, jo
test | all |
and | all |
or, xor, not, neg | none |
shift, rotate | none |

Table 9.2. Instruction fusion
所以基本上, inc/dec可以使用 jcc 进行宏熔断器只要条件只依赖于 inc/dec 修改的位.
(否则,它们不会进行宏融合,并且您会插入一个额外的 uop 来合并标志(就像您在写入 eax 后读取 al 时一样)。或者在早期的 CPU 上,部分标志会停顿。)
Core2/Nehalem 在宏融合能力上更受限制(仅用于 CMP/TEST 具有更有限的 JCC 组合),而 Core2 根本无法在 64 位模式下进行宏融合。
如果您还没有阅读 Agner Fog 的优化 asm 和 C 指南,也可以阅读。他们充满了基本知识。

关于loops - x86_64 - 汇编 - 循环条件和乱序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31771526/

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