11

背景:

许多年前,我继承了一个代码库,它使用 Visual Studio (VC++) 标志“/fp:fast”在特定计算量大的库中生成更快的代码。不幸的是,'/fp:fast' 产生的结果与不同编译器 (Borland C++) 下的同一个库略有不同。因为我们需要产生完全相同的结果,所以我切换到“/fp:precise”,它工作得很好,从那以后一切都很顺利。但是,现在我在 uBuntu Linux 10.04 上使用 g++ 编译同一个库,我看到了类似的行为,我想知道它是否可能有类似的根本原因。我的 g++ 构建的数值结果与我的 VC++ 构建的数值结果略有不同。这让我想到了我的问题:

问题:

g++ 是否具有与 VC++ 中的 'fp:fast' 和 'fp:precise' 选项等效或相似的参数?(它们是什么?我想激活 'fp:precise' 等效项。)

更多详细信息:

我使用'make'编译,它调用g++。据我所知(make 文件有点神秘,不是我写的)添加到 g++ 调用的唯一参数是“正常”参数(包括文件夹和要编译的文件)和 -fPIC(我不确定这个开关的作用,我在“手册”页上看不到它)。

'man g++' 中唯一相关的参数似乎是用于打开优化选项。(例如 -funsafe-math-optimizations)。但是,我不认为我在打开任何东西,我只是想关闭相关的优化。

我尝试过发布和调试版本,VC++ 为发布和调试提供了相同的结果,而 g++ 为发布和调试提供了相同的结果,但我无法让 g++ 版本给出与 VC++ 版本相同的结果。

4

5 回答 5

18

GCC 手册

-ffloat-store 不要将浮点变量存储在寄存器中,并禁止其他可能改变浮点值是从寄存器还是内存中获取的选项。

此选项可防止在诸如 68000 之类的机器上出现不希望出现的过度精度,其中浮动寄存器(68881 的)保持比双精度应有的精度更高。对于 x86 架构也是如此。对于大多数程序来说,超额精度只会带来好处,但少数程序依赖于 IEEE 浮点的精确定义。在修改它们以将所有相关的中间计算存储到变量中之后,对此类程序使用 -ffloat-store。

扩展一点,这些差异大部分来自使用 x86 80 位浮点寄存器进行计算(与用于存储double值的 64 位相比)。如果中间结果保存在寄存器中而不写回内存,您可以在计算中有效地获得 16 位的额外精度,使它们更精确,但可能与将中间值写入/读取到内存(或只有 64 位 FP 寄存器的架构)。

这些标志(在 GCC 和 MSVC 中)通常强制将每个中间结果截断为 64 位,从而使计算对代码生成和优化的变幻莫测以及平台差异不敏感。除了准确性/精度方面的成本外,这种一致性通常会带来轻微的运行时成本。

于 2010-07-13T03:53:02.070 回答
10

过度的寄存器精度仅在 FPU 寄存器上是一个问题,编译器(使用正确的启用开关)无论如何都倾向于避免这种问题。在 SSE 寄存器中执行浮点计算时,寄存器精度等于内存精度。

根据我的经验,大多数 /fp:fast 影响(和潜在的差异)来自编译器冒昧地执行代数变换。这可以像更改 summands 顺序一样简单:

( a + b ) + c --> a + ( b + c)

可以 - 随意分配 a*(b+c) 之类的乘法,并且可以进行一些相当复杂的转换 - 所有这些都旨在重用以前的计算。当然,在无限精度下,这种变换是良性的——但在有限精度下,它们实际上会改变结果。作为一个玩具示例,请尝试使用 a=b=2^(-23), c = 1 的 summand-order-example。MS 的 Eric Fleegal对其进行了更详细的描述

在这方面,最接近 /fp:precise 的 gcc 开关是 -fno-unsafe-math-optimizations。我认为默认情况下它是打开的——也许你可以尝试明确设置它,看看它是否有所作为。同样,您可以尝试显式关闭所有 -ffast-math 优化:-fno-finite-math-only、-fmath-errno、-ftrapping-math、-frounding-math 和 -fsignaling-nans(最后两个选项是非默认!)

于 2010-07-13T05:00:51.590 回答
5

我认为没有确切的等价物。您可以尝试-mfpmath=sse代替默认设置-mfpmath=387,看看是否有帮助。

于 2010-07-13T03:51:21.780 回答
1

这绝对与优化标志无关,假设“调试”是指“关闭优化”。如果 g++ 在调试中给出与在发布中相同的结果,这意味着它不是与优化相关的问题。调试版本应始终将每个中间结果存储在内存中,从而保证与 /fp:precise 对 MSVC 所做的结果相同。

这可能意味着(a)其中一个编译器存在编译器错误,或者更可能是(b)数学库错误。我会深入研究您计算中的各个函数,并缩小差异所在。那时您可能会找到一种解决方法,如果您确实发现了一个错误,我相信相关团队会很乐意听到它。

于 2010-07-13T05:55:22.930 回答
0

-mpc32 还是 -mpc64?

但是您可能需要使用 switch 重新编译 C 和数学库以查看差异......这也可能适用于其他人建议的选项。

于 2010-07-13T06:50:14.737 回答