我遇到 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
是私有(private)的(因此一个线程返回我期望的值,而其他线程返回我期望的值)还给我一些别的东西)。
虽然我用子句 DEFAULT(SHARED)
声明了我的并行区域,但为什么 q
数组不共享,这真的让我很困惑。由于我处于一个孤立的子例程中,因此我无法明确声明 q
为共享,因为它仅在子例程 compute
中已知......我陷入了这个问题,所以到目前为止,我找不到解决方法。
正常吗?我应该期待这种行为吗?有解决方法吗?我错过了一些明显的事情吗?
任何帮助将不胜感激!
最佳答案
q
是 OpenMP 术语中“位于区域内部但不在构造内部”的实体。 q
所属的子例程位于并行构造期间调用的过程中,但 q
本身在词法上并不出现在 PARALLEL 和 END PARALLEL 指令之间。
OpenMP 中此类实体的数据共享规则规定 q 是私有(private)的。
诸如 DEFAULT(SHARED) 等数据共享子句仅适用于结构本身中出现的内容(词汇上出现在 PARALLEL 和 END PARALLEL 之间的内容)。 (它们通常不能应用于该区域中的事物 - 在该区域中调用的过程可能已单独编译,并且可能在任何并行构造之外调用。)
关于fortran - OpenMP 和 Fortran 中不共享的共享变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15231482/