Приложение выдает ошибку сегментации через некоторое время при вызове процедуры (содержащей локальные координаты) в цикле - PullRequest
2 голосов
/ 22 сентября 2019

Я пытаюсь вызвать подпрограмму в цикле.Эта подпрограмма имеет локальную структуру.Ниже приведен код, который я использую:

! 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

Прямо сейчас подпрограмма не делает ничего, кроме выделения локального coarray и освобождения его.Но даже при этом программа выдает мне следующую ошибку после некоторых итераций:

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 равна call Aldeal( GHOST_WIDTH ) внутри цикла do основной программы.И строка 37 соответствует оператору deallocate( shell1_Co, shell2_Co, shell3_Co ) в подпрограмме.

Кроме того, если я удаляю оператор deallocate из подпрограммы, она выдает ту же ошибку, но на этот раз номер строки в операторе ошибки составляет 23 и 39Строка 39 соответствует выражению end subroutine Aldeal.

Я не могу понять, что именно я делаю неправильно.Пожалуйста, помогите.

PS Я использую Centos 7 с Intel (R) Parallel Studio XE 2019 Обновление 4 для Linux.

1 Ответ

0 голосов
/ 28 сентября 2019

Наблюдения:

Если я изменю код, чтобы иметь производный тип с выделяемым компонентом, и использую его для создания coarray в подпрограмме, код выполняется немного дольше, но в конечном итоге прерывается с ошибкой.Ниже приводится модификация:

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 = 1e6 до ti = 2e6 требуется больше времени, чем для запуска с ti = 1 до ti = 1e6.
  2. Объем памяти, используемой программой, увеличивается, т. е. каждое изображение, которое потребляет 2GB в начале работы программы, потребляет 3.5GB при ti = 2e6, 4.7GB приti = 4e6 и 6GB при ti = 6e6.
  3. Память, используемая программой, относительно меньше при работе в Windows, но продолжает увеличиваться с увеличением числа циклов.Например, каждое изображение, которое потребляет 100MB при запуске, потребляет 1.5GB при ti = 2e6, 2.5GB при ti = 4e6 и 3.5GB при ti = 6e6.
  4. При использовании опции компилятора /heap-arrays0в Windows не влияет ни на ход (так как он уже был успешно запущен без него), ни на объем памяти, использованный во время работы.
  5. Исходный код, размещенный в вопросе, по-прежнему выдает ошибку даже при компиляции с использованиемвышеупомянутая опция компилятора.Кажется, он не работает и в Windows.

В конечном счете, я все еще не понимаю, что происходит.

PS Я разместил вопрос на форуме Intel, но пока не получил ответа.

...