我可以并行化我的程序吗?

时间:2012-03-12 11:04:42

标签: cuda fortran parallel-processing

这是我的计划:

program test
implicit none
integer n,m,k,i,j,Errorflag
real :: Yabs(39,39),angle(39,39)
real ,dimension(67,1) :: deltaA,A
real :: V(1,39),d(1,39),v1(29,1),d1(38,1),Ps(1,38),Qs(1,39),Jac(67,67),invJac(67,67)
real :: B1(1,38),B2(1,29),MF(1,67),trnsMF(67,1),P0(1,39),Q0(1,39)
real, dimension(38,38) :: dia1,offdia1,J1
real, dimension(29,29) :: dia2,dia3,dia4,offdia4,J4
real,dimension(38,29) ::offdia2,J2
real,dimension(29,38) ::offdia3,J3
real p,p1,q,q1

n=39;m=9
MF(1,1)=10

open(unit=3,file="ybus.dat",status="old")
open(unit=4,file="angle.dat",status="old")
 do i=1,39
        read(3,*) Yabs(i,1:39)
        read(4,*)angle(i,1:39)
    end do
close(3)
close(4)

open(unit=5,file="activepower.dat",status="old")
open(unit=8,file="reactivepower.dat",status="old")


read(5,*)Ps(1,1:38)
read(8,*)Qs(1,1:29)


close(5)
close(8)

do i=1,67
deltaA(i,1)=0
end do
v1(1:29,1)=1
d1(1:38,1)=0 
A(1:38,1)=d1(1:38,1)
A(39:67,1)=v1(1:29,1)
!call cpu_time(t1)

do while(maxval(abs(MF))>0.0001)

V(1,1)=0.982
V(1,2:30)=v1(1:29,1)
V(1,31)=1.03
V(1,32)=0.9831           
V(1,33)=1.0123
V(1,34)=0.9972
V(1,35)=1.0493
V(1,36)=1.0635 
V(1,37)=1.0278
V(1,38)=1.0265
V(1,39)=1.0475
d(1,1)=0
d(1,2:39)=d1(1:38,1)
 ! % % % %------Active Power Calculation-----%
p1=0;p=0
do i=2,n
    do j=1,n
        p1=(V(i)*V(j)*Yabs(i,j)*cos(angle(i,j)-d(i)+d(j)))
        p=p1+p
     end do
     P0(i-1)=p
     p=0
end do
! % % % %------Reactive Power Calculation-----%  
p=0;p1=0
do i=2,(n-m)
      do j=1,n
p1=-(V(i)*V(j)*Yabs(i,j)*sin(angle(i,j)-d(i)+d(j)))
p=p1+p
      end do
      Q0(i-1)=p
      p=0
end do
!!!!!!!!!!!mismatch factor
do i=1,(n-1)
   B1(i)=Ps(i)-P0(i)
  end do
do i=1,(n-m-1)
   B2(i)=Qs(i)-Q0(i)
end do

MF(1,1:38)=B1(1,1:38)
MF(1,39:67)=B2(1,1:29)
!!!!!!!!jacobian calculation for preddictor step
!!!!!!!!!!!!!!!!!!!!!!dia of j1
p=0;p1=0
do i=2,n
    do j=1,n
       if(j .ne. i)then
 p1=V(i)*V(j)*Yabs(i,j)*sin(angle(i,j)-d(i)+d(j))
 !print*,p1
 p=p1+p
       end if

    end do
    i=i-1
    dia1(i,i)=p

    p=0
    i=i+1
end do

!!!!!!!!!!!!!!off dia. of j1
q=0;q1=0;
do k=2,n
 i=k
    do j=2,n
        if(j .ne. i)then
        q1=V(i)*V(j)*Yabs(i,j)*sin(angle(i,j)-d(i)+d(j))
        end if
        i=i-1;j=j-1
offdia1(i,j)=-q1
q1=0
i=i+1;j=j+1
    end do
end do
do i=1,38
do j=1,38
J1(i,j)=offdia1(i,j)+dia1(i,j)
end do
end do
!!!!!!!!!!!!!!!!!!!dia. of j2
p=0;p1=0
do i=2,(n-m)
    do j=1,n
       if(j .ne. i)then
         p1=V(j)*Yabs(i,j)*cos(angle(i,j)-d(i)+d(j))
 p=p1+p
       end if

    end do

    dia2(i-1,i-1)=p+(2*V(i)*Yabs(i,i)*cos(angle(i,i)))
    p=0;

end do
!!!!!!!!!!!!!!!!!!off dia. of j2
p1=0;
do k=2,n
 i=k
    do j=2,(n-m)
        if(j .ne. i)then
       p1=V(i)*Yabs(i,j)*cos(angle(i,j)-d(i)+d(j));
        end if
        i=i-1;j=j-1
offdia2(i,j)=p1
    p1=0;
    i=i+1;j=j+1
    end do
end do
do i=1,(n-m-1)

   offdia2(i,i)=dia2(i,i)

end do
J2=offdia2
!!!!!!!!!!!!!!!!!!!!dia. of j3
p=0;p1=0
do i=2,(n-m)
    do j=1,n
       if(j .ne. i)then
          p1=V(i)*V(j)*Yabs(i,j)*cos(angle(i,j)-d(i)+d(j))
 p=p1+p;
       end if
    end do
    i=i-1;
    dia3(i,i)=p
    p=0;
    i=i+1;
 end do
 !!!!!!!!!!!!!!off dia of j3
p=0;p1=0
do k=2,(n-m)
 i=k;
    do j=2,n
        if(j .ne. i)then
    p1=V(i)*V(j)*Yabs(i,j)*cos(angle(i,j)-d(i)+d(j))
        end if
     i=i-1;j=j-1
    offdia3(i,j)=-p1;
    p1=0;
    i=i+1;j=j+1
    end do
end do
do i=1,(n-m-1)
      offdia3(i,i)=dia3(i,i)

end do
J3=offdia3
!!!!!!!!!!dia of j4
p=0;p1=0
do i=2,(n-m)
    do j=1,n
       if(j .ne. i)then
           p1=V(j)*Yabs(i,j)*sin(angle(i,j)-d(i)+d(j))
 p=p1+p
       end if

    end do

    dia4(i-1,i-1)=-(2*V(i)*Yabs(i,i)*sin(angle(i,i)))-p
    p=0;p1=0
end do
 !!!!!!!!!!!!!!!off dia of j4
p1=0;p=0
do k=2,(n-m)
 i=k;
    do j=2,(n-m)
        if(j .ne. i)then
       p1=V(i)*Yabs(i,j)*sin(angle(i,j)-d(i)+d(j))
        end if
    i=i-1;j=j-1
    offdia4(i,j)=-p1
    p1=0;
    i=i+1;j=j+1
    end do
 end do
 do i=1,(n-m-1)
offdia4(i,i)=dia4(i,i);
 end do
J4=offdia4
!!!!!!!
!!!!!!!!!!!!!!!!!!!formation of final jacobian!!!!!!!!!!
Jac( 1:38, 1:38) = J1 (1:38,1:38)
Jac( 1:38,39:67) = J2 (1:38,1:29)
Jac(39:67, 1:38) = J3 (1:29,1:38)
Jac(39:67,39:67) = J4 (1:29,1:29)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!print*,Jac(23,21)
CALL FindInv(Jac,invJac ,67, ErrorFlag)
trnsMF=transpose(MF)

deltaA=matmul( invJac, trnsMF)
do i=1,67
A(i)=A(i)+deltaA(i)
end do

!!!!!!!!!!!!updating values
do i=1,(n-1)
    d1(i)=A(i)
end do

k=0
do i=n,(2*n-2-m)
    k=1+k
    v1(k)=A(i)
end do
end do

end program test

数组“Ps”包含一些值。现在,如果我将Ps(15)的值增加Ps(15)+1,那么对于这两个值,我可以并行化此代码以快速得到答案。

我正在为CUDA FORTRAN使用PGI编译器。

2 个答案:

答案 0 :(得分:1)

是的,您可以使用PGI compiler编写CUDA内核并进行CUDA API调用。

PGI Fortran CUDA Homepage

问题,我想,你的意思是“应该我将此代码并行化吗?”

我的回答是肯定的,你可以看到并行化的一些温和的好处,一目了然。

例如,片段如:

 do i=2,n
    do j=1,n
       if(j .ne. i)then
 p1=V(i)*V(j)*Yabs(i,j)*sin(angle(i,j)-d(i)+d(j))
 !print*,p1
 p=p1+p
       end if

    end do
    i=i-1
    dia1(i,i)=p

    p=0
    i=i+1
end do

是一组N ^ 2独立计算(在这种情况下,你设置n = 39,但我认为它可能会改变)。因此,您至少要处理几百次计算。虽然理想情况下你需要在并行化方面进行更多的计算,但至少在你的许多循环看起来每个步骤都做相同的独立工作时,你至少处于良好状态 - 非常适合线程化应用。

因此,您可以看到编写CUDA内核以替换数据后处理算法中的循环代码段有一些轻微的好处。请注意,PCI总线在内存传输方面的延迟确实会使某些性能提升无效,特别是对于小型系统。

因此,我会说,是的,无论如何,你可以并且应该尝试这个,如果你是游戏,但不要指望它快100倍......如果你编码得好,可能会快2-10倍,取决于你的循环边界大小和特定循环内的分歧程度。

最糟糕的情况是你没有收获,甚至看不到放缓,但至少你已经学到了什么!!

答案 1 :(得分:1)

您的代码非常简单,有许多独立的并行循环。这些并行循环似乎包含在外部汇聚do while循环中,因此只要您在汇聚循环的所有迭代中保留设备上的数据,您就不会受到传输的瓶颈。

我建议从这个代码的编译器指令开始,而不是潜入CUDA Fortran。编译器指令适用于这些简单的独立循环 - 它们是您在代码注释中的简单提示,它告诉编译器要并行化哪些循环,要复制哪些数据等等。

您可以先尝试OpenMP加速到多个CPU核心。然后您可以使用诸如OpenACC之类的GPU指令,这些指令很快将在PGI,Cray和CAPS的编译器中提供。要抢先一步,您可以下载PGI compiler的免费试用版,并使用他们的"Accelerator"指令。 Accelerator的语法与OpenACC非常相似。