我正在阅读有关堆栈溢出的一个非常有趣的问题:
评论之一说:
“在Haswell上,FP乘法吞吐量是FP add的两倍,这是毫无价值的。这是因为端口0和1都可以用于乘法,但是只有端口1可以用于加法。也就是说,您可以使用融合作弊-相加,因为两个端口都可以。”
为什么它们允许相加的次数是加法的两倍?
我正在阅读有关堆栈溢出的一个非常有趣的问题:
评论之一说:
“在Haswell上,FP乘法吞吐量是FP add的两倍,这是毫无价值的。这是因为端口0和1都可以用于乘法,但是只有端口1可以用于加法。也就是说,您可以使用融合作弊-相加,因为两个端口都可以。”
为什么它们允许相加的次数是加法的两倍?
Answers:
如果不是正文,这可能会回答问题的标题:
浮点加法要求在将两个尾数相加之前对齐它们(取决于两个指数之间的差异),这可能需要在加法器之前进行大量可变的移位。然后可能需要对尾数加法的结果重新进行归一化,潜在地需要另一个较大的移位量才能正确格式化浮点结果。因此,两个尾数桶形移位器可能需要更多的选通延迟,更大的导线延迟或额外的周期,这些周期超过了紧凑压缩的进位保存加法器树乘法器前端的延迟。
为OP添加的内容:请注意,将2毫米和2公里的长度相加不是两个单位中的4个。这是因为需要在添加之前将一个或另一个度量转换为相同的比例或单位表示。这种转换本质上需要乘以10的幂。在浮点加法过程中通常需要发生同样的事情,因为浮点数是可变缩放整数的形式(例如,存在与之相关的单位或缩放因子,指数)。每个数字)。因此,在添加原始尾数位之前,您可能需要将数字之一按2的幂进行缩放,以使它们都代表相同的单位或比例。这种缩放本质上是2的幂的简单乘法形式。 因此,浮点加法需要乘法(其功率为2时,可以使用可变的移位或桶形移位器来完成,这可能需要相对于晶体管尺寸而言较长的导线,在深亚微米光刻电路中相对较慢)。如果两个数字大部分都被抵消了(因为一个几乎等于另一个的负数),那么可能需要重新调整加法结果并适当格式化结果。因此,由于数字格式的性质(IEEE浮点数),如果还需要2个乘法(前和后)步骤围绕表示相等单位或小数位数的原始固定(有限)个尾数位的二进制加法,则加法可能会很慢。 )。
新增了#2:此外,许多基准测试对FMACS(乘法累加)的权重要大于裸基准。在融合的MAC中,加数的对齐(移位)通常可以与乘法并行进行,尾数加法通常可以在最终进位传播之前包含在CSA树中。
在FP乘法中,指数处理被证明是简单的加法(出于完全相同的原因,对数域中的乘法仅仅是加法)。我希望您遇到了对数。
现在考虑以对数形式将两个数字相加是多么困难...
浮点位于线性域和对数域之间的灰色区域,两者都有。每个FP编号包括一个尾数(线性)和一个(对数)指数。要确定尾数中每个位的含义,您首先必须查看指数(这只是一个比例因子)。
在FP加法中,指数处理通常需要对尾数进行两次桶形移位,其中每个桶形移位实际上是略微简化乘法的特殊情况。
(第一个移位将两个输入对齐为相同的2的幂,以便尾数位在每个操作数中具有相同的二进制权重。
十进制示例就足够了(尽管显然使用了二进制)...
第二个重新缩放输出...
因此,自相矛盾的是,FP加法涉及非常相似的两个乘法,这些乘法必须顺序执行,并且它们之间的尾数加法。因此,报道的性能并不令人惊讶。
TL:DR:因为英特尔认为SSE / AVX FP增加延迟比吞吐量更重要,所以他们选择不在Haswell / Broadwell的FMA单元上运行它。
Haswell(SIMD)FP与FMA(融合乘加)在相同的执行单元上运行FP乘法,其中有两个,因为某些FP密集型代码可以使用FMA最多执行每条指令2个FLOP。与FMA和mulps
早期CPU(Sandybridge / IvyBridge)相同的5个周期延迟。 Haswell想要2个FMA单元,并且让乘法运行没有任何缺点,因为它们的延迟时间与早期CPU中的专用乘法单元相同。
但是它将专用的SIMD FP添加单元从较早的CPU保留下来,仍然可以运行addps
/ addpd
具有3个周期的延迟。 我已经读到,可能的原因可能是大量FP添加的代码往往会成为其延迟而不是吞吐量的瓶颈。对于只有一个(向量)累加器的数组的幼稚求和,这确实是正确的,就像您经常从GCC自动向量化中获得的那样。但是我不知道英特尔是否公开证实了他们的理由。
Broadwell微架构是相同的(但加速mulps
/mulpd
到3C延迟,同时FMA留在5C)。也许他们能够先对FMA单元进行捷径操作,然后再对进行虚拟加法,然后得出乘积结果0.0
,或者可能是完全不同的东西,这太简单了。 BDW主要是HSW的缩水,大多数变化很小。
在Skylake中,除div / sqrt和按位布尔值(例如,用于绝对值或取反)外,所有FP(包括加法器)都以4个周期的延迟和0.5c的吞吐量在FMA单元上运行。英特尔显然认为,为延迟较低的FP添加额外的硅片是不值得的,或者addps
吞吐量不平衡是有问题的。而且标准化的延迟使得避免回写冲突(当在同一周期中准备好2个结果时)更容易在uop调度中避免。即简化了计划和/或完成端口。
因此,是的,英特尔确实在下一个主要的微体系结构修订版(Skylake)中对其进行了更改。 将FMA延迟减少1个周期,从而使专用SIMD FP添加单元的优势小得多,适用于受延迟限制的情况。
Skylake还显示出英特尔为AVX512做好准备的迹象,如果将单独的SIMD-FP加法器扩展到512位宽将占用更多的裸片面积。据报道,Skylake-X(带有AVX512)具有与常规Skylake客户端几乎相同的核心,除了更大的L2缓存和(在某些型号中)额外的512位FMA单元“固定”到端口5上。
在运行512位uops时,SKX将关闭端口1 SIMD ALU,但它需要一种随时执行的方法vaddps xmm/ymm/zmm
。这使得在端口1上具有专用的FP ADD单元成为一个问题,并且是改变现有代码性能的另一个动机。
有趣的事实:除了Cascade Lake添加了一些新的AVX512指令外,Skylake,KabyLake,Coffee Lake甚至Cascade Lake的所有东西在微体系结构上都与Skylake相同。IPC保持不变。不过,较新的CPU具有更好的iGPU。冰湖(Sunny Cove微体系结构)是我们几年来第一次看到实际的新微体系结构(除了从未广泛发行的Cannon Lake)。
基于FMUL单元与FADD单元的复杂度的争论很有趣,但在这种情况下并不重要。 FMA单元包括所有必需的移位硬件,作为FMA 1的一部分进行FP加法。
注意:我的意思不是x87 fmul
指令,我的意思是SSE / AVX SIMD /标量FP乘法ALU,支持32位单精度/ float
和64位double
精度(53位有效数,也就是尾数)。例如mulps
或的指令mulsd
。fmul
在端口0的Haswell上,实际的80位x87 吞吐量仍然仅为1 /时钟。
现代的CPU拥有足够多的晶体管,在值得时以及在不引起物理距离传播延迟问题时,都会引发问题。特别是对于仅在某些时间处于活动状态的执行单元。参见https://en.wikipedia.org/wiki/Dark_silicon和此2011年会议论文:《黑硅与多核扩展的终结》。。这使CPU可以具有大量的FPU吞吐量和大量的整数吞吐量,但不能同时具有两者(因为这些不同的执行单元位于同一调度端口上,因此它们彼此竞争)。在许多没有限制内存带宽的经过精心调优的代码中,限制因素不是后端执行单元,而是前端指令吞吐量。(宽核非常昂贵)。另请参见http://www.lighterra.com/papers/modernmicroprocessors/。
在HSW之前,像Nehalem和Sandybridge这样的Intel CPU在端口0上增加了SIMD FP,在端口1上增加了SIMD FP。因此,有独立的执行单元,并且吞吐量保持平衡。(https://stackoverflow.com/questions/8389648/how-do-i-achieve-the-theoretical-maximum-of-4-flops-per-cycle
Haswell在英特尔CPU中引入了FMA支持(在AMD在推土机中引入FMA4的几年后,英特尔通过等到很晚才公开宣布他们将要实施3-operand FMA而非非4-operand FMA来伪造它们)。 -破坏性目的地FMA4)。有趣的事实:AMD堆驱动器仍然是第一个具有FMA3的x86 CPU,大约在2013年6月的Haswell之前
这需要对内部进行一些重大修改,以支持3个输入的单个uop。但是无论如何,英特尔全力以赴,并利用不断缩小的晶体管来装入两个256位SIMD FMA单元,使Haswell(及其后继产品)成为FP数学的野兽。
英特尔可能已经想到的性能目标是BLAS密集的matmul和矢量点积。这两项都可以主要使用FMA,不需要只是补充。
正如我之前提到的,某些主要执行或仅执行FP添加的工作负载在添加延迟(而非吞吐量)上成为瓶颈。
脚注1:1.0
FMA 乘以,可以从字面上进行加法运算,但是延迟比addps
指令差。这对于诸如对L1d缓存中的阵列进行热计算之类的工作负载很有用,其中FP增加吞吐量比延迟更重要。当然,这仅在您使用多个向量累加器隐藏时延并且在FP执行单元中保持10个FMA操作进行中(5c时延/0.5c吞吐量= 10个操作时延*带宽乘积)时才有帮助。 将FMA用于矢量点积时,您也需要这样做。
请参阅David Kanter关于Sandybridge微体系结构的文章,其中包含框图,其中列出了哪个EU位于NHM,SnB和AMD Bulldozer系列的哪个端口上。(另请参见Agner Fog的指令表和asm优化微体系结构指南,以及https://uops.info/,该版本还对几代英特尔微体系结构上几乎每条指令的uops,端口和延迟/吞吐量进行了实验测试。)
也相关:https : //stackoverflow.com/questions/8389648/how-do-i-achieve-the-theoretical-maximum-of-4-flops-per-cycle
[cpu-architecture]
,[performance]
,[x86-64]
,[assembly]
,和[sse]
。我用C ++代码编写了一个答案,以比手写汇编更快地测试Collatz猜想-为什么?很多人认为很好。这也是关于OoO流水线执行的。
我将看一下这一部分:
“为什么它们允许使用 ... ...
TL; DR-因为他们是这样设计的。这是一项管理决定。当然,答案是尾数和移位器,但这是管理决策中要考虑的事情。
他们为什么这样设计?答案是制定规格是为了达到某些目标。这些目标包括性能和成本。性能并非针对运营,而是针对像《孤岛危机》中的FLOPS或FPS之类的基准。
这些基准测试将具有多种功能,其中一些功能可以同时处理。
如果设计人员认为拥有小部件A的两个功能比小部件B的两个功能要快得多,那么他们将使用小部件A。实现A的两个和B的两个将花费更多。
回顾当超标量和超级流水线(在多核之前)在商业芯片上首次普及时,它们就可以提高性能。奔腾有两个管道,没有向量联合。Haswell具有更多管道,向量单位,更深的管道,专用功能等。为什么没有全部两个?因为他们是这样设计的。
英特尔的这张图可能会有所帮助:
看来他们已经给每个单元一个FMA(融合乘加),以及一个乘法和一个加法器。他们可能会或可能不会在下面共享硬件。
如果没有内部设计依据,为什么很难回答这个问题,但是紫色框中的文字为我们提供了“双峰FLOP”的提示:处理器将针对一组源自实际用例的基准。FMA在这些方面非常受欢迎,因为它是矩阵乘法的基本单位。裸添加不那么受欢迎。
正如已经指出的,您可以通过FMA指令使用两个端口进行加法运算,其中乘法参数为1,计算(A x 1)+B。这将比裸加法稍慢。
让我们看一下耗时的步骤:
加法:对齐指数(可能是大量的移位操作)。一个53位加法器。归一化(最多53位)。
乘法:一个庞大的加法器网络,可将53 x 53的一位乘积减少为两个106位数的总和。一个106位加法器。正常化。我要说的是,将位乘积减为两个数可以像最终加法器一样快。
如果您可以使乘法时间可变,那么您将具有以下优势:标准化大部分时间只会移位一位,并且您可以非常快速地检测到其他情况(非正规化输入或指数总和太小)。
另外,需要规范化的步骤非常普遍(将大小不相等的数字相加,将接近的数字相减)。因此,对于乘法而言,您可以负担得起一条快速道路,而对缓慢道路则承受巨大打击;另外,您不能。
PS。阅读注释:添加非规范化数字不会造成任何损失,这是有道理的:这仅意味着在为对齐指数而移位的位中,许多为零。非规范化的结果意味着您将停止移动以删除前导零,如果这样做会使指数太小。
-ffast-math
集合FTZ / DAZ(将反常态为0的反常态)进行编译而不是使用FP辅助的原因。