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

Parameterized Derived Data Type and OpenMP

Baxter
Beginner
578 Views

I am having a problem using parameterized derived data types with openMP.

I would like to have a derived data type (mytype), that contains both an integer (idx) and an array (a). The array (a) has a dimension (n) that is not known at compiler time, so I parameterize it.

Then I want an array of mytypes (x) of length (m).

This all works great without OpenMP. However, when I try to parallelize it, I get racing conditions that produce terminal errors. For example "forrtl: severe (157): Program Exception - access violation"

Debugging suggests that the problem is that when one thread creates a new instance of x, in assigning the dimension (n) it overwrites the dimension (n) on all other thread's version of x. So if thread 2 assigns n=2, and then thread 1 assigns n=1, when thread 2 goes to access x(:)%a(2) I get an error because thread 1 has overwritten the dimension of (n).

See minimal working example below.


It appears that mytype's parameter (n) is shared across threads. My questions are:
- Is there a way to explicitly make mytype's parameter (n) private?
- Am I trying to violate a standard of which I am unaware here?
- Is there a better way to do this that maintains the array (x) of derived times (mytype) containing an array (a) of unknown size at compiler time?

 

 

!! Module
module Program_SomeMath
    implicit none
    
        type mytype(n)
        integer, len                        :: n
        integer                             :: idx
        real*8, dimension(n)                :: a

    end type mytype
    
    contains

    subroutine SomeMath(i)
        implicit none
        integer, intent(in)                         :: i
        
        type(mytype(i)), dimension(i)               :: x
        integer                                     :: j, k


        do j=1,i
            do k=1,i
                x(k)%idx=k
                x(k)%a(j)=dble(j)**2+k
            end do
        
           
        end do
        do j=1,i
         write(*,"(A,4I,30f12.0)") 'a=', i,j, size(x(j)%a), x%n,  x(j)%a
        end do
        
    end subroutine SomeMath
    
end module Program_SomeMath
    
!! Main Program
program ParameterizedDerviedDataAndOpenMP
    use Program_SomeMath
    implicit none
    integer                                                 :: i
    integer, parameter                                      :: z=10
    
    !$OMP PARALLEL DEFAULT(PRIVATE) 
    !$OMP DO
    do i=z,1,-1
        
        call SomeMath(i)
        
    end do
    !$OMP END DO
    !$OMP END PARALLEL  
    
end program ParameterizedDerviedDataAndOpenMP
Labels (2)
0 Kudos
1 Reply
Baxter
Beginner
566 Views

Update. The below example appears to have solved this problem by making (a) an allocatable array within the derived data type.

 

!! Module
module Program_SomeMath
    implicit none
    
        type mytype
        integer                             :: idx
        real*8, dimension(:), allocatable   :: a

    end type mytype
    
    contains
    
    subroutine SomeMath(i)
        implicit none
        integer, intent(in)                         :: i
        
        type(mytype),dimension(:), allocatable               :: x
        integer                                     :: j, k

        allocate(x(i))
        do j=1,i
            allocate(x(j)%a(i))
        end do
        
        do j=1,i
            do k=1,i
                x(k)%idx=k
                x(k)%a(j)=dble(j)**2+k
            end do
        end do
        
        do j=1,i
         write(*,"(A,4I,30f12.0)") 'a=', i,j, size(x), size(x(j)%a),  x(j)%a
        end do
        
        deallocate(x)
        
    end subroutine SomeMath
    
end module Program_SomeMath
    
!! Main Program
program ParameterizedDerviedDataAndOpenMP
    use Program_SomeMath
    implicit none

    ! Variables
    integer                                                 :: i
    integer, parameter                                      :: z=10
    
    !Body
    !$OMP PARALLEL DEFAULT(PRIVATE) 
    !$OMP DO
    do i=z,1,-1
        
        call SomeMath(i)
        
    end do
    !$OMP END DO
    !$OMP END PARALLEL  
    
end program ParameterizedDerviedDataAndOpenMP

 

0 Kudos
Reply