在循环中,调用计算矩阵myThreadMatrix
的子程序mySub
。结果在mySumMatrix
中求和,REDUCTION
program main
use omp_lib
implicit none
integer :: ii
integer, allocatable, dimension(:,:) :: mySumMatrix, myThreadMatrix
! test on 4 threads (only for this short example, not real life)
call OMP_set_dynamic(.FALSE.)
call OMP_set_num_threads(4)
allocate(mySumMatrix(1:3,1:3), myThreadMatrix(1:3,1:3))
mySumMatrix(1:3,1:3)=0
!$OMP PARALLEL PRIVATE(myThreadMatrix) REDUCTION(+:mySumMatrix)
myThreadMatrix(1:3,1:3)=0
!$OMP DO
do ii=1,10
call mySub(myThreadMatrix)
mySumMatrix=mySumMatrix+myThreadMatrix
enddo
!$OMP END DO
!$OMP END PARALLEL
print *, mySumMatrix
contains
subroutine mySub(myMatrix)
integer, dimension(1:3,1:3), intent(out) :: myMatrix
! doing some long calculations ....
myMatrix(1:3,1:3)=omp_get_thread_num()+1
return
end subroutine mySub
end program main
它工作得很好,但是,在我的实际程序中,mySumMatrix
是大的。所以,我想避免在每个线程中重复它。所以我想知道如何避免使用REDUCTION
条款。经过多次尝试,我成功地用这个程序做到了这一点:
program main
use omp_lib
implicit none
integer :: ii
integer, allocatable, dimension(:,:) :: mySumMatrix, myThreadMatrix
! test on 4 threads (only for this short example, not real life)
call OMP_set_dynamic(.FALSE.)
call OMP_set_num_threads(4)
allocate(mySumMatrix(1:3,1:3), myThreadMatrix(1:3,1:3))
mySumMatrix(1:3,1:3)=0
!$OMP PARALLEL PRIVATE(myThreadMatrix) SHARED(mySumMatrix)
myThreadMatrix(1:3,1:3)=0
!$OMP DO
do ii=1,10
call mySub(myThreadMatrix)
enddo
!$OMP END DO
!$OMP DO ORDERED
do ii=1,omp_get_num_threads()
!$OMP ORDERED
mySumMatrix=mySumMatrix+myThreadMatrix
!$OMP END ORDERED
enddo
!$OMP END DO
!$OMP END PARALLEL
print *,mySumMatrix
contains
subroutine mySub(myMatrix)
integer, dimension(1:3,1:3), intent(out) :: myMatrix
! doing some long calculations ....
myMatrix(1:3,1:3)=myMatrix(1:3,1:3)+omp_get_thread_num()+1
return
end subroutine mySub
end program main
但是,由于我是并行编程和OpenMP的初学者,我不确定这个解决方案没有我不怀疑的问题。我可以提些建议吗?谢谢你的回答。
这可以通过在原始代码中插入一个CRITICAL指令来实现(当然要保留SHARED而不是REDUCTION):
!$OMP PARALLEL PRIVATE(myThreadMatrix) SHARED(mySumMatrix)
myThreadMatrix(1:3,1:3)=0
!$OMP DO
do ii=1,10
call mySub(myThreadMatrix)
!$OMP CRITICAL
mySumMatrix=mySumMatrix+myThreadMatrix
!$OMP END CRITICAL
enddo
!$OMP END DO
!$OMP END PARALLEL
CRITICAL确保一次只有一个线程执行临界区内的代码,所以这里一次只有一个线程更新mySumMatrix。CRITICAL有一些性能损失,但如果在临界段内花费的时间比在整个并行段内花费的时间小,那么这是完全可以接受的。在您的情况下,如果在mySub()中进行的计算比矩阵求和重要得多,您甚至不会注意到惩罚(顺便说一下,如果它们不重要得多,那么整个OMP并行性可能毫无意义)。
另外,我认为你用ORDERED修改的代码是无效的,如果是,我怀疑它是否能给出正确的结果。