シミュレーションコードの一部には、特定の密度と温度で不透明度を見つける必要があります。このための分析的関係はありません。標準的な方法は、opacity(i,j)
がdensity(i)
とtemperature(j)
の不透明度に対応する2D配列を使用し、正確な不透明度を見つけるために双線形補間を実行することです。Fortranの高性能ルックアップテーブル
私のグループコードのボトルネックは、現在のところ、補間ルーチンが異なる密度と温度で約1億回と呼ばれ、ランタイムの約20%を占めています。現在のコードを以下に示します。改善のために使用できるトリックはありますか?私は私が正しく理解していれば、あなたはopc
内の値を見つけるために、後で使用するインデックスを見つけるために、rhoT
の全体をループをやっているオプションを使用して、インテルFortran 16、-O3 -xavx -mcmodel=medium
function smoothopc(den, temp, ig, opc, rhoT)
implicit none
real(kind=8), intent(in) :: den,temp
integer,intent(in) :: ig
real(kind=8), intent(in), dimension(1:50, 1:50, 1:52) :: opc
real(kind=8), intent(in), dimension(1:50, 1:2) :: rhoT
real(kind=8) :: rho, te, smoothopc, r1, r2, t1, t2, &
interpolation, denominator, a, b, c, d, opc11, &
opc12, opc21, opc22, t, tp, r, rp
integer :: rid,tid,i
rho = den * 1d - 3 !g/cc
te = temp/(1.6d - 19) !eV
tid = -1
rid = -1
do i = 1, 49
r = rhoT(i, 1)
rp = rhoT(i + 1, 1)
t = rhoT(i, 2)
tp = rhoT(i + 1, 2)
if (rho .ge. r) then
rid = i
endif
if (te .ge. t) then
tid = i
endif
enddo
r1 = rhoT(rid, 1)
r2 = rhoT(rid + 1, 1)
t1 = rhoT(tid, 2)
t2 = rhoT(tid + 1, 2)
opc11 = opc(rid, tid, ig + 4)
opc12 = opc(rid, tid + 1, ig + 4)
opc21 = opc(rid + 1, tid, ig + 4)
opc22 = opc(rid + 1, tid + 1, ig + 4)
denominator = (r2 - r1) * (t2 - t1)
a = r2 - rho
b = rho - r1
c = t2 - te
d = te - t1
interpolation = a * (c * opc11 + d * opc12) + b * &
(c * opc21 + d * opc22)
smoothopc = interpolation/denominator
return
end function smoothopc
ここでボトルネックを見つけるためにこの機能をプロファイルしようとしましたか?私たちが代表的なデータでコードを呼び出すことなく何かをテストすることは、ほとんど不可能です。また、インデントを一貫して使用すると、コードの構造がわかります。 'kind = 8'は醜いものであり、移植性がないことに注意してください。 –
関数を行単位でプロファイリングすることができなかったのですが、gprofを使ってこの関数をコード全体のボトルネックと見なしましたが、この関数に関する詳細情報はどうすれば得られますか?私は 'real(kind = 8) 'の巨大なファンではないが、私は与えられたものと仕事をしなければならない! – VGP
お気に入りのOracle Performance Analyzer(gfortranでも動作します)のような個々の行をプロファイルするプロファイラーがあります。または、おそらくインテル®FortranにvTune Amplifierを組み込む必要があります。そして、*してください、インデントを修正してください、コードは本当に悪く見えます。 –