2

This is the first time I am using OpenMP, and I apply it for Fortran. I happened to have a problem adjusting the loop where there is a variable that requires update from its previous value. I tried using PRIVATE clause but the result is far from those resulted by serial computation (without OpenMP).

I looked somewhere in OpenMP website and I found one solution using !$OMP PARALLEL DO ORDERED which finally works (produce the same result with the serial one). But it seems that by using this, the speed of computation is considerably slower than using just PRIVATE clause.

Is there any other way to apply OpenMP in such as a case to get maximum speed?

Codes using ORDERED option.

!$OMP PARALLEL DO ORDERED PRIVATE(i,j)
do i = ca,cb
    incre(i) = 0.0d0
    value = 17.0d0*li(i)
    do j = cx,cy
        qx    = hi(i) - hj(j)
        mij   = dsqrt(qx)
        if( mij <= value ) then
            beta   = li(i)*li(j)
            !$OMP ORDERED
            incre(i) = incre(i) + beta
            !$OMP END ORDERED
        end if
    end do
end do
!$OMP END PARALLEL DO

Codes using only PRIVATE clause

!$OMP PARALLEL DO PRIVATE(i,j,incre,value,beta)
do i = ca,cb
    incre(i) = 0.0d0
    value = 17.0d0*li(i)
    do j = cx,cy
        qx    = hi(i) - hj(j)
        mij   = dsqrt(qx)
        if( mij <= value ) then
            beta   = li(i)*li(j)
            incre(i) = incre(i) + beta
        end if
    end do
end do
!$OMP END PARALLEL DO
Alexander Vogt
  • 17,879
  • 13
  • 52
  • 68
Franky
  • 73
  • 4
  • 1
    incre should be "public" and mij should be "private". Add DEFAULT(NONE) in your !$OMP statement please to be sure not to forget the status of a variable – Francois Jacq May 24 '15 at 09:14
  • 1
    I forgot qx which is useless (but private). Only the second version could speed up your code. The clause ORDERED is only used for debug purpose... – Francois Jacq May 24 '15 at 09:16
  • Ah I forgot to put `mij` in private, but thanks a lot for pointing out putting `incre` in public. I just know ORDERED clause is only for debug. Perhaps I should read other codes carefully next time. – Franky May 24 '15 at 14:05

1 Answers1

1

As Francois pointed out in his comments, qx and mij need to be thread private:

!$OMP PARALLEL DO PRIVATE(i,j,value,beta,qx,mij)
do i = ca,cb
    incre(i) = 0.0d0
    value = 17.0d0*li(i)
    do j = cx,cy
        qx    = hi(i) - hj(j)
        mij   = dsqrt(qx)
        if( mij <= value ) then
            beta   = li(i)*li(j)
            incre(i) = incre(i) + beta
        end if
    end do
end do
!$OMP END PARALLEL DO

incre does not need to be private, since access to it is only via the index i. so all threads access a different portion of it. However, if you need to access the elements afterwards, make sure it is public (shared).

Alexander Vogt
  • 17,879
  • 13
  • 52
  • 68
  • So am I correct to say in nested loop the process will divide only to the outer loop so that whatever variable accessed via the outer loop index should not be private even if it is accessed again afterwards in the loop? – Franky May 24 '15 at 14:05
  • Yes, only the `do` loop directly following the OpenMP statement is parallelized. If I understand the second part of your question correctly, then yes, each thread will perform the inner loop on its own set of private variables. If access to shared variables/arrays is not interfering with other threads, there is no need to make those variables private. – Alexander Vogt May 24 '15 at 14:11
  • Great. I got a glimpse about OpenMP now. Thank you @alexander. – Franky May 24 '15 at 14:14