Я программирую версию алгоритма BFGS для многомерной оптимизации на Fortran 90. Я написал код, скомпилировал его с помощью gfortran на своем ноутбуке (под управлением Windows Vista), и он отлично работает. Но когда я пытаюсь использовать тот же код на сервере под управлением Linux 6, он дает неправильные результаты. Это точно такой же код, и он отлично компилируется, но результаты, которые он дает, просто неверны. А именно, он, кажется, развивает арифметическую ошибку с плавающей запятой на какой-то ранней стадии алгоритма и выдает только одну строку числовых результатов, прежде чем начнет выдавать NaN. Я могу только предположить, что это связано с серверной средой, но как я могу узнать, что это такое, и как я могу соответствующим образом исправить свой код?
Почему мой численный алгоритм ведет себя по-разному на двух разных машинах?
Ответы (1)
Проблема описана здесь (CERT.org): FLP00-C. Узнайте об ограничениях чисел с плавающей запятой
Причина такого поведения заключается в том, что Linux использует внутренний режим расширенной точности модуля x87 с плавающей запятой (FPU) на машинах IA-32 для повышения точности вычислений. Когда результат сохраняется в памяти с помощью присвоение с, FPU автоматически округляет результат, чтобы соответствовать двойному. Значение, считанное из памяти, теперь неравномерно сравнивается с внутренним представлением, которое имеет расширенную точность. Windows не использует режим расширенной точности, поэтому все вычисления выполняются с двойной точностью, и нет разницы в точности между значениями, хранящимися в памяти, и значениями, внутренними для FPU. Для GCC компиляция при оптимизации уровень 1 или выше устраняет ненужное сохранение в памяти, поэтому все вычисления происходят внутри FPU с повышенной точностью
Решение описано здесь: FLP02-C. Избегайте использования чисел с плавающей запятой, когда требуются точные вычисления с двумя примерами: неверный пример, показывающий проблему, и исправленный пример без проблемы:
«Этот код можно исправить, заменив числа с плавающей запятой целыми числами для внутренних дополнений. Плавающие числа используются только при печати результатов и при выполнении деления для вычисления среднего значения».