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

9

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

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

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

Я читал, что в старых играх RTS использовалась арифметика с фиксированной запятой, но я не знаю, требуется ли это на современных компьютерах, если они все придерживаются одного и того же стандарта? Мне также сказали, что, хотя неточный, результат с плавающей запятой является детерминированным для одного и того же ввода (что, я предполагаю, означает, что любой компьютер, следующий тому же стандарту, получает тот же неточный результат?).

Есть ли у компьютеров отклонения, даже если они следуют одному и тому же стандарту с плавающей запятой?

Я пишу эту игру на C #, но не уверен, что это имеет значение, но я все равно упомяну об этом.

WDUK
источник
Даже если бы они это сделали, я бы не использовал поплавки для этого
Теластин
Что вы имеете в виду ? Почему бы нет?
WDUK
Использование поплавков может быть нежелательным в любом случае, потому что поведение может зависеть от положения на карте. Far Lands Minecraft были более примечательным примером: движение, рендеринг и рельеф местности становились неуверенными, когда вы уходили далеко от точки появления.
Амон

Ответы:

18

Есть ли у компьютеров отклонения, даже если они следуют одному и тому же стандарту с плавающей запятой?

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

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

Док Браун
источник
Эта. Некоторые основные причины: IEEE Std 754 включает в себя необязательные предложения «следует» (например, обработка NaN) и допускает альтернативы проектирования (например, обнаружение недостаточного уровня). Поскольку языковые привязки поддерживают стандарт с плавающей точкой, они все же могут дать компилятору свободу действий при оценке выражений с плавающей точкой, например, FLT_EVAL_METHODв ISO C / C ++. Трансцендентные функции (например sin, exp, log) в значительной степени нерегулируемых оба стандарта с плавающей точкой IEEE и программированием стандартов языка. Простое обновление версии библиотеки (например, новая glibcверсия) может привести к отличиям результатов.
Нюффа
Я сам попал в игру. Ракета прекрасно летела на моем ноутбуке, не летала на моем рабочем столе, абсолютно идентичные установки.
Лорен Печтел
3

Ошибки с плавающей точкой

Каждое число с плавающей запятой накапливает неточность, поскольку оно используется для расчета. Это простой факт использования неточного формата для расчета в. Расчеты также чувствительны к порядку расчета, коммутативность не гарантируется, т. (a + b) + cЕ. Может совпадать или не совпадать с a + (b + c).

Кроме того, процессоры не обязательно имеют ту же длину мантиссы, что и стандарт памяти. Это может привести к интересному поведению, так как 32/64/128-битное значение с плавающей запятой иногда работает так, как будто у них больше битов.

Ошибки с фиксированной точкой

При этом арифметика с фиксированной точкой также может накапливать ошибки. Разница в том, что числа с фиксированной запятой ясны в отношении того, какая точность потеряна, и в зависимости от выбранных операций можно полностью избежать ошибок округления. Они также коммутативны (a + b) + c = a + (b + c).

Который?

Какой из них использовать, полностью зависит от того, какие свойства вам нужны.

Числа с плавающей точкой:

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

Номера с фиксированной точкой:

  • укажите меньший диапазон чисел с одинаковым расстоянием между любыми двумя последовательными числами.
  • менее чувствительны к порядку расчета
  • понятнее об ошибках округления
  • можно работать с, чтобы минимизировать / избежать проблем округления.
Kain0_0
источник
1
«числа с фиксированной запятой ясны в том, какая точность потеряна» - с плавающей запятой тоже ясно, разница скорее в неточностях с фиксированной запятой, которые более интуитивны для обычной нумерации жизни
whatsisname
1
Таким образом, только фиксированная точка гарантирует, что все компьютеры, независимо от оборудования и т. Д., Будут иметь одинаковые ошибки / потерю точности?
WDUK
1
По сути, да, потому что вы можете указать, что ваши номера с фиксированной точкой 32 или 64 бита, и они будут во всех системах. Числа с плавающей запятой могут быть 32- или 64-разрядными, но аппаратные средства могут фактически использовать 48 или 96-разрядные для вычисления и преобразовывать в 32-64-разрядные в конце, что приводит к различиям между различными типами аппаратных средств.
user1118321
@whatsisname Хотя спецификации с плавающей точкой вполне понятны, вы не можете легко сказать мне , что округление вопросов , я буду сталкиваться в этой сумме: (a + b * c) / d - e. За исключением очевидных проблем, таких как NaNделение на ноль или переполнение / недополнение, возможно, что это выражение будет неправильным. Добавьте к этому зависимость между памятью и регистром с точки зрения точности, и даже простая загрузка / сохранение из памяти «того же» значения с плавающей запятой изменит ответ.
Kain0_0
@ Kain0_0: ты прав, я не могу легко сказать тебе, с чем столкнусь, потому что я не эксперт с плавающей запятой. Это именно то, что имелось в виду, когда я сказал «более интуитивно понятный для нумерации обычной жизни». Когда вы говорите, что фиксированная точка «чистая», а плавающая - нет, вы звучите так, как будто поплавки кажутся случайно неточными.
whatsisname
-1

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

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

Очень мало ситуаций, в которых воспроизводимость действительно важна: в механизме компоновки или сжатии / декомпрессии без потерь. Использование фиксированной точки, скорее всего, будет ошибочным.

gnasher729
источник
Я не опроверг ваш ответ, но, похоже, описанный ОП случай именно «одна из тех немногих ситуаций, где воспроизводимость действительно важна». В игре RTS небольшая ошибка округления может сделать разницу между «столкнулись два объекта» или нет.
Док Браун