我遇到了此页,发现有一个奇怪的浮动乘积加法函数--fma和fmaf。它说结果是这样的:
(x * y) + z #fma(x,y,z)该值对结果格式具有无限精度和一次圆的特点。
然而,AFAICT,我从来没有见过这样的三元操作。所以我想知道这个功能的习惯用法是什么。
发布于 2013-08-14 18:44:22
融合乘法加指令的重要方面是中间结果的(实质上)无限精度。这有助于提高性能,但这并不是因为两个操作是在一条指令中编码的--这有助于性能,因为中间结果的几乎无限精度有时很重要,当程序员真正追求这种精度时,用普通乘法和加法恢复非常昂贵。
示例:将a * b与1.0进行比较
假设对于确定两个双精度数字a和b的乘积相对于一个非零常数(我们将使用1.0)的算法是至关重要的。数字a和b都有完全有意义的二进制数字。如果将a*b计算为一个double,结果可能是1.0,但这并不能说明实际的数学积是否略低于1.0并被舍入到精确的1.0,或略高于1.0和四舍五入。如果没有FMA,你的选择是:
a*b计算为四精度数字.四精度不是在硬件上实现的,但是有软件仿真库.在四精度,该产品的数学结果是完全可表示的,然后你可以将它与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的一系列指令(通常由编译器生成)获得正确的四舍五入。
发布于 2012-11-08 15:27:29
它通常被用作优化。大多数浮点单元都有一个fma指令,所以计算可以在一个指令中执行,而不是两个或多个指令。因此,对于性能关键的浮点代码,它是一个有用的函数。
https://stackoverflow.com/questions/13292013
复制相似问题