优化Fortran ascii文件IO

优化Fortran ascii文件IO,fortran,Fortran,我正在做一个项目,我需要将一些现有数据以ascii码的形式写入磁盘。我有一些工作,但IO本身是相当昂贵的,我想进一步优化它 数据基本上是一个实数数组,但是有些列存储编码的字符串,这些字符串需要重新编码为字符串(不要问!)。这个问题的输入和输出超出了我的控制范围,我正在接收这个真实数组,需要将它写成ascii码 我知道以无格式写入方式一次性写入数组会更快,但这并不能正确处理字符串列。有什么想法吗 下面是一些示例代码: program test implicit none integer(kind

我正在做一个项目,我需要将一些现有数据以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

时间测试

真0m2.65s

用户0m2.24s

系统0m0.04s


编辑:从原始test.F90代码示例中删除“if(j/=1)”以响应注释。

使用自由格式,让系统为您处理更多内容。在这个命题中,我预先处理传输,并使用单个循环将数据写入文件。如果像示例中的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

系统0m0.029s

而不是

时间./test.x

真正的0m2.654s

用户0m2.616s

系统0m0.032s


在我的计算机上

什么是“但这不能正确处理字符串列”是什么意思?数据格式的示例在哪里?如果运行上面提供的test.F90代码并查看out.txt,则可以看到数据格式。您可以将字符串读取为“foo”和“bar”,即人类可读。