使用英特尔编译器时,我在编写和读取大文件时遇到问题。
为了缩小范围,我写了一个简单的例程,它以2种方式写入文件,然后立即读取它。
program readvmold
implicit none
integer :: i,j
real(8),allocatable :: WMSH(:),RMSH(:,:)
integer :: NMSH,JCALC, ierr
integer :: NMSH2,JCALC2
NMSH = 39691212
JCALC = 1
allocate(WMSH(NMSH),RMSH(3,NMSH),STAT=i)
if(i/=0)write(6,*)'error allocating wmsh'
! fill with test numbers
do i=1,NMSH
WMSH(i)=real(i)
RMSH(1,i)=real(i)
RMSH(2,i)=real(i+1)
RMSH(3,i)=real(i+2)
end do
! -------------------------------------------------------------------------
! test stream filetype
write(6,*)'writing VM2',NMSH,JCALC
open(103,file='VM2',FORM='UNFORMATTED',ACCESS='STREAM')
rewind(103)
WRITE(103) NMSH,JCALC
WRITE(103)((RMSH(J,I),J=1,3),I=1,NMSH)
WRITE(103)(WMSH(I),I=1,NMSH)
close(103)
j=-1;i=-1
open(103,file='VM2',FORM='UNFORMATTED',STATUS='OLD',ACCESS='STREAM')
rewind(103)
READ(103,END=103) NMSH2,JCALC2
write(6,*)'2: TOTAL NUMBER OF MESH POINTS: ',NMSH2,JCALC2
READ(103,END=103)((RMSH(J,I),J=1,3),I=1,NMSH)
READ(103,END=103)(WMSH(I),I=1,NMSH)
CLOSE(103)
write(6,*)'done reading VM2'
! check wmsh
ierr=0
do i=1,NMSH
if(RMSH(1,i)/=real(i))ierr=ierr+1
if(RMSH(2,i)/=real(i+1))ierr=ierr+1
if(RMSH(3,i)/=real(i+2))ierr=ierr+1
if(WMSH(i)/=real(i)) ierr=ierr+1
end do
write(6,*)'Stream writing passed'
if(ierr>0)write(6,*)'stream errors:',ierr
go to 150
103 write(6,*)'END 103:j,i',j,i
150 continue
! -------------------------------------------------------------------------
! fill with test numbers
do i=1,NMSH
WMSH(i)=real(i)
RMSH(1,i)=real(i)
RMSH(2,i)=real(i+1)
RMSH(3,i)=real(i+2)
end do
! test rewriting VMOLD
write(6,*)'writing VM3',NMSH,JCALC
open(103,FILE='VM3',FORM='UNFORMATTED',STATUS='UNKNOWN')
rewind(103)
WRITE(103) NMSH,JCALC
WRITE(103)((RMSH(J,I),J=1,3),I=1,NMSH)
WRITE(103)(WMSH(I),I=1,NMSH)
close(103)
write(6,*)'done writing VM3'
j=-1;i=-1
open(103,FILE='VM3',FORM='UNFORMATTED',STATUS='UNKNOWN')
rewind(103)
READ(103) NMSH2,JCALC2
write(6,*)'3: TOTAL NUMBER OF MESH POINTS: ',NMSH2,JCALC2
if(NMSH2/=NMSH)write(6,*)'NMSH2 not equal to NMSH',NMSH2,NMSH
READ(103,END=200)((RMSH(J,I),J=1,3),I=1,NMSH)
READ(103,END=300)(WMSH(I),I=1,NMSH)
CLOSE(103)
write(6,*)'done reading WMSH3'
! check wmsh
ierr=0
do i=1,NMSH
if(RMSH(1,i)/=real(i))ierr=ierr+1
if(RMSH(2,i)/=real(i+1))ierr=ierr+1
if(RMSH(3,i)/=real(i+2))ierr=ierr+1
if(WMSH(i)/=real(i)) ierr=ierr+1
end do
write(6,*)'VM3 read passed'
if(ierr>0)write(6,*)'non-stream errors:',ierr
! end test
go to 250
200 write(6,*)'END 200:j,i',j,i
go to 250
300 write(6,*)'END 300:j,i',j,i
250 continue
deallocate(WMSH,RMSH)
end program readvmold
在第一次阅读期间的某个时刻,它将转到200,或者因错误而崩溃:
forrtl: severe (24): end-of-file during read, unit 100, file /global/u2/c/cdiaz/NRLMOL_CURRENT/git/vmold/VM3
如果我使用ACCESS='STREAM'
来撰写和阅读,我就不会看到这个问题。我宁愿不使用流,因为它会使代码无法读取旧版本生成的文件,我们需要重新启动计算。
我只是尝试过这个,因为我在其他类似的情况下看到了这个建议,但我并不理解为什么它在其他方面起作用。
我默认在intel / 6.0.3 NERSC模块中使用ifort 17.0.1.132,但失败了。只有在我使用-O0优化时,Intel / 6.0.1才有效。
我在另一台显示ifort版本15.0.1.133 Build 20141023的nersc计算机上进行了测试,它运行正常。