私たちはCFDソルバーを持っていて、シミュレーションを実行している間にマシンによっては非常に遅く実行されていましたが、非常に遅いpow()関数の置き換え
RHOV= RHO_INF*((1.0_wp - COEFF*EXP(F0)))**(1.0_wp/(GAMM - 1.0_wp))
ドリルのVTuneで、問題はcall pow
組立ラインにトレースし、スタックをトレースするとき、それが使用したことを示した:インテルのVTuneを使用して、次の行が(Fortranで)問題で見出されました__slowpow()
。何らかの検索の後、this pageが同じことについて不平を言った。
libcバージョン2.12のマシンでは、シミュレーションに18秒かかりました。 libcバージョン2.14のマシンでは、シミュレーションには0秒かかりました。
上記のページの情報に基づいて、pow()
の底辺が1.0に近い場合に問題が発生します。だから我々はpow()
の前に任意の数で基数をスケールし、次にpow()
呼び出しの後に指数に上げた数で除算した別の簡単なテストを行った。これにより、libc 2.12でもランタイムが18秒から0秒に落ちました。
ただし、コード全体にこれを置くことは現実的ではありません。a**b
libcのpow()
機能をどのように置き換えるのですか?例えば、アセンブリラインcall pow
がFortranコンパイラによって生成され、カスタムpow()
という関数を呼び出してスケーリングを行い、libc pow()
を呼び出し、スケーリングで除算したいとします。コンパイラに対して透過的な中間層を作成するにはどうすればよいですか?
は、我々は(擬似コード)のようなものを探している明確にする編集:
double pow(a,b) {
a *= 5.0
tmp = pow_from_libc(a,b)
return tmp/pow_from_libc(5.0, b)
}
はそれにlibcからpow
をロードして、私たちのカスタム関数でその名前を変更することは可能です命名の競合を避けるために? customPow.o
ファイルの名前をpow
からlibcに変更できる場合は、libcがまだ他のものに必要な場合はどうなりますか? libcのpow
とcustomPow.o
とpow
の名前の競合が発生しますか?
Good ol 'Fortran!興味深い質問+1 –