我正在开发具有编译语言(Fortran 95)的代码,该编译语言对大型星系目录进行了某些计算。每次执行一些更改时,我都会编译并运行代码,只需要用磁盘上的星系数据读取ASCII文件大约需要3分钟。这是浪费时间。诀窍在成本汇编之间更快地从硬盘中读取数据
如果我在IDL或Matlab中开始这个项目,那么它会有所不同,因为包含数组数据的变量将保存在不同编译之间的内存中。
但是,我认为可以做一些事情来加速来自磁盘的令人不安的读取,例如将文件放在假的RAM分区或其他东西中。
我正在开发具有编译语言(Fortran 95)的代码,该编译语言对大型星系目录进行了某些计算。每次执行一些更改时,我都会编译并运行代码,只需要用磁盘上的星系数据读取ASCII文件大约需要3分钟。这是浪费时间。诀窍在成本汇编之间更快地从硬盘中读取数据
如果我在IDL或Matlab中开始这个项目,那么它会有所不同,因为包含数组数据的变量将保存在不同编译之间的内存中。
但是,我认为可以做一些事情来加速来自磁盘的令人不安的读取,例如将文件放在假的RAM分区或其他东西中。
而不是在RAM磁盘上的细节我建议你从ASCII数据库切换到二进制。这里是一个非常简单的例子...随机数的数组,存储为ASCII(ASCII.txt)和二进制日期(binary.bin):
program writeArr
use,intrinsic :: ISO_Fortran_env, only: REAL64
implicit none
real(REAL64),allocatable :: tmp(:,:)
integer :: uFile, i
allocate(tmp(10000,10000))
! Formatted read
open(unit=uFile, file='ASCII.txt',form='formatted', &
status='replace',action='write')
do i=1,size(tmp,1)
write(uFile,*) tmp(:,i)
enddo !i
close(uFile)
! Unformatted read
open(unit=uFile, file='binary.bin',form='unformatted', &
status='replace',action='write')
write(uFile) tmp
close(uFile)
end program
下面是结果在大小方面:
:> ls -lah ASCII.txt binary.bin
-rw-rw-r--. 1 elias elias 2.5G Feb 20 20:59 ASCII.txt
-rw-rw-r--. 1 elias elias 763M Feb 20 20:59 binary.bin
因此,您在存储方面节省了约3.35倍。 现在到了有趣的部分:在...
program readArr
use,intrinsic :: ISO_Fortran_env, only: REAL64
implicit none
real(REAL64),allocatable :: tmp(:,:)
integer :: uFile, i
integer :: count_rate, iTime1, iTime2
allocate(tmp(10000,10000))
! Get the count rate
call system_clock(count_rate=count_rate)
! Formatted write
open(unit=uFile, file='ASCII.txt',form='formatted', &
status='old',action='read')
call system_clock(iTime1)
do i=1,size(tmp,1)
read(uFile,*) tmp(:,i)
enddo !i
call system_clock(iTime2)
close(uFile)
print *,'ASCII read ',real(iTime2-iTime1,REAL64)/real(count_rate,REAL64)
! Unformatted write
open(unit=uFile, file='binary.bin',form='unformatted', &
status='old',action='read')
call system_clock(iTime1)
read(uFile) tmp
call system_clock(iTime2)
close(uFile)
print *,'Binary read ',real(iTime2-iTime1,REAL64)/real(count_rate,REAL64)
end program
回读的结果是
ASCII read 37.250999999999998
Binary read 1.5460000000000000
所以,> 24的一个因素!
因此,不要考虑其他任何事情,请先切换到二进制文件格式。
当然,还有很多二进制格式更适合复杂的数据,并且比简单的Fortran二进制文件更具可移植性。其中我建议你考虑HDF5。 –
这是一个非常棒的答案,对很多人来说都很有用(+1),但是原始文件有多种类型(第1列是字符,第2列是整数,其他列是浮点...),我定义了派生类型。编写二进制文件时,我不确定如何处理这个问题。我还有其他的代码,我去了二进制文件,可以在合理的时间内存储和读取16000x16000双精度数组。 – Mephisto
但是,您将ASCII文件读取为派生类型可能适用于未格式化的文件。例如,读取整数分量,然后读取真实分量,等等。如果遇到问题,请提出其他问题。 – Ross
为了更好地匹配我选择的答案,我稍微更改了标题。这个答案并不适合我原来的答案100%(没有关于如何在RAM中做分区的线索),但它不太有用,不会奖励它的绿色标签。我将特意发布有关RAM目录的另一个问题。 – Mephisto
您是否做了一些实际测量,或者您是否猜测瓶颈是磁盘I/O而不是解析ASCII数据格式?假设你有足够的RAM用于虚拟硬盘,你可能还有足够的磁盘缓存可用,所以很可能你已经大部分都是从内存中读取数据。接受的答案暗示了这一点。 –
@DanMašek我忽略了你提出的具体内容,但是我认为登录后第一次执行代码的时间要比连续读取的时间长。另外,当文件正在读取时,TOP命令不会显示100%的cpu活动,所以可能是硬盘读取问题。 – Mephisto