2

一部のIntelFORTRANコードで奇妙なクラッシュが発生しており、最終的に次の行を追跡しました。

L_F = EXP(-L_B2*L_BETASQ*L_DS)

ここで、-L_B2 * L_BETASQ*L_DS項は約-230と評価されました。たまたま、EXP(-230)は約1e-100と評価されます。他のすべての既知のケースでは、L_DSははるかに小さいため、EXPからの最小の(既知の)リターンは約1e-50であり、エラーは発生しません。

FORTRANがEXP(-230)句を評価するとすぐに、次のようになります。

forrtl: severe (157): Program Exception - access violation
Image              PC        Routine            Line      Source

しかし、他の情報はありません。

例外157は一般に相互運用性に関係しており、特定の.cファイルが見つからないため、FORTRANでEXPにデバッグすることはできません。これはおそらくEXPがCで実装されていることを意味します(これは驚くべきことです)。

私の仮説では、FORTRANはCでEXPを実装していますが、インターフェースは1e-100より小さいフロートをREAL(4)に変換できません。以前、floatとREAL(4)はバイト単位で同一であると信じていたので、この仮説を裏付けることはできません。また、それについて何も見つけることができません。

このバグを閉じる前に、誰かが私の仮説を確認または否定できますか?または別の仮説を提供できますか?

よろしくお願いします、

マイク

編集: ハイパフォーマンスマークが当面の質問に回答したので、この質問を回答済みとしてマークします。

私の仮説は残念ながら正しくありません-私はこれを行うことで問題をトラップしようとしました:

L_ARG = L_B2*L_BETASQ*L_DS

IF (L_ARG .GT. 230.0) THEN
    L_F = 0.0
ELSE
    L_F = EXP(-L_ARG)
ENDIF

残念ながら、例外は現在(明らかに)L_ARG.GTで発生しています。230.0句。これは、リリースモードでのデバッグが思ったより悪いか、ある種の「保存された」浮動小数点エラーであることを意味します(文字列ストリームにfloatを入力するときの「浮動小数点の無効な操作」を参照)。

4

1 に答える 1

5

Fortranは(必然的に)Cで何も実装していません。標準の組み込み関数の実装はコンパイラー固有です。libm実装がまたはその親戚の1つを呼び出すことを見つけるのは一般的です。Intel(または他のコンパイラー作成者)の観点からは、これは理にかなってexpいます。好きな言語で堅牢で高速な実装を1つ作成し、Fortran、C、Ada、COBOL、およびこれまでに使用した他のすべての言語から呼び出します。聞いた。それをCで書くことさえ賢明かもしれません。したがって、あなたの仮説の一部は正しいかもしれません。

ただし、CコードとFortranコードを明示的に記述し、それから単一のバイナリを作成しない限り、(Fortranの標準的な意味での)相互運用性は実際には発生しません。コンパイラーは、実装に使用するライブラリーへの正しい呼び出しを生成し、 sなどexpを含む可能性のある戻り値を取得する必要があります。NaN

確かに、の値はexp(-230)40.00000000バイトの実数に対するものですが、Cで記述されたライブラリを使用するFortranプログラムがこれらの数値に遭遇するため、アクセス違反を発生させる理由はわかりません。プログラムの他の場所でエラーが発生している可能性がはるかに高いと思います。おそらく、配列の境界外の配列要素にアクセスしようとしており、ランタイムがソースコードの正しい場所でそれを識別できない可能性があります。これは珍しいことではありません。

編集

質問を(再)読む前に、相互運用性についてこの記事を書きました。相互運用性機能を使用していることを明確にしたので、興味があるか、使用している可能性があります...

real(4)確かに、FortranとCfloatが同一であることに依存することはできません。可能性は非常に高いですが、確実ではありません。最新のFortranコンパイラー(Intelを含む)のほとんどは、表現のバイト数と一致する種類パラメーターを使用するため、コード4は、IEEE-754準拠のプロセッサーでは4バイトの実数を処理していることを示しています。 Cと同じfloatです。Fortran標準では、これらの種類の型パラメーターと、数値を表すために使用されるバイト数との間に対応関係は必要ありません。コンパイラのドキュメントを確認するか、いくつかのテストを行うことは常に価値があります。

相互運用性が心配な場合は、Fortranの固有の機能を使用する必要があります。たとえば、

use :: iso_c_binding

次のように使用できる定数を含む、いくつかの定数をC_FLOAT使用できます。

real(C_FLOAT) :: a_fortran_float

Fortranコンパイラがこれをサポートしている場合は、コンパニオンプロセッサa_fortran_floatのCフロートと一致する必要があります。この最後の用語はやや未定義のままです。実際には、同じ厩舎のコンパイラは常にコンパニオンのように見えます。異なる厩舎の場合は、はい、いいえの場合があります。IntelFortranとCおよびC++コンパイラは、必要な意味でコンパニオンのようです。IntelFortranコンパイラとMSC++コンパイラがうまく連携しないことを知っても驚くことではありません。

私のCの漠然とした記憶には、float標準化された不確実性が含まれています。その場合、ドキュメントをテストまたは読むことなく、実際に4バイトのIEEE単精度浮動小数点数があなたの相互運用のどちらか。

于 2013-01-15T11:57:01.617 に答える