Что на самом деле делает ffast-math gcc?

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

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

2 ответов


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

пример такой:

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

to

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

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

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


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

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

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

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

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

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

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