2

プロセッサをシミュレートするピン ツールを使用していて、非常に奇妙な問題が発生しています。以下のコード スニペットでは、Router::Evaluate() が何度も繰り返し呼び出されています。数百万回呼び出された後、最初の IF ステートメントで「_cycles != 0」が true と評価され、直後の IF ステートメントで false と評価され、ELSE ブロックに陥るという奇妙な動作が断続的に発生します。

void Router::Evaluate( )
{     
  //---------debug print code---------
  if (_cycles != 0) {
    cout << "not a zero" << endl;

    if (_cycles != 0) cout << "---not a zero" << endl;
    else cout << "---zero" << endl;

  }        
  //----------------------------------

  _cycles += _speedup;
  while ( _cycles >= 1.0 ) {
    _Step();
    _cycles -= 1.0;
  }
}

//class definition
class Router : public TimedModule {
  Protected:
    double _speedup;  //initialized to 1.0
    double _cycles;  //initialized to 0.0
  ...
}

以下は、「ゼロではない」の後に「---ゼロ」が続くコードの出力で、ランダムに見えることがあります。

not a zero
---zero
(...some other output...)
not a zero
---zero
(...some other output...)

これはどうして起こり得るのでしょうか?これはマルチスレッド プログラムではないため、同期は問題になりません。プログラムは gcc4.2.4 でコンパイルされ、32 ビット CentOS で実行されます。誰も手がかりを持っていますか?ありがとう。

- 追加した - -

これも言及すべきだった。毎回 _cycles の値を出力しようとしましたが、常に 0.0 でした。 -関数 -O3 -fPIC"

4

1 に答える 1

1

恐ろしいコンパイラのバグがない限り、次のようなことが起こっていると思います。

_cycles には、減算後に残っている小さな部分があります。コンパイラーは、その内容が他に変更されていないことを認識している限り、その値をより高精度の浮動小数点レジスターに保持します。I/O 操作を確認すると、_cycles の値が別の場所で必要とされるかどうかわからないため、その内容を倍精度メモリの場所に格納し、レジスタにあった余分なビットを丸めます。次のチェックでは、I/O 操作中に値が変更された可能性があると悲観的に想定し、前のテストで非ゼロになった余分なビットがない状態でメモリから値をロードし直します。

Daniel Fischer がコメントで述べたように、-ffloat-store使用すると高精度レジスタの使用が妨げられます。このオプションを使用して問題が解決した場合は、私が説明したシナリオの可能性が非常に高くなります。のアセンブリ出力を確認してくださいRouter::Evaluate

于 2012-08-06T18:45:18.370 に答える