Parallel processing 如何在OpenMP中使用锁定
我是OpenMP新手,发现有点难以理解OpenMP中的锁是如何工作的。下面是用Fortran 90编写的执行LU分解的示例代码。有人能解释一下锁在这段代码中是如何工作的吗Parallel processing 如何在OpenMP中使用锁定,parallel-processing,locking,fortran,openmp,fortran90,Parallel Processing,Locking,Fortran,Openmp,Fortran90,我是OpenMP新手,发现有点难以理解OpenMP中的锁是如何工作的。下面是用Fortran 90编写的执行LU分解的示例代码。有人能解释一下锁在这段代码中是如何工作的吗 program lu implicit none integer, parameter :: DP=kind(0.0D0),n=20 !-- Variables integer :: i,j,k,nthr,thrid,chunk=1 real(kind=DP), dimension(:,:),allo
program lu
implicit none
integer, parameter :: DP=kind(0.0D0),n=20
!-- Variables
integer :: i,j,k,nthr,thrid,chunk=1
real(kind=DP), dimension(:,:),allocatable :: A,B,L,U
real(kind=DP) :: timer,error,walltime
integer(kind=8), dimension(n)::lck
integer::omp_get_thread_num,omp_get_max_threads
nthr=omp_get_max_threads()
allocate(A(n,n))
allocate(B(n,n))
allocate(L(n,n))
allocate(U(n,n))
!-- Set up locks for each column
do i=1,n
call omp_init_lock(lck(i))
end do
timer=walltime()
!$OMP PARALLEL PRIVATE(i,j,k,thrid)
thrid=omp_get_thread_num();
!-- Initiate matrix
!$OMP DO SCHEDULE(STATIC,chunk)
do j=1,n
do i=1,n
A(i,j)=1.0/(i+j)
end do
call omp_set_lock(lck(j))
end do
!$OMP END DO
!-- First column of L
if (thrid==0) then
do i=2,n
A(i,1)=A(i,1)/A(1,1)
end do
call omp_unset_lock(lck(1))
end if
!-- LU-factorization
do k=1,n
call omp_set_lock(lck(k))
call omp_unset_lock(lck(k))
!$OMP DO SCHEDULE(STATIC,chunk)
do j=1,n
if (j>k) then
do i=k+1,n
A(i,j)=A(i,j)-A(i,k)*A(k,j)
end do
if (j==k+1) then
do i=k+2,n
A(i,k+1)=A(i,k+1)/A(k+1,k+1)
end do
call omp_unset_lock(lck(k+1))
end if
end if
end do
!$OMP END DO NOWAIT
end do
!$OMP END PARALLEL
timer=walltime()-timer
write(*,*) 'n = ',n,' time = ',timer,' nthr = ',nthr
! CHECK CORRECTNESS
do j=1,n
L(j,j)=1
U(j,j)=A(j,j)
do i=j+1,n
L(i,j)=A(i,j)
U(i,j)=0
end do
do i=1,j-1
U(i,j)=A(i,j)
L(i,j)=0
end do
end do
B=0
do j=1,n
do k=1,n
do i=1,n
B(i,j)=B(i,j)+L(i,k)*U(k,j)
end do
end do
end do
error=0.0
do j=1,n
do i=1,n
error=error+abs(1.0/(i+j)-B(i,j))
end do
end do
write(*,*) 'ERROR: ',error
end program lu
下面列出了另一个包含walltime函数的文件。它应该与主文件一起编译
function walltime()
integer, parameter:: DP = kind(0.0D0)
real(DP) walltime
integer::count,count_rate,count_max
call system_clock(count,count_rate,count_max)
walltime=real(count,DP)/real(count_rate,DP)
end function walltime
免责声明:我没有使用锁机制的经验,并查看了标准以了解这将如何工作。我可能错了
首先,您的代码有一些问题:这段代码不能用最新版本的gfortran编译。您必须将函数walltime移动到程序的contains部分,并且应该使用omp_lib定义所有必需的函数,并删除产生的重复定义。此外,您必须以标准方式定义锁:
integer(kind=OMP_LOCK_KIND), dimension(n) :: lck
现在回答您的问题:调用OMP_INIT_LOCK会将lck数组初始化为解锁状态。所有线程都将获得此变量的副本。然后开始平行段
在第一个循环中,数组初始化为类似于希尔伯特矩阵的东西,并设置每个锁。
第二个块仅由第一个线程执行,第一个锁被释放。还是没什么有趣的。以下循环由所有线程进入,所有线程都在等待第k个锁,因为omp_set_lock等待,直到获得锁为止。以下omp_unset_lock允许所有其他线程跟随。由于已经释放了第一个锁,所有线程将立即进入内部循环,最后一个线程将释放下一个锁。当此线程释放此锁时,其他线程可能已经在等待此锁
原则上,该算法提供某种形式的同步,以确保在输入数据时已计算出k+1循环所需的数据。对于错误,我深表歉意。我自己对Fortran一无所知。walltime函数应该放在一个单独的文件中,并与主文件一起编译。我天真地把它放在主文件的开头,就像我们通常用c/c++做的那样。我道歉!非常感谢你的回答。你的解释很清楚。这对我帮助很大。