Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29007 Discussions

First starting with Open MP but still stuck with a single thread

michel_lestrade
Beginner
1,658 Views

Hi,

I am currently rewriting our ray tracing code and hope to eventually make it work in parallel. I am now at a point where I need to decide what method I will be using. I was looking into Boost (C++) before but hopefully, Open MP will do the job so I do not have to mix languages.

This is my first multi-threaded project so I am starting small to make sure I understand how everything works. In the code below, I am setting the number of threads manually since I do not want to tangle with scheduling concepts just yet.

[cpp]program test

use omp_lib
implicit none

integer ii,th_id

!omp$ parallel
!omp$ do, private(ii,th_id), num_threads(2)
write(6,*) omp_get_num_threads()
write(6,*) omp_get_num_procs()
do ii=1,10
  th_id = omp_get_thread_num()
  write(6,*) th_id
end do
!omp$ end do
!omp$ end parallel

endprogram[/cpp]

The output is 1, 2, followed by zeroes.

Obviously, the two cores are being recognized properly but only a single thread is being created so th_id is always 0. Also, running in debug mode only shows a single thread.

I must be doing something wrong in my !omp$ do declaration but I don't see what it is.

I am using 10.1.021 with default debug options (except for /Qopenmp obviously).

Thanks.

0 Kudos
1 Solution
IanH
Honored Contributor III
1,658 Views
I've been burnt by this too. Check the location of your '$'.

!OMP$ is just a comment. You want !$OMP to introduce the directive.

Look for remarks in the output from the compiler telling you that its actually parallelized the loop.

IanH

View solution in original post

0 Kudos
5 Replies
TimP
Honored Contributor III
1,658 Views
[cpp]#ifdef _OPENMP
!$omp parallel
!$omp single
        nt=omp_get_num_threads()
      write(cmpter(16)(27:72),'(i0)'),nt
!$omp end single
!$omp end parallel
#endif[/cpp]

I agree with the idea of putting your threading in Fortran, rather than making it mixed language.

You are already going beyond the simplest concepts. at least if I judge by what I can find explained in introductory material.

To begin with, your OMP DO directive should be immediately before the Fortran do. OMP END DO isn't needed, it knows enough to finish off with the Fortran end do.

I would suggest !$omp single ...... !$omp end single (inside aparallel region) for omp function calls outside a loop. You would also need #ifdef _OPENMP..... #endif around the function calls, if you want to preserve the ability to turn off OpenMP. In my posted example I use

#ifdef _OPENMP
!$omp parallel
!$omp single
nt=omp_get_num_threads()
write(cmpter(16)(27:72),'(i0)'),nt
!$omp end single
!$omp end parallel
#endif

Gosh, I wonder if the text insertion tools are working properly today. Both of us appear to be having trouble.

0 Kudos
michel_lestrade
Beginner
1,658 Views
Quoting - tim18
[cpp]#ifdef _OPENMP
!$omp parallel
!$omp single
nt=omp_get_num_threads()
write(cmpter(16)(27:72),'(i0)'),nt
!$omp end single
!$omp end parallel
#endif[/cpp]

I agree with the idea of putting your threading in Fortran, rather than making it mixed language.

You are already going beyond the simplest concepts. at least if I judge by what I can find explained in introductory material.

To begin with, your OMP DO directive should be immediately before the Fortran do. OMP END DO isn't needed, it knows enough to finish off with the Fortran end do.

I would suggest !$omp single ...... !$omp end single (inside aparallel region) for omp function calls outside a loop. You would also need #ifdef _OPENMP..... #endif around the function calls, if you want to preserve the ability to turn off OpenMP. In my posted example I use

#ifdef _OPENMP
!$omp parallel
!$omp single
nt=omp_get_num_threads()
write(cmpter(16)(27:72),'(i0)'),nt
!$omp end single
!$omp end parallel
#endif

Gosh, I wonder if the text insertion tools are working properly today. Both of us appear to be having trouble.

I am not sure SINGLE will do what I want: the help says this will be called only from a single thread in the team. Here, I am looking to get a handle that will be unique for each thread.

My reasoning is that in my code, I will need to print the ray trajectory. I want each thread to follow the starting ray from a given emission point as well as any other secondary rays it spawns when hitting various interfaces. Normally I write this to a file but I/O is troublesome in multi-threading and I need to keep the sequence intact fro a given primary ray so the trajectory makes sense.

If this was C++, I would simply use a thread-private vector and push_back() to store this information until I can safely print it (protected by a critical section of course). Since the STL does not exist in Fortran, I was thinking of using scratch files with the thread id to help uniquely identify the unit associated with the file so that 1 thread = 1 scratch file. It's either that or constantly reallocate an array of internal character buffers in order to try and duplicate the C++ approach.

In any case, I tried simplifying the code even further to no avail. This still prints out nothing but zeroes in the loop.

[cpp]program test

use omp_lib
implicit none

integer ii,th_id

write(6,*) 'Number of processors: ', omp_get_num_procs()
!OMP$ PARALLEL DO PRIVATE(th_id) NUM_THREADS(2)
do ii=1,10
  th_id = omp_get_thread_num()
  write(6,*) 'Hello from thread #: ', th_id
end do

endprogram
[/cpp]

Thanks.

0 Kudos
IanH
Honored Contributor III
1,659 Views
I've been burnt by this too. Check the location of your '$'.

!OMP$ is just a comment. You want !$OMP to introduce the directive.

Look for remarks in the output from the compiler telling you that its actually parallelized the loop.

IanH

0 Kudos
michel_lestrade
Beginner
1,658 Views
Quoting - IanH
I've been burnt by this too. Check the location of your '$'.

!OMP$ is just a comment. You want !$OMP to introduce the directive.

Look for remarks in the output from the compiler telling you that its actually parallelized the loop.

IanH

Thanks so much. I had not noticed it was a different style than !DEC$. Works perfectly now so I can start thinking about the bigger project.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,658 Views

Fortran with OpenMP has ThreadPrivate capability (I use this). Create a thread private variable with a thread ID number with default initialization to -1. Add a module variable, intialized to 0 and then when thread runs and notices -1 in thread ID it call InterlockedIncrement on the shared variable, taking the result and placing it into the thread private thread ID (the InterlockedIncrement occures once for the life of the thread).

Jim Dempsey

0 Kudos
Reply