-1

I have a very strange error when I enable OpenMP in my compilation options. I have pinned it down to a call to a module subroutine using a dynamic sized array from my main program subroutine. Here is a simplified example:

module arr_mod
contains
    subroutine add2_mod(arr)
        integer, dimension(:) :: arr
        integer i, n
        n = size(arr)
        do i=1,n
            arr(i) = arr(i)+2
        enddo
    end subroutine
end module

PROGRAM TEST_OMP
    use arr_mod
    integer, dimension(2000000) :: array
    array = 0
    write(*,*) array(1)
contains
    subroutine add2()
        ! Note that this subroutine is not even called in the main program...
        ! When the next line is commented, the program runs.
        call add2_mod(array)
    end subroutine
END PROGRAM TEST_OMP

When I compile and run this program without OpenMP, it runs fine:

$ gfortran -o test_omp test_omp.f90
$ ./test_omp
       0

But when I use OpenMP, the program immediately segfaults:

$ gfortran -o test_omp test_omp.f90 -fopenmp
$ ./test_omp
[1]    10291 segmentation fault  ./test_omp

If I remove the program subroutine (or simply comment the add2_mod call), it works fine even with OpenMP. It still works fine even if I call the add2_mod subroutine from the main program directly.

It also works when compiling with optimizations (tested with -O3), and when setting unlimited stack with ulimit -s unlimited.

As far as I can tell, it works fine with Intel Fortran (tested on version 17, with no specific flags other than -qopenmp).

TonioElGringo
  • 1,007
  • 1
  • 10
  • 17
  • 1
    What happens if you first do "ulimit -s unlimited"? What happens if you compile with optimisation? What version of gfortran? What version and what flags for Intel? Nice minimal example! – Ian Bush Mar 26 '20 at 17:53
  • @IanBush I completed in the question. The program runs with either `-O3` (just tested `-O1` and it works too), or with `ulimit -s unlimited`. I used ifort 17 with the `-qopenmp` flag. – TonioElGringo Mar 26 '20 at 18:05
  • Just about to play chess so no time, but look at https://stackoverflow.com/questions/13264274/why-segmentation-fault-is-happening-in-this-openmp-code?rq=1 and understand with the optimiser on the compiler can work out how to avoid the very large array. Inetl compiles by default with optimisation on, gfortran with it off. – Ian Bush Mar 26 '20 at 18:33
  • @IanBush Intel will still works with `-O0`, but yes it could be some optimization difference. – TonioElGringo Mar 26 '20 at 18:39
  • @IanBush I am not sure it answers my question, since there is no OpenMP code in my question at all. I don't see how the stack size gets increased by simply including the openmp flag. – TonioElGringo Mar 26 '20 at 21:11

1 Answers1

0

As noted in the gfortran documentation:

-fopenmp implies -frecursive, i.e., all local arrays will be allocated on the stack. When porting existing code to OpenMP, this may lead to surprising results, especially to segmentation faults if the stacksize is limited.

To overcome this limitation, you can force the array on the heap with the allocatable specifier:

module arr_mod
contains
    subroutine add2_mod(arr)
        integer, dimension(:) :: arr
        integer i, n
        n = size(arr)
        do i=1,n
            arr(i) = arr(i)+2
        enddo
    end subroutine
end module

PROGRAM TEST_OMP
    use arr_mod
    integer, dimension(:), allocatable :: array ! array is allocated on the heap
    allocate(array(2000000))
    array = 0
    write(*,*) array(1)
contains
    subroutine add2()
        call add2_mod(array)
    end subroutine
END PROGRAM TEST_OMP

Which will work fine with the -fopenmp flag.

TonioElGringo
  • 1,007
  • 1
  • 10
  • 17