在连续编译之间更快地从硬盘读取数据的技巧
Trick to read data from hard drive faster between sucessive compilations
我正在使用一种编译语言 (Fortran 95) 开发代码,该代码对一个巨大的星系目录进行某些计算。每次我实施一些更改时,我都会编译并 运行 代码,从磁盘读取带有星系数据的 ASCII 文件大约需要 3 分钟。这是浪费时间。
如果我在 IDL 或 Matlab 中启动这个项目,那么它会有所不同,因为包含数组数据的变量将在不同的编译之间保存在内存中。
但是,我认为可以采取一些措施来加快从磁盘读取令人不安的速度,例如将文件放在假的 RAM 分区或其他东西中。
我建议您从 ASCII 数据库切换到二进制数据库,而不是深入研究 RAM 磁盘的细节。这是一个非常简单的例子……一个随机数数组,存储为 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 95) 开发代码,该代码对一个巨大的星系目录进行某些计算。每次我实施一些更改时,我都会编译并 运行 代码,从磁盘读取带有星系数据的 ASCII 文件大约需要 3 分钟。这是浪费时间。
如果我在 IDL 或 Matlab 中启动这个项目,那么它会有所不同,因为包含数组数据的变量将在不同的编译之间保存在内存中。
但是,我认为可以采取一些措施来加快从磁盘读取令人不安的速度,例如将文件放在假的 RAM 分区或其他东西中。
我建议您从 ASCII 数据库切换到二进制数据库,而不是深入研究 RAM 磁盘的细节。这是一个非常简单的例子……一个随机数数组,存储为 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!
所以先别想别的,先换成二进制文件格式吧。