fma(a,b,c)
相当于a*b+c
除了它不舍入中间结果。
你能给我一些避免这种舍入的算法的例子吗?
这并不明显,因为我们避免的乘法后舍入往往比我们不避免的加法后舍入问题更少。
fma(a,b,c)
相当于a*b+c
除了它不舍入中间结果。
你能给我一些避免这种舍入的算法的例子吗?
这并不明显,因为我们避免的乘法后舍入往往比我们不避免的加法后舍入问题更少。
举一个重要的例子;更一般地说,FMA 允许库编写者通过正确的舍入有效地实现许多其他浮点运算。
例如,具有 FMA 的平台可以使用它来实现正确的舍入除法和平方根(PPC 和 Itanium 采用这种方法),这使得 FPU 基本上是一个单一用途的 FMA 机器。如果您好奇的话,Peter Tang 和 John Harrison(英特尔)以及 Peter Markstein(惠普)有一些解释这种用途的论文。
taw给出的示例比仅仅在跟踪误差范围更广泛有用。它允许您将两个浮点数的乘积表示为两个浮点数的总和,而不会出现任何舍入误差;这对于实现正确舍入的浮点库函数非常有用。让-米歇尔·穆勒 (Jean-Michel Muller) 的书或相关论文crlibm
将是了解更多有关这些用途的良好起点。
FMA 对于某些类型的论点在数学库风格例程中的论点减少方面也广泛有用;当一个人在做参数缩减时,计算的目标通常是一个形式的项(x - a*b)
,其中(a*b)
非常接近于 x 本身;(a*b)
特别是,如果在没有 FMA 的情况下计算结果,则结果通常在项中的舍入误差的数量级上。我相信穆勒在他的书中也写过一些关于这方面的内容。
到目前为止,我发现的唯一一件事是“无错误的转换”。对于任何浮点数,来自 、 和 的错误a+b
也是a-b
浮点数a*b
(在四舍五入到最接近的模式下,假设没有上溢/下溢等)。
加法(显然是减法)误差很容易计算;如果abs(a) >= abs(b)
,则错误正好是b-((a+b)-a)
(2 次失败,如果我们不知道哪个更大,则为 4-5)。乘法误差计算fma
起来很简单——很简单fma(a,b,-a*b)
。没有fma
它是 16 次失败的相当讨厌的代码。正确舍入fma
的完全通用模拟甚至比这更慢。
每次实际计算的 flop 额外 16 次错误跟踪是一个巨大的过度杀伤力,但只有 1-5 个管道友好的 flop 是相当合理的,并且对于许多基于 50%-200% 的错误跟踪和补偿开销的算法会导致误差小到好像所有计算都以两倍的位数完成,在许多情况下避免了病态。
有趣的fma
是,在这些算法中从未使用它来计算结果,只是为了查找错误,因为查找错误的fma
速度很慢,因为查找乘法错误时没有fma
.
搜索的相关关键字将是“补偿霍纳方案”和“补偿点积”,霍纳方案受益更多。
FMA 的主要好处是速度可以提高一倍。FPU 可以在同一个周期内发出这两个操作,而不是先用 1 个周期进行乘法运算,然后再用 1 个周期进行加法运算。显然,大多数算法将受益于更快的操作。
一些例子:矢量点积。傅里叶变换。数字信号处理。多项式。各种各样的事情。
这是一个优化和硬件开发的问题,而不是其他任何问题。乘积之和是数值方法中非常常见的要求,这种方式可以让您向编译器明确指示如何快速完成某件事,并且可能更精确。除非我弄错了,否则编译器可以自由地将 a=b*c+d 替换为 FMA 指令,但也可以不这样做。(除非标准要求四舍五入,但现实世界的编译器通常会以小的方式违反标准)。
我的头顶 - 矩阵乘法,牛顿规则,多项式评估,数值方法
在 FMA 的Wikipedia 条目中已经很好地解释了与产品积累有关的算法从使用 FMA 中受益最多:
A fast FMA can speed up and improve the accuracy of
many computations that involve the accumulation of products:
* Dot product
* Matrix multiplication
* Polynomial evaluation (e.g., with Horner's rule)
* Newton's method for evaluating functions.