【问题标题】:Why are some Haswell AVX latencies advertised by Intel as 3x slower than Sandy Bridge?为什么英特尔宣传的某些 Haswell AVX 延迟比 Sandy Bridge 慢 3 倍?
【发布时间】:2016-06-21 22:19:58
【问题描述】:

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

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

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

【问题讨论】:

  • 向量置换执行单元不如 Sandy Bridge 中的强大。还有其他事情也受到了打击(pmulldroundss/sd/ps/pd)。这只是构建处理器的常规成本效益分析的一部分。在未来的设计中可能会牺牲“不太重要”的指令。也就是说,向量置换非常重要,但至少它们将吞吐量保持在 1/cycle。
  • Haswell 的重点是功耗。尽管功能缩小了,但它确实,真的做得很好。你不能两者兼得。

标签: x86-64 intel simd cpu-architecture avx2


【解决方案1】:

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

这可能是执行单元中的 1c + 某种不可避免的旁路延迟,因为SnB through Broadwell have standardized latencies of 1, 3, or 5 cycles, never 2 or 4 cycles 中的实际执行单元。 (SKL 生产一些 uops uops 4c,包括 FMA/ADDPS/MULPS)。

(请注意,在使用 128b ALU(例如 Bulldozer/Piledriver/Steamroller)执行 AVX1 的 AMD CPU 上,insert128/extract128 比 VPERM2F128 之类的 shuffle 快得多。)


内在函数指南有时包含虚假数据。我认为它是用于 reg-reg 形式的指令,除了加载内在函数的情况。即使它是正确的,内在函数指南也没有给出非常详细的性能图片。有关 Agner Fog 的表格/指南的讨论,请参见下文。


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


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

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

有趣的是,vextractf128 mem,reg, i 不使用任何 ALU 微指令。这是一个 2-fused-domain-uop 指令,仅使用存储数据和存储地址端口,而不是随机播放单元。 (Agner Fog 的表将其列为在 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 每 1c 吞吐量只有一个 addps,是 mul/fma 的一半。)因此在大多数 FP 算法中使用许多矢量累加器对于同时保持 8 或 10 个 FMA 在飞行中至关重要如果存在循环携带的依赖关系,则使吞吐量饱和。否则,如果循环体足够小,乱序执行将同时进行多次迭代。

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


将数据输入/输出 ymm 高半部分的其他选项都没有更好

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

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

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


回复:天空湖

Agner Fog 的指南/insn 表已于 12 月更新,包括 Skylake。另请参阅 标签 wiki 以获取更多链接。 reg,reg 形式的性能与 Haswell/Broadwell 相同。

【讨论】:

  • 我也很好奇他们移除了端口 1 上的随机播放单元这一事实,以及这与观察有何关系。我对该主题的有限了解表明,删除执行单元会影响吞吐量,而不是延迟。您是否提到它是延迟增加的可能原因?
  • 我已接受您的回答,并喜欢阅读它并查看您推荐的一些链接。我认为其他一些寻求更快阅读速度的人可能会在一开始就从 TLDR 中受益。我认为关于替代方案的主要收获是,大多数(全部?)将数据移入/移出 ymm 寄存器的高半部分的东西在延迟方面是昂贵的,尽管在吞吐量方面不一定。
  • @orm:丢弃 port1 shuffle 单元对延迟没有影响,只会影响吞吐量。 (除非在资源冲突情况下,insn 无法在其输入准备好后立即启动,因为端口正忙于运行也需要 p5 的较旧的 insn。)感谢关于如何总结的建议;对我来说,在 tl;dr. 中放入什么完全不明显。
猜你喜欢
  • 2021-01-14
  • 2016-11-25
  • 1970-01-01
  • 2023-03-06
  • 2015-07-18
  • 2020-05-27
  • 2016-02-17
  • 1970-01-01
相关资源
最近更新 更多