我有以下代码,但是当使用带有各种优化标志的 GCC 4.4 编译它时,我在运行时得到了一些意想不到的结果。
#include <iostream>
int main()
{
const unsigned int cnt = 10;
double lst[cnt] = { 0.0 };
const double v[4] = { 131.313, 737.373, 979.797, 731.137 };
for(unsigned int i = 0; i < cnt; ++i) {
lst[i] = v[i % 4] * i;
}
for(unsigned int i = 0; i < cnt; ++i) {
double d = v[i % 4] * i;
if(lst[i] != d) {
std::cout << "error @ : " << i << std::endl;
return 1;
}
}
return 0;
}
当编译时:“g++ -pedantic -Wall -Werror -O1 -o test test.cpp”我得到以下输出:“错误@:3”
当编译时:“g++ -pedantic -Wall -Werror -O2 -o test test.cpp”我得到以下输出:“错误@:3”
当编译时:“g++ -pedantic -Wall -Werror -O3 -o test test.cpp”我没有收到任何错误
当编译时:“g++ -pedantic -Wall -Werror -o test test.cpp”我没有收到任何错误
我不认为这是与舍入或比较中的 epsilon 差异相关的问题。我已经在 Intel v10 和 MSVC 9.0 上尝试过此操作,它们似乎都按预期工作。我相信这应该只不过是按位比较。
如果我将 if 语句替换为以下内容:if (static_cast<long long int>(lst[i]) != static_cast<long long int>(d))
,并添加“-Wno-long-long”,运行时我在任何优化模式下都没有收到错误。
如果我添加std::cout << d << std::endl;
在“return 1”之前,运行时我在任何优化模式下都没有收到错误。
这是我的代码中的错误,还是 GCC 及其处理双精度类型的方式有问题?
Note:我刚刚用 gcc 版本 4.3 和 3.3 尝试过此操作,没有显示该错误。
解决:Mike Dinsdale 指出了以下错误报告:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323看来GCC团队不是完全确定关于问题的性质。
正如错误报告中所建议的,可能的解决方案是使用 ffloat-store 选项。我已经尝试过这个并且它有效,但是从性能角度来看结果并不是那么好,尽管 ymmv。