我为共轭梯度方法编写了一个串行代码,并尝试将其与OpenMP并行化(我的平台是Intel集群)
当我使用串行代码时,我得到如下输出: -
Test data (matrix and right hand side) :
5.00000 0.00000 -1.00000 -1.00000 1.00000
0.00000 5.00000 -1.00000 -1.00000 1.00000
-1.00000 -1.00000 5.00000 -1.00000 1.00000
-1.00000 -1.00000 -1.00000 5.00000 1.00000
Solution for the linear system:
0.37500 0.37500 0.43750 0.43750
但是当我使用Openmp进行特定的do循环时,我没有得到解决方案。输出只有这个:
Test data (matrix and right hand side) :
5.00000 0.00000 -1.00000 -1.00000 1.00000
0.00000 5.00000 -1.00000 -1.00000 1.00000
-1.00000 -1.00000 5.00000 -1.00000 1.00000
-1.00000 -1.00000 -1.00000 5.00000 1.00000
编译期间没有错误。 有人可以帮忙吗?
我已经复制粘贴了OpenMP代码。
module cg
contains
subroutine cg_method (n,a,y,x)
use omp_lib
implicit none
integer :: n, k , i , j
integer,parameter :: sze = 24 , nt = 4
double precision :: tol = 2.d-16
double precision :: a(0:sze,0:sze),x(0:sze),y(0:sze)
double precision :: d(0:n-1),g(0:n-1),auxD(0:n-1),alpha,beta
double precision :: num,den,aux1,aux2,dist,xnorm
!$call omp_set_num_threads(nt)
! start with x at origin
do i = 0,n-1
x(i) = 0.d0
enddo
! initialize d and g
! d = -g = -(a*x-y) = y as x = 0
do i = 0,n-1
aux1 = y(i)
d(i) = aux1
g(i) = -aux1
enddo
! perform at most n steps of CG algo
do k = 0,n
! compute new alpha
! alpha = -(d(transp)*g)/(d(transp)*(a*d))
num = 0.d0
den = 0.d0
do i = 0,n-1
num = num + d(i)*g(i)
aux1 = 0.d0
do j = 0 , i-1
aux1 = aux1 + a(j,i)*d(j)
enddo
do j = i,n-1
aux1 = aux1 + a(i,j)*d(j)
enddo
auxD(i) = aux1
den = den + d(i)*aux1
enddo
alpha = -num/den
! compute the norm of x and alpha*d and find a new x
!x = x + alpha*d , then check if x is close in order to stop the process
!before n complete steps
xnorm = 0.d0
dist = 0.d0
do i = 0,n-1
aux1 = x(i)
xnorm = xnorm + aux1*aux1
aux2 = alpha*d(i)
dist = dist + aux2*aux2
x(i) = aux1 + aux2
enddo
!compute new g : g + alpha*(a*d)
do i = 0,n-1
g(i) = g(i) + alpha*auxD(i)
enddo
! compute new beta :
! beta = (g(transp)*(a*d))/(d(transp)*(a*d))
num = 0.d0
do i = 0,n-1
num = num + g(i)*auxD(i)
enddo
beta = num/den
!compute new d : d = -g + beta*d
!$omp parallel default(none) shared(beta,d,g) private(i,n)
!$omp do
do i = 0,n-1
d(i) = -g(i) + beta*d(i)
enddo
!$omp enddo
!$omp end parallel
enddo !k loop
end subroutine cg_method
end module cg
program test
use cg
use omp_lib
integer,parameter :: sze = 24
double precision :: a(0:sze,0:sze), y(0:sze),x(0:sze)
integer :: n , i , j
n = 4
!define a matrix
a(0,0)=5.d0;a(0,2)=-1.d0;a(0,3)=-1.d0
a(1,1)=5.d0;a(1,2)=-1.d0;a(1,3)=-1.d0
a(2,2)=5.d0;a(2,3)=-1.d0;a(3,3)=5.d0
!define b vector
y(0)=1.d0;y(1)=1.d0;y(2)=1.d0;y(3)=1.d0
print*,'Test data (matrix and right hand side) :'
do i = 0,n-1
write(*,100) (a(j,i),j=0,i-1),(a(i,j),j=i,n-1),y(i)
enddo
call cg_method(n,a,y,x) !perform CG method
print *,' Solution for the linear system:'
write(*,100) (x(i),i=0,n-1)
100 format(10F9.5)
end program test
答案 0 :(得分:1)
解决方案非常简单:进入OpenMP部分时,以及离开后,private
变量未定义。只需将相应的行更改为
!$omp parallel default(none) shared(beta,d,g) private(i) firstprivate(n)
一切都按预期工作。使用firstprivate
,告诉编译器在进入并行部分时将原始变量的值复制到所有线程。
但为什么你需要声明n
私有?它只是阅读!您的代码也适用于共享的n
:
!$omp parallel default(none) shared(beta,d,g,n) private(i)