并行程序按以下方式计算两个向量的标量积
使用 OpenMP 缩减计算当前 MPI 进程的贡献。结果存储在 SHARED 变量 s_loc
OpenMP master 调用 MPI_Allreduce 来计算所有 MPI 进程的 s_loc 总和。结果存储在 SHARED 变量 s_glob
最后,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
感谢任何有用的评论!
乔尔格
答案 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
,它变成共享的干杯,约尔格