为什么英特尔公布的一些Haswell AVX延迟比Sandy Bridge慢3倍?

orm*_*orm 12 x86-64 intel simd cpu-architecture avx2

在英特尔内部网络应用程序中,从Sandy Bridge到Haswell的几项操作似乎已经恶化.例如,许多插入操作(如_mm256_insertf128_si256)显示如下的成本表:

   Performance
 Architecture   Latency   Throughput
 Haswell        3         -
 Ivy Bridge     1         - 
 Sandy Bridge   1         - 
Run Code Online (Sandbox Code Playgroud)

我发现这种差异令人费解.这有什么不同,因为有新的指令可以取代这些或补偿它的东西(哪些)?有谁知道Skylake是否进一步改变了这个模型?

Pet*_*des 13

TL:DR:根据Agner Fog的测试,所有车道交叉洗牌/插入/提取在Haswell/Skylake上都有3c延迟,但在SnB/IvB上有2c延迟.

这可能是执行单元中的1c +某种不可避免的旁路延迟,因为通过Broadwell的SnB中的实际执行单元具有标准化的1或3或5个周期的延迟,而不是2或4个周期.(SKL制作一些uops uc 4c,包括FMA/ADDPS/MULPS).

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


内在指南有时会出现虚假数据.我认为这是指示reg-reg形式的指令,除了负载内在函数的情况.即使它是正确的,内在指南也没有给出非常详细的性能图; 请参阅下文,了解Agner Fog的表格/指南.


(我对内在函数的一个烦恼是它很难使用PMOVZX/ PMOVSX作为负载,因为提供的唯一内在函数需要一个__m128i源,即使pmovzxbd只加载4B或8B(ymm).它和/或广播加载(_mm_set1_*使用AVX1/2)是压缩内存中常量的好方法.应该有内在函数采用a const char*(因为它允许别名)).


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

reg-mem形式有很大不同. vinsertf128 y,y,m,i的纬度/接收量为: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指令,只使用存储数据和存储地址端口,而不是shuffle单元.(Agner Fog的表格将其列为在SnB上使用一个p015 uop,在IvB上使用0.但即使在SnB上,在任何特定列中都没有标记,因此IDK哪一个是正确的.)

vextractf128在一个立即操作数上浪费一个字节是愚蠢的.我猜他们不知道他们将使用EVEX进行下一个向量长度扩展,并且正在准备从0到3的立即数.但是对于AVX1/2,你不应该使用immediate = 0来使用该指令.相反,只是movups mem, xmm或者movaps xmm,xmm.(我认为编译器知道这一点,当你使用index = 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吞吐量一次,是mul/fma的一半.)因此,在大多数FP算法中使用许多向量累加器是必不可少的,可以同时保持8或10个FMA在飞行中以满足吞吐量,如果有的话循环携带依赖.否则,如果循环体足够小,则无序执行将立即在飞行中进行多次迭代.

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


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

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

与往常一样,尽量使用最便宜的指令序列.例如,对于水平和或其他减少,总是首先减少到128b向量,因为跨车道改组是缓慢的.通常它只是vextractf128/ addps xmm,然后是通常的水平128b.

正如Mysticial所提到的,Haswell和后来的128b向量的SnB/IvB的通道内载矢量混洗吞吐量的一半.SnB/IvB可以pshufb/ pshufd每0.5c一个吞吐量,但每1c只有一个shufps(甚至128b版本); 对于在AVX1中具有ymm版本的其他shuffle也是如此(例如vpermilps,其显然仅存在于FP load-and-shuffle可以在一个指令中完成). Haswell完全摆脱了port1上的128b shuffle单元,而不是为AVX2扩展它.


re:skylake

Agner Fog的指南/ insn表于12月更新,包括Skylake.有关更多链接,另请参阅标记wiki.reg,reg形式具有与Haswell/Broadwell相同的性能.