Какие опции в GCC по умолчанию?
(1) По умолчанию в GCC используется уровень оптимизаций “-O0”. Он явно не оптимален с точки зрения производительности и не рекомендуется для компиляции конечного продукта.
GCC не распознает архитектуру, на которой запускается компиляция, пока не передана опция ”-march=native”. По умолчанию GCC использует опцию, заданную при его конфигурации. Чтобы узнать конфигурацию GCC, достаточно запустить:
gcc -v «Configured with: [PATH]/configure … —with-arch=corei7 —with-cpu=corei7…» |
Это означает что GCC добавит “-march=corei7” к вашим опциям (если не будет указана другая архитектура).
Большинство GCC компиляторов для x86 (базовый для 64 битного Linux) добавляет: “-mtune=generic -march=x86-64” к заданным опциям, так как при конфигурации не были заданы опции, определяющие архитектуру. Вы всегда можете узнать все опции, передаваемые при запуске GCC, а также его внутренние опции при помощи команды:
echo «int main {return 0;}» | gcc [OPTIONS] -x c -v -Q – |
В итоге, часто используемое:
gcc -O2 test.c |
построит “test.c” без каких-либо специфичных архитектурных оптимизаций. Это может привести к существенному спаду производительности (относительно архитектурно оптимизированного кода). Отключенная или ограниченная векторизация и неоптимальное планирование кода являются наиболее распространенными причинами спада производительности, если не указать или указать неправильную архитектуру.
Для указания текущей архитектуры надо компилировать так:
gcc -O2 test.c -march=native |
Указание используемой архитектуры важно для производительности. Единственным исключением можно считать те программы, где вызов библиотечных функций занимает почти все время запуска. GLIBC может выбрать оптимальную для данной архитектуры функцию во время исполнения. Важно отметить, что при статической линковке некоторые GLIBC функции не имеют версий под различные архитектуры. То есть динамическая сборка лучше, если важна быстрота GLIBC функций..
(2) По умолчанию большинство GCC компиляторов для x86 в 32 битном режиме используют x87 модель вычислений с плавающей точкой, так как были сконфигурированы без “-mfpmath=sse”. Только если GCC конфигурация содержит “—with-mfpmath=sse”:
gcc -v «Configured with: [PATH]/configure … —with-mfpmath=sse…» |
компилятор будет использовать SSE модель по умолчанию.Во всех остальных случаях лучше добавлять опцию “-mfpmath=sse” к сборке в 32 битном режиме.
Так, часто используемое:
gcc -O2 -m32 test.c |
может привести к существенным потерям производительности в коде с вещественной арифметикой. Потому правильный вариант:
gcc -O2 -m32 test.c -mfpmath=sse |
Добавление опции ”-mfpmath=sse” важно в 32 битном режиме! Исключением является компилятор, в конфигурации которого есть “—with-mfpmath=sse".
32 битный режим или 64 битный?
32 битный режим обычно используется для сокращения объема используемой памяти и как следствие ускорения работы с ней (больше данных помещается в кеш).
В 64 битном режиме (по сравнению с 32 битным) количество доступных регистров общего пользования увеличивается с 6 до 14, XMM регистров с 8 до 16. Также все 64 битные архитектуры поддерживают SSE2 расширение, поэтому в 64 битном режиме не надо добавлять опцию “-mfpmath=sse”.
Рекомендуется использовать 64 битный режим для счетных задач, а 32 битный режим для мобильных приложений.
Как получить максимальную производительность?
Определенного набора опций для получения максимальной проивзодительности не существует, однако в GCC есть много опций, которые стоит попробовать использовать. Ниже представлена таблица с рекомендуемыми опциями и прогнозами прироста для процессоров Intel® Atom™ и 2nd Generation Intel® Core™ i7 относительно опции “-O2”. Прогнозы основаны на среднем геометрическом результатов определенного набора задач, скомпилированных GCC версии 4.7. Также предполагается, что конфигурация компилятора была проведена для x86-64 generic.
Прогноз увеличения производительности на мобильных приложениях относительно “-O2” (только в 32 битном режиме, так как он основной для мобильного сегмента):
-m32 -mfpmath=sse | ~5% |
-m32 -mfpmath=sse -Ofast -flto | ~36% |
-m32 -mfpmath=sse -Ofast -flto -march=native | ~40% |
-m32 -mfpmath=sse -Ofast -flto -march=native -funroll-loops | ~43% |
Прогноз увеличения производительности на вычислительных задачах относительно “-O2” (в 32 битном режиме):
-m32 -mfpmath=sse | ~4% |
-m32 -mfpmath=sse -Ofast -flto | ~21% |
-m32 -mfpmath=sse -Ofast -flto -march=native | ~25% |
-m32 -mfpmath=sse -Ofast -flto -march=native -funroll-loops | ~24% |
Прогноз увеличения производительности на вычислительных задачах относительно “-O2” (в 64 битном режиме):
-m64 -Ofast -flto | ~17% |
-m64 -Ofast -flto -march=native | ~21% |
-m64 -Ofast -flto -march=native -funroll-loops | ~22% |
Преимущество 64 битного режима над 32 битным для вычислительных задач при опциях “-O2 -mfpmath=sse” составляет около ~5%
Все данные в статье являются прогнозом, основанном на результатах определенного набора бенчмарков.
Ниже представлено описание используемых в статье опций. Полное описание (на английском): http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Optimize-Options.html"
- "-Ofast" аналогично "-O3 -ffast-math" включает более высокий уровень оптимизаций и более агрессивные оптимизации для арифметических вычислений (например, вещественную реассоциацию)
- "-flto" межмодульные оптимизации
- "-m32" 32 битный режим
- "-mfpmath=sse" включает использование XMM регистров в вещественной арифметике (вместо вещественного стека в x87 режиме)
- "-funroll-loops" включает развертывание циклов
ссылка на оригинал статьи http://habrahabr.ru/company/intel/blog/158939/
Добавить комментарий