Что на самом деле делает математика gcc?

Я понимаю, что GCC --ffast-math Флаг может значительно увеличить скорость операций с плавающей запятой и выходит за рамки стандартов IEEE, но я не могу найти информацию о том, что на самом деле происходит, когда он включен. Может ли кто-нибудь объяснить некоторые детали и, возможно, дать четкий пример того, как что-то изменилось бы, если флаг был включен или выключен?

Я попытался покопаться в SO, чтобы найти похожие вопросы, но не смог найти ничего, объясняющего работу ffast-math.

2 ответа

Решение

Как вы упомянули, он допускает оптимизации, которые не сохраняют строгое соответствие IEEE.

Пример таков:

x = x*x*x*x*x*x*x*x;

в

x *= x;
x *= x;
x *= x;

Поскольку арифметика с плавающей точкой не ассоциативна, порядок и факторизация операций будут влиять на результаты из-за округления. Следовательно, эта оптимизация не выполняется при строгом поведении FP.

На самом деле я не проверял, выполняет ли GCC именно эту оптимизацию. Но идея та же самая.

-ffast-math делает гораздо больше, чем просто нарушает строгое соответствие IEEE.

Прежде всего, конечно, это нарушает строгое соответствие IEEE, позволяя, например, переупорядочивать инструкции к чему-то, что математически одинаково (в идеале), но не совсем одинаково с плавающей запятой.

Во-вторых, это отключает настройку errno после математических функций с одной инструкцией, что означает избегание записи в локальную переменную потока (это может иметь 100% -ное различие для этих функций на некоторых архитектурах).

В-третьих, он предполагает, что вся математика является конечной, что означает, что никакие проверки на NaN (или ноль) не производятся там, где они будут иметь вредные последствия. Просто предполагается, что этого не произойдет.

В-четвертых, он обеспечивает взаимное приближение для деления и обратного квадратного корня.

Кроме того, он отключает знаковый ноль (код предполагает, что нулевой знак не существует, даже если цель его поддерживает) и математика округления, что позволяет, среди прочего, выполнять постоянное свертывание во время компиляции.

Наконец, он генерирует код, который предполагает, что никакие аппаратные прерывания не могут произойти из-за математики сигнализации / перехвата (то есть, если они не могут быть отключены на целевой архитектуре и, следовательно , произойдут, они не будут обрабатываться).

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