Как мне убедиться, что lrint встроен в gcc? - PullRequest
12 голосов
/ 23 февраля 2012

После прочтения этой темы из многочисленных источников появилось огромное количество доказательств того, что использование стандартных приведений C или C ++ для преобразования чисел с плавающей запятой в целые числа в Intel очень медленное. Чтобы соответствовать спецификации ANSI / ISO, процессорам Intel необходимо выполнить большое количество инструкций, включая те, которые необходимы для переключения режима округления оборудования FPU.

Существует ряд обходных путей, описанных в различных документах, но наиболее чистым и переносимым представляется вызов lrint (), добавленный в стандарты C99 и C ++ 0x. Во многих документах говорится, что компилятор должен встроить эти функции, когда оптимизация включена, что приводит к коду, который быстрее обычного преобразования или к вызову функции.

Я даже нашел ссылки на пакеты отслеживания функций gcc, чтобы добавить это встроенное расширение в оптимизатор gcc, но в моих собственных тестах производительности я не смог заставить его работать. Все мои попытки показывают, что производительность lrint намного ниже, чем при использовании простого стиля C или C ++. Изучение выходных данных компилятора и дизассемблирование скомпилированных объектов всегда показывает явный вызов внешней функции lrint () или lrintf ().

Версии gcc, с которыми я работал, - это 4.4.3 и 4.6.1, и я попробовал несколько комбинаций флагов на 32-битных и 64-битных целевых объектах x86, включая опции для явного включения SSE.

Как получить gcc для встроенного расширения lrint и быстрого преобразования?

Ответы [ 2 ]

10 голосов
/ 23 февраля 2012

Функция lrint() может вызвать ошибки домена и диапазона.Один из возможных способов, с помощью которого libc справляется с такими ошибками, - установка errno (см. C99 / C11 раздел 7.12.1).Затраты на проверку ошибок могут быть весьма значительными, и в данном конкретном случае, по-видимому, этого вполне достаточно, чтобы оптимизатор принял решение против встраивания.

Флаг gcc -fno-math-errno (который является частью -ffast-math) отключитэти проверки.Было бы неплохо изучить -ffast-math, если вы не полагаетесь на совместимую со стандартами обработку семантики с плавающей точкой, в частности NaN и бесконечностей ...

0 голосов
/ 23 февраля 2012

Вы пробовали флаг -finline-functions для gcc.

Вы также можете указать GCC попытаться интегрировать все «достаточно простые» функции в своих вызывающих с помощью опции -finline-functions.

см. http://gcc.gnu.org/onlinedocs/gcc/Inline.html

Здесь вы можете сказатьgcc сделать все функции встроенными, но не все будут встроены.Компилятор использует некоторую эвристику, чтобы определить, достаточно ли малая функция для встраивания.Еще одна вещь заключается в том, что рекурсивная функция здесь также не будет встроенной.

...