#optimization #iterator #fortran #do-loops
#оптимизация #итератор #fortran #циклы выполнения
Вопрос:
Я написал подпрограмму fortran, которая использует некоторый устаревший код fortran 77 для конечных элементов. Однако в конкретной сетке, когда включен флаг оптимизации -O, каким-то образом изменяется важный итератор цикла do-loop, даже несмотря на то, что fortran предположительно запрещает это. Я скомпилировал этот код с использованием gfortran4.5 с включенной проверкой -fcheck=do во время выполнения, и это подтвердило то, что я отметил выше. Ошибка во время выполнения возникает только при включении оптимизации и указывает непосредственно на итератор выполнения.
Использование gdb в оптимизированном коде кажется (хотя это кажется неустойчивым — строки скачут взад и вперед), кажется, ясно указывает на то, что итератор do каким-то образом возвращается к нулю, и, по сути, это приводит к приятному бесконечному циклу.
Я был бы очень признателен за любые предложения относительно того, как найти и исправить то, что вызывает эту ошибку, поскольку я хотел бы убедиться, что весь проект может быть последовательно скомпилирован с одинаковыми флагами.
Комментарии:
1. Не могу предложить много информации без некоторого кода, предпочтительно небольшого тестового набора, который воспроизводит проблему. Очевидный вопрос, однако, заключается в том, что вы запускали что-либо через valgrind или что-то подобное, чтобы посмотреть, есть ли какие-либо перезаписи памяти? Возможно, вы (скажем) переходите к концу массива, и в неоптимизированном коде вы задели что-то безвредное, но с измененным расположением памяти вы теперь задели итератор цикла выполнения.
2. источник цикла выполнения, о котором идет речь?
Ответ №1:
Вы говорите, что используете fcheck = do; почему бы не пройти весь путь и не использовать fcheck = all? То, что вы видите, похоже на типичный случай повреждения памяти из-за нарушения границ массива, которое в некоторых случаях может быть обнаружено fcheck= all. Где проверка границ массива не работает так хорошо, так это при неявных интерфейсах и передаче неправильных границ; решение здесь состоит в том, чтобы поместить ваши процедуры в модули, позволяя компилятору проверять интерфейсы.
И, как сказал Джонатан Дурси, рассмотрите возможность использования такого инструмента, как valgrind.
Комментарии:
1. Я думаю, что на данный момент я просто запущу его в режиме отладки. Код fortran, с которым я взаимодействую, использует C для динамического выделения памяти и изначально был написан на f77. Используя valgrind и fcheck = all, программа выдает ошибки задолго до моей проблемы (вероятно, указывая на другие проблемы с кодом). Я выбрал fcheck= do, потому что переменная цикла do изменяется, и это вызывает бесконечный цикл (сброс j= 1 на j = 0). Странная вещь — тот же код, когда оптимизированный работает нормально с конечным элементом tetrahedra (возможно, другой макет), чем с конечными элементами hexahedral brick, где он терпит неудачу.
2. Если программа вызывает ошибки с valgrind и fcheck = all, я, конечно, не стал бы доверять результатам.