每时钟性能- 我可以对同一条指令使用不同的寄存器吗?

per clock perf. - can I use different registers for same instruction?

我可以使用四个通用寄存器,比如 r8、r9、r10、r11,每个寄存器都带有 MOV 指令以进行独立操作,并且给人的印象是 CPU 在一个时钟内执行所有这些指令吗?

我想知道,因为根据 Agner Fog 的指令 Table,它说 MOV 指令的倒数吞吐量是 0.25。这意味着 CPU 每个周期应该能够执行 4 次 MOV 操作。或者我误解了这一切 ??

我是菜鸟,两个月以来一直在学习 MASM 中的汇编(主要是为了学习调试寄存器的工作原理,这真的很有趣)。

编辑,重新阅读你的问题,你问的是不同的寄存器。我会留下我原来的答案;让我们假设您的问题不仅仅是最微不足道的案例。 :P

是的,即使不重命名寄存器,这些指令也可以在同一周期内(在不同的执行单元上)全部执行,因为它们彼此完全独立。

mov   eax, 1
mov   ebx, ecx
mov   edx, [mem]
xor   esi,esi     ;xor-zero: doesn't even use an execution unit on SnB-family

这是超标量执行的最简单情况。如果 eax/rax 是所有四个指令的目的地,寄存器重命名仍将允许所有四个指令并行执行。

乱序执行允许来自独立依赖链的四个相邻指令同时执行,即使它们不是在同一时钟周期内解码或发出的。如果他们之间有指示,他们也可能不会在同一个周期内退休。 (x86 ISA 保证精确的异常,就像大多数其他 ISA (ARM/PPC/etc)。所有当前的设计都是通过有序退出来完成的。因此,如果内存操作出现段错误,程序将恰好在该指令处停止,而不仅仅是 "well, there was a segfault somewhere recently, but we can't tell you where"。(那将是不精确的例外)。)

像 Atom 或 P5(原始奔腾)这样的超标量有序设计仍然可以利用这四个独立指令的并行性,但在许多其他情况下则不然。

在手工制作的循环中,SnB 系列 CPU 通常能够在每个循环中维持超过 3 个融合域微指令。 (由于延迟,编写 运行 每个周期少于一个融合域 uop 的循环也很容易,更不用说缓存未命中或分支预测错误了。)


是的,对同一架构寄存器的多次写入可以并行执行。寄存器重命名不是 Intel 或 AMD 设计的瓶颈。

要理解和充分利用 Agner Fog 的表格,您必须阅读 his microarch guide, or at least his "optimizing assembly" guide. See also good stuff at the wiki。

正如 Agner Fog 的 microarch pdf 指出的那样(第 9.8 节关于英特尔 SnB/IvB):

Register renaming is controlled by the register alias table (RAT) and the reorder buffer (ROB), shown in figure 6.1. The μops from the decoders and the stack engine go to the RAT via a queue and then to the ROB-read and the reservation station. The RAT can handle 4 μops per clock cycle. The RAT can rename four registers per clock cycle, and it can even rename the same register four times in one clock cycle.

读取-修改-写入是另一回事(add 指令的目的地)。架构寄存器的读取-修改-写入是依赖链的(一部分),而无条件 mov 或异或归零启动新的依赖链。 (与某些其他指令的输出相同,例如 lea 不读取其目的地)。

那些寄存器写入仍然将架构寄存器重命名为新的物理寄存器。这就是 CPU 处理像

这样的案例的方式
mov eax, 1      ; start of a dep chain
mov [mem+rax+rcx], eax
inc eax         ; eax renamed again

存储需要 inc 之前的 eax 值。它得到它是因为当它检查 RAT 时,架构 eax 仍然指向 mov eax,1 写入的同一个物理寄存器。 inc 不能只修改同一个物理寄存器,因为它不知道如果还没有用 eax.

的先前值做任何事情会怎样