7

当我在发布模式和调试模式下编译它时,我的应用程序会生成不同的浮点值。我发现的唯一原因是我保存了一个二进制跟踪日志,而来自发布版本的日志与调试版本略有不同,看起来 32 位浮点值的底部两位相差约 1/2的案例。

您会认为这种“差异”是一个错误,还是会出现这种差异。这是编译器错误还是内部库错误。

例如:

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

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

问题与 X360 编译器有关。

4

9 回答 9

11

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

于 2008-09-26T20:29:35.110 回答
4

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

现在考虑发布版本将进行优化,将中间结果保存在 FPU 寄存器中,而调试版本可能会天真地在内存和寄存器之间来回复制中间结果 - 并且您的行为有所不同。

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

于 2008-09-26T20:37:05.327 回答
3

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

于 2008-09-26T20:29:31.757 回答
3

我帮助一位同事找到了一个编译器开关,该开关在发布与调试版本中不同,这导致了他的差异。

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

于 2008-09-26T20:33:31.293 回答
2

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

于 2008-09-26T23:57:36.170 回答
1

不是错误。这种差异是意料之中的。

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

于 2008-09-26T20:33:42.480 回答
0

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

所以,我会说它很可能不是一个错误。如果您真的担心这一点,请尝试在 Debug 模式下打开优化。

于 2008-09-26T20:34:45.160 回答
0

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

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

于 2008-09-26T23:51:03.817 回答
0

如果你设置了一个编译器开关,允许编译器重新排序浮点运算——例如/fp:fast——那么显然这不是一个错误。

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

于 2008-11-25T21:52:27.423 回答