Revisited: Fortran Stack Overflow

I get stack overflow when executing the following code in Compac Fortran. Especially 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 reading NX, NY, DX, DY from the 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 changed all instances of NGMAX to 30.

The new version is given 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'm sorry: I worked on the code all day and finally worked. However, announcing NX and NY, we do not need. I want to read these parameters from a parameter file. The code is as follows:


  PARAMETER(NX=322,NY=399,NGMAX=30000) CI 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 

+4
source share
4 answers

It appears that the ANALYSIS routine allocates space on the stack based on the parameters passed to it ( NX and NY ). If these values ​​are too large, then there may not be enough space on the stack to place the arrays.

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

+1
source

Assuming the exception occurs on the line you specify, your program stack is not large enough for the variables that stand out on it. You need to find the flag in your compiler to increase the default stack allocation in your program. Or, if you do not use recursion at all, you can make these variables global variables so that they are not distributed on the stack.

Pay attention to the size you allocate:

 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 allocate space for 30,000 * 100 values ​​( real s, I guess) for each of the four arrays of XLS , XLE , YLS and YLE . These are 12,000,000 values. Assuming 32-bit values, this is 48 megabytes of memory. But I vaguely remember that on some platforms the reals are 80 bits? In this case, it will be 120 megabytes of memory.

Do you really need your arrays to make up 30,000 elements in one dimension? If not, reducing this distribution may help you.

See the compiler options for the used FORTRAN compiler. I remember that the VAX / VMS FORTRAN compiler had a command line option to make all variables static, i.e. not allocated on the stack. Assuming that you can guarantee that you will not do recursions, this might be the quickest solution to your problem.

Another option you have is to put all large arrays in a COMMON block, but note that arrays in a common block cannot have dynamic size.

0
source

Heh. Well, technically, this probably applies to ServerFault, because it is an OS problem, but I don’t think there is anyone there who will answer VMS questions there either. It was time for me and VMS, and even longer for FORTRAN, but I will give it ...

OK, here's what you have: the ANALYSIS routine has 4 arrays with (30,000 * 100) = 3,000,000 cells, each of which contains 12 M or 8 bytes (I think?) For 72 MB. Add to this the space occupied by the whole array of IZ and the real arrays of VX, VY and VZ, which I cannot evaluate, because I do not know what the maximum values ​​of NX and NY are.

In any case, at least 144,000 pages on the VAX or 24,000 pages for Alpha (plus add 4 more arrays to this). Your process address table should be at least two times smaller (in fact), because the user stack only gets half that.

So go to the command line and type “SHOW PROC / MEM” and tell me what it says (I think everything is fine with me).

Note: NX, NY are only parameters of the DIMENSION parameter, these are arrays that occupy the stack.

Creating Global arrays probably won't work, because heaps and static allocation spaces are nothing more than a stack.

OK, I see that your maximum NX, NY values ​​are 5,000. This is another 4 * 25,000,000 or 100,000,000. At 8 bytes each, which is 800 MB plus 72 MB higher. The bad news is that VAX is architecturally limited to a 1 GB user stack, regardless of the settings of the VMS Process, so let's hope that the floats are 4 bytes (not 8) or that you are on Alpha.

0
source

Your code seems to be Fortran77 if that makes sense, if it can't give you some clues.

Fortran77 does not support dynamic allocation of memory in the language standard; some compilers had some support for it, but with the help of special extensions for the compiler. Your code does not call any extension memory similar to this.

One way to do what you wanted is to generate a main program that will declare an array space and then pass arrays as parameters to the routines. This main program will be compiled and linked to the rest of the code. Each set of values ​​will create a new main program.

For example, for NX = 2456 and 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 don’t remember, but it may have been possible to use the parameter operator in the main program so that you completely parameterize the main program above.

0
source

Source: https://habr.com/ru/post/1286499/


All Articles