为什么英特尔宣传的某些 Haswell AVX 延迟比 Sandy Bridge 慢 3 倍?

Why are some Haswell AVX latencies advertised by Intel as 3x slower than Sandy Bridge?

在 Intel intrinsics webapp 中,从 Sandy Bridge 到 Haswell 的几个操作似乎已经恶化。例如,许多像 _mm256_insertf128_si256 这样的插入操作显示成本 table,如下所示:

   Performance
 Architecture   Latency   Throughput
 Haswell        3         -
 Ivy Bridge     1         - 
 Sandy Bridge   1         - 

我发现这种差异令人费解。这种差异是因为有新的指令取代了这些指令还是对其进行了补偿(哪些指令)?有谁知道Skylake是否进一步改变了这个模型?

TL:DR:所有跨车道洗牌/插入/提取在 Haswell/Skylake 上有 3c 延迟,但在 SnB/IvB 上有 2c 延迟,根据Agner Fog's testing.

这可能是执行单元中的 1c + 某种不可避免的旁路延迟,因为实际执行单元在 中。 (SKL制作一些uops uops 4c,包括FMA/ADDPS/MULPS)。

(请注意,在使用 128b ALU 执行 AVX1 的 AMD CPU 上(例如 Bulldozer/Piledriver/Steamroller),insert128/extract128 比像 VPERM2F128 这样的随机播放要快得多。)


内部函数指南有时会有虚假数据。我假设它是针对 reg-reg 形式的指令,除了加载内在函数的情况。即使它是正确的,内在函数指南也没有给出非常详细的性能描述;参见下文对 Agner Fog 的 tables/guides.

的讨论

(我对内在函数的不满之一是很难使用 PMOVZX / PMOVSX 作为负载,因为提供的唯一内在函数采用 __m128i 源,即使pmovzxbd 仅加载 4B 或 8B (ymm)。它 and/or 广播加载(_mm_set1_* 和 AVX1/2)是压缩内存中常量的好方法。应该有内在函数取一个 const char*(因为它允许给任何东西起别名))。


在这种情况下,Agner Fog's measurements 显示 SnB/IvB reg-reg vinsertf128/vextractf128 有 2c 延迟,而他对 Haswell 的测量(3c 延迟,1每 1c tput) 同意英特尔的 table。所以这是另一种情况,英特尔的内在函数指南中的数字是错误的。 它非常适合寻找正确的内在函数,但不是可靠性能数据的良好来源。它不会告诉您有关执行端口或总 uops 的任何信息,并且经常省略甚至吞吐量数字。 无论如何,延迟通常不是向量整数代码的限制因素。这可能是英特尔让 Haswell 的延迟增加的原因。

reg-mem 形式明显不同。 vinsertf128 y,y,m,i 有 lat/recip-tput 个:IvB:4/1,Haswell/BDW:4/2,SKL:5/0.5。它始终是一个 2-uop 指令(融合域),使用一个 ALU uop。 IDK 为什么吞吐量如此不同。也许 Agner 的测试略有不同?

有趣的是,vextractf128 mem,reg, i 没有使用任何 ALU uops。这是一个 2-fused-domain-uop 指令,只使用存储数据和存储地址端口,而不是洗牌单元。 (Agner Fog 的 table 将其列为在 SnB 上使用一个 p015 uop,在 IvB 上使用 0。但即使在 SnB 上,在任何特定列中也没有标记,因此 IDK 哪个是正确的。)

vextractf128 在立即操作数上浪费了一个字节,这很愚蠢。我猜他们不知道他们将使用 EVEX 进行下一个矢量长度扩展,并且正在准备立即从 0..3 开始。但是对于 AVX1/2,你永远不应该使用立即数 = 0 的指令。相反,只是 movups mem, xmmmovaps xmm,xmm。 (我认为编译器知道这一点,并且在您使用索引 = 0 的内在函数时这样做,就像它们对 _mm_extract_epi32 等 (movd) 所做的那样。)


延迟通常是 FP 代码中的一个因素,而 Skylake 是 FP ALU 的怪物。他们设法将 FMA 的延迟降低到 4 个周期,因此 mulps/addps/fma...ps 都是 4c 延迟,每 0.5c 吞吐量一个。 (Broadwell 是 mulps/addps = 3c 延迟,fma = 5c 延迟。Haswell 是 addps=3c 延迟,mul/fma=5c)。 Skylake 放弃了单独的加法单元,所以 addps 实际上从 3c 恶化到 4c,但吞吐量增加了一倍。 (Haswell/BDW 仅添加 ps 每 1c 吞吐量一个,是 mul/fma 的一半。)因此 在大多数 FP 算法中使用许多向量累加器是必不可少的 用于同时保持 8 或 10 个 FMA 在飞行中以使吞吐量饱和,如果存在循环携带依赖性。否则,如果循环体足够小,乱序执行将同时进行多次迭代。

整数通道内 ops 通常只有 1c 延迟,因此您需要更少的并行度来最大化吞吐量(并且不受延迟限制)。


None 获取数据的其他选项into/out-of ymm 的高半部分更好

vperm2f128 或 AVX2 vpermps 更贵。遍历内存会导致存储转发失败 -> 插入的大延迟(2 个窄存储 -> 宽负载),所以这显然很糟糕。不要试图避免 vinsertf128 在有用的情况下。

一如既往,尽可能使用最便宜的指令序列。例如对于水平和或其他减少,总是首先减少到 128b 向量,因为跨车道洗牌很慢。通常只是 vextractf128 / addps xmm,然后是通常的 horizontal 128b.

正如 Mysticial 所暗示的,对于 128b 向量,Haswell 和后来的向量洗牌吞吐量只有 SnB/IvB 的一半。 SnB/IvB 可以 pshufb / pshufd 每 0.5c 吞吐量一个,但对于 shufps (即使是 128b 版本)每 1c 只能有一个;对于在 AVX1 中具有 ymm 版本的其他洗牌也是如此(例如 vpermilps,它显然只存在,因此 FP 加载和洗牌可以在一条指令中完成)。 Haswell 完全摆脱了端口 1 上的 128b 洗牌单元,而不是为 AVX2 加宽它。


回复:天空湖

Agner Fog 的 guides/insn table 已于 12 月更新以包含 Skylake。另请参阅 标签 wiki 以获取更多链接。 reg,reg 形式与 Haswell/Broadwell.

具有相同的性能