我遇到了我无法理解的 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
......到目前为止我一直遇到这个问题,我找不到解决方法。
正常吗?我应该期待这种行为吗?有解决方法吗?我错过了一些明显的东西吗?
任何帮助将不胜感激!