Fortran OpenMP中的全局变量

Fortran OpenMP中的全局变量,fortran,openmp,Fortran,Openmp,为什么Fortran中的以下代码只有在我将循环变量“I”和“j”作为子程序“mat_init”的输入参数时才起作用?循环变量'i'和'j'被声明为私有的,所以当我调用它时,它们不应该在子例程中保持私有吗 program main use omp_lib implicit none real(8), dimension(:,:), allocatable:: A integer:: i, j, n n = 20 allocate(A(n,n)); A(:,:)

为什么Fortran中的以下代码只有在我将循环变量“I”和“j”作为子程序“mat_init”的输入参数时才起作用?循环变量'i'和'j'被声明为私有的,所以当我调用它时,它们不应该在子例程中保持私有吗

program main
   use omp_lib
   implicit none
   real(8), dimension(:,:), allocatable:: A
   integer:: i, j, n

   n = 20
   allocate(A(n,n)); A(:,:) = 0.0d+00

   !$omp parallel do private(i, j)
   do i=1,n
   do j=1,n
   call mat_init
   end do
   end do

   do i=1,n
   write(*,'(20f7.4)') (A(i,j), j=1,n)
   end do

contains
   subroutine mat_init

      A(i,j) = 1.0d+00
   end subroutine
end program main

我知道这与“词法”和“动态”扩展有关,但我不明白为什么OpenMP以这种方式实现,不识别反并行区域内“动态”扩展中的私有变量。对我来说,这似乎不合逻辑,或者我做错了什么?

首先,我认为子程序mat_init应该明确地将I和j的值作为输入参数。然后,i和j的值必须是私有的,因为每个线程都处理i和j的特定值。我还认为openmp认识到I是私有的,因为并行循环在I上。同上。但是,这适用于全局变量i和j,而不适用于子程序内部的变量。因此,您必须指定i和j是私有的,以便强制子例程内部变量继承此方面

我认为问题是由于子程序mat_init的重入。实际上,当多个线程同时以不同的i和j值进入子例程时会发生什么?如果不执行任何特殊操作,则被调用的子例程可能无法识别i和j的私有方面


通常,不欢迎在循环中多次调用子例程,因为每次调用都需要给定的时间。我建议编写一个并行的子例程,而不是在并行部分中调用子例程。

可能重复的
j
不是全局的,因为您声明它是
private
I
private
,因为它是最外层循环的循环计数器