2012-03-12 7 views
-4

これが私のプログラムである:プログラムを並列化できますか?

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.
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コンパイラを使用しています。

+4

私は、user991852の質問が多少あいまいで、あまり言い表られていないことが分かります。しかし、私は多くの人々が理由についてのフィードバックを与えずに彼/彼女を投票していることに失望しています。私にとっては、それは本当にかわいそうだ。StackOverflowは、ベテランのユーザーが多くの場合に役立つフィードバックを出すことなく、初心者の質問をしゃべっているという点で、最近はかなり意地悪しています。 CUDAの質問セクションは特に厳しいようです。さて、それはあまりにも言葉の問題ですが、大声で叫ぶために彼/彼女にいくつかのフィードバックを与える... –

+0

ジェイソンとこれに同意します。 – harrism

答えて

1

あなたのコードは、多くの独立した並列ループでかなり簡単です。これらの並列ループは、外部収束do whileループでラップされているように見えます。したがって、コンバージェンスループのすべての反復でデバイスにデータを保持する限り、転送によってボトルネックにはなりません。

CUDA Fortranにダイビングするのではなく、このコード用のコンパイラ指令で始めることをお勧めします。コンパイラ指令は、コンパイラに並列化するループ、コピーするデータなどをコードコメントに記述するための簡単なヒントです。

まず加速するためにOpenMPを試すことができます複数のCPUコア。その後、OpenACCなどのGPU指令を使用できます。これは、PGI、Cray、およびCAPSのコンパイラですぐに利用できるようになります。まず、PGI compilerの無料試用版をダウンロードし、その"Accelerator"指令を使用することができます。アクセラレータはOpenACCと非常に似ています。

+0

OPがすでにPGI CUDAコンパイラを使用している場合は、おそらくACCが最適です。すでにかなり進んでいる競合する標準である 'OpenHMPP'がCAPSとPathscaleによって存在します。 –

+0

私はPGIコンパイラを使用しています "CUDA FORTRAN"プログラミングを並列化に使用する必要があり、並列化に "PGIアクセラレータ指令"を使用する必要があると混乱します – user991852

+0

私はあなたの既存のループあなたはそれをどうやって見てください。 PGIには、アクセラレータのページに関する多くの例があります。 CUDA Fortranを使用するとパフォーマンスが向上する可能性がありますが、より多くの努力とコードの変更が必要になります。そのため、指示文をスマートな場所に配置する必要があります。 – harrism

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倍速くなるでしょうまあ、あなたのループの束縛されたサイズと特定のループ内の相違のレベルに応じて。

最悪のシナリオでは、利益が見られない、または減速が見られるが、少なくともあなたは何かを学んだことがある!!

+0

返信ありがとう...実際に私の質問は、配列Psの異なる値のこのコードを並列で実行したいです。 – user991852

+0

私は大きな絵を見る必要があると思います。 CUDAカーネルを使用して配列をインクリメントすることは、大規模なものであっても、レイテンシを考慮した場合、コードをSLOWにすることはほぼ確実です。それはあなたのコードが大きくループ駆動されていると言いました。だから、CUDAカーネルの強力な候補のように思えますが、上記で概説したように、フルポートで利益を得ることができます。 –

関連する問題