我遇到此页面,发现有一个奇数 floing乘乘添加函数- fma
和 fmaf
。它说结果是:
(x * y) + z #fma(x,y,z)
和该值为无限的精度,然后将其圆形为结果格式。
但是,我以前从未见过这样的三元操作。因此,我想知道此功能的混乱用法是什么。
融合 - 添加指令的重要方面是中间结果的(实际上)无限精度。这有助于表现,但没有很多,因为两个操作是在单个指令中编码的 - 它有助于表现,因为中间结果的几乎无限精度有时很重要,非常与普通恢复的昂贵当该精确度是程序员之后的乘法和添加。
示例:将a * b
与1.0
进行比较假设对算法至关重要,以确定两个双重精度 a
和 b
的乘积相对于非零常数(我们将使用1.0
)。a
和b
的数字都具有完整的二进制数字。如果将a*b
计算为double
,则结果可能为1.0
,但这并不能告诉您实际的数学产品是否略低于1.0,恰好达到1.0,还是略高于1.0,或者略高于1.0并舍入。没有FMA,您的选择是:
将
a*b
计算为Quad-Precision编号。硬件中未实现Quad Precision,但有软件仿真库。在Quad-Precision中,产品的数学结果是完全表示的,然后您可以将其与1.0进行比较。以圆形模式和圆向模式以双重精度计算
a*b
。如果两个结果均为1.0,则表示a*b
正好是1.0。如果RU(A * B)大于1.0,则表示数学产品高于1.0,并且RD(A * B)低于1.0,则意味着数学产品低于1.0。在大多数处理器上,这种方法意味着更改圆形模式三次,每个更改都很昂贵(涉及冲洗CPU管道)。
使用FMA指令,可以计算fma(a, b, -1.0)
并将结果比较为0.0。由于浮点数数量较高,因此中间产品在计算中没有四舍五入,因此我们可以确定fma(a, b, -1.0) > 0
是指a
和b
的数学产品大于1,等等。
示例:Veltkamp/Dekker乘法
双双格式是数字的有效表示,作为两个双精度浮点数的总和。它几乎和四元素一样精确,但利用了现有的双精度硬件。
考虑以下功能Mul12(a, b)
,该功能采用两个双精度数字a
和b
,并将其产品计算为双双数字。由于Veltkamp和Dekker,一种算法仅通过双重添加和乘法(参考)来计算此功能。它需要6个乘法(一个是算法主体中每个Split()
加四个的一部分),还有很多添加。
如果有FMA指令可用,则可以将Mul12
实现为两个操作,一个乘法和一个FMA。
high = a * b; /* double-precision approximation of the real product */
low = fma(a, b, -high); /* remainder of the real product */
/* now the real product of a and b is available as the sum of high and low */
更多示例
示例FMA用于其精确度,而不仅是作为乘法和添加的指令,还包括平方根和除法的计算。这些操作必须根据IEEE 754标准正确圆形(数学结果的最接近的浮点数)。当可以使用硬件FMA指令时,可以有效地实施这两个操作。该方面通常被编译链隐藏,但是IA-64指令集(ITANIUM)没有分裂的说明。取而代之的是,可以通过涉及FMA的一系列指令(通常由编译器生成)获得正确的圆形划分。
通常用作优化。大多数浮点单元具有fma
指令,因此可以在单个指令中而不是两个或更多指令中执行计算。因此,对于关键绩效浮点代码,它具有有用的功能。