如何在内存中存储双打

时间:2011-02-22 05:53:07

标签: c++ memory floating-point double

最近我改了一些代码

double d0, d1;
// ... assign things to d0/d1 ...
double result = f(d0, d1)

double d[2];
// ... assign things to d[0]/d[1]
double result = f(d[0], d[1]);

我没有更改d的任何分配,也没有更改f中的计算,除了双打现在存储在固定长度数组中之外的任何其他内容。

但是,在发布模式下进行编译时,如果进行了优化,result已更改。

我的问题是,为什么,我应该知道如何存储双打?一种方式比另一种更有效,更好吗?是否存在内存对齐问题?我正在寻找任何可以帮助我了解正在发生的事情的信息。


编辑:我会尝试使用一些代码来演示问题,但是这很难,因为这些数字经过的过程非常庞大(很多数学,数值解算器等)

然而在Debug 中编译时没有变化。我将再次仔细检查以确保这一点,但这几乎可以肯定,即版本1和版本2之间的Debug中的双值相同

将Debug与Release进行比较,由于各种优化原因,两种编译模式之间的结果从未如此相同。

4 个答案:

答案 0 :(得分:2)

您可能已打开“快速数学”编译器开关,或正在“分配事物”(我们看不到)中执行某些操作,这允许编译器合法地重新排序计算。尽管序列是等价的,但优化器可能会以不同的方式处理它们,因此最终会产生稍微不同的代码生成。如果它被重新排序,你最终会在最低有效位上略有不同。这就是生命的浮点。

您可以通过不使用“快速数学”(如果已启用)或通过构建公式和中间值的方式强制排序来防止这种情况发生。即使这很难(不可能?)来保证。问题是“为什么编译器为数组和编号变量生成不同的代码?”,但这基本上是对代码生成器的分析。

答案 1 :(得分:0)

没有这些是等价的 - 你还有别的错误。

检查/ fp:精确标志(或等效)处理器浮点硬件可以更高精度或更高速度模式运行 - 它在优化构建中可能有不同的默认值

答案 2 :(得分:0)

关于浮点语义,这些是等价的。但是,可以想象编译器可能决定为两者生成略有不同的代码序列,这可能会导致结果的差异。

你能发布一个完整的代码示例来说明差异吗?如果不继续下去,任何人发布的答案都只是猜测。

关注你的问题:内存对齐不能影响double的值,编译器应该能够为这两个例子生成等效的代码,所以你不必担心你做的事情错误< / em>(至少,不是在您发布的有限示例中)。

答案 3 :(得分:0)

第一种方式以非常理论的方式更有效率。它为编译器分配堆栈槽和寄存器提供了更多的余地。在第二个例子中,编译器必须选择2个连续的插槽 - 当然,如果编译器足够聪明,可以意识到你从未注意到它。

很有可能double[2]导致数组被分配为两个相邻的堆栈插槽,而不是之前,这反过来会导致代码重新排序以提高内存访问效率。 IEEE754浮点数学不遵守常规数学规则,即a + b + c!= c + b + a