4

32ビットをターゲットにして、centos5.9 32ビット(64ビットマシンで実行)でコンパイルしています。g++ バージョンは 4.4.7 であり、centos5.9 でデフォルトで出荷されるものではありませんが、yum でダウンロードでき、ディストリビューションの一部として提供されます。

次のような非常に単純なループがあります

std::vector<double> result(n);
std::vector<double> values(n);
// here I compute values(). They are correct and I extensively noted 
// that there's nothing wrong there. The problem is here
result[0] = 0.0;
for ( int i = 0 ; i < n-1 ; ++i ) {
    result[i+1] = result[i]+values[i];
    // printf("x");
}

このコードのより複雑なバージョン (まったく同じ問題を示しています) では、パススルーとして std::vector をカプセル化するクラス RealVector に次の演算子を使用しました。

inline double & operator[] (int index) { return data_[index]; }

問題は、operator[] がインラインであるかどうかに応じて、結果にわずかではあるが関連する数値の違いが見つかったことです。同様に、上記の printf() 行のコメントを外すと、結果も変わります。同じ構成の centos59 64 ビットでは問題が発生しないか、発生した場合でも検出可能性を下回っていることに注意してください。

それはコンパイラのバグですか、それとも微妙な魔法が起こっていますか? asm と parse ツリーの両方をチェックしようとしましたが、複雑すぎてわかりません。私は通常、C で管理しますが、C++ では、結果のファイルに暗黒の魔法がかかりすぎています。

4

1 に答える 1

8

おそらく古い x87 の楽しい機能である 80 ビット レジスタです。そのレジスタをメモリにスピルすると、64 ビットへの丸めが発生し、予測できない瞬間に発生します。C++ に固有のものではありませんが、C にも同じ問題があります。Javaでは「複雑」です

64 ビット ビルドと SSE に移行することで修正されました。

于 2013-11-15T08:39:52.473 に答える