GCC: Разница между -O3 и -Os
Я достаточно знаком с флагом компилятора GCC -O3, но хотел бы узнать, чем он отличается от флага -Os. В каких ситуациях следует предпочесть один флаг другому?
3 ответ(ов)
Это зависит. Вам нужно оптимизировать скорость или размер?
-O3
Оптимизация еще больше. Ключ -O3
включает все оптимизации, указанные в -O2
, и также активирует флаги -finline-functions
, -funswitch-loops
, -fpredictive-commoning
, -fgcse-after-reload
, -ftree-loop-vectorize
, -ftree-slp-vectorize
, -fvect-cost-model
, -ftree-partial-pre
и -fipa-cp-clone
.
-O0
Снижает время компиляции и гарантирует, что отладка будет давать ожидаемые результаты. Это значение по умолчанию.
-Os
Оптимизация на размер. -Os
включает все оптимизации -O2
, которые обычно не увеличивают размер кода. Кроме того, выполняет дополнительные оптимизации, предназначенные для уменьшения размера кода.
Флаг -Os
отключает следующие оптимизации:
-falign-functions
, -falign-jumps
, -falign-loops
, -falign-labels
, -freorder-blocks
, -freorder-blocks-and-partition
, -fprefetch-loop-arrays
.
На самом деле, -O является сокращением для длинного списка независимых оптимизаций. Если вы не уверены, что вам нужно, просто используйте -O3.
Больше информации можно найти в документации GCC.
Флаг -O3 оптимизирует код для быстродействия, в то время как -Os оптимизирует его для экономии места. Это означает, что -O3 создаст быстрое исполняемое приложение, но его размер может быть довольно большим, тогда как -Os даст вам более компактное приложение, но с возможной потерей скорости.
Эффективность по пространству и времени обычно представляет собой компромисс. Быстрые алгоритмы, как правило, используют больше памяти, тогда как алгоритмы, работающие на месте (то есть не увеличивающие использование памяти), часто менее эффективны.
В большинстве случаев современные компьютеры располагают достаточным объемом оперативной памяти, поэтому флаг -O3 чаще всего предпочтительнее. Однако, если вы программируете для устройств с ограниченной оперативной памятью (например, для маломощных устройств), то вам может быть предпочтительнее использовать -Os.
На этот вопрос сложно дать однозначный ответ. Простое правило заключается в том, что следует оптимизировать код на критических участках для скорости, а на некритических, таких как загрузка, — для размера.
Некоторые компиляторы могут работать в два прохода, чтобы провести такую оптимизацию за вас. В первом проходе создается специальный исполняемый файл с поддержкой профилирования, после чего вы запускаете приложение для сбора данных. Во втором проходе компилятор может принять решение, основываясь на собранной информации, о том, что будет наилучшим. Это позволяет осуществить такие оптимизации, как девиртуализация, предсказание ветвлений и т.д.
В чём разница между g++ и gcc?
Как вывести список символов из .so файла?
Отладка против Релиза в CMake
Неопределенная ссылка на виртуальную таблицу (vtable)
`unsigned int` против `size_t`: когда и что использовать?