这取决于它们有多长,以及每个周期可以独立运行多少个微指令。
这还取决于硬件的宽度。例如
- 具有两个 ALU 执行单元和每个时钟 3 个融合域 uop 吞吐量的 PIII
- Haswell 具有四个 ALU 执行单元(其中只有三个可以处理向量),以及每个时钟 4 个融合域 uop 吞吐量。
我认为“最关键的指令”是指构成关键路径大部分长度的指令。如果循环携带的依赖链由具有不同延迟的多条指令组成,则它是某种平均值。(比如几何平均值?)
一个很好的例子是 FP add(例如对数组求和):
在 Sandybridge 上,它具有每时钟一个吞吐量,但延迟为 3c,因此单条相关addps
指令链以每 3c 一个 uop 的速度运行,仅维持最大 FP 乘法吞吐量的 1/3。(并让其他两个执行端口完全无人占用。)
addps
三个并行的 dep 链可以使 port1 的指令饱和。所以如果你使用三个累加器,你可以保持三个加法。如果你还在飞行中保持 5 个 FP 乘法,你也可以使 port0 饱和。循环开销可以在端口 5 上运行(希望不会从 p01 窃取循环)。负载微控制器可以与添加物进行微融合,因此它们不会占用融合域带宽。但是您可以使用单独的指令来执行一些负载,movaps
并且仍然不会使每时钟 4 个融合域 uop 吞吐量饱和,但是前端的瓶颈可能会限制您降低吞吐量。
Haswell 对于 FP add 仍然只有一个时钟吞吐量,但对于 FP mul 和 FMA 每个时钟两个吞吐量。
因此,如果您使用 FMA(乘数为 1.0)对数组求和,则需要 10 个向量累加器(10 个 dep 链)来保持 10 个 FMA 处于飞行状态,使 p01 饱和。p5 和 p6 未使用,但您也可以使用微熔负载使负载端口饱和。
Skylake 将 FMA 的延迟降低了 1 个周期,降至 4 个,并丢弃了 FP 添加单元。(因此 FP 添加是在 FMA 单元中完成的,这使 的吞吐量增加了一倍[v]addps
,但延迟增加了 1c)。
所以在 SKL 上,你只需要 8 个向量累加器(8 个 dep 链)就可以使 p01 饱和。但是拥有更多的 dep 链并没有什么坏处,只要你没有用完寄存器。因此,在 Haswell 上理想的代码,使用 10 个累加器,在 SKL 上应该仍然是理想的。不过,您可以通过使用1.0 的常量向量addps
代替(或其他)来节省一些功率。fma213ps
有关更多详细信息,请参阅 Agner 的吞吐量/延迟/端口号说明表和他的 microarch PDF。我没有检查端口号或延迟号,但我经常输入这个例子,我很确定它是正确的:P。
另请参阅x86标签 wiki中的其他链接。