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