Haswell 内核一次可以执行多少个 32 位整数操作?
How many 32-bit integer ops can a Haswell core perform at once?
在准备一些演示文稿时,我突然想到,我不知道 Haswell 内核一次可以执行的整数运算数量的理论限制是多少。
我曾经天真地假设 "Intel cores have HT, but that's probably parallelizing different kinds of work, so probably a core maxes out its parallelism with 256-bit AVX operations, so 8 integer ops which can be issued per clock cycle (and assuming nice pipelining, 8 completing as well)." - 所以 8 ops/cycle.
但后来我注意到 this article,这告诉我 Haswells(和 Sandy Bridges)有 3 个调度端口,可以为矢量单元供电。那么真正的24位数字是整数吗ops/cycle?
PS - 我意识到在实践中您可能需要实际从内存中读取所有这些数据,而它的带宽将是限制因素。或者是QPI太慢了。
理论最大值是 25 每个周期 32 位整数操作数:
- 端口 0:1 个标量运算或 1 个向量常量移位或按位布尔运算
- 端口 1:1 个标量运算或 1 个向量 add/sub/min/max 或 cmp 或按位布尔运算
- 端口 5:1 个标量运算或 1 个向量 add/sub/min/max 或 cmp 或按位布尔运算
- 端口 6:1 个标量运算(或 2 个,如果你用 64 位整数寄存器计算 SWAR)。
由于矢量运算可以执行 8 个 32 位运算,因此每个周期最多 25 个整数运算 - 端口 0、1 和 5 各 8 个,端口 1 个6. 或者 26 当 p6 上的 SIMD-within-a-register 可行时。 (参见 Paul Clayton 的评论。)
如果我们只是在谈论 "normal" 整数(add/multiply/bitwise/shift),那么如果我们想要的话,我们必须排除 32 位乘法(除了 2 的幂常数)每个时钟实现 25 次操作。真正的整数代码通常能够让 p0 忙于乘法、PSADBW
、移位和布尔运算,并且几乎总是有大量的改组 (p5)。我们人为地排除了严格来说不是每个时钟吞吐量 8 个 32 位操作的东西,例如乘法、可变计数移位以及整数和向量寄存器之间的数据移动。 (MOVD
/ MOVQ
).
向量在 p0 上乘以 运行,但是 VPMULLD
(8 个 32x32 -> 32b 乘法)每 2 个周期仅 运行s,因为它需要 2 个相关的微指令(10c潜伏)。有关说明 uop/port/throughput/latency 表,请参阅 http://agner.org/optimize/。
在前端维持此吞吐量将需要循环缓冲区,因此请保持循环小于 28 微指令(或 56 微指令,没有超线程)。这包括比较和分支循环开销,因此理论吞吐量实际上略低于 25。不过,在 p6 上融合了宏融合比较和分支 运行s,因此它仅取代每 7 个标量运算,使得可持续的吞吐量大约是每时钟 24.85 次操作。 (或 SWAR 为 25.85)。
在准备一些演示文稿时,我突然想到,我不知道 Haswell 内核一次可以执行的整数运算数量的理论限制是多少。
我曾经天真地假设 "Intel cores have HT, but that's probably parallelizing different kinds of work, so probably a core maxes out its parallelism with 256-bit AVX operations, so 8 integer ops which can be issued per clock cycle (and assuming nice pipelining, 8 completing as well)." - 所以 8 ops/cycle.
但后来我注意到 this article,这告诉我 Haswells(和 Sandy Bridges)有 3 个调度端口,可以为矢量单元供电。那么真正的24位数字是整数吗ops/cycle?
PS - 我意识到在实践中您可能需要实际从内存中读取所有这些数据,而它的带宽将是限制因素。或者是QPI太慢了。
理论最大值是 25 每个周期 32 位整数操作数:
- 端口 0:1 个标量运算或 1 个向量常量移位或按位布尔运算
- 端口 1:1 个标量运算或 1 个向量 add/sub/min/max 或 cmp 或按位布尔运算
- 端口 5:1 个标量运算或 1 个向量 add/sub/min/max 或 cmp 或按位布尔运算
- 端口 6:1 个标量运算(或 2 个,如果你用 64 位整数寄存器计算 SWAR)。
由于矢量运算可以执行 8 个 32 位运算,因此每个周期最多 25 个整数运算 - 端口 0、1 和 5 各 8 个,端口 1 个6. 或者 26 当 p6 上的 SIMD-within-a-register 可行时。 (参见 Paul Clayton 的评论。)
如果我们只是在谈论 "normal" 整数(add/multiply/bitwise/shift),那么如果我们想要的话,我们必须排除 32 位乘法(除了 2 的幂常数)每个时钟实现 25 次操作。真正的整数代码通常能够让 p0 忙于乘法、PSADBW
、移位和布尔运算,并且几乎总是有大量的改组 (p5)。我们人为地排除了严格来说不是每个时钟吞吐量 8 个 32 位操作的东西,例如乘法、可变计数移位以及整数和向量寄存器之间的数据移动。 (MOVD
/ MOVQ
).
向量在 p0 上乘以 运行,但是 VPMULLD
(8 个 32x32 -> 32b 乘法)每 2 个周期仅 运行s,因为它需要 2 个相关的微指令(10c潜伏)。有关说明 uop/port/throughput/latency 表,请参阅 http://agner.org/optimize/。
在前端维持此吞吐量将需要循环缓冲区,因此请保持循环小于 28 微指令(或 56 微指令,没有超线程)。这包括比较和分支循环开销,因此理论吞吐量实际上略低于 25。不过,在 p6 上融合了宏融合比较和分支 运行s,因此它仅取代每 7 个标量运算,使得可持续的吞吐量大约是每时钟 24.85 次操作。 (或 SWAR 为 25.85)。