繁体   English   中英

-Ofast 的 GCC 问题?

[英]GCC issue with -Ofast?

我有一个关于最新 GCC 编译器(版本 >= 5)的问题,代码如下:

#include <math.h>

void test_nan (
    const float * const __restrict__ in,
    const int n,
    char * const __restrict__ out )
{
    for (int i = 0; i < n; ++i)
        out[i] = isnan(in[i]);
}

GCC 的组装清单:

test_nan:
        movq    %rdx, %rdi
        testl   %esi, %esi
        jle     .L1
        movslq  %esi, %rdx
        xorl    %esi, %esi
        jmp     memset
.L1:
        ret

这看起来像memset(out, 0, n) 为什么 GCC 假设没有条目可以是 -Ofast 的 NaN? 使用相同的编译选项,ICC 不会显示此问题。 对于 GCC,问题会随着“-O3”而消失。

请注意,使用“-O3”,此查询gcc -c -Q -O3 --help=optimizers | egrep -i nan gcc -c -Q -O3 --help=optimizers | egrep -i nan给出-fsignaling-nans [disabled]

我在本地和Godbolt上都验证了这一点,并带有附加选项“-std=c99”。

编辑:按照下面的有用答案,我可以确认-Ofast -std=c99 -fno-finite-math-only正确解决了这个问题。

来自控制优化文档的 GCC 选项

-Ofast除了-O3之外还启用了以下优化:

它会打开-ffast-math 、 -fallow-store-data-races 和 Fortran 特定的 -fstack-arrays,除非指定了 -fmax-stack-var-size 和 -fno-protect-parens。

-ffast-math启用以下功能:

-fno-math-errno、-funsafe-math-optimizations、 -ffinite-math-only 、-fno-rounding-math、-fno-signaling-nans、-fcx-limited-range 和 -fexcess-precision=fast。

-ffinite-math-only执行以下操作:

允许优化浮点运算,假设 arguments 和结果不是 NaN或 +-Infs。

这允许它假设isnan()总是返回0

Barmar 的回答解释了为什么-Ofast导致编译器假定 NaN 永远不会发生。 我有两件事要补充。

首先,您谈到在--help=optimize output 中看到-fsignaling-nans [disabled] 信令NaN 是所有 NaN 位模式的子类别。 CPU 将在使用时触发浮点异常(请参阅架构手册以了解“使用时”的确切含义)。 通常人们只使用另一种安静的 NaN,因为处理浮点异常很痛苦; 因此,默认情况下,GCC 生成处理安静 NaN(和 ±Inf)但发出信号的代码。 isnan对于安静和信号 NaN 都是正确的。 简而言之, -fsignaling-nans是一条红鲱鱼; 直接控制您不喜欢的行为的选项是-ffinite-math-only

其次,如果您使用-Ofast是因为您希望将此 function 进行矢量化,请尝试使用-O3 -march=native代替。 -O3启用循环矢量化,并且-march=native指示 GCC 优化其运行的 CPU 的全部功能。 如果没有任何-march开关,GCC 将假定它只能使用 psABI 保证可用的 CPU 功能; 对于 x86-64(看起来你有),那是 SSE2,但之后没有,这遗漏了大部分矢量功能。 在我正在输入的计算机上, -O3 -march=native为您的示例 function 生成代码,其大小只有 -O3 的一半速度可能大约是-O3的四倍。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM