您的Fortran实现有两个主要缺点:您可以混合IO和计算(并按条目从文件条目读取)。
您不使用向量/矩阵操作。
此实现确实执行与您的实现相同的操作,并且在我的机器上比您的执行速度快20倍:program test
integer gridsize,unit
real mini,maxi,mean
real, allocatable :: tmp (:,:,:)
gridsize=512
unit=40
allocate( tmp(gridsize, gridsize, gridsize))
open(unit=unit,file='T.out',status='old',access='stream',&
form='unformatted',action='read')
read(unit=unit) tmp
close(unit=unit)
mini = minval(tmp)
maxi = maxval(tmp)
mean = sum(tmp)/gridsize**3
print *, mini, maxi, mean
end program
这样做的目的是将整个文件读入一个数组中。tmp一步一步。然后,我可以使用这些函数MAXVAL,MINVAL,和SUM直接在数组上。
对于精度问题:只需使用双精度值,并执行动态转换,如mean = sum(real(tmp, kind=kind(1.d0)))/real(gridsize**3, kind=kind(1.d0))
只略微增加计算时间。我试着按元素的顺序和切片执行操作,但这只会增加默认优化级别所需的时间。
在-O3,元素级加法比数组运算执行约3%的运算。下面是使用LAPACK的一个非常快速的实现:program test
integer gridsize,unit, i, j
real mini,maxi
integer :: t1, t2, rate
real, allocatable :: tmp (:,:,:)
real, allocatable :: work(:)
! double precision :: mean
real :: mean
real :: slange
call system_clock(count_rate=rate)
call system_clock(t1)
gridsize=512
unit=40
allocate( tmp(gridsize, gridsize, gridsize), work(gridsize))
open(unit=unit,file='T.out',status='old',access='stream',&
form='unformatted',action='read')
read(unit=unit) tmp
close(unit=unit)
mini = minval(tmp)
maxi = maxval(tmp)
! mean = sum(tmp)/gridsize**3
! mean = sum(real(tmp, kind=kind(1.d0)))/real(gridsize**3, kind=kind(1.d0))
mean = 0.d0
do j=1,gridsize
do i=1,gridsize
mean = mean + slange('1', gridsize, 1, tmp(:,i,j),gridsize, work)
enddo !i
enddo !j
mean = mean / gridsize**3
print *, mini, maxi, mean
call system_clock(t2)
print *,real(t2-t1)/real(rate)
end program
这使用单精度矩阵1-范数。SLANGE在矩阵列上。运行时甚至比使用单精度数组函数的方法还要快,并且没有显示精度问题。