【发布时间】: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