我在 Fortran 90 中编写了一个相当大的程序。它已经运行了很长一段时间,但是今天我试图将它提高一个档次并增加问题的大小(它是一个研究非标准 FE 求解器,如果帮助任何人...)现在我收到“堆栈溢出”错误消息,程序自然会终止,而没有给我任何有用的东西。
该程序首先设置所有相关的数组和矩阵,然后将几行有关此的统计信息打印到日志文件中。即使有我的新的更大的问题,这也可以正常工作(尽管有点慢),但是随着“数字运算”的进行,它会失败。
让我感到困惑的是,那时所有的东西都已经分配好了(并且工作没有错误)。我不完全确定堆栈是什么(维基百科和这里的几个步骤并没有做太多,因为我对计算机的“幕后”工作只有相当基本的了解)。
假设我有一些数组初始化为:
INTEGER,DIMENSION(64) :: IA
REAL(8),DIMENSION(:,:),ALLOCATABLE :: AA, BB
在一些初始化例程(即从文件中读取输入等)之后被分配为(我存储了一些大小整数以便更容易地传递给固定大小的 IA 中的子例程):
ALLOCATE( AA(N1,N2) , BB(N1,N2) )
IA(1) = N1
IA(2) = N2
这基本上是在初始部分发生的事情,到目前为止一切都很好。但是当我然后调用一个子程序时
CALL ROUTINE_ONE(AA,BB,IA)
例程看起来像(没什么花哨的):
SUBROUTINE ROUTINE_ONE(AA,BB,IA)
IMPLICIT NONE
INTEGER,DIMENSION(64) :: IA
REAL(8),DIMENSION(IA(1),IA(2)) :: AA, BB
...
do lots of other stuff
...
END SUBROUTINE ROUTINE_ONE
现在我得到一个错误!屏幕输出显示:
forrtl: severe (170): Program Exception - stack overflow
但是,当我使用调试器运行程序时,它会在名为winsig.c
(不是我的文件,但可能是编译器的一部分?)的文件中的第 419 行中断。它似乎是调用例程的一部分,sigreterror:
它是已调用的默认情况,返回 text Invalid signal or error
。附有一条注释行,奇怪的是/* should never happen, but compiler can't tell */
……?
所以我想我的问题是,为什么会发生这种情况以及实际发生了什么?我以为只要我可以分配所有相关的内存就可以了?对子例程的调用是否会复制参数,或者只是指向它们的指针?如果答案是副本,那么我可以看到问题可能出在哪里,如果是这样:关于如何解决它的任何想法?
我试图解决的问题很大,但绝不是疯狂的。标准有限元求解器可以处理比我目前的更大的问题。我在 Dell PowerEdge 1850 上运行程序,操作系统是 Microsoft Server 2008 R2 Enterprise。根据提示systeminfo
,cmd
我有 8GB 的物理内存和几乎 16GB 的虚拟内存。据我了解,我的所有数组和矩阵的总和不应超过 100MB - 大约 5.5Minteger(4)
和 2.5M real(8)
(根据我的说法应该只有大约 44MB,但公平地说,再增加 50MB 的开销)。
我使用与 Microsoft Visual Studio 2008 集成的 Intel Fortran 编译器。
添加一些实际的源代码以澄清一点
! Update continuum state
CALL UpdateContinuumState(iTask,iArray,posc,dof,dof_k,nodedof,elm,&
bmtrx,detjac,w,mtrlprops,demtrx,dt,stress,strain,effstrain,&
effstress,aa,fi,errmsg)
是对例程的实际调用。大数组是posc
,bmtrx
并且aa
- 所有其他数组至少小一个数量级(如果不是更多)。posc
是INTEGER(4)
和是bmtrx
_aa
REAL(8)
SUBROUTINE UpdateContinuumState(iTask,iArray,posc,dof,dof_k,nodedof,elm,bmtrx,&
detjac,w,mtrlprops,demtrx,dt,stress,strain,effstrain,&
effstress,aa,fi,errmsg)
IMPLICIT NONE
!I/O
INTEGER(4) :: iTask, errmsg
INTEGER(4) :: iArray(64)
INTEGER(4),DIMENSION(iArray(15),iArray(15),iArray(5)) :: posc
INTEGER(4),DIMENSION(iArray(22),iArray(21)+1) :: nodedof
INTEGER(4),DIMENSION(iArray(29),iArray(3)+2) :: elm
REAL(8),DIMENSION(iArray(14)) :: dof, dof_k
REAL(8),DIMENSION(iArray(12)*iArray(17),iArray(15)*iArray(5)) :: bmtrx
REAL(8),DIMENSION(iArray(5)*iArray(17)) :: detjac
REAL(8),DIMENSION(iArray(17)) :: w
REAL(8),DIMENSION(iArray(23),iArray(19)) :: mtrlprops
REAL(8),DIMENSION(iArray(8),iArray(8),iArray(23)) :: demtrx
REAL(8) :: dt
REAL(8),DIMENSION(2,iArray(12)*iArray(17)*iArray(5)) :: stress
REAL(8),DIMENSION(iArray(12)*iArray(17)*iArray(5)) :: strain
REAL(8),DIMENSION(2,iArray(17)*iArray(5)) :: effstrain, effstress
REAL(8),DIMENSION(iArray(25)) :: aa
REAL(8),DIMENSION(iArray(14)) :: fi
!Locals
INTEGER(4) :: i, e, mtrl, i1, i2, j1, j2, k1, k2, dim, planetype, elmnodes, &
Nec, elmpnodes, Ndisp, Nstr, Ncomp, Ngpt, Ndofelm
INTEGER(4),DIMENSION(iArray(15)) :: doflist
REAL(8),DIMENSION(iArray(12)*iArray(17),iArray(15)) :: belm
REAL(8),DIMENSION(iArray(17)) :: jelm
REAL(8),DIMENSION(iArray(12)*iArray(17)*iArray(5)) :: dstrain
REAL(8),DIMENSION(iArray(12)*iArray(17)) :: s
REAL(8),DIMENSION(iArray(17)) :: ep, es, dep
REAL(8),DIMENSION(iArray(15),iArray(15)) :: kelm
REAL(8),DIMENSION(iArray(15)) :: felm
dim = iArray(1)
...
它在上面的最后一行之前失败了。