Портативное отключение FMA для одной функцииC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Портативное отключение FMA для одной функции

Сообщение Anonymous »

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

Код: Выделить всё

a*b - c*d = -(d*c - b*a)
Нет проблем, если это вычисляется как два умножения и одно вычитание. Умножение дает одинаковые результаты, а вычитание дает тот же результат с противоположными знаками.
Однако современные процессоры реализуют инструкции FMA, и компиляторы могут использовать их автоматически. Это вообще фантастика. Однако я полагаю (не уверен), что результат вышеизложенного может отличаться, если он вычисляется как одно умножение и одно FMA. Поэтому, хотя нам, вероятно, следует включить FMA глобально ( и т. д.), нам нужно отключить его только в этом случае.
Поэтому мы приступили к написанию функции без 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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»