我编写了一个程序,可用于探索英特尔处理器中未记录的 RS 限制,希望我能够最终回答这个问题。基本思想是在循环中分配和执行特定的微指令序列之前确保 RS 完全为空。RESOURCE_STALLS.RS
可用于确定该序列是否已达到 RS 本身的限制。例如,如果RESOURCE_STALLS.RS
每次迭代为 1,则分配器必须停止一个周期才能为序列中的所有微指令分配 RS 条目。如果RESOURCE_STALLS.RS
每次迭代远小于 1,那么它基本上不必停止,因此我们知道我们没有遇到任何 RS 限制。
我已经尝试过一系列相关ADD
指令、一系列相关 BSWAP 指令、一系列相关加载指令到同一位置、一系列后向或前向无条件跳转指令以及一系列存储指令到同一位置。以下两张图显示了add
针对不同目标 RS 占用的指令序列的结果(微指令序列同时需要和占用的最大 RS 条目数)。每次迭代都会显示所有值。
下图显示,RESOURCE_STALLS.RS
当 RS 占用率为 50 时,每次迭代至少(或接近)1 个循环。虽然不是很明显,RESOURCE_STALLS.RS
但当 RS 占用率超过 43 时变得大于零,但仅在 RS 占用率超过 1 时占用率超过 49。换句话说,我只能同时使用 60 个(在 Haswell 中)中的 49 个 RS 条目,而没有 RS 档位。之后,RESOURCE_STALLS.RS
序列中每增加一个 uop,平均增加 1,这与分配器的突发行为以及每个ADD
uop 可以在每个周期完成的事实一致(每个 uop 仅占用 1 个周期的 RS 条目)。cycles
每增加一个 uop,平均增加 2.3。每个额外的 uop 大于 1,因为 ROB 上还有额外的档位,原因与add
uops 无关,但这些都可以,因为它们不会影响RESOURCE_STALLS.RS
.
![在此处输入图像描述](https://i.stack.imgur.com/hKzSV.png)
下图显示了cycles
每次RESOURCE_STALLS.RS
迭代的变化。它说明了执行时间和 RS 停顿之间的强相关性。
![在此处输入图像描述](https://i.stack.imgur.com/zXThS.png)
当目标 RS 占用率在 44-49 之间时,RESOURCE_STALLS.RS
它非常小,但仍然不是真正的零。我还注意到,不同微指令呈现给分配器的确切顺序会稍微影响可以达到的 RS 占用率。我认为这是英特尔手册中提到的 RS 阵列写入端口分配方案的效果。
那么其他 11 个 RS 条目是怎么回事(Haswell 的 RS 应该有 60 个条目)?RESOURCE_STALLS.ANY
表演活动是回答问题的关键。我更新了用于执行这些实验以测试不同类型负载的代码:
- 可以使用推测地址分派的负载以实现 4 周期 L1D 命中延迟。这种情况被称为
loadspec
。
- 无法使用推测地址分派的负载。这些在 Haswell 上的 L1D 命中延迟为 5 个周期。这种情况被称为
loadnonspec
。
- 可以使用推测但不正确的地址分派的负载。这些在 Haswell 上的 L1D 命中延迟为 9 个周期。这种情况被称为
loadspecreplay
。
我对指令采用了相同的方法ADD
,但这次我们需要观察RESOURCE_STALLS.ANY
而不是RESOURCE_STALLS.RS
(实际上不会捕获由于负载导致的 RS 停顿)。下图显示了cycles
每次RESOURCE_STALLS.ANY
迭代的变化。第一个尖峰表示目标 RS 占用率已超过该类型 uop 的可用 RS 条目。我们可以清楚地看到,对于这个loadspec
案例,load uops 正好有 11 个 RS 条目!当目标 RS 占用率超过 11 时,一个 RS 条目平均需要 3.75 个周期才能空闲到下一个加载 uop。这意味着微指令在完成时从 RS 中释放,而不是在它们被分派时。这也解释了 uop replay 的工作原理。峰值loadspecreplay
出现在 RS 占用 6 处。loadnonspec
发生在 RS 占用 9 处。正如您稍后将看到的,这 11 个条目并非专用于负载。负载使用的 11 个条目中的一些可能在ADD
uops 使用的 49 个条目中。
![在此处输入图像描述](https://i.stack.imgur.com/830cw.png)
我还为商店开发了两个测试用例:一个达到了存储缓冲区的限制,另一个达到了 RS 的限制。上图显示了前一种情况。请注意,商店需要 RS 中的两个条目,因此目标 RS 占用为奇数的情况与之前的偶数 RS 占用相同(变化为零)。该图显示,RS 中最多可以同时存在 44/2 = 22 个存储。(我用来制作 store graph 的代码有一个 bug,会导致实现的 RS 占用率大于实际值。修复后,结果显示 RS 中最多可以同时存在 20 个 store。)存储地址或存储数据uop 占用的条目可以在一个周期内释放。英特尔说 Haswell 的存储缓冲区有 42 个条目,但我无法同时使用所有这些条目。我'
跳跃序列没有造成任何停顿。我认为这可以解释如下:跳转微指令释放它在一个周期内占用的 RS 条目,并且分配器在分配跳转微指令时不会以突发方式运行。也就是说,每个周期都有一个 RS 条目空闲,分配器将只分配一个跳转 uop 而不会停止。因此,无论有多少跳转 uops,我们最终都不会停滞不前。这与添加微指令相反,其中突发分配器行为使其停止,直到所需数量的 RS 条目变为空闲(4 个条目),即使添加微指令的延迟也是一个周期。尽快分配跳转是有道理的,以便可以尽早检测到任何错误预测。因此,如果分配器看到一个跳转,并且 RS 中有足够的空间供它使用,但它的 4 uop 组中没有稍后的 uop,那么它仍然会分配它。否则,它可能不得不等待可能会显着延迟错误预测检测的许多周期。这可能非常昂贵
有没有一条指令可以同时占用RS的60个条目?是的,一个例子是BSWAP
。它的两个微指令需要两个 RS 条目,我可以清楚地看到RESOURCE_STALLS.RS
,它的微指令可以同时使用 RS 的所有 60 个条目(假设我的计算对于使用该指令的 RS 占用率如何增长是正确的)。这证明 RS 中确实有 60 个条目。但是对于它们的使用方式存在一些限制,我们仍然不太了解。