c - 有没有可以使用libc中的fma函数的场景?

标签 c floating-point posix libc fma

我遇到了this page并发现有一个奇数浮点乘加函数——fmafmaf .它说结果是这样的:

 (x * y) + z             #fma(x,y,z)

并且该值是无限精度并四舍五入到结果格式。

但是,AFAICT 我以前从未见过这样的三元运算。所以我想知道这个函数的自定义用法是什么。

最佳答案

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

示例:比较 a * b1.0
假设确定两个 double 数 a 的乘积在哪里对算法至关重要。和 b是关于一个非零常数(我们将使用 1.0 )。号码 ab两者都有二进制数字的完整有效数。如果你计算 a*b作为 double ,结果可能是 1.0 ,但这并不能告诉您实际的数学乘积是略低于 1.0 并向上取整为 1.0,还是略高于 1.0 并向下取整。如果没有 FMA,您的选择是:

  • 计算 a*b作为四精度数。四精度不是在硬件中实现的,但有软件仿真库。在四精度中,乘积的数学结果是完全可表示的,然后您可以将其与 1.0 进行比较。
  • 计算 a*b在向上舍入模式和向下舍入模式下 double 。如果两个结果都是 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 乘法

    double-double format 是将数字有效表示为两个 double 浮点数之和的方法。它几乎与四精度一样精确,但利用了现有的 double 硬件。

    考虑以下函数,Mul12(a, b) ,这需要两个 double 数 ab并将他们的乘积计算为双双数。由于 Veltkamp 和 Dekker,一种算法仅使用 double 加法和乘法 ( reference ) 来计算此函数。它需要 6 次乘法(每个 Split() 的一部分加上算法主体中的 4 次)和大量的加法。

    如果 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 的一系列指令(通常由编译器生成)来获得正确舍入的除法。

    关于c - 有没有可以使用libc中的fma函数的场景?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13292013/

    相关文章:

    c - writev(或pwritev)会与c中的O_DIRECT冲突吗?

    c - 查看管道的读取端当前是否阻塞

    ios - 如何在 Swift 中解析由蓝牙设备发送的 float ?

    c - long double(80 位)是使用 -funsafe-math-optimizations 的两倍快

    c - <semaphore.h> 和 <sys/sem.h> 的区别

    multithreading - pthread rwlock从不同线程锁定/解锁

    shell - 为什么 fish 不支持POSIX?

    c - 当 Allegro 中一个位图跟随另一个位图时闪烁

    java - 使用java的浮点值精度丢失

    c - 修改函数中的指针值