【问题标题】:How can memory destination BTS be significantly slower than load / BTS reg,reg / store?内存目标 BTS 如何比加载/BTS reg,reg/store 慢得多?
【发布时间】:2020-12-03 22:49:33
【问题描述】:

在一般情况下,可以占用内存或寄存器操作数的指令怎么会比内存操作数更慢,然后是 mov + mov -> 指令 -> mov + mov

基于在Agner Fog's instruction tables 中发现的吞吐量和延迟(在我的案例中查看 Skylake,p238) 我看到btr/bts 指令的以下数字:

instruction, operands, uops fused domain, uops unfused domain, latency, throughput
mov          r,r       1                  1                    0-1      .25
mov          m,r       1                  2                    2        1
mov          r,m       1                  1                    2        .5
... 
bts/btr      r,r       1                  1                    N/A      .5
bts/btr      m,r       10                 10                   N/A      5

我看不出这些数字怎么可能是正确的。即使在最坏的情况下,没有可用的寄存器并且您将一个存储在临时内存位置,它也会更快:

## hypothetical worst-case microcode that saves/restores a scratch register
mov m,r  // + 1  throughput , save a register
mov r,m  // + .5 throughput , load BTS destination operand
bts r,r  // + 1  throughput , do bts (or btr)
mov m,r  // + 1  throughput , store result
mov r,m  // + .5 throughput , restore register

在最坏的情况下,这比 bts m,r (4

而且微码指令有自己的一组寄存器,因此看起来不太可能实际需要。谁能解释为什么bts(或一般任何指令)在内存、寄存器操作数方面比使用最坏情况移动策略具有更高的吞吐量。

(编者注:是的,微码可以使用一些隐藏的临时寄存器。像add [mem], reg 这样的东西至少在逻辑上只是加载到其中一个然后存储结果。)

【问题讨论】:

  • 注意位串指令的疯狂 CISC 语义;他们可以在寻址模式寻址的双字之外建立索引!!这就是它的特别之处。
  • 您的模拟似乎基于 AT&T 语法,目的地位于最后。 Agner 的表是 Intel 语法,目标优先。 Skylake 有 2 个/时钟负载,1 个/时钟存储,反之亦然(希望您意识到这更有意义。)我建议在您的示例中使用 Intel 语法来保存 regs,即交换前 2 个的顺序行,以及评论的 perf 部分等。
  • 我为您解决了这个问题,并留下了一些关于您的假设的注释。

标签: performance assembly x86-64 cpu-architecture microcoding


【解决方案1】:

您缺少的是 BT、BTC、BTS 和 BTR 在使用内存操作数时不像您描述的那样工作。您假设内存版本与寄存器版本的工作方式相同,但事实并非如此。对于寄存器版本,使用的第二个操作数的值取模 64(或 16 或 32)。对于内存版本,第二个操作数的值按原样使用。这意味着指令访问的实际内存位置可能不是内存操作数给出的地址,而是在它之后的某个位置。

例如,忽略保存寄存器和原子性的需要,要使用 BTS 的寄存器版本获得与 BTS [rsi + rdi], rax 相同的操作,您需要执行以下操作:

LEA rbx, [rsi + rdi]
MOV rcx, rax
SHR rcx, 8
MOV rdx, [rbx + rcx]
BTS rdx, rax
MOV [rbx + rcx], rdx

如果您知道 RAX 的值小于 64,或者它是一个更简单的内存操作数,则可以简化此操作。事实上,正如您所注意到的,在这种情况下,使用较快的寄存器版本而不是较慢的内存版本可能是一个优势,即使这意味着更多的指令。

【讨论】:

  • 现在做lock bts [rsi+rdi], rax。 :-)(这是我用过的唯一一种。)
  • @prl 啊,我知道我忘记了什么。谢谢。
猜你喜欢
  • 2021-10-15
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
  • 1970-01-01
  • 2016-02-16
相关资源
最近更新 更多