problems with compiling C++ code including openMP directive

General OpenMP discussion

problems with compiling C++ code including openMP directive

Postby tobiash » Sat Dec 15, 2007 10:35 am

I have two questions:

I'm new to openMP and currently working my way through the openMP tutorial given at
http://kallipolis.com/openmp/

Question1:

I have installed the C++ and Fortran compiler and tested the (C++) programs
(serial and parallel versions). However, when I try to compile the parallel version (the
one including the openMP directives) without the -openmp option, I get error messages like

******************************************************************************************
tobiash@arpc2/parallel> icc taylor_yes_omp.c -o taylor_yes_omp.c.exe
taylor_yes_omp.c(15): warning #161: unrecognized #pragma
#pragma omp parallel sections num_threads(2)
^
taylor_yes_omp.c(17): warning #161: unrecognized #pragma
#pragma omp section
^
taylor_yes_omp.c(31): warning #161: unrecognized #pragma
#pragma omp section
******************************************************************************************

I thought, that when compiling a (parallelized) code without enabling the -openmp option
should compile the code in (default?) serial mode?!?

Question 2:

I'm a Fortran programmer and therefore I translated the taylor program into
Fortran90 language. Here is the code:

**************************************************************************************
program taylor

implicit none

double precision :: s_tart,s_top
double precision :: e,pi,factorial,product,test
integer*8 :: i,j,num_steps

num_steps = 20000000

call CPU_TIME(s_tart)
print *, 'Calculating e is started'

e = 1.0
factorial = 1.0

!$omp parallel do
do i=1,num_steps
factorial = factorial * i
e = e + 1.0/factorial
end do

print *, 'Calculating e is done, e=',e
print *, '*********************'
print *, 'Calculating pi is started'
pi = 0.0

!$omp parallel do
do j = 0,num_steps*10
pi = pi + 1.0/(j*4.0 + 1.0)
pi = pi - 1.0/(j*4.0 + 3.0)
end do

pi = pi * 4.0

print *, 'Calculating pi is done, pi=',pi

product = e * pi

call CPU_TIME(s_top)

print *, 'Reached result', product, 'in', s_top-s_tart, 'seconds.'

end
*******************************************************************************

However, when I run the code, I get erratic results! Sometimes PI is calculated
correctly and e is not correct and sometimes e is calculated correctly and PI is
not correct! And sometimes both are not calculated correctly!

Here is an example of the output (I compile in the beginning and run the code
7 times from the prompt):

tobiash@arpc2/parallel> ifort -openmp taylor.f90 -o taylor.f90.exe
taylor.f90(17): (col. 7) remark: OpenMP DEFINED LOOP WAS PARALLELIZED.
taylor.f90(28): (col. 7) remark: OpenMP DEFINED LOOP WAS PARALLELIZED.
tobiash@arpc2/parallel> ./taylor.f90.exe
Calculating e is started
Calculating e is done, e= 1.00000010000000
*********************
Calculating pi is started
Calculating pi is done, pi= 3.14159264858941
Reached result 3.14159296274867 in 26.6179540000000 seconds.
tobiash@arpc2/parallel> ./taylor.f90.exe
Calculating e is started
Calculating e is done, e= 1.00000010000000
*********************
Calculating pi is started
Calculating pi is done, pi= 2.499999959002954E-009
Reached result 2.500000209002950E-009 in 26.7519340000000 seconds.
tobiash@arpc2/parallel> ./taylor.f90.exe
Calculating e is started
Calculating e is done, e= 1.00000010000000
*********************
Calculating pi is started
Calculating pi is done, pi= 2.499999959002954E-009
Reached result 2.500000209002950E-009 in 26.5929570000000 seconds.
tobiash@arpc2/parallel> ./taylor.f90.exe
Calculating e is started
Calculating e is done, e= 1.00000010000000
*********************
Calculating pi is started
Calculating pi is done, pi= 2.499999959002954E-009
Reached result 2.500000209002950E-009 in 26.7169390000000 seconds.
tobiash@arpc2/parallel> ./taylor.f90.exe
Calculating e is started
Calculating e is done, e= 1.00000010000000
*********************
Calculating pi is started
Calculating pi is done, pi= 2.499999959002954E-009
Reached result 2.500000209002950E-009 in 26.5649620000000 seconds.
tobiash@arpc2/parallel> ./taylor.f90.exe
Calculating e is started
Calculating e is done, e= 1.00000010000000
*********************
Calculating pi is started
Calculating pi is done, pi= 3.14159264858941
Reached result 3.14159296274867 in 26.7009400000000 seconds.
tobiash@arpc2/parallel> ./taylor.f90.exe
Calculating e is started
Calculating e is done, e= 2.71828182845905
*********************
Calculating pi is started
Calculating pi is done, pi= 2.499999959002954E-009
Reached result 6.795704459706088E-009 in 26.5679620000000 seconds.
tobiash@arpc2/parallel>

However, when I compile without -openmp option. I get correct results everytime! But then,
of course, only fully serial!

What is going wrong!? Any help and explanations are very welcomed. This experience disencouraged
me in proceeding with openMP, since I'm reading Chandra et al. (Parallel Programming in OpenMP) and
wanted to test the "!$omp parallel do" directive on the taylor program - but getting wrong results! The
two do-loops in the taylor program are fully parallelisable and hence, each time the loops should split
into two threads. I don't understand why this problem occurs!

Any help/explanation is appreciated, but remember I'm new to OpenMP! I'm running Fedora 5 with an
Intel Pentium D (dual-core) processor.

Thank you!

Tobias
tobiash
 
Posts: 2
Joined: Sat Dec 15, 2007 8:19 am

Re: problems with compiling C++ code including openMP directive

Postby Keres » Mon Dec 17, 2007 4:26 am

Answer2:
Of course you'll get wrong result. More than one thread may write to variables e and pi at one time. That's not thread safe. In this case you must use reduction directive. Value of variable factorial is undetermined. You must use directive ordered or, better, array of factorial values. Like this:
Code: Select all
program taylor

implicit none

double precision :: s_tart,s_top
double precision :: e,pi,factorial,product,test
integer*8 :: i,j,num_steps

num_steps = 20000000

call CPU_TIME(s_tart)
print *, 'Calculating e is started'

e = 0.0
factorial = 1.0

!$omp parallel do reduction(+:e)
do i=1,num_steps
!$omp ordered
factorial = factorial * i
!$omp end ordered
e = e + 1.0/factorial
end do
e = e + 1.0

print *, 'Calculating e is done, e=',e
print *, '*********************'
print *, 'Calculating pi is started'
pi = 0.0

!$omp parallel do reduction (+:pi)
do j = 0,num_steps*10
pi = pi + (1.0/(j*4.0 + 1.0) - 1.0/(j*4.0 + 3.0))
end do

pi = pi * 4.0

print *, 'Calculating pi is done, pi=',pi

product = e * pi

call CPU_TIME(s_top)

print *, 'Reached result', product, 'in', s_top-s_tart, 'seconds.'

end
Keres
 
Posts: 4
Joined: Fri Dec 14, 2007 8:08 am
Location: Russia, Moscow

Re: problems with compiling C++ code including openMP directive

Postby tobiash » Mon Dec 17, 2007 6:49 am

Keres, - thank you very much for bringing me back on track with OpenMP! However, when I implement the openMP directives as suggested by you then I get a an error message. Based on the error output message, I put "ordered" infront of "reduction(+:e)" and then compiling gives no error! But, when running the program it takes much longer than the "fully seriel" compilation!! So there must still be something wrong! My question to you (or any one else) how would you translate the C++ OpenMP directives in the taylor.c program as shown at http://kallipolis.com/openmp/ to my F90 program? Also, regarding to my first question: I found out that the program compiles nicely and the binary is running without problems. I guess it is a feature of the icc compiler to give error output if one compiles without the -openmp flag. Looking forward to hear from you! Cheers, Tobias :-)
tobiash
 
Posts: 2
Joined: Sat Dec 15, 2007 8:19 am

Re: problems with compiling C++ code including openMP directive

Postby Keres » Tue Dec 18, 2007 7:36 am

tobiash wrote:Keres, - thank you very much for bringing me back on track with OpenMP! However, when I implement the openMP directives as suggested by you then I get a an error message. Based on the error output message, I put "ordered" infront of "reduction(+:e)" and then compiling gives no error! But, when running the program it takes much longer than the "fully seriel" compilation!!

My code is perfectly in order. It uses 2.5 openMP standart. Maybe your version of ICC uses another standart, read its manual. I think it will be ok, if you use gcc 4.2+ compiler or icc 10+.
You should know that omp use system calls, which are very "heavy". That's why using ordered, critical, barrier and other types of synchronization in light-weight iterations not recommended.
Code: Select all
factorial = factorial * i

Here we have strong data dependence. We can't avoid it without ordering(also we get wrong result). In this case we get barrier sync inside loop with "light" iterations. As a result - bad productivity. Try to use array of factorial values, such as factorial(1)=1, factorial(2)=2, factorial(3)=6 etc. This will be faster.
So there must still be something wrong! My question to you (or any one else) how would you translate the C++ OpenMP directives in the taylor.c program as shown at http://kallipolis.com/openmp/ to my F90 program? Also, regarding to my first question: I found out that the program compiles nicely and the binary is running without problems. I guess it is a feature of the icc compiler to give error output if one compiles without the -openmp flag. Looking forward to hear from you! Cheers, Tobias :-)

There's no problem to translate this program to F90. Just replase #pragma to !$ ;) And check your compiler manual, to avoid problems with directives names.
Keres
 
Posts: 4
Joined: Fri Dec 14, 2007 8:08 am
Location: Russia, Moscow


Return to Using OpenMP

Who is online

Users browsing this forum: Google [Bot], Yahoo [Bot] and 12 guests