我的应用程序在发布模式和调试模式下编译时生成不同的浮点值。我发现的唯一原因是我保存了一个二进制跟踪日志,并且发布版本中的一个从调试版本中略微偏离,看起来32位浮点值的底部两位不同于1/2案件。

你会考虑这种“差异”吗?成为一个错误或预计会出现这种差异。这会是编译器错误还是内部库错误。

例如:

LEFTPOS and SPACING are defined floating point values.
float def_x;
int xpos;

def_x = LEFTPOS + (xpos * (SPACING / 2));

问题在于X360编译器。

有帮助吗?

解决方案

发布模式可能具有不同的FP策略集。根据您想要的优化级别,有不同的浮点运算模式。例如,MSVC具有严格,快速和精确的模式。

其他提示

我知道在PC上,浮点寄存器是80位宽。因此,如果计算完全在FPU内完成,则可以获得80位精度的好处。另一方面,如果将中间结果移出到正常寄存器并返回,则会将其截断为32位,这会产生不同的结果。

现在考虑一个发布版本会有优化,可以将中间结果保存在FPU寄存器中,而调试版本可能会在内存和寄存器之间反复复制中间结果 - 而且你的行为也有所不同。

我不知道这是否也会在X360上发生。

我帮助一位同事找到了一个编译器开关,它在发布版和调试版之间有所不同,导致了他的差异。

查看 / fp(指定浮点数)行为)

这不是一个错误。任何浮点运算都有一定的不精确性。在发布模式下,优化将改变操作的顺序,您将得到略微不同的结果。不过,差异应该很小。如果它很大,你可能还有其他问题。

除了其他人指出的不同浮点模式之外,可以启用SSE或类似的向量优化以便发布。将浮点运算从标准寄存器转换为向量寄存器会对结果的低位产生影响,因为向量寄存器通常比标准浮点寄存器更窄(更少的位)。

不是错误。这种差异是可以预期的。

例如,某些平台的浮点寄存器使用的位数多于存储在存储器中的位数,因此与存储到存储器并从存储器重新加载相比,在寄存器中保留一个值会产生稍微不同的结果。

这种差异很可能是由编译器优化引起的,编译器优化通常在发布模式下完成,但不在调试模式下完成。例如,编译器可能会重新排序某些操作以加快执行速度,这可能会导致浮点结果略有不同。

所以,我想说很可能不是一个bug。如果您真的担心这一点,请尝试在调试模式下启用优化。

与其他提到的一样,浮点寄存器的精度高于浮点数,因此最终结果的准确性取决于寄存器分配。

如果您需要一致的结果,可以使变量变为volatile,这将导致更慢,更不精确但一致的结果。

如果设置允许编译器重新排序浮点运算的编译器开关,例如, / fp:快 - 然后显然它不是一个错误。

如果您没有设置任何此类切换,那么这是一个错误 - C和C ++标准不允许编译器在未经您许可的情况下重新排序操作。

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