有没有可以使用libc中的函数fma的情况?

Hon*_*hen 5 c floating-point posix libc fma

我遇到这个页面,发现有一个奇怪的浮动乘法加法 函数 - fmafmaf.它说结果是这样的:

 (x * y) + z             #fma(x,y,z)
Run Code Online (Sandbox Code Playgroud)

并且值是无限精度并且对结果格式进行一次舍入.

然而,AFAICT我以前从未见过这样的三元手术.所以我想知道这个功能的cumstom用法是什么.

Pas*_*uoq 16

融合乘加指令的重要方面是中间结果的(虚拟)无限精度.这有助于提高性能,但不是因为两个操作在单个指令中编码 - 它有助于提高性能,因为中间结果的几乎无限精度有时很重要,并且通过普通乘法和加法来恢复非常昂贵精确度正是程序员追求的目标.

实施例:比较a * b1.0

假设一个算法确定两个双精度数的乘积在哪里a并且b相对于非零常数(我们将使用1.0)是至关重要的.数字ab两者都有二进制数字的完整有效数字.如果你计算a*b为a double,结果可能是1.0,但这并不能告诉你实际的数学乘积是否略低于1.0并且向上舍入到恰好为1.0,或略高于1.0并向下舍入.没有FMA,您的选择是:

  1. 计算a*b为四精度数.四精度没有在硬件中实现,但有软件仿真库.在四精度中,产品的数学结果是完全可表示的,然后您可以将其与1.0进行比较.

  2. 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装置的数学乘积ab大于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 */
Run Code Online (Sandbox Code Playgroud)

更多例子

FMA用于其精度的示例,而不仅仅是作为乘法和加法的指令,是平方根和除法的计算.根据IEEE 754标准,这些操作必须正确舍入(到数学结果的最近浮点数).当硬件FMA指令可用时,可以有效地实现这两个操作.这个方面通常由编译链隐藏,但IA-64指令集(Itanium)没有划分指令.相反,可以通过涉及FMA的一系列指令(通常由编译器生成)来获得正确舍入的除法.