Недопустимый доступ к памяти Фортран Инспектор

Я получаю неправильно рассчитанные значения, если я запускаю свою программу на Фортране с массивами (посмотрите на код). Если я воспользуюсь инспектором intel (-mi3), он скажет мне, что возникают проблемы с памятью при "неправильном доступе к памяти" каждый раз, когда в программе используется один из больших массивов, а также ошибка в /lib64/ld-linux-x86-64.so.2. Прежде всего, я подумал, что мне не хватает места в памяти, но на моей 64-битной машине с 16 ГБ памяти достаточно ((-m ~14 ГБ). Если я оцениваю объем памяти моей программы, то достаточно около 4 ГБ. Во время работы моей программы используемая память увеличивается с 0% до ~20 % и останавливается там до тех пор, пока программа не завершится "нормально". Поэтому я думаю, что у меня достаточно памяти. Для небольших массивов (например, nemax=3 000 000) я получаю правильные рассчитанные значения и никаких ошибок в инспекторе Intel. Я также проверил массивы с флагом проверить все. Я компилирую программу с помощью ifort -mcmodel=medium -shared-intel -o test.f.f90. Я не знаю, что еще я мог сделать, чтобы решить эти ошибки доступа к памяти? У кого-нибудь есть идея? Спасибо за вашу помощь!

  module lz_data

  integer,parameter :: maxsite=16   
  integer,parameter :: nmax =6000000 
  integer,parameter :: nemax=300000000

  real*8,save :: diag(nmax)        

  real*8,save  :: werte(nemax)              !Here are the only large arrays
  integer,save :: izeile(nemax)
  integer,save :: ispalt(nemax)

  integer,save :: nentry

  end module lz_data

  prgram test
  use lz_data

  implicit real*8 (a-h,o-z)
  real*8 umat(maxsite,maxsite)
  logical lav(nmax,maxsite) 
  logical lbv(nmax,maxsite) 

  ...

  do is=1,ns
    diag(is)=0.0d0    ! HERE the debugging tool says invalid memory access 
    do i=1,msite
      do j=1,msite
        if (lav(is,i).and.lbv(is,j)) diag(is)=diag(is)+umat(i,j) ! invalid memory access
      enddo
    enddo
  enddo

4 ответа

В дополнение к другим отличным советам, я предлагаю компилировать с максимально возможным количеством включенных параметров отладки, включая проверку ошибок во время выполнения. Компилятор выдаст вам предупреждения о неправильных действиях, которые могут привести к ошибкам, и найдет другие ошибки. Плохие практики включают необъявленные или неинициализированные переменные. Я предлагаю не использовать неявную типизацию и объявлять каждую переменную. При проверке нижнего индекса во время выполнения компилятор сообщит вам, когда нижний индекс выходит за пределы массива... более понятная ошибка, чем недопустимый доступ к памяти. С intel ifort попробуйте: -O2 -stand f03 -assume realloc_lhs -check all -traceback -warn all -fstack-protector -assume protect_parens -implicitnone

После редактирования вашего примера кода, чтобы он правильно скомпилировался с правилами, установленными этими параметрами, запуск выдает сообщение об ошибке:

forrtl: severe (193): Run-Time Check Failure. The variable '_test_$NS' is being used without being defined

т.е. ifort находит неинициализированную переменную во время выполнения. Что заставляло программу запускаться через конец массива и обращаться к недействительной памяти.

Похоже, вы столкнулись с некоторыми ограничениями размера статического массива. mcmodel=medium "должен" помочь с этим, но, очевидно, это не так. Вы можете заменить свои большие статические массивы на размещаемые массивы и посмотреть, поможет ли это.

Да, и, как сказал High Performane Mark, используйте неявное none, обязательно инициализируйте все переменные и предоставьте отдельный пример кода.

В дополнение к другим советам, вы также должны убедиться, что вы не попали под ограничение размера стека по умолчанию в вашей оболочке. Статические массивы обычно создаются в стеке, а размер стека по умолчанию в BASH составляет 8 МБ. Если у вас есть массивы больше чем это, вы в конечном итоге с нарушением доступа. Вы можете переопределить этот предел, установив

ulimit -s unlimited

в BASH, так что размер вашего стека ограничен только объемом памяти, доступным в вашей системе.

Спасибо за вашу помощь! Я уже установил ulimit -s без ограничений или 10 ГБ. Я знаю, что использование implicit не очень хорошо, но для небольших систем моя программа работает абсолютно нормально, поэтому почему при использовании implicit должна возникать ошибка. Я хотел бы использовать размещаемые массивы вместо больших статических массивов, но в моем случае это не имеет смысла, потому что вычисление значений большого массива werte связано с экстентом массива. Поэтому мне приходится тратить немного (!) Памяти на предсказание достаточного измерения для моих статических массивов. Прогнозирование размера в моем случае не усложняет, и я абсолютно (на 100%) уверен, что вычисленный массив помещается в статический массив. Я даже проверил это с -check all flag. Я могу создать выделяемый массив с массивом diag(nmax), поэтому я проверю это, но этот массив далеко не такой большой, как массив werte(nemax).

Другие вопросы по тегам