【问题标题】:long double (80 bits) twice as fast as double with -funsafe-math-optimizations使用 -funsafe-math-optimizations 的 long double(80 位)是 double 的两倍
【发布时间】:2013-12-16 02:38:34
【问题描述】:

在我使用-funsafe-math-optimizations 进行计算时,我始终发现使用long double 数据类型的速度大约是使用double 的两倍。我想对此有所了解,因为长期以来不推荐使用 80 位格式,或者我可能正在使用 double 数据类型做一些非常愚蠢的事情。编译器是 g++ 4.8.2,目标是 x86_64(所以如果我不使用 long double,gcc 会更喜欢 SSE2)。

我的代码或多或少是这样的(伪代码):

//x is an array of floating point numbers
for i -> x.size
        accumulator = 0
        for k -> kmax
            accumulator += A[k]*(B[k]*cos(C*k*x[i]) - D[k]*sin(C*k*x[i]));
        x[i] += F*accumulator;
        if(x[i] >= 1/2) x[i] -= integer(x[i]+1/2);
        else if(x[i] < -1/2) x[i] -= integer(x[i]-1/2);

AB、.. 是一些预先计算的数组/常量。

加速似乎与缓存线问题无关,因为如果我将外部 for 循环与 OpenMP 并行化,我将获得相同的相对加速。

编辑: 我更正了伪代码:请注意 cossin 具有相同的参数,这最终是加速的原因(参见 gsg 的答案和 cmets)。

【问题讨论】:

  • iffor 语句的分支历史是否有任何变化?
  • 这两个版本的汇编输出是什么?
  • 当使用long double时,你是使用cosl()还是cos()
  • “80 位格式已被弃用很久”的来源是什么?
  • @PatriciaShanahan 我不确定我理解你的意思。我不使用任何基于配置文件的优化,并且 if/elseif 的平均使用次数不会改变。

标签: c gcc floating-point compiler-optimization


【解决方案1】:

我的猜测是差异是由于cos

long double 数学必须编译成 x87 指令,以便轻松高效地使用 x87 操作fcos。但是,xmm 寄存器没有超越操作,因此对 cos 的调用必须生成代码以将double 移动到 x87 堆栈并调用fcos,或者进行函数调用以完成等效工作。对于这个编译器和机器来说,这些可能更昂贵。

您可以尝试通过查看程序集来验证这一点 - 查找 call cos 或 x87 指令 - 也可能值得使用 -mfpmath=387 进行编译以查看性能特征是否发生变化。

【讨论】:

  • 要去检查。你有什么解释只发生在-funsafe-math-optimizations 上吗?从什么时候开始 x87 fcos 是“不安全的”?
  • @LorenzoPistone x87 三角指令在某些型号的处理器上具有低于标准的参数减少。见software.intel.com/en-us/forums/topic/289702
  • 观察一下:gcc 在历史上已经发出了对cos 的调用,除非指定了-ffast-math,在这种情况下它使用fcos 指令。这个决定可能是因为cos(3) 应该为NaN 参数设置errno,但我不确定。
  • 我在问题中打错了字:我没有两个cos,而是一个cos 和一个sin 具有相同的论点。我在程序集中看到了这条指令fsincos,我很确定这就是显着加速的原因。如果没有-funsafe-math-optimizations,我会接到sincosl 的电话。
  • @gsg 我接受了你的回答。如果你也提到这个fsincos 事情会很好。 sqrt 等其他操作似乎不受-funsafe-math-optimizations 存在与否的影响。
猜你喜欢
  • 2015-03-23
  • 2021-12-10
  • 2014-09-23
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
  • 2013-09-25
  • 2018-11-30
  • 1970-01-01
相关资源
最近更新 更多