我制作了一个更复杂的 Fortran 代码的最小示例,其中使用英特尔 Fortran 编译器 ifort 而不是使用 GNU 编译器 gfortran 编译和运行时出现分段错误。
如果我用
gfortran <source file> -fopenmp
编译它就可以了。
如果我使用
ifort <source file> -qopenmp
进行编译,运行后会出现分段错误。
在下面的最小示例中,分段错误似乎来自 y_index 在第 31 行“g = x + y(y_index)”处没有其初始化值。这是为什么?
program segfault
implicit none
integer :: i, y_index
real(16) :: x(20), y(20)
x = 1
y = 1
y_index = 5
!$omp parallel do shared(x,y,y_index) num_threads(1)
do i=1, size(x)
print*, 'g(x) = ', f(g, x(i))
end do
!$omp end parallel do
contains
real(16) function f(g, x)
real(16), intent(in) :: x
interface
real(16) function g(x)
real(16), intent(in) :: x
end function
end interface
f = g(x)
end function
real(16) function g(x)
real(16), intent(in) :: x
g = x + y(y_index)
end function
end program
我尝试使用 OpenMP do 构造的 private、firstprivate 和共享子句。我还使用了 kind 参数,它似乎适用于 real(4) 和 real(8)。但我需要真实的(16)。我还将线程数设置为 1,以检查问题是否与多个线程的并行化有关。无论如何,分段错误都会出现。
ifort 使用 OpenMP 5.0 版本 TR4 https://www.intel.com/content/www/us/en/docs/fortran-compiler/developer-guide-reference/2023-0/openmp-support.html。 OpenMP 5.0 版本 TR4 规范支持 Fortran 2003,其中不允许内部过程作为虚拟参数。请参阅 https://www.openmp.org/wp-content/uploads/openmp-tr4.pdf 中的第 24 和 34 页。
两种可能的解决方案:
将 g 放入模块中
创建一个过程指针 g_ptr => g 并将 g_ptr 传递给 f。