2

我遇到了我无法理解的 OpenMP 和共享变量问题。我所做的一切都在 Fortran 90/95 中。

这是我的问题:我在我的main程序中定义了一个并行区域,带有子句DEFAULT(SHARED),我在其中调用了一个执行一些计算的子例程。我有一个分配的局部变量(一个数组)并在其上进行计算。我期待这个数组是共享的(因为该DEFAULT(SHARED)子句),但似乎并非如此。

这是我正在尝试做的一个例子,它重现了我得到的错误:

program main
  !$ use OMP_LIB
  implicit none

  integer, parameter :: nx=10, ny=10
  real(8), dimension(:,:), allocatable :: array

  !$OMP PARALLEL DEFAULT(SHARED)
  !$OMP SINGLE
  allocate(array(nx,ny))
  !$OMP END SINGLE

  !$OMP WORKSHARE
  array = 1.
  !$OMP END WORKSHARE

  call compute(array,nx,ny)

  !$OMP SINGLE
  deallocate(array)
  !$OMP END SINGLE
  !$OMP END PARALLEL

contains
  !=============================================================================
  ! SUBROUTINES
  !=============================================================================
  subroutine compute(array, nx, ny)
    !$ use OMP_LIB
    implicit none

    real(8), dimension(nx,ny) :: array
    integer :: nx, ny
    real(8), dimension(:,:), allocatable :: q
    integer :: i, j

    !$OMP SINGLE
    allocate(q(nx,ny))
    !$OMP END SINGLE

    !$OMP WORKSHARE
    q = 0.
    !$OMP END WORKSHARE

    print*, 'q before: ', q(1,1)

    !$OMP DO SCHEDULE(RUNTIME)
    do j = 1, ny
       do i = 1, nx
          if(mod(i,j).eq.0) then
             q(i,j) = array(i,j)*2.
          else
             q(i,j) = array(i,j)*0.5
          endif
       end do
    end do
    !$OMP END DO

    print*, 'q after: ', q(1,1)

    !$OMP SINGLE
    deallocate(q)
    !$OMP END SINGLE

  end subroutine compute
  !=============================================================================
end program main

当我这样执行它时,会出现分段错误,因为本地数组q是在一个线程上分配的,而不是在其他线程上分配的,当其他线程尝试在内存中访问它时,它会崩溃。

如果我摆脱了分配SINGLE本地数组的区域q(尽管有时它会崩溃,这是有道理的,如果不同的线程尝试分配它而已经是这种情况(实际上它让我感到困惑,为什么它不会每次都崩溃))但是那么很明显,该数组好像q是私有的(因此一个线程返回给我预期值,而其他线程返回给我其他东西)。

q虽然我用子句声明了我的并行区域,但为什么不共享数组确实让我感到困惑DEFAULT(SHARED)。而且由于我在一个孤立的子例程中,我不能明确地声明q为共享,因为它只在子例程中知道compute......到目前为止我一直遇到这个问题,我找不到解决方法。

正常吗?我应该期待这种行为吗?有解决方法吗?我错过了一些明显的东西吗?

任何帮助将不胜感激!

4

2 回答 2

7

q就 OpenMP 而言,是“在区域内但不在构造内”的实体。本地子例程q位于并行构造期间调用的过程中,但q其本身在词法上不会出现在 PARALLEL 和 END PARALLEL 指令之间。

然后,OpenMP 中此类实体的数据共享规则规定 q 是私有的。

DEFAULT(SHARED) 等数据共享子句仅适用于出现在构造本身中的事物(词法上出现在 PARALLEL 和 END PARALLEL 之间的事物)。(它们通常不适用于区域中的事物 - 在区域中调用的过程可能已经单独编译,并且可能在任何并行构造之外调用。)

于 2013-03-05T18:52:42.693 回答
3

该数组q是在被调用的子程序内部定义的。每个线程独立调用这个子程序,因此每个线程都有自己的副本。外部子程序中的shared指令不能改变这一点。尝试用save属性声明它。

于 2013-03-05T18:52:29.597 回答