2012-04-22 117 views
1

我正在使用Fortran和OpenMP,但当我尝试使用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 

编译:

.SUFFIXES: .f90 

F90 = gfortran 
FFLAGS_PFM = -ffree-form -ffree-line-length-none -fopenmp 
LIB = -llapack 
OBJ90 = main.o 

main: $(OBJ90) 
    $(F90) $(FFLAGS_PFM) -o [email protected] $(LIB) $(OBJ90) 

${OBJ90}: %.o: %.f90 
    $(F90) $(FFLAGS_PFM) $(LIB) -c -o [email protected] $< 

崩溃时的Windows机器上,使用gfortran编译。但是,如果我将NUMLOOPS值更改为小于260000左右,则程序运行得很好。同样,大约1000x1000的矩阵会崩溃(大约500x500以上的任何事实上都不起作用)。因此,使用OpenMP时似乎允许最大数组大小?尽管如此,我还没有遇到过这样的事情。我在多台Windows机器上尝试过,结果相同,但都使用相同的配置,例如带有gfortran编译器的Windows 7。代码始终编译时没有问题,但运行时崩溃。

回答

3

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

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

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

如果你不能说服你的编译器让你在编译时声明一个更大的数组,那么尝试使数组ALLOCATABLE在运行时分配它。

+1

感谢您的回复。使TESTMAT可分配确实可行!然而,我仍然好奇为什么这首先出现。我想我忘记提到上面的代码工作,如果我删除了OpenMP位,即OMP声明和makefile中的-fopenmp标志,所以行为似乎特定于gfortran + openmp。但无论如何,向前迈进了一步,再次感谢! – user870029 2012-04-22 22:00:47

+2

这可能是,对于OpenMP版本,编译器会将数组放在堆栈中而不是可执行文件中的静态位置,在这种情况下,您可能还会通过限制堆栈大小来解决问题,通常使用“ulimit无限“。 – haraldkl 2012-04-24 22:38:17

3

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

为了增加Windows的堆栈大小可执行您可以使用editbin.exe微软用以下命令行:

editbin /STACK:<size> yourexe.exe 

或提供以下选项GCC:-Wl,--stack,<size in bytes>,其中<size in bytes>是所需的堆栈大小以字节表示。您应该将堆栈大小设置为至少足够大以适应整个阵列(即8*NUMLOOPS)以及局部变量和内容。

2

我有同样的问题。据我了解,选项-fopenmp默认使用-frecursive。后者迫使大批队伍成为队伍,这是我们的问题。

伪解决方案是使用另一个选项来覆盖-fopenmp隐含的-frecursive选项。为此,我添加了gfortran编译器选项-fno-automatic选项