Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29298 Discussions

Private allocatable arrays inside subroutine in parallel region.

Intel_C_Intel
Employee
1,458 Views
I was searching forum but didnt find any similar problem.

I am having a problem with parallelizing some code. 
It seems to be according to spec but still causes errors. 
I have parallel do loop which has several small allocation and 
deallocation of arrays which is private to each thread, and subroutine 
call, so I would like to use that arrays inside subroutine, but looks 
like it cant see that arrays are allocated and gives such error: 
forrtl: severe <408>: fort: <2>: Subscript #3 of the array GLOBAL has 
value 1 which is greater than the upper bound of -1.

Here is the sample code which demonstrates this problem.


module variables

integer :: row, col

integer :: omp_threads_id, omp_num_of_nodes

real*8, allocatable, dimension ( : ) :: GLOBAL ( :, :, : )

real*8, allocatable, dimension ( : ) :: LOCAL( :, : )

end module variables

program openmp

use variables

use sublocal

use omp_lib

implicit none

print*, '-------------------------------- --------------'

omp_num_of_nodes = omp_get_num_procs()

call omp_set_num_threads( omp_num_of_nodes )

print*, 'Number of threads available: ', omp_num_of_nodes

!$omp parallel

omp_threads_id = omp_get_thread_num()

print*, 'Thread number: ', omp_threads_id, 'responded.'

!$omp end parallel

print*, '----------------------------------------------'

!$omp parallel default(shared)

!$omp do private(row, col, GLOBAL, LOCAL)

do row=1, 10

allocate(GLOBAL(2, 10, 10))

GLOBAL = 0

do col=1, 10

omp_threads_id = omp_get_thread_num()

call sub

print*, GLOBAL(1, row, col), omp_threads_id, row, col

end do

deallocate(GLOBAL)

end do

!$omp end do

!$omp end parallel

  ; call system("PAUSE")

end program openmp

module sublocal

use variables

implicit none

contains

subroutine sub

integer :: i, j

do i = 1, 2

allocate(LOCAL(2, 2))

LOCAL = 0

do j = 1, 2

LOCAL(i, j) = i+j*4

GLOBAL(1, i, j) = LOCAL(i, j)

print*, GLOBAL(1, i, j)

end do

deallocate(LOCAL)

end do

print*, 'Hello world.'

end subroutine sub

end module sublocal 

So my question is what is happening with private allocatable array when it goesinside subrou tine?

I dont know how helpful will be this, but I use Intel Visual Fortran Compiler 9.1 Professional with Microsoft Visual Studio 2005 Professional, and I have Core 2 Duo processor. OS is Windows Vista Ultimate.

Any help will be appreciated.

0 Kudos
5 Replies
Intel_C_Intel
Employee
1,458 Views

I tried to pass array as an argument that all threads will know address of any such object, so that they may access the original data and not local copies. It runs but my array has wrong numbers.

But since GLOBAL is private, each thread should have its own local copy. Hence, we do not need to pass in an address in this case. But its not working as it should.

0 Kudos
gib
New Contributor II
1,458 Views
If you want LOCAL to be local to sub, why not put the declaration in sub? I'm no expert, but placing it in the module as you have seems to make it global.

Gib
0 Kudos
Intel_C_Intel
Employee
1,458 Views

My bad code above doesnt have exactly everything I wanted to do. I need to store some values from the main program into array which is private to each thread and then use it inside subroutine, after that get results back to main program. I have one big 3 dimensional matrix which store local elements inside, each local element can be calculated separately since they store in different location of the global array, for example GLOBAL_MESH (LocalElementNumber, row, col) so I can store element number 1 in LOCAL(row, col) and calculated and store results back to GLOBAL_MESH.

By declaring array private inside subroutine will create local copy of array which doesnt have information which I need from main program. Yes you are right they become global so how can I change that, and I wonder whether it is even OK ("legal") to put a private variable in a module?

I am concerned with the following statement in OpenMP:

2.6.3 Data environment rules

...

7.... Common blocks and modules in called routines in the dynamic extent of a parallel region always have an implicit SHARED attribute, unless they are THREADPRIVATE common blocks.

It seems to me, any variables defined in the data segments of Fortran 90 MODULEs would be limited to be SHARED.

So even if I declare them threadprivate, it gives me allocation error. Like this:


!$omp parallel default(shared)

!$threadprivate(/GLOBAL/, /LOCAL/)

!$copyin(/GLOBAL/,LOCAL)

!$omp do private(row, col)

do row=1, 2

allocate(GLOBAL(2, 2, 2)) !forrtl: severe<151>: allocatable array is already allocated

GLOBAL = 0

do col=1, 2

omp_threads_id = omp_get_thread_num()

GLOBAL(1, row, col) = 1

call sub

end do

deallo cate(GLOBAL)

end do

!$omp end do

!$omp end parallel


I am not sure since I dont have much experience coding in OpenMP.

But thanks for respond.

0 Kudos
Intel_C_Intel
Employee
1,458 Views

I am been such a nube, here how it works:


module variables

use omp_lib

integer :: row, col

integer :: omp_threads_id, omp_num_of_nodes

real*8, allocatable, dimension ( : ) :: GLOBAL ( :, :, : )

real*8, allocatable, dimension ( : ) :: LOCAL( :, : )

!$omp threadprivate(GLOBAL, LOCAL)

end module variables

module sublocal

use variables

implicit none

contains

subroutine sub

integer :: i, j

do i = 1, 2

allocate(LOCAL(2, 2))

LOCAL = 0

do j = 1, 2

LOCAL(i, j) = i+j*4

GLOBAL(1, i, j) = LOCAL(i, j)

print*, 'SUB: ',GLOBAL(1, i, j)

end do

deallocate(LOCAL)

end do

end subroutine sub

end module sublocal

program openmp

use variables

use sublocal

use omp_lib

implicit none

print*, '----------------------------------------------'

omp_num_of_nodes = omp_get_num_procs()

call omp_set_num_threads( omp_num_of_nodes )

print*, 'Number of threads available: ', omp_num_of_nodes

!$omp parallel

omp_threads_id = omp_get_thread_num()

print*, 'Thread number: ', omp_threads_id, 'responded.'

!$omp end parallel

print*, '----------------------------------------------'

!$omp parallel default(shared)

!$omp do private(row, col)

do row=1, 2

allocate(GLOBAL(2, 2, 2))

GLOBAL = 0

do col=1, 2

omp_threads_id = omp_get_thread_num()

call sub

print*, 'MAIN: 'GLOBAL(1, row, col)

end do

deallocate(GLOBAL)

end do

!$omp end do

!$omp end parallel

call system("PAUSE")

end program openmp


Rules:

A variable can only appear in a THREADPRIVATE directive in the scope in which it is declared, and a THREADPRIVATE variable or common block may only appear once in a given scope. The variable must not be an element of a common block, or be declared in an EQUIVALENCE statement.

NOTE: I wanted to know how often Intel support checks this forum thread? Since my question was here more than 24 hours, and if I post my question wrong can you highlight which part in order to post next time more correct question to get faster respond.

Thanks for everything.

0 Kudos
Steven_L_Intel1
Employee
1,458 Views
This forum is checked frequently, but this is a user forum and for "how to" questions we encourage other users to help.

I am not an OpenMP expert, but reading the manual, what happens in your DO PRIVATE section is that a copy of the module variables is made, the section uses the copy and nothing done to the copy inside the section is reflected in the module variable.

However, I do see the following text in the Language Reference section on PRIVATE:

  • Contents, allocation state, and association status of variables defined as PRIVATE are undefined when they are referenced outside the lexical extent (but inside the dynamic extent) of the construct, unless they are passed as actual arguments to called routines.
This tells me that in your call to SUB, the module variables referenced in SUB are the original, unallocated variables and not the private copy. To fix this, you should pass the variable as an argument and not rely on use or host association.

I also note that you are using an old compiler version that is not supported on Vista, though I doubt that the OS has any bearing on the issue.
0 Kudos
Reply