Значения с плавающей запятой ведут себя по-разному в сборках выпуска и отладки - PullRequest
7 голосов
/ 27 сентября 2008

Мое приложение генерирует различные значения с плавающей запятой, когда я компилирую его в режиме выпуска и в режиме отладки. Единственная причина, по которой я узнал, это то, что я сохраняю двоичный журнал трассировки, и тот, что из сборки выпуска, очень немного отличается от сборки отладки, похоже, что два нижних бита 32-битных значений с плавающей точкой отличаются примерно на 1/2 случаев.

Считаете ли вы эту «разницу» ошибкой или можно ожидать такой разницы? Это будет ошибка компилятора или ошибка внутренней библиотеки.

Например:

LEFTPOS and SPACING are defined floating point values.
float def_x;
int xpos;

def_x = LEFTPOS + (xpos * (SPACING / 2));

Проблема связана с компилятором X360.

Ответы [ 9 ]

11 голосов
/ 27 сентября 2008

Режим релиза может иметь другую установленную стратегию FP. Существуют различные арифметические режимы с плавающей запятой в зависимости от уровня оптимизации, который вы хотите. MSVC, например, имеет строгий, быстрый и точный режимы.

4 голосов
/ 27 сентября 2008

Я знаю, что на ПК регистры с плавающей запятой имеют ширину 80 бит. Таким образом, если вычисление выполняется полностью внутри FPU, вы получите преимущество в 80 бит точности. С другой стороны, если промежуточный результат перемещается в обычный регистр и обратно, он усекается до 32 бит, что дает разные результаты.

Теперь учтите, что сборка выпуска будет иметь оптимизации, которые сохраняют промежуточные результаты в регистрах FPU, тогда как сборка отладки, вероятно, будет наивно копировать промежуточные результаты назад и вперед между памятью и регистрами - и в этом ваша разница в поведении.

Я не знаю, происходит ли это на X360 или нет.

3 голосов
/ 27 сентября 2008

Я помог коллеге найти переключатель компилятора, который отличался в сборках выпуска и отладки, что вызывало его различия.

Взгляните на / fp (указать поведение с плавающей точкой) .

2 голосов
/ 27 сентября 2008

В дополнение к различным режимам с плавающей запятой, на которые указывали другие, для выпуска могут быть включены SSE или аналогичные векторные оптимизации. Преобразование арифметики с плавающей запятой из стандартных регистров в векторные регистры может повлиять на младшие биты ваших результатов, поскольку векторные регистры, как правило, будут более узкими (меньше битов), чем стандартные регистры с плавающей запятой.

2 голосов
/ 27 сентября 2008

Это не ошибка. Любая операция с плавающей запятой имеет определенную неточность. В режиме Release оптимизация изменит порядок операций, и вы получите немного другой результат. Разница должна быть небольшой, хотя. Если он большой, у вас могут быть другие проблемы.

1 голос
/ 27 сентября 2008

Не ошибка. Этот тип различий следует ожидать.

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

0 голосов
/ 26 ноября 2008

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

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

0 голосов
/ 27 сентября 2008

Как и другие упомянутые, регистры с плавающей точкой имеют более высокую точность, чем плавающие, поэтому точность конечного результата зависит от распределения регистров.

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

0 голосов
/ 27 сентября 2008

Это несоответствие вполне может быть вызвано оптимизацией компилятора, которая обычно выполняется в режиме выпуска, но не в режиме отладки. Например, компилятор может переупорядочить некоторые операции, чтобы ускорить выполнение, что может вызвать небольшую разницу в результате с плавающей запятой.

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

...