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

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

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

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

Примером может служить следующее:

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

в

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

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

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

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

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

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

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

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

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

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

  • Как вы объедините число с плавающей запятой в Perl?
  • Составляют ли какие-либо JIT-компиляторы JVM код, который использует векторизованные инструкции с плавающей запятой?
  • Сравнение с плавающей точкой
  • Почему я вижу двойную переменную, инициализированную некоторым значением, например 21.4, как 21.399999618530273?
  • Разница между десятичной, плавающей и двойной в .NET?
  • Приведение float в int (побитовое) в C
  • почему f помещается после значений float?
  • Почему я не могу использовать значение float в качестве параметра шаблона?
  • Почему мы не можем использовать '==' для сравнения двух чисел с плавающей запятой или двойных чисел
  • Какой диапазон чисел может быть представлен в 16-, 32- и 64-битных системах IEEE-754?
  • Как изменить поплавок на наименьший приращение (или близко к нему)?
  • Давайте будем гением компьютера.