OpenMP and polymorphic entities

OpenMP and polymorphic entities

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

5 posts / 0 nouveau(x)
Dernière contribution
Reportez-vous à notre Notice d'optimisation pour plus d'informations sur les choix et l'optimisation des performances dans les produits logiciels Intel.
Portrait de Steve Lionel (Intel)

You get a stack overflow because enabling OpenMP causes everything to be stack-allocated, and on Windows the default stack size is only 1MB. If you enable /heap-arrays (Fortran > Optimization > Heap Arrays > 0), the first program runs ok.

Yes, the OpenMP standard says that some F2003 features are "not supported", but I don't think that's relevant to your issue.

Steve

Thanks Steve,

Interesting! I suppose the follow up question has to be why does an es_link_t type with a pointer class component require so much stack in the OpenMP loop when the version with a type pointer component does not?

Mark.

Portrait de Steve Lionel (Intel)

I don't get a stack overflow when I build and run that code.

C:\Projects\U508609>ifort /Qopenmp U508609.f90
Intel(R) Visual Fortran Compiler XE for applications running on IA-32, Version 1
4.0.2.176 Build 20140130
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:U508609.exe
-subsystem:console
-defaultlib:libiomp5md.lib
-nodefaultlib:vcomp.lib
-nodefaultlib:vcompd.lib
U508609.obj

C:\Projects\U508609>U508609.exe
           3
          10
           1
           9
           4
           5
           8
           7
           6
           2

C:\Projects\U508609>

So I don't know what you're seeing. I replied about using /heap-arrays as that's my usual suggestion for stack overflow issues.

Steve

Sorry, Steve, my bad.  The stack overflow occurs if you use compiler version 14.0.1.139 (which is what we are currently using for production builds).  As you say, the original OpenMP_and_class program runs fine with 14.0.2.176.

Connectez-vous pour laisser un commentaire.