fp:精确 vs. fp:严格性能

15

我发现在发布版和调试版的程序结果中存在一些差异。经过一些研究,我意识到一些浮点数优化导致了这些差异。通过使用fenv_access指令来禁用一些关键方法的优化,我解决了这个问题。

考虑到这一点,我意识到由于其特性,使用fp:strict模型可能比使用fp:precise模型更好,但我担心它会影响性能。我试图找到有关fp:strict的性能问题或精确和严格模型之间性能差异的信息,但我找到的信息非常少。

有人知道这方面的情况吗?

提前感谢。

4个回答

14
这是因为您正在以32位模式编译,它使用x86浮点处理器。代码优化器从FPU寄存器到内存和反向移动中删除冗余移动,使中介结果保留在FPU堆栈中。这是一个非常重要的优化。
问题在于,FPU使用80位精度存储双精度数,而不是64位的双精度数。Intel最初认为这是一种功能,可以产生更准确的中间计算结果,但实际上这是一个错误。他们在设计SSE2指令集时没有犯同样的错误,64位编译器用于执行浮点数运算。XMM寄存器为64位。
因此,在发布模式构建中,由于使用了更多位进行计算,结果会微妙地有所不同。在使用浮点值进行计算的程序中,这永远不应该是问题,因为double只能存储15个有效数字。不同的是噪声数字,即第一组15个数字之外的数字。但如果你的计算严重失去有效数字,就可能会少得多。例如计算1-3 *(1/3.0)。
但是,您可以使用fp:precise获得一致的噪声数字。它强制将中间值刷新到内存中,因此不能保留在具有80位精度的FPU中。当然,这会使您的代码变慢。

1
首先感谢您的回答。正如您所说,我正在32位模式下编译,但我总是使用fp:precise,这是Visual Studio 2008的默认设置。使用此配置,我会得到不同的结果(在我的代码中,我比较两个值并根据它执行不同的代码部分)。在方法之前使用#pragma fenv_access(on)和#pragma fenv_access(off)之后,我解决了这个问题。现在我正在考虑使用fp:strict而不是fp:precise来防止未来的错误,但我担心性能问题。您知道fp:strict的性能是否明显低于fp:precise吗? - Alex
2
很好的解释80位与64位之间的区别。但是,也许有点吹毛求疵……这真的回答了问题吗?或者“隐含”的问题呢?Alex主要在问“性能影响”……而这正是你没有回答的部分。 - André
但是,汉斯,阅读了您的帖子后,我认为这就是问题的根源。我想,在优化过程中,比较会在FPU寄存器之间进行,具有更高的精度,并且一些值可能被视为相等(精度较低),被认为是不相等的。非常有趣的观点,谢谢 ;) - Alex
2
32位编译器也可以使用SSE2进行浮点数运算,如果在MSVC上设置/arch:SSE2,它会尽可能地用SSE2变体覆盖x87指令 :) - Necrolis
我要做的是编写一个测试程序,执行浮点运算,据说在fp:precise下进行了优化,而不是在fp:strict下进行优化,然后测量性能。虽然这不是我想要的,但总比没有好。从我已经阅读的资料中,精确模型和严格模型之间的性能差异可能很小。我会在这里发布我的结果。感谢大家。 - Alex
英特尔最初认为这是一个功能,可以产生更准确的中间计算结果,但实际上这是一个错误。他们没有犯同样的错误[...]抱歉,但完全搞错了。英特尔在1976年开始研发8087芯片,并聘请William Kahan担任顾问(http://www.cs.berkeley.edu/~wkahan/ieee754status/754story.html)。8087芯片于1980年发布。Kahan随后在IEEE 754标准的浮点运算标准化方面发挥了重要作用。IEEE 754于1985年正式发布。 - Pascal Cuoq

2

我不确定这是否是一个解决方案,但这是我所拥有的 :) 就像我之前发过的帖子一样,我编写了一个测试程序,执行浮点运算,据说在 fp:precise 下进行优化,而在 fp:strict 下则没有进行优化,然后测量性能。我运行了它 10000 次,在平均情况下,fp:strict 比 fp:precise 慢了 2.85%。


1

我只是提供一些意见:

我有一个图像处理程序,可以自动矢量化,目的是将Matlab作为黄金标准进行性能和准确性比较。

使用VS2012和Intel i950。

关键区域错误和运行时间。

2.3328196e-02 465 ms with strict 
7.1277611e-02 182 ms with precise
7.1277611e-02 188 ms with fast

strict没有矢量化

使用strict会使代码变慢2倍,这是不可接受的。


-5

在Debug版本和Release版本之间看到性能差异是完全正常的。

编译器和运行时会在Debug版本中进行更多的附加检查;不要将其与其他版本进行比较,特别是在性能方面;请使用不同的编译器开关进行Release vs. Release的比较。

另一方面,如果这两个版本之间的结果不同,则必须进入程序内部检查错误(最有可能的情况)。

Max.


1
他已经找到了错误(精确与严格的浮点计算),并且担心在任何构建模式下都会出现这种情况。 - RedX
2
正如您所说,调试版和发布版的性能不可比较。我也不想进行比较。但是,我在调试版和发布版之间得到了不同的结果。现在我已经解决了这个问题。我的疑问是因为可能更好地将fp:strict作为我的程序的浮点模型。因此,我正在寻找一些关于fp:strict模型性能问题及其与fp:precise的差异的分析或概述。 - Alex
@Alex,你应该对具体的计算进行一些分析。每段代码的性能都会有很大的差异。你可以比较在不同模式下执行所需的时间,然后决定是否值得使用“strict”模式。 - ScienceDiscoverer

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