Mec*_*Eng 5 bash fortran runtime-error
尝试使用Fortran中的execute_command_line内部函数创建目录时遇到运行时错误。Ifort(18.0.3 20180410)和gfortran(4.8.5)均会发生错误。这是一个最小的示例,该示例因我使用的任何编译标志而失败:
PROGRAM directory_test
IMPLICIT NONE
INTEGER :: cstat, estat, i, j
CHARACTER(LEN=100) :: cmsg
REAL, DIMENSION(:,:), ALLOCATABLE :: field
INTEGER, PARAMETER :: fieldsize = 80000
allocate(field(fieldsize,fieldsize))
do j=1, fieldsize
do i=1, fieldsize
field(i,j) = real(i+j)
end do
end do
call execute_command_line('mkdir -p newdir', WAIT=.true., EXITSTAT=estat, CMDSTAT=cstat, CMDMSG=cmsg)
write(*,*) 'estat: ', estat
write(*,*) 'cstat: ', cstat
write(*,*) 'cmsg: ', cmsg
END PROGRAM directory_test
Run Code Online (Sandbox Code Playgroud)
输出ifort:
estat:0
cstat:124
cmsg:提供给EXECUTE_COMMAND_LINE的命令无效
输出gfortran:
estat:-520880432
cstat:1
cmsg:无法获得命令语言解释器的终止状态
要注意的是:只要数组大小足够小,程序就可以正常运行。对我来说,阈值大约是所用物理内存的一半(如果您想尝试代码,请调整“ fieldsize”的值)。如果数组大于该数组,则会发生错误。如果数组较小,则代码将正确执行,并创建目录。我用来测试的机器都具有2个物理CPU和128GB-256GB的RAM。
我究竟做错了什么?
操作系统:Linux,Opensuse 42.3
shell:bash
文件系统:Ext4
编辑:问题不仅仅限于“ execute_command_line()”。尝试用“ call system()”做同样的事情,我得到类似的行为。如果原始方法因运行时错误而失败,则不会创建新目录。在较小/较旧的双插槽计算机上进行的其他测试(可用内存低至48GB)得出相同的结果。有些故障较早发生,有些故障几乎需要程序占用的整个物理内存。不幸的是,我现在没有单插槽机器可以测试。
因此,EXECUTE_COMMAND_LINE 以及 SYSTEM 内在函数在 Linux 上的实现方式是,进程首先调用 fork() 系统调用,该系统调用创建进程的克隆。然后子进程将调用 exec() ,该进程用要执行的新进程替换该进程。
因此,即使第二个分叉进程在被新的 exec()ed 进程替换之前生命周期很短,系统仍然需要足够的虚拟内存来容纳原始进程和分叉子进程。在 Linux 上,如果您具有超级用户访问权限,则可以使用各种“过量使用”旋钮调整限制(作为物理内存的函数)。
如果可能,解决此问题的一种方法是在分配大量内存之前或释放内存之后调用 EXECUTE_COMMAND_LINE。