晚上好,
我有一个用Fortran编写的模拟程序,它可以生成未格式化(直接访问)数据的大文件。从这些文件中,我想产生ascii人类可读的文件。
出于某种原因,这(在python中):
f = open(filename,'rb')
for i in xrange(0,N):
pos = i * 64
f.seek(pos)
name = struct.unpack('ffff',f.read(16))
print name[0],name[1],name[2],name[3]
只需约4秒(将输出管道传输到shell上的文件中),而此(在Fortran中)
open (1,file=inputfile,access='direct',recl=64, action='read',status="OLD")
open (2, file=outputfile, access="sequential", action="write",status="REPLACE")
do i=1,(N)
read(1, rec = i ) a,b,c,d
write(2,*) a,b,c,d
enddo
大约需要20秒。我做错了什么?在Fortran中有更快的方法吗?
致以最良好的问候!rer
免责声明:我不知道这是否能解决问题,但我知道,我可以得到20倍的时差。我也只测试了数据的输出,没有读取
我正在研究Fortran与python的交互,因此我想知道Fortran的二进制文件是如何构建的。在进行此操作时,我注意到ifort
和gfortran
都可以选择打开或关闭缓冲IO
ifort:打开文件时可以指定关键字BUFFERED=['YES'|'NO']
。
gfortran:您可以将环境变量GFORTRAN_UNBUFFERED_ALL
分别设置为无缓冲和缓冲IO的y|Y|1
或n|N|0
。
请注意,gfortran默认情况下会缓冲IO,而ifort则不会。
我在底部的示例代码导致以下时间:
|buffered|unbuffered
--------+--------+----------
ifort | 1.9s | 18.2s
gfortran| 2.4s | 37.5s
此示例代码编写了一个直接访问二进制文件,其中包含10M个数据集,每个数据集有12个字节。
PROGRAM btest
IMPLICIT NONE
INTEGER :: i
! IFORT
OPEN(11,FILE="test_d.bin",ACCESS="DIRECT",FORM="UNFORMATTED",RECL=3, &
& STATUS="REPLACE",BUFFERED="NO") ! ifort defines RECL as words
! GFORTRAN
!OPEN(11,FILE="test_d.bin",ACCESS="DIRECT",FORM="UNFORMATTED",RECL=12, &
!& STATUS="REPLACE") ! gfortran defines RECL as bytes
DO i = 1, 10000000
WRITE(11,REC=i) i,i*1._8
END DO
CLOSE(11)
END PROGRAM
尝试使用StreamIO请参阅http://www.star.le.ac.uk/~cgp/streamIO.html这应该允许在没有固定记录大小的情况下进行随机访问,并可能导致使用相同的底层O.S.系统调用,从而有望获得相同的性能。