fortran - OpenMP 和 Fortran 中不共享的共享变量

标签 fortran openmp shared

我遇到 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/

相关文章:

c++ - OpenMP 中 std::queue 可以并发插入吗?

linux - 在 Linux 中查找共享库的加载地址

fortran - 使用不带 % 的 Fortran 派生类型变量

fortran - 以非零退出状态停止 fortran 程序

python - 如何使用模块将 Python 回调公开给 Fortran

c - 无法弄清楚在c中的OPENMP程序中发生竞争条件的位置

c - 如何在 Xeon Phi 中传递结构以卸载

c# - 如何在 C# 中为两个项目创建一个安装文件?

docker - 在 Docker 容器之间流式传输数据的最有效方式是什么

c++ - 混合语言代码文档 - 需要帮助来调试 doxygen