问题
I'm using Fortran and OpenMP, but I keep encountering an issue when I try to parallelize loops using OpenMP when there are large arrays. For example, the following code:
PROGRAM main
IMPLICIT NONE
INTEGER, PARAMETER :: NUMLOOPS = 300000
REAL(8) :: TESTMAT(NUMLOOPS)
INTEGER :: i,j
!$OMP PARALLEL SHARED(TESTMAT)
!$OMP DO
DO i=1,NUMLOOPS
TESTMAT(i) = i
END DO
!$OMP END DO
!$OMP END PARALLEL
write(*,*) SUM(TESTMAT)/(NUMLOOPS)
END PROGRAM main
compiled using this Makefile:
.SUFFIXES: .f90
F90 = gfortran
FFLAGS_PFM = -ffree-form -ffree-line-length-none -fopenmp
LIB = -llapack
OBJ90 = main.o
main: $(OBJ90)
$(F90) $(FFLAGS_PFM) -o $@ $(LIB) $(OBJ90)
${OBJ90}: %.o: %.f90
$(F90) $(FFLAGS_PFM) $(LIB) -c -o $@ $<
Crashes when on a windows machine, compiled using gfortran. However, if I change the NUMLOOPS value to anything less than around 260000, the program runs just fine. Similarly, a matrix of about 1000x1000 would crash (anything above around 500x500, in fact, doesn't work). Thus, it seems like there is a maximum array size allowed when using OpenMP? I haven't come across anything of this kind though. I've tried on multiple windows machines, with the same result, however all use the same configuration, e.g. Windows 7 with gfortran compiler. The code always compiles without issue, but crashes when run.
回答1:
Specifying -fopenmp
in GNU Fortran implies -frecursive
which means that all local variables (even large arrays) are automatic (i.e. allocated on the stack). On Windows the stack size is fixed in the PE executable header file and has to be specified during link phase, very much unlike on Unix systems where it can be dynamically controlled by the limits mechanism.
To increase the stack size of your Windows executable you can either use editbin.exe
from Microsoft with a command line like:
editbin /STACK:<size> yourexe.exe
or supply the following option to GCC: -Wl,--stack,<size in bytes>
, where <size in bytes>
is the desired stack size in bytes. You should set the stack size at least large enough to fit the whole array (that is 8*NUMLOOPS
) and the local variables and stuff.
回答2:
OpenMP does not impose any limits on the size of arrays that you can instantiate. Your Fortran compiler might; check the documentation for that.
The hardware you are using does impose a limit -- you won't be able to declare an array which has an index value larger than HUGE(int) on your machine; since HUGE(int) is likely to be either (2^31)-1 or (2^63)-1 (Fortran does not have unsigned integers) this is probably not affecting you at the moment.
The other limit, which may be affecting you, is that there is likely to be a limit to the size of a variable that your compiler will let you declare. I'm not familiar with gfortran, but I suggest you Google around or look in the documentation. It may be that there is a limit on the size of stack that gfortran can handle, on many platforms Fortran variables which are declared statically (i.e. are not ALLOCATABLE) will be placed on a stack. I suspect that this is the root of your problem.
If you can't persuade your compiler to let you declare a larger array at compile time, try making the array ALLOCATABLE and allocating it at run time.
回答3:
I had the same problem. As far as I understand the option -fopenmp came by default with -frecursive. This latter force large array to be in a stack and that is our probelm.
A pseudo-solution is to overwrites the -frecursive option implied by the -fopenmp using another option against it. For this I add the option -fno-automatic for gfortran compiler option
回答4:
I have a better solution in comparison to my previous one that consists in inserting, before running your code the following cmd: ulimit -s unlimited
. This in order to get rid of the default limitation on stack size.
来源:https://stackoverflow.com/questions/10269836/openmp-crashing-with-large-arrays