Пересмотрено: переполнение стека в программе на Фортране - PullRequest
4 голосов
/ 20 июня 2009

Я получаю переполнение стека при выполнении следующего кода в 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)

Мне очень жаль: Я работал над кодом весь день и, наконец, он работает. Однако, объявляя 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

Ответы [ 4 ]

1 голос
/ 20 июня 2009

Похоже, что подпрограмма ANALYSIS выделяет место в стеке на основе переданных в него параметров (NX и NY). Если эти значения слишком велики, возможно, в стеке недостаточно места для размещения массивов.

Что вы можете сделать, это распечатать значения NX и NY, считанные из файла linana.para, чтобы увидеть, имеют ли они смысл для вашего приложения.

0 голосов
/ 29 июня 2009

Похоже, что ваш код 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

Я не могу вспомнить, но, возможно, было возможно использовать оператор параметров в основной программе, чтобы вы полностью параметризовали основную программу выше.

0 голосов
/ 20 июня 2009

Хех. Ну, технически это, вероятно, относится к ServerFault, потому что это проблема ОС, но я не думаю, что там есть кто-то, кто тоже собирается отвечать на вопросы VMS. Это было какое-то время для меня и VMS и даже дольше для FORTRAN, но я попробую ...

Хорошо, вот что у вас получилось: подпрограмма АНАЛИЗ имеет 4 массива с (30 000 * 100) = 3 000 000 ячеек каждый, что составляет 12 М ячеек или 8 байтов каждая (я думаю?) Для 72 МБ. Добавьте к этому пространство, занимаемое целочисленным массивом IZ и реальными массивами VX, VY и VZ, которое я не могу оценить, потому что я не знаю, каковы максимальные значения NX и NY.

В любом случае, это минимум 144 000 страниц на VAX или 24 000 страниц для Альфы (плюс добавьте к этому остальные 4 массива). Ваша таблица адресов процессов должна быть как минимум в 2 раза больше (на самом деле, немного больше), потому что пользовательский стек получает только половину этого.

Итак, перейдите в командную строку и введите «SHOW PROC / MEM» и скажите мне, что он говорит (я думаю, что я правильно понял).

Примечание: NX, NY - это просто параметры DIMENSION, это массивы, которые занимают стек.

Создание массивов Global, вероятно, не сработает, потому что пространство кучи и статического размещения не больше стека.

ОК, я вижу, что ваши максимальные значения NX, NY равны 5000. Это еще 4 * 25 000 000 или 100 000 000. На 8 байтов каждый это 800 МБ плюс 72 МБ выше. Плохая новость заключается в том, что VAX архитектурно ограничен пользовательским стеком в 1 ГБ, независимо от настроек процесса VMS, поэтому будем надеяться, что значения с плавающей запятой равны 4 байтам (а не 8), или что вы используете Alpha.

0 голосов
/ 20 июня 2009

Если исключение происходит в указанной вами строке, то стек вашей программы недостаточно велик для переменных, размещаемых на нем. Вам нужно найти флаг в вашем компиляторе, чтобы увеличить выделение стека по умолчанию в вашей программе. Или, если вы вообще не используете рекурсию, вы можете сделать эти переменные глобальными переменными, чтобы они не размещались в стеке.

Обратите внимание на размер, который вы выделяете:

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)

Вы выделяете пространство для 30000 * 100 значений (real с, я полагаю) для каждого из четырех массивов XLS, XLE, YLS и YLE. Это 12 000 000 ценностей. Предполагая 32-битные значения, это 48 мегабайт памяти. Но я смутно припоминаю, что на некоторых платформах реалы 80 бит? В этом случае это будет 120 мегабайт памяти.

Вам действительно нужно, чтобы ваши массивы имели длину 30 000 элементов в одном измерении? Если нет, то сокращение этого распределения может вам помочь.

Посмотрите на опции компилятора для используемого вами компилятора FORTRAN. Я помню, что компилятор VAX / VMS FORTRAN имел параметр командной строки, чтобы сделать все переменные статическими, то есть не размещенными в стеке. Если вы можете гарантировать, что не будете выполнять рекурсию, это может быть самым быстрым решением вашей проблемы.

Другой вариант, который у вас есть, - поместить все большие массивы в ОБЩИЙ блок, но учтите, что массивы в общем блоке не могут иметь динамический размер.

...