给出如下所示的小程序(从顺序一致性/ TSO角度看,它看起来手工相同),并假设它是由超标量无序x86 cpu运行的:
this.setState({ matchInfo: body });
我有几个问题:
谢谢
答案 0 :(得分:3)
术语:“指令窗口”通常表示乱序的执行窗口,CPU可以在该窗口上找到ILP。即ROB或RS大小。参见Understanding the impact of lfence on a loop with two long dependency chains, for increasing lengths
在一个周期内可通过多少条指令的术语是管线 width 。例如Skylake是4级超标量故障。 (它的部分管线,例如解码,uop-cache提取和报废,宽于4 oups,但问题/重命名是最窄的点。)
术语:“ 等待提交到存储缓冲区中”,存储数据+地址在执行存储时被写入到存储缓冲区中。当已知报废是非投机性的时,它会在退役后的任何时候将存储缓冲区从仓库中的 提交给L1d。
(按程序顺序,以保持不进行存储重新排序的TSO内存模型。存储缓冲区允许存储在该内核内无序执行执行,但仍会提交给L1d(并变为 执行存储=将地址+数据写入存储缓冲区。)
what is a store buffer?
Size of store buffers on Intel hardware? What exactly is a store buffer?
前端无关。 3个连续的指令很可能会在同一16字节的提取块中提取,并且可能会以与一组相同的周期进行预解码和解码。并且(也可以替代地)作为一组3或4 uops的一部分分发到无序后端。 IDK为什么您认为其中任何一个都会引起任何潜在的问题。
前端(从提取到发布/重命名)按程序顺序处理指令。同时处理不会将后面的指令放在之前的之前,而是将它们放在相同的时间内。更重要的是,它保留了有关程序顺序的信息。不会丢失或丢弃,因为对于依赖于前一个 1 !
的指令很重要!大多数流水线阶段之间都有队列,因此(例如,在Intel Sandybridge上)作为一组多达6条指令进行预解码的指令可能不会与同一组up-up中的一部分击中解码器。到4(或在宏融合时更多)。有关提取,请参见https://www.realworldtech.com/sandy-bridge/3/,有关解码,请参见下一页。 (还有uop缓存。)
执行(从无序的调度程序向执行端口分配uops)在这里很重要。 乱序调度程序必须避免破坏单线程代码。 2
通常情况下,发布/重命名比执行早得多,除非您在前端遇到瓶颈。因此,通常没有理由期望一起发出的微指令将一起执行。 (为争辩起见,假设您显示的2个负载确实在同一周期内被调度执行,而不管它们是如何通过前端到达的。)
但是无论如何,在这里开始加载和存储都是相同的。 uop调度程序不知道L1d中的负载是命中还是未命中。它仅以一个周期向负载执行单元发送2个负载uop,并向这些端口发送一个store-address + store-data uop。
2)[负载排序]
这是棘手的部分。
正如我在对your last question的答复和评论中所解释的那样,即使内存模型要求这样做,现代的x86 CPU也会推测性地使用Load B的L2命中结果用于以后的指令。加载发生在加载A之后。
但是,如果在加载A完成之前没有其他内核写入高速缓存行B,则没有任何区别。内存顺序缓冲区负责检测之前加载的高速缓存行的无效性。较早的负载已完成,并且在极少数情况下允许进行内存重新排序可能会改变结果,从而进行内存顺序错误推测管道刷新(回滚到退役状态)。
3)为什么商店必须等待装载?
除非存储地址取决于加载值,否则不会。 uop调度程序将在输入准备好后将存储地址和存储数据uup分派给执行单元。 / p>
这是按程序顺序加载之后,并且就全局内存顺序而言,存储缓冲区将使其在加载后甚至更远。存储缓冲区不会将存储数据提交到L1d(使其在全球范围内可见),直到商店退休为止。由于是在装载之后,它们也将退休。
(报废是有序的,以允许确切的例外情况,并确保没有以前的指令接受了例外或分支的错误预测。有序报废使我们能够可以肯定地说,一条指令在退休后是非推测性的。)
所以是的,这种机制确实确保了直到两个加载都从内存中获取了数据之后,存储设备才能提交给L1d(通过L1d高速缓存,该高速缓存为所有内核提供了一致的内存视图)。因此,这可以防止LoadStore重新排序(对于较早的加载和后续的存储)。
我不确定是否有任何顺序较弱的OoO CPU进行LoadStore重新排序。在有序CPU上,当高速缓存未命中加载在高速缓存命中存储之前出现时,CPU可能会使用记分板来避免停顿,直到尚未真正从寄存器中读取加载数据为止。 (LoadStore很奇怪:另请参阅Jeff Preshing的Memory Barriers Are Like Source Control Operations)。也许某些OoO执行CPU在已知确实发生故障时也可以跟踪退休后的高速缓存未命中存储,但是数据仍未到达。 x86不会这样做,因为它会违反TSO内存模型。
脚注1:在某些体系结构(通常为VLIW)中,同时指令包是体系结构的一部分,其方式对于软件是可见的。因此,如果软件不能用可以同时执行的指令填充所有3个插槽,则必须用NOP填充它们。甚至可能允许将2个寄存器与包含mov r0, r1
和mov r1, r0
的包交换,这取决于ISA是否允许同一包中的指令读取和写入相同的寄存器。
但是x86不是那样的:超标量无序执行必须始终保持以程序顺序一次运行一条指令的错觉。 OoO执行人员的基本规则是:不要破坏单线程代码。
任何违反此规定的操作都只能通过checking for hazards来完成,或者只能在发现错误时通过回滚进行推测。
脚注2:(续脚注1)
您可以获取/解码/发出两个背对背的inc eax
指令,但是它们不能在同一周期内执行,因为寄存器重命名+ OoO调度程序必须检测到第二个读取输出第一个。