在 FMA(3) 的 BSD 库函数手册中,它说“这些函数计算 x * y + z”。
那么 FMA 和执行 x * y + z 的简单代码有什么区别?以及为什么 FMA 在大多数情况下都有更好的性能?
在 FMA(3) 的 BSD 库函数手册中,它说“这些函数计算 x * y + z”。
那么 FMA 和执行 x * y + z 的简单代码有什么区别?以及为什么 FMA 在大多数情况下都有更好的性能?
[我没有足够的业力发表评论;添加另一个答案似乎是唯一的可能性。]
埃里克的回答很好地涵盖了一切,但需要注意的是:有时使用fma(a, b, c)
代替a*b+c
可能会导致难以诊断的问题。
考虑
x = sqrt(a*a - b*b);
如果换成
x = sqrt(fma(a, a, -b*b));
有a
和的值,函数b
的参数sqrt
可能为负,即使|a|>=|b|
. 特别是,如果|a|=|b|
和 无限精确乘积a*a
小于 的四舍五入值,则会发生这种情况a*a
。这是因为计算中的舍入误差a*a
由 给出fma(a, a, -a*a)
。
a*b+c
产生一个结果,就好像计算是:
a
乘积b
。c
。fma(a, b, c)
产生一个结果,就好像计算是:
a
乘积b
。c
。所以它跳过了将中间产品四舍五入为浮点格式的步骤。
在具有 FMA 指令的处理器上,融合乘加可能更快,因为它是一条浮点指令而不是两条,并且硬件工程师通常可以设计处理器以高效地执行此操作。在没有 FMA 指令的处理器上,融合乘加可能会更慢,因为软件必须使用额外的指令来维护获得所需结果所需的信息。