Каковы возможные побочные эффекты использования gcc -fno-math-errno? - PullRequest
2 голосов
/ 11 июня 2019

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

Не устанавливать "errno" после вызова математических функций, которые выполняются с одной инструкцией, например, "sqrt"

Мне не ясно, что такое «errno» и как оно используется в другом месте (это то же самое, что код выхода программы?) Кроме того, на странице руководства написано:

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

Мне непонятно, что это значит, являются стандартом исключений IEEE для c ++ или общими библиотеками c ++ (например, Eigen, Boost и т. Д.)

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

РЕДАКТИРОВАТЬ: Мой код представляет собой простой одноразовый процедурный код для решения научной проблемы. Это не будет частью глубоко внедренной системы, которая требует сложной обработки ошибок. Тем не менее, код не должен давать сбой тонкими, тихими способами.

1 Ответ

3 голосов
/ 11 июня 2019

C ввел концепцию единого errno или «номера ошибки», который можно использовать для определения точной причины отказа некоторых стандартных функций, включая математические функции, при выполнении своих обязанностей.POSIX расширила errno, и C ++ 11 также выбрал некоторые из этих расширений.

Когда одна из этих функций не работает, глобальному целому числу errno присваивается значение, которое говорит вам, почему.Очевидно, это влечет за собой снижение производительности.

GCC говорит, что этот флаг отключает это поведение для определенных математических функций, ускоряя вашу программу за счет диагностической утилиты и соответствия стандартам.

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


Однако вы можете случайно наблюдать побочные эффекты, если у вас естьЖук.Представьте, что вы делаете что-то вроде следующего:

std::some_maths_function(42);
if (errno == ERANGE)
   exit(-1);

Упс!Мы проверяем errno, даже когда some_maths_function(42) удалось.Предположим, что над этим кодом находится вызов std::some_other_maths_function(999), который обычно завершается неудачно и в результате errno устанавливается на EDOM.Это скрывало ошибку в приведенном выше коде.

Теперь включите флаг компилятора.Если some_other_maths_function является одной из функций, которые больше не устанавливают errno, ваша ошибка будет снята, и вам может потребоваться несколько минут, чтобы понять, что вы должны написать что-то вроде:

if (std::some_maths_function(42) == -1)
{
   if (errno == RANGE)
      exit(-1);
}

Конечно, вряд ли GCC виноват в том, что у вас была ошибка, но это действительно показывает, как поведение вашей программы может отличаться после включения этого флага «оптимизации».Действительно, документация гласит:

Эта опция не включена ни одним параметром -O, так как это может привести к неправильному выводу для программ, которые зависят от точной реализации IEEE илиПравила / спецификации ISO для математических функций.Однако это может привести к более быстрому коду для программ, которые не требуют гарантий этих спецификаций.

Другими словами, этот флаг отправляет вас за пределы книги.Но, возможно, оно того стоит.


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

...