Различное математическое поведение между Linux, Mac OS X и Windows - PullRequest
7 голосов
/ 25 декабря 2009

HI

Я разработал некоторый смешанный код C / C ++ с некоторыми интенсивными числовыми вычислениями. При компиляции в Linux и Mac OS X я получаю очень похожие результаты после завершения симуляции. В Windows программа также компилируется, но я получаю очень разные результаты, и иногда программа, похоже, не работает.

Я использовал компиляторы GNU во всех системах. Некоторые друзья рекомендуют мне добавить -frounding-math, и теперь версия для Windows, кажется, работает более стабильно, но Linux и Os X, их результаты, вообще не меняются.

Не могли бы вы порекомендовать другие варианты, чтобы добиться большего соответствия между версиями Win и Linux / OSX?

Спасибо

P.D. Я также попытался -O0 (без оптимизации) и указал -m32

Ответы [ 4 ]

10 голосов
/ 25 декабря 2009

Я не могу говорить о реализации в Windows, но чипы Intel содержат 80-битные регистры с плавающей запятой и могут дать большую точность, чем указано в стандарте IEEE-754. Вы можете попробовать вызвать эту подпрограмму в main () вашего приложения (на чиповых платформах Intel):

inline void fpu_round_to_IEEE_double()
{
   unsigned short cw = 0;
   _FPU_GETCW(cw);        // Get the FPU control word
   cw &= ~_FPU_EXTENDED;  // mask out '80-bit' register precision
   cw |= _FPU_DOUBLE;     // Mask in '64-bit' register precision
   _FPU_SETCW(cw);        // Set the FPU control word
}

Я думаю это отличается от режимов округления, обсуждаемых @ Alok.

9 голосов
/ 25 декабря 2009

Существует четыре различных типа округления чисел с плавающей запятой: округление до нуля, округление вверх, округление вниз и округление до ближайшего числа. В зависимости от компилятора / операционной системы значение по умолчанию может отличаться в разных системах. Для программного изменения метода округления см. fesetround. Он определен стандартом C99, но может быть доступен для вас.

Вы также можете попробовать вариант -ffloat-store gcc. Это попытается помешать gcc использовать 80-битные значения с плавающей точкой в ​​регистрах.

Кроме того, если ваши результаты меняются в зависимости от метода округления и различия значительны, это означает, что ваши расчеты могут быть нестабильными. Пожалуйста, рассмотрите возможность анализа интервалов или использования другого метода, чтобы найти проблему. Для получения дополнительной информации см. Насколько бесполезны бессмысленные оценки округления в вычислениях с плавающей точкой? (pdf) и Подводные камни проверки вычислений с плавающей точкой (ссылка ACM, но вы можете получить PDF из многих мест, если это не работает для вас).

1 голос
/ 25 декабря 2009

В дополнение к параметрам округления времени выполнения, о которых упоминали люди, вы можете управлять настройками компилятора Visual Studio в Свойствах> C ++> Генерация кода> Модель с плавающей запятой. Я видел случаи, когда установка этого параметра на «Быстрый» может привести к некоторому плохому числовому поведению (например, итерационные методы не сходятся).

Настройки описаны здесь: http://msdn.microsoft.com/en-us/library/e7s85ffb%28VS.80%29.aspx

0 голосов
/ 30 мая 2014

Стандарты IEEE и C / C ++ оставляют некоторые аспекты математики с плавающей точкой неопределенными. Да, точный результат добавления в число с плавающей точкой определяется, но более сложный расчет - нет. Например, если вы добавите три числа с плавающей запятой, то компилятор может выполнить оценку с точностью с плавающей запятой, двойной точностью или выше. Точно так же, если вы добавите три двойника, то компилятор может выполнить оценку с двойной точностью или выше.

VC ++ по умолчанию устанавливает точность точности FPU на x87 вдвое. Я считаю, что gcc оставляет это с 80-битной точностью. Ни одно из них явно не лучше, но они могут легко дать разные результаты, особенно если в ваших расчетах есть нестабильность. В частности, «крошечный + большой - большой» может дать очень разные результаты, если у вас есть дополнительные биты точности (или если порядок оценки изменяется). Последствия различной промежуточной точности обсуждаются здесь:

http://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/

Проблемы детерминированной плавающей точки обсуждаются здесь:

http://randomascii.wordpress.com/2013/07/16/floating-point-determinism/

Математика с плавающей точкой сложна. Вам нужно выяснить, когда ваши расчеты расходятся, и изучить сгенерированный код, чтобы понять, почему. Только тогда вы сможете решить, какие действия предпринять.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...