在Compac Fortran中执行以下代码时,我发现堆栈溢出。 特别为该行:
DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)
我正在做的是从参数文件中读取NX,NY,DX,DY。
有什么建议吗?
PARAMETER(NGMAX=30000)
INTEGER NX,NY,DX,DY
OPEN(6,FILE='MGSTAOriggroup15.asc',STATUS='old')
OPEN(7,FILE='Gravity.asc',STATUS='old')
OPEN(8,FILE='Gravity200.nor',STATUS='old')
OPEN(9,FILE='linana.para',STATUS='old')
OPEN(10,FILE='MGSTAOriggroup15coord.dat',STATUS='unknown')
OPEN(12,FILE='MGSTAOriggroup15ncoord.dat',STATUS='unknown')
OPEN(11,FILE='linana.fsn',STATUS='unknown')
READ(9,*) NX,NY,DX,DY
CALL ANALYSIS(NX,NY)
Close(6)
Close(7)
Close(8)
Close(9)
Close(10)
Close(11)
Close(12)
C
STOP
END
C
SUBROUTINE ANALYSIS(NX,NY)
INTEGER NX,NY,DX,DY
COMMON/COM1/ DX,DY
PARAMETER(NGMAX=30000)
DIMENSION KO(NGMAX)
DIMENSION XLS(NGMAX,100),XLE(NGMAX,100),
& YLS(NGMAX,100),YLE(NGMAX,100)
DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)
""""""""""""""""""""""""""""""""""""""""""""
To the end
注意:从(NGMAX=30000)
更改为(NGMAX=30)
无效。
是的,我已将NGMAX的所有实例更改为30。
新版本如下所示。
INTEGER NX,NY,DX,DY
PARAMETER(NGMAX=30)
COMMON /CM1/ FX(NGMAX),FY(NGMAX),FZ(NGMAX),FR(NGMAX),IL(NGMAX)
COMMON /CM2/ JST(NGMAX),KST(NGMAX),JDP(NGMAX),KDP(NGMAX)
COMMON /CM3/ XC(NGMAX),YC(NGMAX),ZC(NGMAX),KTYP(NGMAX)
COMMON /CM4/ A(4,4),B(4),U(4)
COMMON /CM5/ KO(NGMAX)
COMMON /CM6/ XLS(NGMAX,10),XLE(NGMAX,10),
& YLS(NGMAX,10),YLE(NGMAX,10)
OPEN(6,FILE='MGSTAOriggroup15.asc',STATUS='old')
OPEN(7,FILE='Gravity.asc',STATUS='old')
OPEN(8,FILE='Gravity200.nor',STATUS='old')
OPEN(9,FILE='linana.para',STATUS='old')
OPEN(10,FILE='MGSTAOriggroup15coord.dat',STATUS='unknown')
OPEN(12,FILE='MGSTAOriggroup15ncoord.dat',STATUS='unknown')
OPEN(11,FILE='linana.fsn',STATUS='unknown')
READ(9,*) NX,NY,DX,DY
CALL ANALYSIS(NX,NY)
Close(6)
Close(7)
Close(8)
Close(9)
Close(10)
Close(11)
Close(12)
C
STOP
END
C
SUBROUTINE ANALYSIS(NX,NY)
INTEGER NX,NY,DX,DY
COMMON/COM1/ DX,DY
PARAMETER(NGMAX=30)
COMMON /CM1/ FX(NGMAX),FY(NGMAX),FZ(NGMAX),FR(NGMAX),IL(NGMAX)
COMMON /CM2/ JST(NGMAX),KST(NGMAX),JDP(NGMAX),KDP(NGMAX)
COMMON /CM3/ XC(NGMAX),YC(NGMAX),ZC(NGMAX),KTYP(NGMAX)
COMMON /CM4/ A(4,4),B(4),U(4)
COMMON /CM5/ KO(NGMAX)
COMMON /CM6/ XLS(NGMAX,10),XLE(NGMAX,10),
& YLS(NGMAX,10),YLE(NGMAX,10)
DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)
我很抱歉: 我整天都在处理代码,最后还在工作。 Howevere,宣布NX和NY,是我们不需要的。 我想从参数文件中读取这些参数。 代码如下:
PARAMETER(NX=322,NY=399,NGMAX=30000)
C I need to change NX and NY to read from the parameter file
CHARACTER infile1*80,infile2*80,infile3*80,outfile1*80
&,outfile2*80,outfile3*80
DIMENSION KO(NGMAX)
DIMENSION XLS(NGMAX,100),XLE(NGMAX,100),
& YLS(NGMAX,100),YLE(NGMAX,100)
DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)
DIMENSION FX(NGMAX),FY(NGMAX),FZ(NGMAX),FR(NGMAX),IL(NGMAX)
DIMENSION JST(NGMAX),KST(NGMAX),JDP(NGMAX),KDP(NGMAX)
DIMENSION XC(NGMAX),YC(NGMAX),ZC(NGMAX),KTYP(NGMAX)
DIMENSION A(4,4),B(4),U(4)
C
CALL getenv('INFILE1',infile1)
CALL getenv('INFILE2',infile2)
CALL getenv('INFILE3',infile3)
CALL getenv('OUTFILE1',outfile1)
CALL getenv('OUTFILE2',outfile2)
CALL getenv('OUTFILE3',outfile3)
OPEN(1,FILE='Alaa1.para',STATUS='old')
READ(1,*)DX,DY,infile1,infile2,infile3,outfile1,outfile2
&,outfile3
C
OPEN(6,FILE=infile1,STATUS='old')
OPEN(7,FILE=infile2,STATUS='old')
OPEN(8,FILE=infile3,STATUS='old')
OPEN(10,FILE=outfile1,STATUS='unknown')
OPEN(12,FILE=outfile2,STATUS='unknown')
OPEN(11,FILE=outfile3,STATUS='unknown')
TO THE END
答案 0 :(得分:1)
听起来子程序ANALYSIS
正在根据传递给它的参数(NX
和NY
)在堆栈上分配空间。如果这些值太大,那么堆栈上可能没有足够的空间来分配数组。
您可以执行的操作是打印出从NX
文件中读取的NY
和linana.para
的值,看看它们是否对您的应用程序有意义。
答案 1 :(得分:0)
假设您提到的行发生了异常,那么您的程序堆栈对于在其上分配的变量来说是非常大的。您需要在编译器中找到标志以增加程序的默认堆栈分配。或者,如果您根本不使用递归,则可以将这些变量设为全局变量,以便它们不会在堆栈中分配。
请注意您分配的尺寸:
PARAMETER(NGMAX=30000)
DIMENSION KO(NGMAX)
DIMENSION XLS(NGMAX,100),XLE(NGMAX,100),YLS(NGMAX,100),YLE(NGMAX,100)
DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)
您为四个数组real
,XLS
,XLE
和{中的每一个都分配了30000 * 100个值(YLS
s,我假设)的空间{1}}。这是12,000,000个值。假设32位值,它的内存为48兆。但我依旧回忆起在某些平台上,实时是80位?在那种情况下,它将是120兆的内存。
你真的需要你的数组在一个维度上长达30,000个元素吗?如果没有,减少分配可能会对您有所帮助。
查看您正在使用的FORTRAN编译器的编译器选项。我记得VAX / VMS FORTRAN编译器有一个命令行选项,可以将所有变量设置为静态,也就是说不在堆栈上分配。假设您可以保证不会进行任何递归,这可能是解决问题的最快方法。
另一个选择是将所有大型数组放入COMMON块,但请注意,公共块中的数组不能动态调整大小。
答案 2 :(得分:0)
嘿。嗯,从技术上讲,这可能属于ServerFault,因为它是一个操作系统问题,但我不认为那边有人会在那里回答VMS问题。对我和VMS来说,它已经有一段时间了,对于FORTRAN来说甚至更长一段时间,但我会试一试......
好的,这就是你所拥有的:ANALYSIS子程序有4个阵列,其中(30,000 * 100)= 3,000,000个单元,每个单元为12M单元,或者每个8字节(我认为?)为72M字节。再加上整数数组IZ和真实数组VX,VY和VZ占用的空间,我无法估计,因为我不知道NX和NY的最大值是什么。
无论如何,这在VAX上至少有144,000页,对于Alpha来说是24,000页(加上其他4个数组)。您的进程地址表必须至少为2倍(实际上稍微多一点),因为用户堆栈只能获得其中的一半。
所以,转到命令提示符并输入“SHOW PROC / MEM”并告诉我它的内容(我认为我已经做到了)。
注意:NX,NY只是DIMENSION的参数,它是占用堆栈的数组。
使数组Global可能无法工作,因为堆和静态分配空间不大于堆栈。
好的,我看到你的最大NX,NY值是5,000。这是另一个4 * 25,000,000或100,000,000。每个8字节,800MB加上72MB以上。坏消息是VAX的架构限制为1GB的用户堆栈,无论VMS进程设置如何,所以我们希望Floats是4bytes(而不是8)或者你是Alpha。
答案 3 :(得分:0)
看起来您的代码是Fortran77,如果是这样,以下内容应该有所帮助,如果不是它可能会给你一些线索。
在Fortran77中,语言标准中没有动态内存分配支持,许多编译器确实对它有一些支持,但是使用了特定于编译器的扩展。您的代码不会触发任何类似的扩展内存。
执行所需操作的一种方法是生成一个主程序,该程序将声明数组空间,然后将数组作为参数传递给子程序。该主程序将被编译并与其余代码链接。每组值都会产生一个新的主程序。
例如 - 对于NX = 2456& NY = 789
PROGRAM MAIN
INTEGER NX, NY
DIMENSION IZ(2456,789),VX(2455,788),VY(2455,788),VZ(2455,788)
NX=2456
NY=789
CALL ANALYSIS(NX,NY,IZ,VX,VY,VZ)
STOP
END
SUBROUTINE ANALYSIS(NX,NY,IZ,VX,VY,VZ)
INTEGER NX,NY,DX,DY
DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)
... 返回 END
我记不清了但是可能在主程序中使用参数语句,因此您可以完全参数化上面的主程序。