2

これは問題を引き起こすプログラムのクリティカル セクションであり、プログラムは完全にシーケンシャルです。

exist_はクラスのboolプライベート メンバーでありdbl_num_、クラスのdoubleプライベート メンバーです

exist_ = false;
dbl_num_ = 0;
std::cout << dbl_num_ << " " ;
if(exist_ == true)
{
  dbl_num_ = 5;
}else
{
  dbl_num_ = NAN;
}

std::cout << exist_ << " " << dbl_num_ << std::endl;

オプション -ffast-math を使用すると、「0 0 5」という出力が得られました

オプション -ffast-math を指定しないと、"0 0 NAN" という出力が得られました

さらに、プログラムを次のように変更すると

exist_ = false;
dbl_num_ = 0;
std::cout << dbl_num_ << " " ;
if(exist_ == true)
{
  std::cout << exist_ << " " ;
  dbl_num_ = 5;
}else
{
  dbl_num_ = NAN;
}

std::cout << exist_ << " " << dbl_num_ << std::endl;

オプション -ffast-math を使用すると、「0 0 NAN」になりました

NANを-5に変更するよりも

exist_ = false;
dbl_num_ = 0;
std::cout << dbl_num_ << " " ;
if(exist_ == true)
{
  dbl_num_ = 5;
}else
{
  dbl_num_ = -5;
}

std::cout << exist_ << " " << dbl_num_ << std::endl;

オプション -ffast-math を使用すると、「0 0 -5」が得られました

-ffast-math がIEEE標準に違反していることは知っていましたが、NANをチェックしませんが、上記の単純な条件チェックを破る正確な理由は何ですか?

4

1 に答える 1

3

-ffast-math は、NaN が発生しないと仮定するように g++ に指示します。したがって、何かを NaN に設定することは、未定義の動作とほぼ同等であり、コンパイラはそれが発生しないと安全に想定できます。コンパイラが実行できないことを「認識」している分岐をどのように削除できるか、およびそれがどのように驚くべきかについては、この一連の LLVM ブログ投稿を参照してください。

短いバージョン: g++ は、「高速数学モードであるため、dbl_num_ が NaN に設定されないため、else ブランチが取得されないため、exist_ が true である必要があるため、そのパス以外のすべてを最適化できます」となります。

編集:このgcc バグレポートも参照してください。

于 2015-12-03T03:53:23.873 に答える