2017-12-07 13 views
1

`で正常に動作しません:いくつかの方法でISNANには、次のテストプログラムを検討-Ofast`フラグ

# include <gsl/gsl_statistics_double.h> 
# include <iostream> 

using namespace std; 

int main() 
{ 
    double y = 50.2944, yc = 63.2128; 
    double pearson_corr = gsl_stats_correlation(&y, 1, &yc, 1, 1); 
    cout << "pearson_corr = " << pearson_corr << endl; 
    if (isnan(pearson_corr)) 
    cout << "It is nan" << endl; 
    else 
    cout << "Not nan" << endl; 
} 

を、このコードはいくつかの不合理であるが、その目的は、私が経験しています微妙なエラーを表示することです。

gsl_stats_correlation()への呼び出しでは、サンプル数が1でピアソン係数が少なくとも2つのサンプルの感覚を持つため、エラーが発生します。

は、私はこのようにコンパイルするとき:

c++ test-r2.cc -lgsl -lgslcblas 

プログラムが出力した結果、私が言ったように、係数を計算することはできませんので、私が正しい考えるメッセージ「それがNaNである」、など-nanisnan()を呼び出すと、結果はnanであることが正しく検出されます。しかし、私はこのようにコンパイル:

c++ -Ofast test-r2.cc -lgsl -lgslcblas 

プログラムは、その結果が、isnan()への呼び出しがpearson_corr変数の無効を検出することができなかったことを示唆しているメッセージが「未ナン」、として-nanを出力します。

だから、私の最初の質問は、なぜ-Ofastフラグでisnan()への呼び出しは、変数がnanであることを検出することができません。そして、私の2番目の質問は、最適化フラグに依存しない方法でこの問題を解決する方法だろう」ESコンパイラに与えられた

私は64ビットモードでのUbuntu 16.04上のGNU C++バージョン5.4.0およびインテルi5の実行を使用しています事前に

おかげ

+0

「高速数学は、プログラムの誤った出力につながることができます数学関数のIEEEまたはISOルール/仕様の正確な実装に依存しています」https://stackoverflow.com/questions/15944614/is-it-possible-to-make-isnan-work-in-gfortran-o3- ffast-math –

+0

どちらの場合でも 'fpclassify(pearson_corr) 'の値を確認してください。 –

答えて

7

-Ofastは、とりわけ、GCCの-ffast-mathモード、および-ffast-mathを活性化し、とりわけ、コンパイラがNaN(およびInfを)が発生しないことを前提としたコードを生成させます。

したがって、NaNまたはInfを使用する必要がある場合は、を使用しないでください。-Ofastを使用してください。回避策はありません。

ほとんどすべてのプログラムは、とにかく-O2 -march=nativeによってサービスされます。 -Ofastは、非常に積極的なインライン展開とループ展開を行い、私の経験ではほとんどの場合、Iキャッシュを吹き飛ばしてプログラムを作成します遅い

+0

が合意しました: '-O2'が最良の妥協です。'-O3' /' -Ofast'は_real_ players用です:)いくつかの魔法のオプションに頼るよりも、手動でコードを最適化するほうがいいです。 –

+0

@ Jean-FrançoisFabre厳密に選択された複合体のサブセットに '-O3'を適用すると便利ですプログラムのソースファイル、最もホットな内部ループを持つもの人間の組立ウィザードがしばしばより良くできることは事実ですが、来ることは難しく、安く働かないのです。 :) – zwol

+0

が合意した。コードが移植性がなくなったことは言うまでもありません。このパイプライニングとキャッシュのすべてのことで、コンパイラは通常良く分かります。 68000日が終わった(一言:) –

3

man gccがこれを言う:?

-Ofast 
     Disregard strict standards compliance. -Ofast enables all -O3 optimizations. It also enables optimizations that are not valid for all standard-compliant programs. It turns on -ffast-math 
     and the Fortran-specific -fno-protect-parens and -fstack-arrays. 

と、この:

-ffast-math 
     Sets -fno-math-errno, -funsafe-math-optimizations, -ffinite-math-only, -fno-rounding-math, -fno-signaling-nans and -fcx-limited-range. 

     This option causes the preprocessor macro "__FAST_MATH__" to be defined. 

     This option is not turned on by any -O option besides -Ofast since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications 
     for math functions. It may, however, yield faster code for programs that do not require the guarantees of these specifications. 

あなたは浮動小数点ファミリーの他の奇妙な種の間で、NaNを無視するようにコンパイラを語っています。コンパイラがそれをしないようにするには、代わりに-O2または-O3と伝えてください。

1

あなたはGCCにNaNがないと仮定したので、NaNがないと仮定しました。 NaNに依存するコードは、そうしても信頼できるものではありません。docsから

  • -Ofast

    無視厳格な基準に準拠。 -Ofastはすべての-O3最適化を有効にします。また、すべての標準準拠のプログラムに対して有効でない最適化も可能にします。 -fmax-stack-var-sizeが指定されていない限り、-fast-mathとFortran固有の-fstack-arraysが有効になり、-fno-protect-parensが有効になります。

  • -ffast-数学

    は、-fno-数学-errnoに、-funsafe-数学の最適化、-ffinite-数学のみの、-fno-丸め数学のオプションを設定します。 -fno-signaling-nans、-fcx-limited-rangeおよび-fexcess-precision = fastです。 ...

  • -ffinite-数学のみの

    引数と結果はNaNをまたは+ -Infsていないことを前提と浮動小数点演算のための最適化を許可します。

2

無視厳格な基準に準拠

-Ofast。 -Ofastはすべての-O3最適化を有効にします。 また、すべての標準準拠の プログラムでは有効ではない最適化を有効にします。 それは-ffast-数学

をオンにし、より良いがMingw32 std::isnan with -ffast-math

(答えの一つが動作する実装が含まれ、ここで説明したように、その場合にはisnanは、動作しませんが、それも可能ですそうisnanまだ動作し、-Ofast -fno-finite-math-only:あなたは、このオプションを使用することができます

1

-OfastでコンパイルされていないACファイル)にisnanをラップします。

-fno-finithe-math-onlyを使用したくない場合でも、NaN番号を検出したい場合は、プラットフォームに依存した方法で行うことができます。isnan関数を実装します。あなたはフロート32ビットでIEEE-754プラットフォームにしていると64ビットを倍増場合

たとえば、あなたが行うことができます:

#include <cstdint> 
#include <string.h> 

bool myIsnan(float v) { 
    std::uint32_t i; 
    memcpy(&i, &v, 4); 
    return ((i&0x7f800000)==0x7f800000)&&(i&0x7fffff); 
} 

bool myIsnan(double v) { 
    std::uint64_t i; 
    memcpy(&i, &v, 8); 
    return ((i&0x7ff0000000000000)==0x7ff0000000000000)&&(i&0xfffffffffffff); 
} 
関連する問題