为什么强制使用 -ffast-math 与 g++ 实现循环的向量化 double是?我不喜欢 -ffast-math 因为我不想失去精度。

有帮助吗?

解决方案

您不一定会失去精确度 -ffast-math. 。它只会影响处理 NaN, Inf 等以及执行操作的顺序。

如果您有一个特定的代码,您不希望GCC重新排序或简化计算,则可以将变量标记为使用 asm 陈述。

例如,以下代码在 f. 。但是,两个 f += gf -= g 运营可能会被海湾合作委员会(GCC)优化:

static double moo(double f, double g)                                      
{                                                                          
    g *= 4503599627370496.0; // 2 ** 52                                    
    f += g;                                                                
    f -= g;                                                                
    return f;                                                            
}                                                                     

在x86_64上,您可以使用此 asm 指示GCC不要执行优化的声明:

static double moo(double f, double g)                                      
{                                                                          
    g *= 4503599627370496.0; // 2 ** 52                                    
    f += g;                                                                
    __asm__("" : "+x" (f));
    f -= g;
    return f;
}

不幸的是,您需要为每个体系结构进行调整。在PowerPC上,使用 +f 代替 +x.

其他提示

很可能是因为矢量化意味着您可能有不同的结果,或者可能意味着您错过了浮点信号/异常。

如果您要编译32位X86,则GCC和G ++默认值用于使用X87进行浮点数学,在64位上它们默认为SSE,但是X87可以并且会为同一计算产生不同的值,因此不太可能G ++如果您无法保证您将获得相同的结果,则将考虑矢量化 -ffast-math 或它打开的一些旗帜。

基本上,它归结为矢量化代码的浮点环境可能与非矢量化代码的浮点数不一样,有时以重要的方式,如果差异对您无关紧要,类似

-fno-math-errno -fno-trapping-math -fno-signaling-nans -fno-rounding-math

但是首先查找这些选项,并确保它们不会影响您的程序的正确性。 -ffinite-math-only 也可能会有所帮助

因为 -ffast-math 使 操作数重新排序 它允许对许多代码进行矢量化。

例如计算这个

sum = a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + … a[99]

编译器是 必需的 做补充 依次地 没有 -ffast-math, ,因为浮点数学既不满足交换律也不满足结合律。

这也是同样的原因 为什么编译器不能优化 a*a*a*a*a*a(a*a*a)*(a*a*a) 没有 -ffast-math

这意味着除非您有非常有效的水平矢量添加,否则矢量化不可用。

然而如果 -ffast-math 启用后,可以计算表达式 像这样 (看着 A7. Auto-Vectorization)

sum0 = a[0] + a[4] + a[ 8] + … a[96]
sum1 = a[1] + a[5] + a[ 9] + … a[97]
sum2 = a[2] + a[6] + a[10] + … a[98]
sum3 = a[3] + a[7] + a[11] + … a[99]
sum’ = sum0 + sum1 + sum2 + sum3

现在,编译器可以通过并行添加每一列来轻松对其进行矢量化,然后在末尾进行水平添加

sum’ == sum?除非 (a[0]+a[4]+…) + (a[1]+a[5]+…) + (a[2]+a[6]+…) + ([a[3]+a[7]+…) == a[0] + a[1] + a[2] + … 这在关联性下成立,而浮动对象始终不遵守关联性。指定 /fp:fast 让编译器转换您的代码以使其运行速度更快 – 对于这个简单的计算,速度最多可提高 4 倍。

您喜欢快速还是精确? - A7。自动矢量化

它可以通过以下方式启用 -fassociative-math 海湾合作委员会的旗帜

进一步阅读

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top