Один и тот же код с использованием поплавков на двух компьютерах дает два разных результата - PullRequest
2 голосов
/ 30 сентября 2010

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

Когда я запускаю этот код на одном и том же образе на двух разных компьютерах: на одном Pentium IV работает последняя версия Fedora, на другом - Core i5 с последней Ubuntu, обе 32-битные, я получаю немного разные результаты.Например, после некоторого длительного расчета 1,3456f для некоторой переменной на одной машине и 1,3457f на другой.Это ожидаемое поведение или я должен искать ошибки в моей программе?

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

Ответы [ 7 ]

11 голосов
/ 30 сентября 2010

Это не редкость, и это будет зависеть от вашего компилятора, настроек оптимизации, математических библиотек, ЦП и, конечно, числовой стабильности используемых вами алгоритмов.

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

4 голосов
/ 30 сентября 2010

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

Поведение с плавающей запятой часто настраивается в зависимости от параметров компилятора, даже на уровне разных процессоров.Проверьте свои документы компилятора, чтобы видеть, можете ли Вы уменьшить или устранить несоответствие.В Visual C ++ (например) это делается через /fp.

3 голосов
/ 30 сентября 2010

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

Чтение «Подводные камни при проверке вычислений с плавающей точкой» ДэвидаMonniaux для деталей.

3 голосов
/ 30 сентября 2010

Это из-за явления, называемого машинным эпсилоном?

http://en.wikipedia.org/wiki/Machine_epsilon

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

1 голос
/ 30 сентября 2010

К сожалению, это совершенно нормально.

Существуют библиотеки, которые могут выдавать идентичные результаты везде - см. http://www.mpfr.org/ для примера. Но затраты на производительность существенны и, вероятно, не стоят того, если точно идентичные результаты не являются наиболее важным критерием.

На самом деле я написал библиотеку с закрытым исходным кодом, в которой реализована математика с плавающей запятой в целочисленном блоке, чтобы плавающие выражения давали одинаковые результаты на разных платформах (Intel, AMD, PowerPC) для разных компиляторов. У нас было приложение, которое просто не могло функционировать, если результаты с плавающей точкой менялись. Это была довольно сложная задача. Если бы мы могли сделать это снова, мы бы просто разработали оригинальное приложение с фиксированной запятой, но в то время это было слишком много кода для перезаписи.

1 голос
/ 30 сентября 2010

Я также скажу, что это очень распространено, и, вероятно, не ваша вина.

Я провел много времени в прошлом, пытаясь выяснить ту же проблему.

Я быпредлагаем использовать decimal вместо float и double, если ваши цифры относятся не к научным расчетам, а к таким значениям, как цены, количество, обменные курсы и т. д.

0 голосов
/ 30 сентября 2010

Либо это разница между внутренним представлением поплавка, приводящая к несколько иным результатам, либо, возможно, разница в способе вывода поплавка на экран? Я сомневаюсь, что это твоя вина ...

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