使用Gfortran写入并使用SLEEP()等待后,写入的数据在文件中不可见
当我在程序中遇到一个奇怪的行为时,我正在用下面的代码进行一些测试。当我在程序中调用内在子例程“sleep”时,没有任何内容写入文件testing.dat。如果我删除了对这个子程序的调用,它工作得很好,数字就被写出来了。我用英特尔Fortran尝试了同样的代码(调用子例程“sleep”),效果也不错 在我看来,在使用gfortran编译的程序写入文件之前,睡眠子例程在某种意义上会停止执行,这是使用英特尔fortran不会发生的行为。我不是计算机科学专家,但这是我的猜测,其他人有更好的吗? 我尝试了下面所有的旗帜,但没有任何改变: gfortran-g file.f90-o可执行文件 gfortran file.f90-o可执行文件 gfortran-O3 file.f90-o可执行文件 我使用的是xubuntu 18.01操作系统使用Gfortran写入并使用SLEEP()等待后,写入的数据在文件中不可见,fortran,sleep,gfortran,intel-fortran,Fortran,Sleep,Gfortran,Intel Fortran,当我在程序中遇到一个奇怪的行为时,我正在用下面的代码进行一些测试。当我在程序中调用内在子例程“sleep”时,没有任何内容写入文件testing.dat。如果我删除了对这个子程序的调用,它工作得很好,数字就被写出来了。我用英特尔Fortran尝试了同样的代码(调用子例程“sleep”),效果也不错 在我看来,在使用gfortran编译的程序写入文件之前,睡眠子例程在某种意义上会停止执行,这是使用英特尔fortran不会发生的行为。我不是计算机科学专家,但这是我的猜测,其他人有更好的吗? 我尝试了
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, j, k
write(34,'(3I8)') i, j, k
call sleep (1)
end do
end do
end do
end program
文件输出可以缓冲。这意味着要写入外部文件的字符或字节首先在内存中的某个位置收集,然后以较大的块写入外部文件。这样可以加快文件输出速度。如果随机查看外部文件i,它不必包含所有执行的
write
语句的输出,有些语句可能在缓冲区中。flush(unit)
语句通过刷新数据使外部进程可以看到数据。gfortran手册用于旧的子例程状态
FLUSH内在语句和Fortran 2003 FLUSH语句
相同的效果:它们刷新运行库的I/O缓冲区,以便
数据对其他进程可见。这并不能保证
数据已提交到磁盘
文件缓冲通常也可以通过使用编译器标志或环境变量的编译器或运行时库设置来控制。对于gfortran,您可以在以下位置找到运行时变量:
您可能对以下四个变量感兴趣:
GFORTRAN\u UNBUFFERED\u ALL
:不要为所有单元缓冲I/OGFORTRAN\u未缓冲\u预连接
:不要为预连接的单元缓冲I/O。GFORTRAN\u格式化的\u缓冲区大小
:格式化文件的缓冲区大小GFORTRAN\u未格式化\u缓冲区大小
:未格式化文件的缓冲区大小您不会在任何地方关闭文件。使用关闭(34)
。你真的打算等待9999997000002999999秒吗?那将是一个漫长的等待。请注意,只有经过一些缓冲后,数据才能在文件中可见。先尝试少量数据,9x9x9应该足够了。您也可以尝试使用flush(34)
。您可以说该代码可以编译并与Intel配合使用。一年大约有31536000秒。因此,如果该计划真的需要睡眠,则需要3.17e13年才能完成。“工作正常”是什么意思?关于运行程序的时间,我只是用gdb做了一些实验(我正在学习)。我没想到它会一直运行。“英特尔fortran”的良好运行意味着它在程序完成之前将数字写入文件(我用Ctrl+c停止了它),而gfortran则没有。我将数据量减少到2x2x2,即使使用gfortran,它也会写入数字。对我来说,最终的结果是,如果我使用gdb调试任何结合了睡眠和写入命令的程序,我可以在执行结束之前获得空文件。使用flush(34),使用gfortran编译的程序在执行过程中写入了我所期望的文件。我不知道这个函数。谢谢@VladimirFgfortran将缓冲其输出。您可以使用手册中记录的环境变量来控制这一点。请参阅GFORTRAN_UNBUFFERED_ALL。请注意,即使在刷新之后,数据也可能位于操作系统或磁盘固件控制的其他缓冲区或缓存中,因此“这并不保证数据提交到磁盘。”。