Обратный след ошибки Фортрана приводит к циклу где - PullRequest
0 голосов
/ 23 мая 2018

Я работаю над большим кодом Fortran, и прежде чем компилировать с быстрыми параметрами (чтобы выполнить тестирование на большой базе данных), я обычно компилирую с опциями "warnings", чтобы обнаружить и отследить все проблемы.

Итак, при компиляции gfortran -fbacktrace -ffpe-trap=invalid,zero,overflow,underflow -Wall -fcheck=all -ftrapv -g2 я получаю следующую ошибку:

Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation.
Backtrace for this error:
 #0  0x7fec64cdfef7 in ???
 #1  0x7fec64cdf12d in ???
 #2  0x7fec6440e4af in ???
 #3  0x7fec64a200b4 in ???
 #4  0x7fec649dc5ce in ???
 #5  0x4cf93a in __f_mod_MOD
    at /f_mod.f90:132
 #6  0x407d55 in main_loop_
    at main.f90:419
 #7  0x40cf5c in main_prog
    at main.f90:180
 #8  0x40d5d3 in main
    at main.f90:68

И часть кода f_mod.f90: 132 содержит цикл where:

! Compute s parameter
do i = 1, Imax
   where (dprim .ne. 1.0)
      s(:,:,:, :) = s(:,:,:, :) +vprim(:,:,:, i,:)*dprim(:,:,:, :)*dprim(:,:,:, :)/(1.0 -dprim(:,:,:, :))
   endwhere
enddo

Но я не вижу здесь никакой ошибки.Все остальные местоположения являются вызовами подпрограммы, ведущей к этой части.И, конечно же, поскольку это ошибка SIGFPE, у меня возникают проблемы с выполнением при компиляции gfortran -g1.(Я использую gfortran 6.4.0 на linux)

Более того, эта ошибка появляется и исчезает с изменениями совершенно другой части кода.Таким образом, проблема заключается в том, где цикл?Или откуда-то еще и обратный след неправильный?Если это так, как я могу найти эту ошибку?

РЕДАКТИРОВАТЬ:

Так как, я не могу воспроизвести эту ошибку в минимальном примере (они работают), я думаю, что проблема приходитдля где-то еще.Но как найти проблему в большом коде?

1 Ответ

0 голосов
/ 23 мая 2018

Поскольку код умирает с SIGFPE, используйте каждую из возможных ловушек, чтобы узнать, является ли она FE_DIVBYZERO, FE_INVALID, FE_OVERFLOW или FE_UNDERFLOW.Если это недостаток, измените маску на '1 - dprim .ne.0 '.

PS: не использовать обозначение раздела массива, когда вместо него может использоваться ссылка на весь массив.

PPS: Вы можете вычислить dprim * drpim / (1 - dprim)вне цикла do, поскольку он инвариантен к циклу.

...