Как мне убедиться, что lrint встроен в gcc?

12

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

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

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

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

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

  • 1
    Вы действительно профилировали и подтвердили, что использование очевидного приведения занимает значительное количество времени выполнения вашей программы?
  • 2
    Профилирование показывает, что я могу получить разницу в скорости 2-4%, используя рукописный макрос на ассемблере, взятый из статьи. Это имеет смысл, поскольку вычисления выполняются между кадрами приложения трехмерного рендеринга.
Показать ещё 2 комментария
Теги:
gcc
c99

2 ответа

10
Лучший ответ

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

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

0

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

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

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

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

  • 0
    Я пробовал -finline-functions, и это не имело никакого значения для вывода компилятора.
  • 0
    если вы используете в своем коде lrint () из математической библиотеки и компилируете ее с помощью gcc, то lrint () не будет встроенным, поскольку в вашем случае он будет получен из бинарно-связанной библиотеки. код lrint () здесь не собирается
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню