OpenMP分段错误,带有未调用的程序子例程[duplicate]

问题描述 投票:-1回答:1

在编译选项中启用OpenMP时,我遇到一个非常奇怪的错误。我已将其固定为使用主程序子例程中的动态大小数组对模块子例程的调用。这是一个简化的示例:

module arr_mod
contains
    subroutine add2_mod(arr)
        integer, dimension(:) :: arr
        integer i, n
        n = size(arr)
        do i=1,n
            arr(i) = arr(i)+2
        enddo
    end subroutine
end module

PROGRAM TEST_OMP
    use arr_mod
    integer, dimension(2000000) :: array
    array = 0
    write(*,*) array(1)
contains
    subroutine add2()
        ! Note that this subroutine is not even called in the main program...
        ! When the next line is commented, the program runs.
        call add2_mod(array)
    end subroutine
END PROGRAM TEST_OMP

当我在没有OpenMP的情况下编译并运行该程序时,它运行良好:

$ gfortran -o test_omp test_omp.f90
$ ./test_omp
       0

但是当我使用OpenMP时,程序会立即出现段错误:

$ gfortran -o test_omp test_omp.f90 -fopenmp
$ ./test_omp
[1]    10291 segmentation fault  ./test_omp

如果删除程序子例程(或简单地注释add2_mod调用),即使使用OpenMP,它也可以正常工作。即使我直接从主程序调用add2_mod子例程,它仍然可以正常工作。

[使用优化进行编译(使用-O3测试时,以及使用ulimit -s unlimited设置无限堆栈时,也可以使用。

据我所知,它与Intel Fortran兼容(已在版本17上进行了测试,除了-qopenmp之外没有其他特定标志)。

fortran openmp gfortran subroutine
1个回答
0
投票

gfortran documentation中所述:

-fopenmp表示-frecursive,即所有本地数组都将分配在堆栈上。将现有代码移植到OpenMP时,可能会导致令人惊讶的结果,尤其是如果堆栈大小导致分段错误有限制。

为了克服此限制,您可以使用allocatable说明符将数组强制放在堆上:

module arr_mod
contains
    subroutine add2_mod(arr)
        integer, dimension(:) :: arr
        integer i, n
        n = size(arr)
        do i=1,n
            arr(i) = arr(i)+2
        enddo
    end subroutine
end module

PROGRAM TEST_OMP
    use arr_mod
    integer, dimension(:), allocatable :: array ! array is allocated on the heap
    allocate(array(2000000))
    array = 0
    write(*,*) array(1)
contains
    subroutine add2()
        call add2_mod(array)
    end subroutine
END PROGRAM TEST_OMP

哪个可以与-fopenmp标志一起正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.