Код: Выделить всё
a*b - c*d = -(d*c - b*a)
Однако современные процессоры реализуют инструкции FMA, и компиляторы могут использовать их автоматически. Это вообще фантастика. Однако я полагаю (не уверен), что результат вышеизложенного может отличаться, если он вычисляется как одно умножение и одно FMA. Поэтому, хотя нам, вероятно, следует включить FMA глобально (
Код: Выделить всё
-mfmaПоэтому мы приступили к написанию функции без FMA. У меня получилось следующее:
Код: Выделить всё
#ifdef __clang__
#pragma clang fp contract(off)
#elifdef _MSC_VER
#pragma float_control(push)
#pragma fp_contract(off)
#elifdef __GNUC__
__attribute__((optimize("fp-contract=off")))
#endif
[[nodiscard]] constexpr
float ab_minus_cd_no_fma( float a,float b, float c,float d )
{
return a*b - c*d;
}
#ifdef __clang__
#pragma clang fp contract(on)
#elifdef _MSC_VER
#pragma float_control(pop)
#endif
- В Clang сокращения с плавающей запятой будут безоговорочно разрешены в коде ниже функции. Это может не соответствовать среде над функцией. Как правильно вернуть все в исходное состояние?
- В GCC и MSVC функция не встраивается. Компилятор выдает, например. вместо этого вызов или jmp Tailcall. Я могу с этим жить, но это неоптимально. Можно ли это улучшить? Если да, то как?
Обратите внимание, что компиляция всей единицы перевода без включенного FMA — не решение. Мы хотим FMA повсюду. Более того, создание выделенной единицы трансляции исключает встраивание (или требует LTCG) и требует исключения из флагов компилятора для этого модуля, что неприятно и подвержено ошибкам для системы сборки.
Подробнее здесь: https://stackoverflow.com/questions/798 ... e-function
Мобильная версия