首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >clang/gcc只用数学生成fma,为什么?

clang/gcc只用数学生成fma,为什么?
EN

Stack Overflow用户
提问于 2019-05-03 16:45:52
回答 1查看 1K关注 0票数 4

在icc 19上,点积编译成fma指令的循环。在clang和gcc上,fma只与-ffast-math一起生成。

然而,-ffast-math破坏了IEEE-754的遵从性,但是fma完全符合IEEE-754 2008,所以如果我必须使用-ffast-math编译,那么我会引发其他问题。

为什么gcc和clang不生成没有-ffast-math的fma指令

哥德波特;编译器标志是-O3 -march=skylake-avx512,+- -ffast-math

EN

回答 1

Stack Overflow用户

发布于 2021-02-12 07:23:19

编译器是否应该使用合并乘法/加法来实现用dot({a,c}, {b,d}) := a*b + c*d编写的点积,从而给出fl(⋅+ fl(⋅)),就好像它是写的fma(a,b, c*d)一样?一般不会!

下面是从W. Kahan关于IEEE 754的讲稿改编的几个例子

  • 假设我们想要评估平方−2的差异。 这可以写成一个点积dot({x,y}, {-x,y}) = x*x - y*y。这种天真的公式在≈时会被灾难性地取消,但至少当=时,它可靠地返回零,因为fl(fl(2)−fl(2 2))=fl(M2)−fl(2)= fl( 0 ) =0。 这可以用FMA作为fma(x,x, -y*y)来计算。但如果= fl(1.234) = 0x1.3be76c8b43958p+0,则结果是IEEE 754 binary64算法中的−1.3532e7b3d8ep−55≈−3.352 × 10⁻⁷,而不是我们所希望的零。 它不仅是非零的,而且是负的,所以如果你试图取下游的平方根,即使你能保证上游的NaN,你也会遇到≥。 (当然,保理(x + y)*(x - y)更好地避免中间灾难性取消,但这个问题是关于在不附加假设的情况下评估点积。)
  • 假设我们要在直角坐标(+ )⋅(+)=(−+(+)中求复乘积。 它的虚部可以写成一个点积dot({a,d}, {b,c}) = a*d + b*c。它可以用FMA作为fma(a,d, b*c)来计算。 您可能会期望复数+的乘积+及其复共轭−是实的,零虚部,如果用fma(a,d, b*c)计算,它是实的,而不是用fma(a,d, b*c)计算的。例如,如果= fl(1.234) = 1.3be76c8b43958p+0和= fl(5.678) = 1.6b645a1cac083p+2,则fl(⋅(−) +fl(⋅))=−1.6f6512a94ffp−55≈3.983 × 10⁻=⁷)。

因此,在这些场景中使用FMA将是糟糕的形式,而不需要您显式地要求使用来自fma(a,b, c*d)fma函数编写FMA,或者添加#pragma STDC FP_CONTRACT ON来授权这样的恶作剧。

上面写着…仅仅通过传递说服GCC 10.2滥用vfmadd231sd (即使是使用显式#pragma STDC FP_CONTRACT OFF国际刑事法院也是如此21.1.9 )似乎并不困难。在我看来,这就像一个buggy优化器!相反,#pragma STDC FP_CONTRACT ON,但没有将语用省略或设置为OFF

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55974090

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档