分配给未知范围的变量时的竞争条件

时间:2021-06-30 08:17:41

标签: openmp

并行程序按以下方式计算两个向量的标量积

  1. 使用 OpenMP 缩减计算当前 MPI 进程的贡献。结果存储在 SHARED 变量 s_loc

  2. OpenMP master 调用 MPI_Allreduce 来计算所有 MPI 进程的 s_loc 总和。结果存储在 SHARED 变量 s_glob

  3. 最后,s_glob 被分配给过程输出参数: s = s_glob

请注意,s 的范围是未知的,因为它是在过程之外定义的。在 PRIVATE 情况下,分配只是每个线程,一切都很好。但是,如果 s 是 SHARED,则会发生竞争条件,因为 s_glob 是 SHARED。我想知道这种赛车状况是否会造成任何问题,如果是,如何避免。

在下面的例子中,MPI 部分被删除了,因为它只对变量的作用域很重要,对问题本身并不重要。

program Scalar_Product
  implicit none
  integer, parameter :: n = 10000000
  real, save :: a(n), b(n)
  real :: ab

  call random_number(a)
  call random_number(b)

  !$omp parallel private(ab)
  ab = ScalarProduct(a, b)
  !$omp end parallel

contains

  real function ScalarProduct(a, b) result(s)
    real, intent(in) :: a(:) ! left operand
    real, intent(in) :: b(:) ! right operand

    real, save :: s_loc, s_glob
    integer :: i

    !$omp master
    s_loc = 0
    !$omp end master

    !$omp do reduction(+:s_loc) schedule(static)
    do i = 1, size(a)
      s_loc = s_loc + a(i) * b(i)
    end do

    !$omp master       ! in the real application
    s_glob = s_loc     ! s_glob is computed using
    !$omp end master   ! MPI_Allreduce

    ! this is the assignment to which the question refers
    s = s_glob

  end function ScalarProduct

end program Scalar_Product

感谢任何有用的评论!

乔尔格

1 个答案:

答案 0 :(得分:0)

我修改了示例并认为可以回答我的问题。

program Scalar_Product
  integer, parameter :: n = 10000000
  real :: a(n), b(n), ab

  ! skipping initialization of a and b ...
 
  !$omp parallel shared(a,b) private(ab)
  ab = ScalarProduct(a, b)  ! would give a racing condition, if ab is shared
  !$omp end parallel

contains

  function ScalarProduct(a, b) result(s)
    real, intent(in) :: a(:) ! left operand
    real, intent(in) :: b(:) ! right operand
    real, save       :: s    ! force result to be shared
    integer          :: i

    !$omp master
    s = 0
    !$omp end master

    !$omp do reduction(+:s) schedule(static)
    do i = 1, size(a)
      s = s + a(i) * b(i)
    end do

  end function ScalarProduct

end program Scalar_Product

观察

  • 通过声明函数结果 save,它变成共享的
  • 这可以消除函数内部有问题的赋值
  • 但是,由于在并行区域内调用该函数,因此必须将其结果分配给私有变量以避免竞争条件

干杯,约尔格

相关问题