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


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

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

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

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

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

2 12

2 ответа:

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

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

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

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

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

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