最佳答案
我得到了一个512 ^ 3的数组,它代表了一个模拟的温度分布(用 Fortran 编写)。数组存储在一个二进制文件中,大小约为1/2G。我需要知道这个数组的最小值、最大值和平均值,因为我很快就需要理解 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)
现在,我当然希望它能更快,但是我真的被震惊了。在相同的条件下,不到一秒钟。平均值偏离了我的 Fortran 例程找到的那个(我也用128位浮点运行,所以我多少更信任它) ,但只有在第7个有效数字左右。
麻木怎么会这么快?我的意思是你必须查看数组的每个条目才能找到这些值,对吗?我是不是在 Fortran 例程中做了什么很蠢的事情,以至于花了这么长时间?
编辑:
回答评论中的问题:
iso_fortran_env
。编辑2:
我实现了@Alexander Vogt 和@casey 在他们的回答中提出的建议,速度和 numpy
一样快,但现在我有一个精度问题,正如@Luaan 指出的那样。使用32位浮点数组,由 sum
计算的平均值会减少20% 。做什么
...
real,allocatable :: tmp (:,:,:)
double precision,allocatable :: tmp2(:,:,:)
...
tmp2=tmp
mean=sum(tmp2)/size(tmp)
...
解决了这个问题,但是增加了计算时间(不是很多,但是很明显)。
有没有更好的办法来解决这个问题?我找不到一种方法直接从文件中读取单个文件到双个文件。
那么 numpy
如何避免这种情况呢?
谢谢你到目前为止的帮助。