26

CFDソルバーがあり、シミュレーションの実行中に、一部のマシンでは非常に低速で実行されることがわかりましたが、他のマシンでは実行されませんでした。Intel VTuneを使用すると、次の行が問題であることがわかりました(Fortranの場合)。

RHOV= RHO_INF*((1.0_wp - COEFF*EXP(F0)))**(1.0_wp/(GAMM - 1.0_wp))

VTuneでドリルインすると、問題はcall pow組立ラインにトレースされ、スタックをトレースすると、を使用していることがわかりました__slowpow()。いくつか検索した後、このページは同じことについて不平を言っているように見えました。

libcバージョン2.12のマシンでは、シミュレーションに18秒かかりました。libcバージョン2.14のマシンでは、シミュレーションに0秒かかりました。

上記のページの情報に基づくと、ベースがpow()1.0に近い場合に問題が発生します。そこで、別の簡単なテストを実行しました。このテストでは、ベースの前に任意の数値をスケーリングし、呼び出しpow()後に指数に累乗した数値で除算しました。pow()これにより、libc2.12でもランタイムが18秒から0秒に短縮されました。

ただし、これをコード全体に配置することは実用的ではありませんa**bpow()libcの関数をどのように置き換えますか?たとえばcall pow、Fortranコンパイラーによって生成された組立ラインpow()で、スケーリングを実行し、libcpow()を呼び出してから、スケーリングで除算するカスタム関数を呼び出すようにします。コンパイラに対して透過的な中間層をどのように作成しますか?

編集

明確にするために、(擬似コード)のようなものを探しています:

double pow(a,b) {
   a *= 5.0
   tmp = pow_from_libc(a,b)
   return tmp/pow_from_libc(5.0, b)
}

pow名前の競合を回避するために、from libcをロードし、カスタム関数で名前を変更することは可能ですか?customPow.oファイルの名前をlibcから変更できる場合、pow他の目的でlibcがまだ必要な場合はどうなりますか?powそれはincustomPow.oとinlibcの間で名前の競合を引き起こしpowますか?

4

4 に答える 4

24

さて、ちょっと待ってください。__slowpow()図書館はあなたと一緒におもちゃを呼ぶだけではありません。__slowpow()与えている値(この場合、1に非常に近いベース、次数1の指数)に対して正確な結果を与えるには、追加の精度が必要であると考えているため、呼び出しています。この計算の精度に関心がある場合は、それを回避する前に、その理由とそれが重要かどうかを理解する必要があります。(たとえば)大きな負のF0の場合、この全体を安全に1に丸めることができます。または、後でこの値をどのように処理するかによっては、そうでない場合もあります。1.d0からこの結果を差し引いたものが必要な場合は、その精度を高める必要があります。

于 2012-02-14T17:12:42.450 に答える
9

pow独自の関数を記述し、ファイルをリンカーのライブラリパスのどこかに.oある静的ライブラリアーカイブに配置し、リンク時に渡すだけです。libmypow.a-lmypow

于 2012-02-14T05:38:33.927 に答える
4

pow(a,b)と同じですexp(b*ln(a))、多分その置換はあなたのために働くでしょう。

于 2012-02-14T05:31:56.293 に答える
1

私はこれを自分でテストしました。実際、リンク先のページからテストプログラムをコンパイルするとcall pow、アセンブリコードで使用されます。ただし、最適化を使用してコンパイルする-ffast-math場合、powを呼び出す必要はありませんが、結果はわずかに異なります。

于 2012-02-14T10:00:46.167 に答える