在英特尔intrinsics webapp中,有几项行动似乎从桑迪桥变为哈斯威尔。例如,许多插入操作(如_mm256_insertf128_si256)显示如下的成本表:
Performance
Architecture Latency Throughput
Haswell 3 -
Ivy Bridge 1 -
Sandy Bridge 1 -
我发现这种差异令人费解。这有什么不同,因为有新的指令可以取代这些或补偿它的东西(哪些)?有谁知道Skylake是否进一步改变了这个模型?
答案 0 :(得分:13)
TL:DR :根据Agner Fog's testing,所有车道交叉shuffle /插入/提取在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 uc 4c,包括FMA / ADDPS / MULPS)。
(请注意,对于使用128b ALU执行AVX1的AMD CPU(例如Bulldozer / Piledriver / Steamroller),insert128 / extract128比VPERM2F128之类的shuffle快得多。)
内在指南有时会出现虚假数据。我认为它的意思是注册形式的指令,除了负载内在函数的情况。即使它是正确的,内在指南也没有给出非常详细的表现图;请参阅下文,了解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输出一次)同意英特尔的表格。因此,英特尔内在指南中的数字是错误的另一种情况。 找到合适的内在数据非常有用,但不是获得可靠性能数据的良好来源。它并没有告诉你有关执行端口或总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指令,只使用存储数据和存储地址端口,而不是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延迟,因此您需要更少的并行度来最大化吞吐量(并且不受延迟限制)。
vperm2f128
或AVX2 vpermps
更贵。通过内存将导致存储转发失败 - >插入的延迟很大(2个窄存储 - >宽负载),所以它显然很糟糕。在有用的情况下,请不要试图避免使用vinsertf128
。
与往常一样,尽量使用最便宜的指令序列。例如对于水平总和或其他减少,总是首先减少到128b向量,因为跨车道改组是缓慢的。通常它只是vextractf128
/ addps xmm
,而不是通常的horizontal 128b。
正如Mysticial所提到的,Haswell以及后来对于128b载体具有SnB / IvB的一半的通道内载体随机吞吐量。 SnB / IvB可以pshufb
/ pshufd
,每0.5c吞吐量一个,但{1}仅一个1c(即使是128b版本)也只有一个;对于在AVX1中具有ymm版本的其他shuffle也是如此(例如shufps
,这显然仅存在于FP load-and-shuffle可以在一个指令中完成)。 Haswell完全摆脱了port1上的128b shuffle单元,而不是为AVX2扩展它。
Agner Fog的指南/ insn表于12月更新,包括Skylake。有关更多链接,另请参阅x86标记wiki。 reg,reg形式与Haswell / Broadwell具有相同的性能。