围绕-ffast-math的gcc链接器行为的奇怪结果

时间:2015-12-18 15:29:52

标签: c gcc optimization linker fast-math

我注意到编译器链接器的标志周围有一个有趣的现象,它以我无法理解的方式影响正在运行的代码。

我有一个库,它提供了相同算法的不同实现,以测试这些不同实现的运行速度。

最初,我用一对相同的实现测试了这种情况,以检查发生的正确事情(两者都以大致相同的速度运行)。我首先使用以下编译器标志编译对象(每个实现一个):

-g -funroll-loops -flto -Ofast -Werror

然后在链接期间传递了gcc以下标志:

-Ofast -flto=4 -fuse-linker-plugin

这给了一个快速运行的库,但奇怪的是,对于链接期间参数中包含的第一个对象,可靠且可重复地快了约7%(因此,如果首先链接,则实现速度更快)。

所以:

gcc -o libfoo.so -O3 -ffast-math -flto=4 -fuse-linker-plugin -shared support_obj.os obj1.os obj2.os -lm

VS

gcc -o libfoo.so -O3 -ffast-math -flto=4 -fuse-linker-plugin -shared support_obj.os obj2.os obj1.os -lm

第一种情况是obj1中的实现比obj2中的实现运行得更快。在第二种情况下,反过来是正确的。需要明确的是,除了函数入口名称外,代码在两种情况下都是相同的。

现在我通过在链接过程中删除-Ofast标记来删除这个奇怪的链接参数顺序差异(实际上加了一点)。

我可以通过将-Ofast更改为-O3 -ffast-math来复制大致相同的情况,但在这种情况下,我需要在链接期间提供-ffast-math,这又会导致奇怪的订购速度差异。我不确定为什么在-Ofast期间保持加速,但在链接期间未传递-ffast-math时{for} -ffast-math不能保持加速,但我可以接受它可能会延迟到链接时间优化在一个案例中传递相关信息但不传递另一个案例。但这并不能解释速度差异。

删除-ffast-math意味着它运行速度慢〜8倍。

是否有人能够了解可能导致这种影响的原因?我真的很想知道可能会发生什么导致这种有趣的行为,所以我不能不小心触发它。

运行速度测试是在python中使用库和timeit周围的包装器执行的,我很确定这是做正确的事情(我可以​​旋转命令和事物来显示python副作用可以忽略不计)。 / p>

我还测试了库的输出正确性,所以我也可以对此有合理的信心。

1 个答案:

答案 0 :(得分:0)

对于发表评论的评论来说,

太长了:

由于在数学运算中获得不正确结果的风险,我建议不要使用它。

使用-ffast_math和/或-Ofast会导致错误的结果,如gcc手册中的摘录所示:

选项:-ffast-math设置选项:

  1. -fno-math-errno,
  2. -funsafe-math-optimizations,
  3. -ffinite-math-only,
  4. -fno-rounding-math,
  5. -fno-signaling-nans和
  6. -fcx-有限范围。
  7. 此选项可以定义预处理器宏__FAST_MATH__

    -Ofast之外的任何-O选项都不会打开此选项,因为它可能导致程序的输出不正确,这些程序依赖于IEEE或ISO规则/数学函数规范的精确实现。但是,对于不需要保证这些规范的程序,它可能会产生更快的代码。 "

    选项:-Ofast

    无视严格的标准合规性。 -Ofast启用所有-O3优化。它还支持对所有符合标准的程序无效的优化。它会启用-ffast-math和特定于Fortran的-fno-protect-parens-fstack-arrays