我正在开发一个项目,我需要将一些现有数据写入磁盘ascii。我有一些有用的东西,但IO本身非常昂贵,我想进一步优化它。
数据基本上是一个实数数组,但是有些列存储了需要重新编码为字符串的编码字符串(不要问!)。这个问题的输入和输出是我无法控制的,我收到这个真正的数组,需要把它写成ascii。
我知道一次编写数组作为无格式写入更快,但这并不能正确处理字符串列。有什么想法吗?
以下是一些示例代码:
program test
implicit none
integer(kind=4), parameter :: nrows = 5000
integer(kind=4), parameter :: ncols = 400
integer, parameter :: real_kind = 8
integer(kind=4) :: i,j, handle
character(len=256) :: value_str
character(len=1) :: delimiter
real(kind=real_kind) :: data(nrows,ncols)
delimiter = " "
data(:,:) = 999.999
! Some examples of the "string columns"
data(:,10) = transfer(' foo ',data(1,1))
data(:,20) = transfer(' bar ',data(1,1))
handle=10
open(handle,file="out.txt",status="replace", access="stream")
do i=1,nrows
do j=1,ncols
! If this column contains encoded strings then recast
if((j==10).or.(j==20))then
write(handle) delimiter
value_str = transfer(data(i,j),value_str(1:real_kind))
write(handle) trim(value_str)
else
write(value_str,*) data(i,j)
write(handle) trim(value_str)
endif
enddo
write(handle) new_line('x')
enddo
close(handle)
end program test
gfortran test.F90 -o test.x
time test.x
真正的0m2.65s
用户0m2.24s
sys 0m0.04s
编辑:从原始test.F90代码示例中删除“if(j / = 1)”以回应评论。
答案 0 :(得分:2)
使用免费格式,让系统处理更多。在这个命题中,我事先处理传输并使用单个循环将数据写入文件。如果您只有几列字符数据,例如示例中的2,那么这很方便。
您的代码将如下所示
program test
implicit none
integer(kind=4), parameter :: nrows = 5000
integer(kind=4), parameter :: ncols = 400
integer, parameter :: real_kind = 8
integer, parameter :: pos1 = 10 ! I like named constants
integer, parameter :: pos2 = 20 ! I like named constants
integer(kind=4) :: i,j, handle
character(len=256) :: value_str
character(len=1) :: delimiter
real(kind=real_kind) :: data(nrows,ncols)
character(real_kind), dimension(nrows,2) :: cdata ! two columns array for
delimiter = " "
data(:,:) = 999.999
! Some examples of the "string columns"
data(:,pos1) = transfer(' foo ',data(1,1))
data(:,pos2) = transfer(' bar ',data(1,1))
handle=10
open(handle,file="out.txt",status="replace", form="formatted")
! Transfer beforehand
cdata(:,1) = transfer( data(:,pos1), cdata(1,1) )
cdata(:,2) = transfer( data(:,pos2), cdata(1,1) )
do i=1,nrows
write(handle,*) data(i,1:pos1-1), cdata(i,1)&
, data(i,pos1+1:pos2-1), cdata(i,2)&
, data(i,pos2+1:)
enddo
close(handle)
end program test
并给出这个时间
时间./test.x
真正的0m1.696s
用户0m1.661s
sys 0m0.029s
而不是
时间./test.x
真正的0m2.654s
用户0m2.616s
sys 0m0.032s
在我的电脑上