Fortran execute_command_line运行时错误,取决于内存消耗

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)得出相同的结果。有些故障较早发生,有些故障几乎需要程序占用的整个物理内存。不幸的是,我现在没有单插槽机器可以测试。

jan*_*neb 3

因此,EXECUTE_COMMAND_LINE 以及 SYSTEM 内在函数在 Linux 上的实现方式是,进程首先调用 fork() 系统调用,该系统调用创建进程的克隆。然后子进程将调用 exec() ,该进程用要执行的新进程替换该进程。

因此,即使第二个分叉进程在被新的 exec()ed 进程替换之前生命周期很短,系统仍然需要足够的虚拟内存来容纳原始进程和分叉子进程。在 Linux 上,如果您具有超级用户访问权限,则可以使用各种“过量使用”旋钮调整限制(作为物理内存的函数)。

如果可能,解决此问题的一种方法是在分配大量内存之前或释放内存之后调用 EXECUTE_COMMAND_LINE。