OpenMP Problem Set

 

The OpenMP Problem Set is composed of problems 1-3 on slide 116, 4-6 on slide 117 and 7-9 on slide 118.

 

Problem 1: If the output is completely unreadable (seen with Fortran 77), enclosed the PRINT statement in a Critical Section.

 

Our machine has 24 processors so using more than 24 threads results in a warning.

 

Problem 3: Add the following code to time the actual computation section of the problem:

Declaration:

REAL, EXTERNAL :: DTime

REAL, DIMENSION(0:3,2) :: Tarray

REAL, DIMENSION(0:3) :: Time

Start timing:

Time(0) = DTime(Tarray(0,:))

End timing and output:

Time(0) = DTime(Tarray(0,:))

PRINT*, 'Exercise 3'

PRINT*, 'Time:', Time(0), &

           'User:', Tarray(0,1), &

           'System:',Tarray(0,2), &

 

In addition, the program needs to run on the same speed processor to make the comparisons meaningful. Prefix the command to run the program with either 250 or 300.

 

Problem 5: A Fortran 90 version is also available as mystery.f90. Copy either from ~jmatrow/openmp.

 

Problem 6: Copy points.dat from ~jmatrow/openmp. There are 50001 data points. Also, you may get different results from two different solutions. Why?

 

Problem 8: Copy dotp.f90 from ~jmatrow/openmp. Parallelize what you can. Then compile the original with –apo and compare the results. Do not time for more than 16 processors.


Suggested Solutions in Fortran 90

 

Problem 1:

 

      PROGRAM hello

!$omp parallel

      PRINT *, "Hello World! from thread number", &

      omp_get_thread_num(), ' out of ', omp_get_num_threads()

!$omp end parallel

      END

 

 

Problem 2:

 

      PROGRAM hello

!$omp parallel

      IF (MOD(omp_get_thread_num(),2) == 0) THEN

        PRINT *, "Hello World! from thread number", &

        omp_get_thread_num(), ' out of ', omp_get_num_threads()

      END IF

!$omp end parallel

      END

 


Problem 3:

 

        PROGRAM osc3

        INTEGER  i

        INTEGER, PARAMETER :: arraymax = 64000000

        INTEGER, DIMENSION(arraymax) :: a

        REAL, DIMENSION(arraymax) :: b

        REAL, EXTERNAL :: DTime

        REAL, DIMENSION(0:3,2) :: Tarray

        REAL, DIMENSION(0:3) :: Time

 

!$omp parallel do

        DO i = 1, arraymax

           a(i) = i

        END DO

!       PRINT *, 'OMP_MAX_THREADS = ', omp_get_max_threads()

        Time(0) = DTime(Tarray(0,:))

!$omp parallel do schedule(guided,1000)

        DO i = 1, arraymax

           IF (i == 1) THEN

                b(i) = (a(i)+a(i+1))/2.0

           ELSEIF (i == arraymax) THEN

                b(i) = (a(i-1)+a(i))/2.0

           ELSE

                b(i) = (a(i-1)+a(i)+a(i+1))/3.0

           END IF

        END DO

 

        Time(0) = DTime(Tarray(0,:))

        PRINT*, 'Exercise 3'

        PRINT*, 'Time:', Time(0), &

           'User:', Tarray(0,1), &

           'System:',Tarray(0,2), &

           "DP = ", DP

 

        END

 


Problem 4:

 

        PROGRAM osc4

        INTEGER :: numthreads, i

        numthreads = omp_get_max_threads()

        i = numthreads - 1

!$omp parallel

        DO WHILE (i >= 0)

!$omp critical

        IF (i == omp_get_thread_num()) THEN

           PRINT *, "Hello World! from thread number", &

              i, ' out of ', numthreads

           i = i - 1

        END IF

!$omp end critical

        END DO

!$omp end parallel

        END

 

 

Problem 5:

 

      program sum

      integer :: i, m

      real :: xsum, x

!

! Compute global sum

!

      call omp_set_num_threads(16)

      xsum = 0.0

!$omp parallel do private(i,m,x) reduction(+:xsum)

      do i = 1, 800

        m = (i-1)/100

        x = m + 1.0

        xsum = xsum + x

      enddo

      print *, 'Global Sum = ', xsum

 

 

      end

 



Problem 6:

 

      PROGRAM osc6

      IMPLICIT NONE

      INTEGER, PARAMETER :: maxsize = 55000

      INTEGER :: i = 1

      INTEGER :: actualmax

      REAL, DIMENSION (maxsize) :: x, y, z

      REAL :: xsum, ysum, zsum = 0.0

 

      OPEN (14,FILE='points.dat',ACTION='READ')

      DO WHILE (i > 0)

         READ (14,FMT=*,END=10) x(i), y(i), z(i)

         i = i + 1

      END DO

   10 CLOSE (14)

      actualmax = i

     

!$omp parallel do private(i) reduction(+:xsum,ysum,zsum)

      DO i = 1, actualmax

        xsum = xsum + x(i)

        ysum = ysum + y(i)

        zsum = zsum + z(i)

      ENDDO

 

      PRINT *, 'Number of points = ', actualmax

      PRINT *, 'Avg x = ', xsum/actualmax, ', Avg y = ', ysum/actualmax, &

        ', Avg z = ', zsum/actualmax

      END

 


Problem 7:

 

PROGRAM osc7

  IMPLICIT NONE

    INTEGER, PARAMETER :: maxsize = 55000

    INTEGER :: i = 1

    INTEGER :: actualmax

    REAL, DIMENSION (maxsize) :: x, y, z

    REAL :: xsum, ysum, zsum, sumsum = 0.0

 

      OPEN (14,FILE='points.dat',ACTION='READ')

      DO WHILE (i > 0)

         READ (14,FMT=*,END=10) x(i), y(i), z(i)

         i = i + 1

      END DO

   10 CLOSE (14)

      actualmax = i

     

!$omp parallel sections

!$omp section

      xsum = sumarray(x,actualmax)

!$omp critical

      sumsum = sumsum + xsum

!$omp end critical

 

!$omp section

      ysum = sumarray(y,actualmax)

!$omp critical

      sumsum = sumsum + ysum

!$omp end critical

 

!$omp section

      zsum = sumarray(z,actualmax)

!$omp critical

      sumsum = sumsum + zsum

!$omp end critical

!$omp end parallel sections

 

      PRINT *, 'Number of points = ', actualmax

      PRINT *, 'Avg x = ', xsum/actualmax, ', Avg y = ', ysum/actualmax, ', Avg z = ', zsum/actualmax

      PRINT *, 'Avg point value = ', sumsum/(3.0 * actualmax)

 

CONTAINS

 

  REAL FUNCTION sumarray (a,max)

    REAL, INTENT(IN), DIMENSION(:) :: a

    INTEGER, INTENT(IN) :: max

    INTEGER :: i

!!!$omp do private(i) reduction(+:sumarray)

      DO i = 1, max

        sumarray = sumarray + a(i)

      ENDDO

  END FUNCTION

 

END

 


Problem 8:

 

PROGRAM dotp

 IMPLICIT NONE

 INTEGER, PARAMETER :: Asize = 26800000

 REAL, DIMENSION (ASize) :: a, b

 REAL*8, DIMENSION (ASize) :: a1, a2, res

 REAL :: DP = 0.0

 INTEGER :: i, j

 

 REAL, EXTERNAL :: DTime

 REAL, DIMENSION(0:3,2) :: Tarray

 REAL, DIMENSION(0:3) :: Time

 

  CALL RANDOM_NUMBER (a)

  a1=a

  CALL RANDOM_NUMBER (b)

  a2=b

 

! Method 0 old f77

   Time(0) = DTime(Tarray(0,:))

    DP = 0.0

!$omp parallel do reduction(+:DP)

    DO i = 1, ASize

     DP = DP + a1(i) * a2(i)

   END DO

   Time(0) = DTime(Tarray(0,:))

   PRINT*, 'F77 Method'

   PRINT*, 'Time:', Time(0), &

           'User:', Tarray(0,1), &

           'System:',Tarray(0,2), &

           "DP = ", DP

 

! Method 1 my code

   Time(1) = DTime(Tarray(1,:))

    DP = 0.0

    res = a1 * a2

!$omp parallel do reduction(+:DP)

    DO i = 1, ASize

     DP = DP+res(i)

   END DO

   Time(1) = DTime(Tarray(1,:))

   PRINT*, 'My Method'

   PRINT*, 'Time:', Time(1), &

           'User:', Tarray(1,1), &

           'System:',Tarray(1,2), &

           "DP = ", DP

 

! Method 2 use * and intrinsic SUM

   Time(2) = DTime(Tarray(2,:))

    DP = SUM(a1*a2)

   Time(2) = DTime(Tarray(2,:))

   PRINT*, '* and SUM'

   PRINT*, 'Time:', Time(2), &

           'User:', Tarray(2,1), &

           'System:',Tarray(2,2), &

           "DP = ", DP

 

! Method 3 intrinsic DOT_PROD

   Time(3) = DTime(Tarray(3,:))

    DP = DOT_PRODUCT(a1,a2)

   Time(3) = DTime(Tarray(3,:))

   PRINT*, 'DOT_PRODUCT'

   PRINT*, 'Time:', Time(3), &

           'User:', Tarray(3,1), &

           'System:',Tarray(3,2), &

           "DP = ", DP

 

 

    END PROGRAM

 

 

Problem 9:

 

       program alias

       parameter(jmax=1000000, kmax=4)

       real sum(4)

 

       do k = 1, kmax

         sum(k) = float(k) * float(jmax)

       enddo

 

       print *, 'Sum:  ', sum

       end