Tutorial :Revisited:Stack Overflow in Fortran program



Question:

I am getting stack overflow when executing the following code in Compac Fortran. Specially for the line:

DIMENSION IZ(NX,NY),VX(NX-1,NY-1),VY(NX-1,NY-1),VZ(NX-1,NY-1)  

What I am doing is to read the NX,NY,DX,DY from a parameter file.

Any suggestions?

       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  

NOTE: Changing from (NGMAX=30000) to (NGMAX=30) did not help.

Yes I have changed all the instances of NGMAX to 30.

The new version is listed below.


    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)  

I am so sorry: I worked on the code all the day and finally its working. Howevere, declaring NX and NY, is what we do not need. I want to to read these parameters from the parameter file. The code is as follows:


      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  


Solution:1

It sounds like the subroutine ANALYSIS is allocating space on the stack based on the parameters passed into it (NX and NY). If those values are too large, then there may not be enough space on the stack to allocate the arrays.

What you can do is print out the values of NX and NY as read from the linana.para file to see whether they make sense for your application.


Solution:2

Heh. Well, technically, this probably belongs on ServerFault because it's an OS problem, but I don't think that there's anyone over there who going to answer VMS questions over there either. IT been a while for me and VMS and even longer for FORTRAN, but Ill give it a go...

OK, here's what you've got: the ANALYSIS subroutine has 4 arrays with (30,000*100)=3,000,000 cells each that's 12M cells or 8 bytes each (I think?) for 72Mbytes. Add to that the space taken up by the integer array IZ and the real arrays VX, VY and VZ, which I cannot estimate because I do not know what the max values of NX and NY are.

Anyway, that's a minimum of 144,000 pages on a VAX or 24,000 pages for an Alpha (plus add to that the other 4 arrays). Your process address table needs to be at least 2x that (slighty more, actually), because the user stack only get's half of that.

So, go to the command prompt and type "SHOW PROC/MEM" and tell me what it says (I think I've got that right).

Note: NX, NY are just the parameters to the DIMENSION, it the arrays that are taking up the stack.

Making the arrays Global probably won't work because the heap and static allocation spaces aren't any larger than the stack.

OK, I see your max NX, NY values are 5,000. That's another 4*25,000,000 or 100,000,000. At 8 bytes each that's 800MB plus the 72MB above. The bad news is that the VAX is architecurally limited to a user stack of 1GB, regardless of the VMS Process settings, so let's hope either that the Floats are 4bytes (and not 8) or that you are on an Alpha.


Solution:3

Assuming the exception is happening on the line you mention, then your program's stack is insufficently large for the variables being allocated on it. You need to find the flag in your compiler to increase the default stack allocation on your program. Or, if you are not using recursion at all, you can make those variables global variables so they are not allocated on the stack.

Note the size you're allocating:

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)  

You're allocating space for 30000 * 100 values (reals, I assume) for each of the four arrays XLS, XLE, YLS, and YLE. That's 12,000,000 values. Assuming 32-bit values, it's 48 Meg of memory. But I vaguely recall that on some platforms, reals are 80 bits? In that case it would be 120 Meg of memory.

Do you really need your arrays to be 30,000 elements long in one dimension? If not, reducing that allocation may help you.

Look at the compiler options for the FORTRAN compiler you're using. I remember that the VAX/VMS FORTRAN compiler had a command-line option to make all variables static, which is to say not allocated on the stack. Assuming you can guarantee that you will not do any recursion, this may be the quickest solution to your problem.

Another option you have is putting all of the large arrays into a COMMON block, but note that arrays in a common block cannot be dynamically sized.


Solution:4

It looks like your code is Fortran77 if so the following should make some sense if not it might give you some clues.

In Fortran77 there is no dynamic memory allocation support in the language standard, a number of compilers did have some support for it but by using compiler specific extensions. Your code does not trigger any memory of an extension looking like that.

One way of doing what you wanted would be to generate a main program which would declare the array space and then pass the arrays as parameters to subroutines. This main program would be compiled and linked with the rest of the code. Each set of values would produce a new main program.

For example - for 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)  

... RETURN END

I cannot remember but it may have been possible to use the parameter statement in the main program so you fully parameterize the main program above.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »