Могу ли я распараллелить мою программу? - PullRequest
0 голосов
/ 12 марта 2012

Это моя программа:

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, то для обоих значений я могу распараллелить этот код, чтобы быстро получить ответ.

Я использую компилятор PGI для CUDA FORTRAN.

Ответы [ 2 ]

1 голос
/ 13 марта 2012

Ваш код довольно прост с большим количеством независимых параллельных циклов. Эти параллельные циклы, по-видимому, заключены во внешний цикл конвергенции do while, поэтому до тех пор, пока вы сохраняете данные на устройстве для всех итераций цикла конвергенции, вы не будете ограничены переносами.

Я бы рекомендовал начинать с директив компилятора для этого кода, а не погружаться в CUDA Fortran. Директивы компилятора хорошо работают для таких простых независимых циклов, как эти, - это простые подсказки, которые вы помещаете в комментарии кода, которые сообщают компилятору, какие циклы распараллеливать, какие данные копировать и т. Д.

Сначала вы можете попробовать OpenMP для ускорения до нескольких ядер ЦП. Затем вы можете использовать директивы GPU, такие как OpenACC , которые скоро будут доступны в компиляторах от PGI, Cray и CAPS. Чтобы начать, вы можете загрузить бесплатную пробную версию PGI компилятора и использовать их "Accelerator" директивы. Ускоритель по синтаксису очень похож на OpenACC.

1 голос
/ 12 марта 2012

Да, вы можете использовать PGI compiler для написания ядер CUDA и выполнения вызовов CUDA API.

ЗГУ Домашняя страница Fortran CUDA

Вопрос, я думаю, вы хотите спросить: " Должен ли распараллелить этот код?"

Мой ответ будет таким: да, вы можете увидеть некоторые небольшие преимущества параллелизации, с первого взгляда.

Например, такие сегменты, как:

 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 раз быстрее, если вы хорошо закодируете , в зависимости от размера границы вашего цикла и уровня расхождения в определенных циклах.

В худшем случае вы не видите выигрыша или даже видите замедление, но, по крайней мере, вы чему-то научились !!

...