Почему мой численный алгоритм ведет себя по-разному на двух разных машинах?

Я программирую версию алгоритма BFGS для многомерной оптимизации на Fortran 90. Я написал код, скомпилировал его с помощью gfortran на своем ноутбуке (под управлением Windows Vista), и он отлично работает. Но когда я пытаюсь использовать тот же код на сервере под управлением Linux 6, он дает неправильные результаты. Это точно такой же код, и он отлично компилируется, но результаты, которые он дает, просто неверны. А именно, он, кажется, развивает арифметическую ошибку с плавающей запятой на какой-то ранней стадии алгоритма и выдает только одну строку числовых результатов, прежде чем начнет выдавать NaN. Я могу только предположить, что это связано с серверной средой, но как я могу узнать, что это такое, и как я могу соответствующим образом исправить свой код?


person pr0gramR    schedule 14.12.2012    source источник
comment
Я знаком с основами арифметики с плавающей запятой, и я думаю, что мой код был разработан достаточно хорошо, по крайней мере, в той мере, в какой он работает и дает правильные результаты для задач минимизации тестов на моем ноутбуке. Мой вопрос касается кода, работающего по-разному на разных платформах. Я не понимаю, почему мой код работает в Windows, а не в Linux. Он был скомпилирован с помощью gfortran на обеих платформах.   -  person pr0gramR    schedule 14.12.2012
comment
Одной из распространенных проблем является компиляция кода с отладочной информацией в одной среде, а затем компиляция кода без отладочной информации в другой среде. Если у вас есть объекты или массивы, записывающие за пределы своих ограничений в отладочных версиях, они просто перезаписывают отладочную информацию и не влияют на работающий код. Вы можете скомпилировать оба с отладочной информацией и посмотреть, как это происходит.   -  person kermit    schedule 14.12.2012
comment
@clioi, различное поведение с плавающей запятой определенно является возможным источником проблем между разными платформами.   -  person Carl Norum    schedule 14.12.2012
comment
@CarlNorum, не могли бы вы дать какой-нибудь конкретный совет или ссылку, которую я мог бы прочитать о том, как определить, какие могут быть такие проблемы?   -  person pr0gramR    schedule 14.12.2012
comment
@kermit, код относительно короткий, всего ~ 300 строк, и я почти уверен, что он был скомпилирован одинаково с одинаковой информацией в обоих местах.   -  person pr0gramR    schedule 14.12.2012
comment
Как вы загружаете входные данные, с которыми работает ваш алгоритм? Зашито в код или из файлов, как-то иначе?   -  person Digikata    schedule 14.12.2012
comment
Программа предназначена для минимизации многомерной функции. В этой конкретной реализации функция является фактической функцией Фортрана, которая при передаче вектора соответствующей длины оценивает функцию в этой точке.   -  person pr0gramR    schedule 14.12.2012
comment
Итак, отвечая на ваш вопрос, все это жестко запрограммировано в программе, оно не передается во время выполнения или считывается из файлов.   -  person pr0gramR    schedule 14.12.2012


Ответы (1)


Проблема описана здесь (CERT.org): FLP00-C. Узнайте об ограничениях чисел с плавающей запятой

Причина такого поведения заключается в том, что Linux использует внутренний режим расширенной точности модуля x87 с плавающей запятой (FPU) на машинах IA-32 для повышения точности вычислений. Когда результат сохраняется в памяти с помощью присвоение с, FPU автоматически округляет результат, чтобы соответствовать двойному. Значение, считанное из памяти, теперь неравномерно сравнивается с внутренним представлением, которое имеет расширенную точность. Windows не использует режим расширенной точности, поэтому все вычисления выполняются с двойной точностью, и нет разницы в точности между значениями, хранящимися в памяти, и значениями, внутренними для FPU. Для GCC компиляция при оптимизации уровень 1 или выше устраняет ненужное сохранение в памяти, поэтому все вычисления происходят внутри FPU с повышенной точностью

Решение описано здесь: FLP02-C. Избегайте использования чисел с плавающей запятой, когда требуются точные вычисления с двумя примерами: неверный пример, показывающий проблему, и исправленный пример без проблемы:

«Этот код можно исправить, заменив числа с плавающей запятой целыми числами для внутренних дополнений. Плавающие числа используются только при печати результатов и при выполнении деления для вычисления среднего значения».

person kermit    schedule 14.12.2012