- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi folks!
I recently updated to Intel Fortran 12. Unfortunately my code does not compile with OpenMP anymore.
The compiler seems to have problems with OpenMP statements in module procedures where the
enclosing parallel region is not in the same module. Example:
The Compiler (Version 12.0.2 20110112) aborted with the following error message:
error #7982: Variables in the COPYPRIVATE list must be PRIVATE in the enclosing parallel region.
Putting myfun into the main program, everything works again.
However, such constructs work with Intel Fortran 11.1, gfortran, xlf, etc.
Does anyone know how to solve this problem?
I recently updated to Intel Fortran 12. Unfortunately my code does not compile with OpenMP anymore.
The compiler seems to have problems with OpenMP statements in module procedures where the
enclosing parallel region is not in the same module. Example:
[fortran]module modtest implicit none contains subroutine myfun(x) integer, intent(inout) :: x !$omp single x = x + 1 !$omp end single copyprivate(x) end subroutine myfun end module modtest program test use modtest implicit none integer :: a !$omp parallel private(a) a = 1 call myfun(a) !$omp end parallel end program test[/fortran]
The Compiler (Version 12.0.2 20110112) aborted with the following error message:
error #7982: Variables in the COPYPRIVATE list must be PRIVATE in the enclosing parallel region.
Putting myfun into the main program, everything works again.
However, such constructs work with Intel Fortran 11.1, gfortran, xlf, etc.
Does anyone know how to solve this problem?
Link Copied
7 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your function myfun could be called from anywhere (that includes modtest). This includes from within and without a parallel region. Therefore your use of single is ambiguous with this respect, as well as if called within a parallel region it isambiguous as to which team made the call (i.e. nested levels in effect). The !$omp single must be placed where thread team scope is visible (and unambiguous) to the compiler. Also the copyprivate is meaningless in this context
Did you mean to use !$omp critical instead? critical and atomiccan be use in function/subroutine that has no knowledge of parallel region scope.
Jim Dempsey
Did you mean to use !$omp critical instead? critical and atomiccan be use in function/subroutine that has no knowledge of parallel region scope.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, I don't think that the use of single is ambiguous (see OpenMP standard):
- "The binding thread set for a single region is the current team. A single region
binds to the innermost enclosing parallel region."
- current team tasks: "All tasks encountered during the execution of the innermost enclosing
parallel region by the threads of the corresponding team. Note that the
implicit tasks constituting the parallel region and any descendant tasks
encountered during the execution of these implicit tasks are included in this
binding task set."
- if the above routine _is not_ called within an explicit parallel region, the innermost enclosing parallel region is the implicit (inactive) parallel region with only one thread, which is automatically generated
- if the above routine _is_ called within an explicit parallel region, this region is the innermost enclosing parallel region
Sure, in the above example, the use of copyprivate is meaningless (as the whole example). In practice, copyprivate is heavily used to share pointers, allocated in a single construct. See appendix A.37 in the current OpenMP standard for examples.
From the OpenMP standard I don't see, why an explicit parallel region must be visible to the compiler in order to use copyprivate. I think the check for the variable used in copyprivate is just too severe. In general, a compiler cannot determine (at compile time) if the variable is really private, it just has to assume that.
Besides, everything worked fine with all available Fortran compilers until now.
- "The binding thread set for a single region is the current team. A single region
binds to the innermost enclosing parallel region."
- current team tasks: "All tasks encountered during the execution of the innermost enclosing
parallel region by the threads of the corresponding team. Note that the
implicit tasks constituting the parallel region and any descendant tasks
encountered during the execution of these implicit tasks are included in this
binding task set."
- if the above routine _is not_ called within an explicit parallel region, the innermost enclosing parallel region is the implicit (inactive) parallel region with only one thread, which is automatically generated
- if the above routine _is_ called within an explicit parallel region, this region is the innermost enclosing parallel region
Sure, in the above example, the use of copyprivate is meaningless (as the whole example). In practice, copyprivate is heavily used to share pointers, allocated in a single construct. See appendix A.37 in the current OpenMP standard for examples.
From the OpenMP standard I don't see, why an explicit parallel region must be visible to the compiler in order to use copyprivate. I think the check for the variable used in copyprivate is just too severe. In general, a compiler cannot determine (at compile time) if the variable is really private, it just has to assume that.
Besides, everything worked fine with all available Fortran compilers until now.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In checking the OpenMP 3.0 spec, you are correct about SINGLE being used in the subroutine as posted.
However, it is unnecessary (andinvalid)to have copyprivate inside the subroutine because each thread will enter with a different variable for a.
insert
write(*,*) omp_get_thread_num(), a
following the call to the subroutine wiht the SINGLE.
only one of the threads should print 2, the remainder will print 1
Jim Dempsey
However, it is unnecessary (andinvalid)to have copyprivate inside the subroutine because each thread will enter with a different variable for a.
insert
write(*,*) omp_get_thread_num(), a
following the call to the subroutine wiht the SINGLE.
only one of the threads should print 2, the remainder will print 1
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, copyprivate is necessary (and valid). The whole purpose of copyprivate that one thread can send the value of his own thread local variable to the other threads (where the variable is again thread local)
Doing your suggestion to print the thread local values of a after the call to the subroutine, every thread will give the same result. Otherwise there would be no need to have copyprivate at all:
> gfortran -fopenmp test.F90 && OMP_NUM_THREADS=4 ./a.out
2 2
1 2
0 2
3 2
The only problem is that this program doesn't compile with Intel Fortran in version 12 anymore.
Doing your suggestion to print the thread local values of a after the call to the subroutine, every thread will give the same result. Otherwise there would be no need to have copyprivate at all:
[fortran]module modtest implicit none contains subroutine myfun(x) integer, intent(inout) :: x !$omp single x = x + 1 !$omp end single copyprivate(x) end subroutine myfun end module modtest program test use modtest use omp_lib implicit none integer :: a !$omp parallel private(a) a = 1 call myfun(a) write(*,*) omp_get_thread_num(),a !$omp end parallel end program test [/fortran]
> gfortran -fopenmp test.F90 && OMP_NUM_THREADS=4 ./a.out
2 2
1 2
0 2
3 2
The only problem is that this program doesn't compile with Intel Fortran in version 12 anymore.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The output you provided, contradicts the (your)premise that the SINGLE in the called subroutine is cognizant of the caller's parallel region. The behavior is as if no parallel region was detected.
The calling argument (a) was private to each thread
Each thread initialized their private copy of a to 1
Each thread called myfun with there private copy of a
The SINGLE was apparently executed by all threads, since all threads report 2 for value of their private copy of a.
Place a break on the x=x+1 in myfun
I will bet you see 4 breaks
If so, this then indicates that SINGLE is not OpenMP 3.0 compliant (as use in your sample program).
The subroutine myfun cannot observe that the caller's arguments are private variables of the same name, and would have no information as to how to copy back to the other threads (of the caller's team) variables of same name. If this function were inlined, then maybe the compiler could make this determination.
Jim Dempsey
The calling argument (a) was private to each thread
Each thread initialized their private copy of a to 1
Each thread called myfun with there private copy of a
The SINGLE was apparently executed by all threads, since all threads report 2 for value of their private copy of a.
Place a break on the x=x+1 in myfun
I will bet you see 4 breaks
If so, this then indicates that SINGLE is not OpenMP 3.0 compliant (as use in your sample program).
The subroutine myfun cannot observe that the caller's arguments are private variables of the same name, and would have no information as to how to copy back to the other threads (of the caller's team) variables of same name. If this function were inlined, then maybe the compiler could make this determination.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, the single construct (which is OpenMP compliant) is definitly not exedcuted by all threads. You can easily prove that by the example below. Sure, the compiler cannot check if the variable in the copyprivate was declared private (and the new intel fortran version 12 should not try to check that) but this check is just not necessary.
The mechanism, how the compiler copies private variables to the other threads depends on the implementation, but the compiler has all the information it needs, even without the knowledge of explicit parallel region.
!> gfortran -fopenmp test.F90 && OMP_NUM_THREADS=4 ./a.out
This is thread 3
2 2
1 2
3 2
0 2
The mechanism, how the compiler copies private variables to the other threads depends on the implementation, but the compiler has all the information it needs, even without the knowledge of explicit parallel region.
[fortran]module modtest use omp_lib implicit none contains subroutine myfun(x) integer, intent(inout) :: x !$omp single x = x + 1 write(*,*) 'This is thread ',omp_get_thread_num() !$omp end single copyprivate(x) end subroutine myfun end module modtest program test use modtest use omp_lib implicit none integer :: a !$omp parallel private(a) a = 1 call myfun(a) write(*,*) omp_get_thread_num(),a !$omp end parallel end program test [/fortran]
!> gfortran -fopenmp test.F90 && OMP_NUM_THREADS=4 ./a.out
This is thread 3
2 2
1 2
3 2
0 2
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is a rather interesting example. What it seems to indicate is:
copyprivate(x), which occures at an !$omp end single, and which the !$omp single my be called from within or without a parallel region, must be declaring that the scalar x, which at compile timerepresents a cell inan array, rank 1, of unknown size at compile time, and unknown position within the array, other than the position represents the position within the array for the current thread of the thread team, or the scalar itself in the event the call is made from outside a parallel region.
Example, assume 4 thread team as you exampled above, and thread 3 is the winning thread for the single region.
Thecaller, with !$omp parallel private(a) is apparently creating a 0-basedinteger array of size of thread team. Each thread receives a reference to one of the elements of this array (indexed by thread number within the team) and uses that reference via the alias "a". Each thread calls with a seperate pointer(reference) into this array (at there own private a). Inside myfunc !$omp end single copyprivate(x) says: x is not a dummy variable to a scalar integer, instead it is a dummy reference to a 0-based array of same type (integer) with assumed index of thread team member number. When not called from parallel region this reduces to team member number 0 of a 0-based array with 1 element. Any thread therefore can determin where each of the other threads (or all threads) variables of x are located.
So then, yes, the !$omp single... !$omp end single copyprivate(x) in a subroutine without compile time knowledge of being called from parallel region, or not, can work.
And your error message is erronious (compiler error).
Jim Dempsey
copyprivate(x), which occures at an !$omp end single, and which the !$omp single my be called from within or without a parallel region, must be declaring that the scalar x, which at compile timerepresents a cell inan array, rank 1, of unknown size at compile time, and unknown position within the array, other than the position represents the position within the array for the current thread of the thread team, or the scalar itself in the event the call is made from outside a parallel region.
Example, assume 4 thread team as you exampled above, and thread 3 is the winning thread for the single region.
Thecaller, with !$omp parallel private(a) is apparently creating a 0-basedinteger array of size of thread team. Each thread receives a reference to one of the elements of this array (indexed by thread number within the team) and uses that reference via the alias "a". Each thread calls with a seperate pointer(reference) into this array (at there own private a). Inside myfunc !$omp end single copyprivate(x) says: x is not a dummy variable to a scalar integer, instead it is a dummy reference to a 0-based array of same type (integer) with assumed index of thread team member number. When not called from parallel region this reduces to team member number 0 of a 0-based array with 1 element. Any thread therefore can determin where each of the other threads (or all threads) variables of x are located.
So then, yes, the !$omp single... !$omp end single copyprivate(x) in a subroutine without compile time knowledge of being called from parallel region, or not, can work.
And your error message is erronious (compiler error).
Jim Dempsey
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page