シミュレーション(Fortranで書かれている)から温度分布を表す512^3の配列が得られます。配列は約1/2Gサイズのバイナリファイルに格納されます。私はこの配列の最小値、最大値および平均値を知る必要があります。そして、とにかくFortranコードを理解する必要があるので、私はそれを実行し、次の非常に簡単なルーチンを思いつきました。numpyは私のFortranルーチンよりもずっと高速でしょうか?
integer gridsize,unit,j
real mini,maxi
double precision mean
gridsize=512
unit=40
open(unit=unit,file='T.out',status='old',access='stream',&
form='unformatted',action='read')
read(unit=unit) tmp
mini=tmp
maxi=tmp
mean=tmp
do j=2,gridsize**3
read(unit=unit) tmp
if(tmp>maxi)then
maxi=tmp
elseif(tmp<mini)then
mini=tmp
end if
mean=mean+tmp
end do
mean=mean/gridsize**3
close(unit=unit)
これは、使用しているマシンでファイルごとに約25秒かかります。それはかなり長いものとして私を襲ったので、私は先に行って、Pythonで次のようでした:
import numpy
mmap=numpy.memmap('T.out',dtype='float32',mode='r',offset=4,\
shape=(512,512,512),order='F')
mini=numpy.amin(mmap)
maxi=numpy.amax(mmap)
mean=numpy.mean(mmap)
は今、私は、これは当然の速くなると予想したが、私は本当に吹き飛ばされました。同じ条件下では1秒もかかりません。私のFortranルーチンが見つけたものからの平均(128ビット浮動小数点でも動いていたので、何とかそれをもっと信頼しています)が、7番目の有意な桁にすぎません。
どのようにnumpyを高速にすることができますか?これらの値を見つけるために配列のすべてのエントリを調べなければならないのですよね?私はFortranのルーチンで非常に愚かなことをしていますか?
EDIT:
コメントでの質問に答えるために:
- はい、また私は、32ビットおよび64ビットの浮動小数点数とFortranのルーチンを実行しましたが、それは、パフォーマンスに影響を及ぼしませんでした。
- 私は128ビット浮動小数点を提供する
iso_fortran_env
を使用しました。 - 32ビット浮動小数点を使用すると、私の平均値はかなり小さくなります。したがって、精度は本当に問題です。
- 私は両方のルーチンを別々のファイルで異なる順序で実行しました。だから、キャッシュは私が推測している比較の中で公正であったはずですか?
- 私は実際に開いたMPを試みましたが、同時に異なる位置でファイルから読み込みました。あなたのコメントと答えを読んだら、これは本当にばかげた音となり、日常生活にもかなり時間がかかりました。私はそれを配列操作で試してみるかもしれませんが、多分それは必要ではないでしょう。
- ファイルは実際にはサイズが1/2Gです。これはタイプミスです。ありがとうございました。
- ここで配列の実装を試みます。
EDIT 2:
私はその答えで提案されているものを@Alexanderフォークトと@casey実装し、それが早くnumpy
ようですが、@Luaanが、私は可能性があります指摘したように、今私は、精度の問題を抱えています取得する。 32ビット浮動小数点配列を使用すると、sum
で計算された平均は20%オフです。 Doing
...
real,allocatable :: tmp (:,:,:)
double precision,allocatable :: tmp2(:,:,:)
...
tmp2=tmp
mean=sum(tmp2)/size(tmp)
...
問題を解決しますが、計算時間が増加します(ただし、それほど顕著ではありません)。 この問題を回避するより良い方法はありますか?私は、ファイルから直接ダブルスにシングルを読む方法を見つけることができませんでした。 そして、どうすればnumpy
はこれを避けますか?
これまでのお役に立てていただきありがとうございます。
128ビット浮動小数点なしでFortranルーチンを試しましたか?私はそれらを実際にサポートするハードウェアは認識していないので、ソフトウェアで行う必要があります。 – user2357112
配列を使用してFortranバージョンを試してみると(特に10億ではなく1つの読み込みを使用して)どうすればよいでしょうか? – francescalus
Fortranでも配列演算子を使用することを検討しましたか?次に、 'minval()'、 'maxval()'、 'sum()'を試すことができますか?さらに、IOをFortranでの演算と混合していますが、Pythonではそうではありません - それは公正な比較ではありません;-) –