动态-ffast-math

6

在运行时是否有可能选择性地打开/关闭-ffast-math?例如,创建具有公共基类Math的类FastMath和AccurateMath,以便能够在运行时使用两种实现?对于将次规范化值闪烁为零等操作也是如此。

特别是,我不知道使用-ffast-math编译是否会发出一条指令,一旦执行,就会影响线程中的所有数值计算(例如,设置一个标志来清除次规范化值)。


13
你需要编译两个版本,一个进行优化,另一个不进行优化。然后将它们链接在一起,并在运行时选择要调用哪个版本。 - Mysticial
2
很不幸,https://dev59.com/e2s05IYBdhLWcg3wIelj 只提供了一个例子,但是-ffast-math的效果大多数(完全?)是编译时选择,例如将/10编译为*0.1,或者将“简化”a+b-a-b0(对于IEEE 754计算而言并非为零)。因此,正如Mysticial所说,没有办法在运行时打开和关闭标志:如果您真的想要这样做,必须编译两个版本。 - Pascal Cuoq
1
@Mysticial 把你的评论变成答案 - 这是唯一的方法... - user2363448
1
@PascalCuoq。-ffast-math可能也会启用一些近似数学运算的指令,如果CPU支持它们(例如,您可能会得到一个不太准确的平方根,但您可能不在意)。否则,我认为你说的是准确的。 - ams
如果使用不同的-ffast-math选项编译了两个不同的源文件,会发生什么?只要所有受影响的数学运算都封装在这两个源文件中,那么这是否可以得到Op想要的结果? - ash
2个回答

7
如果你不想深入到构建系统中,你可以按照以下步骤进行操作:
#pragma fast-math push
#pragma fast-math on
[..]
#pragma fast-math pop

GCC可能有略微不同的语法,但我认为也是可能的。

2
只是为了帮助其他人省去搜索的麻烦;微软编译器也有这样的编译指示:https://learn.microsoft.com/en-us/cpp/preprocessor/float-control?view=vs-2019 - AlexGeorg

3

试试这个:

gcc -ffast-math -c first.c
gcc -c second.c
gcc -o dyn_fast_math first.o second.o

将具有唯一命名的函数放在first.c和second.c中。这应该可以解决问题。编译器优化很少会对“全局”产生影响。如果确实存在影响,由于冲突,链接通常会失败。
我尝试了一个小样本,没有问题。
下面是一个例子。
first.c
extern double second();

double  first ()
{
    double  dbl;

    dbl = 1.0;
    dbl /= 10.0;

    return  dbl;
}

int main ()
{
    printf("first = %f\n", first());
    printf("second = %f\n", second());

    return  0;
}

second.c

double  second ()
{
    double  ddbl;

    ddbl = 1.0;
    ddbl /= 10.0;

    return  ddbl;
}

编译

gcc -S first.c
gcc -c first.s
gcc -ffast-math -S second.c
gcc -ffast-math -c second.s
gcc -o prog first.o second.o

检查first.s和second.s之间的差异,你会发现:

movapd  %xmm1, %xmm2
divsd   %xmm0, %xmm2
movapd  %xmm2, %xmm0

将此更改为:

mulsd   %xmm1, %xmm0

两个函数都被调用,并且都返回了预期的结果。


1
谢谢。我想知道是否可以在不更改构建系统的情况下完成这样的事情,我的情况包括数千个源文件的几十个makefile风格脚本。是否有#pragma fast-math?搜索它会导致一个错误报告,声称这样的编译指示符应该在GCC中起作用,但实际上并没有。 - Michael
啊,我不知道有没有#pragma或其他方法。如果有需要的话,Make支持对特定目标的设置进行修改。 - ash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接