晚上好,
我有一个用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
答案 0 :(得分:4)
免责声明:我不知道,如果这解决了问题,但我知道,我可以将时间差异提高到20倍。我也只测试了输出数据并没有读过它。
我正在调查Fortran与python的交互,因此想知道Fortran的二进制文件是如何构建的。在执行此操作时,我注意到,ifort
和gfortran
都可以选择打开或关闭缓冲IO。
ifort :您可以在打开文件时指定关键字BUFFERED=['YES'|'NO']
。
gfortran :您可以分别为无缓冲和缓冲的IO设置环境变量GFORTRAN_UNBUFFERED_ALL
为y|Y|1
或n|N|0
。
请注意,gfortran默认会缓冲IO,而ifort则不会。
我在底部的示例代码会产生以下时间:
|buffered|unbuffered
--------+--------+----------
ifort | 1.9s | 18.2s
gfortran| 2.4s | 37.5s
此示例代码写入一个直接访问二进制文件,其中包含每个12字节的10M数据集。
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
答案 1 :(得分:0)
尝试使用StreamIO,请参阅http://www.star.le.ac.uk/~cgp/streamIO.html 这应该允许没有固定记录大小的随机访问,并且可能导致使用相同的底层O.S.系统调用,从而希望获得相同的性能。