OpenMP崩溃与大数组

时间:2012-04-22 16:37:18

标签: fortran openmp fortran90 gfortran

我正在使用Fortran和OpenMP,但是当我在有大型数组时尝试使用OpenMP并行化循环时,我遇到了一个问题。例如,以下代码:

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

使用此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 $@ $<

在使用gfortran编译的Windows机器上崩溃。但是,如果我将NUMLOOPS值更改为小于260000的任何值,程序运行就可以了。类似地,大约1000x1000的矩阵会崩溃(任何高于500x500的东西,实际上都不起作用)。因此,使用OpenMP时似乎允许最大数组大小?我没有遇到过这种类似的东西。我尝试过多台Windows机器,结果相同,但都使用相同的配置,例如Windows 7与gfortran编译器。代码总是编译没有问题,但在运行时崩溃。

4 个答案:

答案 0 :(得分:3)

OpenMP不会对可以实例化的数组大小施加任何限制。您的Fortran编译器可能;检查文档。

您正在使用的硬件确实施加了限制 - 您将无法在计算机上声明索引值大于HUGE(int)的阵列;因为HUGE(int)可能是(2 ^ 31)-1或(2 ^ 63)-1(Fortran没有无符号整数),所以这可能不会影响你。

可能影响您的另一个限制是,编译器允许您声明的变量大小可能存在限制。我不熟悉gfortran,但我建议你到谷歌或查看文档。可能是gfortran可以处理的堆栈大小有限制,在许多平台上,静态声明(即不可分配)的Fortran变量将放在堆栈上。我怀疑这是你问题的根源。

如果无法说服编译器让你在编译时声明一个更大的数组,请尝试使用数组ALLOCATABLE并在运行时分配它。

答案 1 :(得分:3)

在GNU Fortran中指定-fopenmp意味着-frecursive这意味着所有局部变量(甚至大型数组)都是自动的(即在堆栈上分配)。在Windows上,堆栈大小在PE可执行头文件中是固定的,必须在链接阶段指定,与Unix系统不同,它可以通过限制机制动态控制。

要增加Windows可执行文件的堆栈大小,可以使用Microsoft的editbin.exe命令行,如:

editbin /STACK:<size> yourexe.exe

或向GCC提供以下选项:-Wl,--stack,<size in bytes>,其中<size in bytes>是所需的堆栈大小(以字节为单位)。您应该将堆栈大小设置为至少足以适合整个数组(即8*NUMLOOPS)以及局部变量和东西。

答案 2 :(得分:2)

我遇到了同样的问题。据我所知,-fopenmp选项默认带有-frecursive。后者迫使大阵列成堆,这就是我们的问题。

伪解决方案是使用针对它的另一个选项覆盖-fopenmp隐含的-frecursive选项。为此,我为gfortran编译器选项

添加了选项-fno-automatic

答案 3 :(得分:0)

与前一个解决方案相比,我有一个更好的解决方案,其中包括在运行代码之前插入以下cmd:ulimit -s unlimited。这是为了摆脱默认的堆栈大小限制。