2013-03-05 50 views
2

我遇到OpenMP和共享变量的问题,我无法理解。我所做的每件事都在Fortran 90/95。Fortran中的OpenMP和共享变量不共享

这是我的问题:我在我的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分配在一个线程上但不在其他线程上,而当其他人试图在内存中访问它时,它会崩溃。

如果我摆脱了本地阵列q被分配SINGLE区域的(虽然有时它崩溃,这是有意义的,如果不同的线程尝试分配它,而它已经是这样了(实际上它为什么它让我为难每次都不会崩溃)),但是很明显,数组q是私有的(因此一个线程返回给我预期值,而其他线程返回给我一些其他值)。

它真的让我很困惑,为什么q数组没有被共享,虽然我用DEFAULT(SHARED)条款声明了我的并行区域。由于我处于孤儿子程序中,因此我无法明确地声明q为共享,因为它仅在子例程compute中已知......我对此问题坚持到目前为止,我无法找到解决方法。

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

任何帮助将不胜感激!

回答

3

数组q被定义在INSIDE子程序中。每个线程都独立调用这个子例程,因此每个线程都会拥有自己的副本。外部子程序中的shared指令无法更改此设置。尝试使用save属性声明它。

+0

感谢弗拉基米尔的解释和解决方法!事实上,通过'save'属性的工作,我的示例编译并运行。谢谢! – MBR 2013-03-05 18:59:41

7

q是一个“在一个区域内但不在构造内部”的实体,用于OpenMP讲话。 q是本地的子例程位于并行构造期间调用的过程中,但q本身不会在PARALLEL和END PARALLEL指令之间词汇出现​​。

OpenMP中这些实体的数据共享规则决定q是私有的。

DEFAULT(SHARED)等数据共享子句只适用于出现在构造本身中的东西(词法上出现在PARALLEL和END PARALLEL之间的东西)。 (他们不能适用于该地区的一般情况 - 该地区所调用的程序可能已经单独编译,并可能在任何并行构造之外被调用。)

+0

谢谢你的解释,现在我明白了。有什么解决方法吗? – MBR 2013-03-05 18:58:49