Всегда ли команды FMA (слитые с умножением-сложением) дают тот же результат, что и команда затем добавить?

У меня есть эта сборка (AT&T синтаксис):

mulsd   %xmm0, %xmm1
addsd   %xmm1, %xmm2

Я хочу заменить его на:

vfmadd231sd %xmm0, %xmm1, %xmm2

Будет ли это преобразование всегда оставлять эквивалентное состояние во всех задействованных регистрах и флагах? Или результат будет немного отличаться? (Если они отличаются, то почему?)

(Об инструкциях FMA: http://en.wikipedia.org/wiki/FMA_instruction_set)

1 ответ

Решение

Нет. Фактически, большая часть преимущества объединенного умножения-сложения состоит в том, что он (не обязательно) дает тот же результат, что и отдельное умножение и сложение.

В качестве (несколько надуманного) примера предположим, что мы имеем:

double a = 1 + 0x1.0p-52 // 1 + 2**-52
double b = 1 - 0x1.0p-52 // 1 - 2**-52

и мы хотим вычислить a*b - 1, "Математически точное" значение a*b - 1 является:

(1 + 2**-52)(1 - 2**-52) - 1 = 1 + 2**-52 - 2**52 - 2**-104 - 1 = -2**-104

но если мы сначала вычислим a*b используя умножение, он округляет до 1,0, поэтому последующее вычитание 1,0 дает нулевой результат.

Если мы используем fma(a,b,-1) вместо этого мы исключаем промежуточное округление продукта, что позволяет нам получить "реальный" ответ, -1.0p-104,

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

Другие вопросы по тегам