一段时间后,应用程序在循环中调用过程(包含本地协数组)时引发分段错误

时间:2019-09-22 13:53:42

标签: fortran intel-fortran fortran-coarrays

我试图在循环中调用子程序。该子例程具有局部协同数组。以下是我正在使用的代码:

! Test local coarray in procedure called in a loop.
!
program main
    use, intrinsic :: iso_fortran_env, only : input_unit, output_unit, error_unit

    implicit none

    ! Variable declaration.
    integer :: me, ti
    integer :: GHOST_WIDTH, TSTART, TSTEPS

    sync all

    ! Initialize.
    GHOST_WIDTH = 1
    TSTART = 0
    TSTEPS = 100000
    me = this_image()

    ! Iterate.
    do ti = TSTART + 1, TSTART + TSTEPS
        call Aldeal( GHOST_WIDTH )
        if ( me == 1 ) write( output_unit, * ) ti
    end do

    if ( me == 1 ) write( output_unit, * ) "All done!"

    contains
        subroutine Aldeal( width )
            integer, intent(in) :: width

            integer, allocatable, codimension[:] :: shell1_Co, shell2_Co, shell3_Co

            allocate( shell1_Co[*], shell2_Co[*], shell3_Co[*] )

            deallocate( shell1_Co, shell2_Co, shell3_Co )

            return
        end subroutine Aldeal
end program main

现在,子例程除了分配本地协数组并取消分配之外,没有执行其他任何操作。但是即使执行此操作,该程序在某些迭代后仍会引发以下错误:

forrtl: severe (174): SIGSEGV, segmentation fault occurred
In coarray image 1
Image              PC                Routine            Line        Source             
coarray_main       0000000000406063  Unknown               Unknown  Unknown
libpthread-2.17.s  00007F21D8B845F0  Unknown               Unknown  Unknown
libicaf.so         00007F21D90970D5  for_rtl_ICAF_CO_D     Unknown  Unknown
coarray_main       0000000000405054  main_IP_aldeal_            37  coarray_main.f90
coarray_main       0000000000404AEC  MAIN__                     23  coarray_main.f90
coarray_main       0000000000404A22  Unknown               Unknown  Unknown
libc-2.17.so       00007F21D85C5505  __libc_start_main     Unknown  Unknown
coarray_main       0000000000404929  Unknown               Unknown  Unknown

Abort(0) on node 0 (rank 0 in comm 496): application called MPI_Abort(comm=0x84000003, 0) - process 0

其他图像也会重复同样的错误。

第23行位于主程序的do循环内的call Aldeal( GHOST_WIDTH )。第37行对应于子例程中的deallocate( shell1_Co, shell2_Co, shell3_Co )语句。

此外,如果我从子例程中删除了deallocate语句,它将引发相同的错误,但是这次错误语句中的行号是23和39。第39行对应于end subroutine Aldeal语句。

我无法理解我到底在做什么错。请帮忙。

P.S。我正在将Centos 7与Intel(R)Parallel Studio XE 2019 Update 4 for Linux结合使用。

1 个答案:

答案 0 :(得分:0)

观察:

如果我将代码修改为具有可分配组件的派生类型,并使用它在子例程中创建协数组,则代码将运行更长的时间,但最终会因错误而中止。以下是修改:

module mod_coarray_error
    implicit none

    type :: int_t
        integer, allocatable, dimension(:) :: var
    end type int_t

    contains
        subroutine Aldeal_type( width )
            integer, intent(in) :: width

            type(int_t), allocatable, codimension[:] :: int_t_Co

            allocate( int_t_Co[*] )

            allocate( int_t_Co%var(width) )
            sync all

            ! deallocate( int_t_Co%var )
            deallocate( int_t_Co )

            return
        end subroutine Aldeal_type
end module mod_coarray_error


program main
    use, intrinsic :: iso_fortran_env, only : input_unit, output_unit, error_unit
    use :: mod_coarray_error

    implicit none

    ! Variable declaration.
    integer :: me, ti
    integer :: GHOST_WIDTH, TSTART, TSTEPS, SAVET

    sync all

    ! Initialize.
    GHOST_WIDTH = 3
    TSTART = 0
    TSTEPS = 100000
    SAVET = 1000
    me = this_image()

    ! Iterate.
    do ti = TSTART + 1, TSTART + TSTEPS
        sync all
        call Aldeal_type( GHOST_WIDTH )
        if ( mod( ti, SAVET ) == 0 ) then
            if ( me == 1 ) write( output_unit, * ) ti
        end if
    end do

    sync all

    if ( me == 1 ) write( output_unit, * ) "All done!"
end program main

此外,在Windows中编译时,此代码可以正常运行到最后。

现在,如果我添加了编译器选项heap-arrays 0,即使在Linux中,代码似乎也可以运行到最后。

我尝试将循环数(即代码中的TSTEPS)增加到1e7。即使这样,它也可以成功运行到最后。但我观察到以下效果:

  1. 代码随着循环计数的增加而变慢,即,从ti = 1e6ti = 2e6运行所需的时间比从ti = 1ti = 1e6运行所花费的时间更多。
  2. 程序使用的内存不断增加,即,在程序运行开始时消耗2GB,在3.5GB消耗ti = 2e6,在{{ {1}}和4.7GB的{​​{1}}。
  3. 在Windows中运行时,程序使用的内存相对较少,但随着循环计数的增加,它仍在不断增加。例如,每个在开始时消耗ti = 4e6,在6GB消耗ti = 6e6,在100MB消耗1.5GBti = 2e6 2.5GB的图像。
  4. 在Windows中使用编译器选项ti = 4e6对运行(因为没有它就已经成功运行)或运行时消耗的内存量都没有影响。
  5. 即使使用上述编译器选项进行编译,问题中发布的原始代码仍然会引发错误。它似乎也不能在Windows中运行。

最终,我仍然对正在发生的事情感到困惑。

P.S。我在英特尔论坛上发布了问题,但尚未收到任何回复。