Этот трюк мог сработать в 2007 году, когда был представлен документ, но я думаю, что он вряд ли будет работать на современной платформе.
На современном процессоре x86 (32- и 64-разрядном) есть два отдельных набора команд для вычислений с плавающей запятой:
более старые инструкции x87 (начиная с оригинального сопроцессора 8087), которые имели 80-битные регистры
более свежие инструкции SSE, в которых используются регистры той же ширины, что и формат (32 бита для float
, 64 бита для double
).
Новые инструкции SSE обычно предпочитаются современными компиляторами, так как они, как правило, быстрее, так как они могут быть полностью конвейерными и поддерживают такие интересные вещи, как операции SIMD. Однако в 2007 году некоторые компиляторы по-прежнему использовали только инструкции x87 по умолчанию, поскольку двоичные файлы можно было использовать на старых машинах (это было особенно актуально на 32-разрядных машинах).
80-битные регистры поддерживали значение до 64 бит, что на 11 бит больше, чем 53-битное значение и 64-бит double
. Идея состоит в том, что вы могли бы потенциально уменьшить промежуточную ошибку округления, которую в этом случае вы могли бы использовать.
Рассмотрим более простую версию их задачи: вычисления
Y = A*X
путем разбиения A
на B+C
, как они предполагают, B
имеет только 10 значащих бит. Тогда операция
B*X
не вызывает ошибок округления, так как в нем будет не более 63 значащих бит. Полный расчет
Y = B*X + C*X
Таким образом,
даст вам результат с почти полными 64 битами точности.
Без расширенной точности B*X
будет обычно вызывать ошибку округления примерно того же размера, как если бы вы только что вычислили A*X
напрямую (если только X
не был сохранен с уменьшенной точностью).
Теперь это звучит замечательно: вы можете задаться вопросом, почему инструкции SSE избавились от этого? К сожалению, это не было предсказуемо: в некоторых случаях компилятор устроил бы это так, чтобы это работало, но в других случаях ему нужно будет «пролить» регистры в память, и в этом случае вы потеряете эту дополнительную точность. Это, в свою очередь, дает иногда странные результаты, например, когда такие операции, как x+y == x+y
, оцениваются как ложные, в зависимости от того, когда были оценены отдельные операции.
Однако еще не все потеряно! Если у вас достаточно свежая машина, вы можете воспользоваться преимуществами операций плавное умножение-сложение (fma) , чтобы повысить точность. В этом случае это будет выглядеть примерно так:
Y = fma(B,X,C*X)