使用Gfortran写入并使用SLEEP等待后,文件中的书面数据不可见

问题描述

当我在程序中遇到奇怪的行为时,我正在使用以下代码进行测试。当我在程序中使用内部子例程“ sleep”的调用时,什么都没有写入文件testing.dat。如果我删除了对该子程序的调用,它的运行正常,那么数字就被写入了。我在Intel Fortran上尝试了相同的代码(将子例程称为“ sleep”),并且效果也很好。

在我看来,sleep子例程在某种意义上会停止执行使用gfortran编译的程序写入文件之前的执行,这是使用intel fortran不会发生的行为。我不是计算机科学专家,但这是我的猜测,是否还有其他人会更好? 我尝试了以下所有标志,但没有任何改变:

gfortran -g file.f90 -o可执行文件

gfortran file.f90 -o可执行文件

gfortran -O3文件。f90-o可执行文件

我正在使用xubuntu 18.01操作系统。

  program test
            implicit none
            integer ::       i,j,k
            open(34,file="testing.dat")
            do i=1,9999999
              do j=1,9999999
                do k=1,9999999
                    print*,i,k
                    write(34,'(3I8)') i,k
                    call sleep (1)
                end do
              end do
            end do
    end program

解决方法

可以缓冲文件输出。这意味着要写在外部文件中的字符或字节首先聚集在内存中的某个位置,然后再以较大的块写入到外部文件中。这样可以加快文件输出速度。如果您随机查看外部文件,则它不必包含所有已执行的write语句的输出,有些可能在缓冲区中。 flush(unit)语句通过刷新数据使数据对外部进程可见。较旧的flush intrinsic子例程状态的gfortran手册

FLUSH内在函数和Fortran 2003 FLUSH语句具有 效果相同:它们刷新运行时库的I / O缓冲区,以便 数据对其他进程变为可见。这不保证 数据已提交到磁盘。

文件缓冲通常还可以由编译器或运行时库设置使用编译器标志或环境变量来控制。对于gfortran,您可以在https://gcc.gnu.org/onlinedocs/gfortran/Runtime.html#Runtime

中找到运行时变量

您可能对四个变量感兴趣:

GFORTRAN_UNBUFFERED_ALL:请勿为所有单元缓冲I / O
GFORTRAN_UNBUFFERED_PRECONNECTED:请勿为预连接的设备缓冲I / O。
GFORTRAN_FORMATTED_BUFFER_SIZE:格式化文件的缓冲区大小
GFORTRAN_UNFORMATTED_BUFFER_SIZE:未格式化文件的缓冲区大小