Quantcast
Channel: Intel® Software - Intel® Visual Fortran Compiler for Windows*
Viewing all articles
Browse latest Browse all 5691

OpenMP and polymorphic entities

$
0
0

Consider this simple program:

program OpenMP_and_class
    implicit none

    type link_t
        integer :: id
    end type link_t

    type link_element_t
        type(link_t), allocatable :: element
    end type link_element_t

    type es_link_t
        class(link_t), pointer :: link_ptr => null()
    end type es_link_t

    type(link_element_t), allocatable, target :: links(:)

    integer, parameter :: n_links = 10
    integer :: i
    type(es_link_t) :: this_link

    allocate(links(n_links))

    do i = 1, n_links
        allocate(links(i)%element)
        links(i)%element%id = i
    end do

    !$OMP parallel do private(this_link)
    do i = 1, n_links
        call set_es_link_t(this_link, i)
        call process_link(this_link)
    end do
    !$OMP end parallel do
contains
    subroutine set_es_link_t(this_link, i)
        type(es_link_t), intent(inout) :: this_link
        integer, intent(in) :: i

        this_link%link_ptr => links(i)%element
    end subroutine set_es_link_t

    subroutine process_link(this_link)
        type(es_link_t), intent(inout) :: this_link

        print*, this_link%link_ptr%id
    end subroutine process_link
end program OpenMP_and_class

If you compile this program with /Qopenmp then when you run it it crashes with a stack overflow at the start of the parallel region.

The program runs fine without /Openmp and also if link_ptr is declared as type(link_t).

Now, I know the OpenMP 4.0 standard (1.6) states that Fortran 2003 polymorphic entities are not supported, so I shouldn't be surprised by this behaviour. However, it would be nice if the compiler provided a compilation diagnostic for this.

To get around this, is it legal to put the loop body into a subroutine and call it like this?

program OpenMP_and_class_2
    implicit none

    type link_t
        integer :: id
    end type link_t

    type link_element_t
        type(link_t), allocatable :: element
    end type link_element_t

    type es_link_t
        class(link_t), pointer :: link_ptr => null()
    end type es_link_t

    type(link_element_t), allocatable, target :: links(:)

    integer, parameter :: n_links = 10
    integer :: i

    allocate(links(n_links))

    do i = 1, n_links
        allocate(links(i)%element)
        links(i)%element%id = i
    end do

    !$OMP parallel do
    do i = 1, n_links
        call set_and_process_link(i)
    end do
    !$OMP end parallel do
contains
    subroutine set_and_process_link(i)
        integer, intent(in) :: i

        type(es_link_t) :: this_link

        call set_es_link_t(this_link, i)
        call process_link(this_link)
    end subroutine set_and_process_link

    subroutine set_es_link_t(this_link, i)
        type(es_link_t), intent(inout) :: this_link
        integer, intent(in) :: i

        this_link%link_ptr => links(i)%element
    end subroutine set_es_link_t

    subroutine process_link(this_link)
        type(es_link_t), intent(inout) :: this_link

        print*, this_link%link_ptr%id
    end subroutine process_link
end program OpenMP_and_class_2

This seems to work ok.  BTW, I'm using Intel Visual Fortran Composer for WIndows XE 2013 SP1 Update 2


Viewing all articles
Browse latest Browse all 5691

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>