优化Fortran ascii文件IO

时间:2016-02-05 11:06:28

标签: fortran

我正在开发一个项目,我需要将一些现有数据写入磁盘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)”以回应评论。

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

在我的电脑上