是否存在可以使用libc中的函数fma的场景?

是否存在可以使用libc中的函数fma的场景?,c,floating-point,posix,libc,fma,C,Floating Point,Posix,Libc,Fma,我发现有一个奇数的浮点乘加函数--fma和fmaf。它说结果是这样的: (x * y) + z #fma(x,y,z) 该值是无限精度的,并对结果格式进行一次四舍五入 然而,我以前从未见过这样的三元运算。所以我想知道cumstom对这个函数的用法是什么。它通常被用作优化。大多数浮点单元都有一条fma指令,因此计算可以在一条指令中执行,而不是在两条或更多条指令中执行。因此,对于性能关键型浮点代码,它是一个有用的函数。融合乘法加法指令的重要方面是中间结果的(实际上)无限精

我发现有一个奇数的浮点乘加函数--
fma
fmaf
。它说结果是这样的:

 (x * y) + z             #fma(x,y,z)
该值是无限精度的,并对结果格式进行一次四舍五入


然而,我以前从未见过这样的三元运算。所以我想知道cumstom对这个函数的用法是什么。

它通常被用作优化。大多数浮点单元都有一条
fma
指令,因此计算可以在一条指令中执行,而不是在两条或更多条指令中执行。因此,对于性能关键型浮点代码,它是一个有用的函数。

融合乘法加法指令的重要方面是中间结果的(实际上)无限精度。这有助于提高性能,但不是因为两个操作编码在一条指令中,而是因为中间结果的几乎无限精度有时很重要,所以这有助于提高性能,而且用普通的乘法和加法来恢复非常昂贵,而这种精度水平正是程序员所追求的

示例:将
a*b
1.0
假设对于一个算法来说,确定两个双精度数字
a
b
的乘积相对于非零常数的位置至关重要(我们将使用
1.0
)。数字
a
b
都具有二进制数字的完整有效位。如果将
a*b
计算为
double
,结果可能是
1.0
,但这并不能告诉您实际的数学积是略低于1.0并精确向上舍入到1.0,还是略高于1.0并向下舍入。如果没有FMA,您的选择是:

  • a*b
    计算为四精度数字。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指令集(安腾)没有用于除法的指令。相反,正确的四舍五入除法可以通过涉及FMA的一系列指令(通常由编译器生成)获得。

    “MAC”在数字信号处理中经常使用:“一条指令而不是两条指令”是FMA中最不重要的方面。当FMA指令存在时,它所占用的周期数不必小于乘法和加法所占用的周期数。它至少和乘法一样昂贵,加上一个可以忽略不计的加法,可能是免费的,也可能不是免费的。我会写一个答案。@Zboson谢谢,我已经用另一个快速扫描后立即查看的引用替换了该引用。直到你的回答,我才真正理解FMA的优点。FMA的性能优势没有我预期的那么大。但这是因为我对额外的精度不感兴趣。在需要额外精度的情况下,例如在实现
    double-double
    时,我可以看出它非常有用。谢谢您可能会感兴趣。在第二个示例中,为什么不能简单地返回fma(a,b,0)?@Royce,因为融合乘法加法的最终结果是一个双精度浮点数。只有中间结果(实际上)具有无限精度(注:“实际上”,因为在实践中,由于已知此中间结果仅用于添加到double以返回double,因此处理器中不可能同时表示所有位)。如果您计算