【问题标题】:OpenMP segmentation error with uncalled program subroutine [duplicate]带有未调用程序子例程的 OpenMP 分段错误 [重复]
【发布时间】:2020-03-26 17:46:54
【问题描述】:

当我在编译选项中启用 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 之外没有特定标志)。

【问题讨论】:

  • 如果你先执行“ulimit -s unlimited”会发生什么?如果你用优化编译会发生什么?什么版本的gfortran?英特尔的版本和标志是什么?不错的小例子!
  • @IanBush 我在问题中完成了。该程序使用-O3(刚刚测试过-O1,它也可以运行)或ulimit -s unlimited 运行。我将 ifort 17 与 -qopenmp 标志一起使用。
  • 刚要下棋所以没时间,但是看看stackoverflow.com/questions/13264274/… 并了解编译器上的优化器可以解决如何避免非常大的数组。 Inetl 编译默认开启优化,gfortran 关闭。
  • @IanBush 英特尔仍可与-O0 合作,但可能存在一些优化差异。
  • @IanBush 我不确定它是否能回答我的问题,因为我的问题中根本没有 OpenMP 代码。我看不到通过简单地包含 openmp 标志是如何增加堆栈大小的。

标签: fortran openmp gfortran subroutine


【解决方案1】:

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 标志可以正常工作。

【讨论】:

    猜你喜欢
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    • 2016-05-22
    • 2023-03-13
    • 1970-01-01
    • 2020-06-04
    • 1970-01-01
    相关资源
    最近更新 更多