GCC: разница между -O3 и -Os
Я хорошо знаком с флагом GCC-O3, но как он отличается от -O, в какой ситуации мы должны предпочитать одну над другой?
Ответы
Ответ 1
Документация GCC описывает, что эти параметры делают явно.
-O3 пытается оптимизировать код очень сильно для производительности. Он включает в себя все оптимизации -O2, а также еще несколько.
-Os, с другой стороны, инструктирует GCC "оптимизировать размер". Он включает все оптимизации -O2, которые не увеличивают размер исполняемого файла, а затем он также переключает некоторые флаги оптимизации для дальнейшего уменьшения размера исполняемого файла.
Обратите внимание, что я был преднамеренно немного расплывчатым в своих описаниях - прочитайте документацию GCC для более подробного обсуждения того, какие флаги включены для любого уровня оптимизации.
Я считаю, что уровни оптимизации -O * - это просто взаимоисключающие, различные уровни оптимизации. На самом деле нет смысла смешивать их, поскольку два уровня будут включать или исключать флаги, которые другой намеренно упускает или разрешает (соответственно). Если вы хотите смешивать и сопоставлять (вы, вероятно, на самом деле не хотите этого делать, если у вас нет по-настоящему веских причин для получения определенного набора флагов), вам лучше всего читать документацию и смешивать и сопоставлять флаги на каждом уровне позволяет вручную.
Я думаю, что я также свяжу эту статью с Gentoo Linux Wiki, в которой говорится о флажках оптимизации, поскольку они связаны с созданием пакетов для операционной системы. Очевидно, что не все это применимо, но оно все еще содержит некоторую интересную информацию - для одного:
Компиляция с -O3 не является гарантированным способом повышения производительности, и на самом деле во многих случаях может замедлить работу системы из-за больших двоичных файлов и увеличения использования памяти. -O3 также, как известно, разбивает несколько пакетов. Поэтому использование -O3 не рекомендуется.
В соответствии с этой статьей, -O2, в большинстве случаев, "так же хорошо, как" -O3 ", и более безопасно использовать, в отношении сломанного исполняемого вывода.
Ответ 2
Я предлагаю прочитать документацию GCC. -O3 предназначен для быстрого выполнения кода (даже за счет раздувания кода), тогда как -Os
оптимизирует размер сгенерированный код.
Есть много других (неясных) GCC флаги оптимизации (например, -fgcse-sm
), многие из которых не включены даже в -O3
.
Возможно, вас также может заинтересовать -flto (для оптимизации времени привязки), который будет использоваться, кроме того, например, -O3
или -Os
, как во время компиляции, так и во время соединения. Затем см. Также этот ответ.
Наконец, позаботьтесь о том, чтобы использовать последнюю версию GCC (в настоящее время 4,8 на конец 2013 года), потому что GCC значительно улучшает свои оптимизации.
Возможно, вы захотите также использовать - mtune = native (по крайней мере для x86).
И вы даже можете написать свой собственный пароль для оптимизации, специфичный для ваших собственных библиотек и API, возможно, используя MELT плагин.
Как CmdrMoozy ответил, вы можете использовать -O2
над -O3
(но обратите внимание, что последние версии GCC значительно улучшили их -O3
, поэтому Gentoo цитата -рекомендация против -O3
и в пользу -O2
становится менее актуальной.).
Кроме того, поскольку это SlashDot-ed Стек-бумага (Си Ван, Николай Зельдович, М. Франс Каашоек и Армандо Солнечно-Лезама ) показывает, что многие программы не полностью совместимы с C и не довольны (и ведут себя некорректно), когда выполняются некоторые правильные оптимизации. Undefined поведение - сложный вопрос.
BTW, обратите внимание, что использование -O3
обычно делает ваше время компиляции намного больше и приносит часто (но не всегда) максимум на несколько процентов большую производительность, чем -O2
или даже -O1
.... (это еще хуже с -flto
). Вот почему я редко его использую.
Ответ 3
Это зависит. Вам нужно оптимизировать скорость или размер?
-O3
Оптимизируйте еще больше. -O3 включает все оптимизации, заданные -O2, а также включает функции -finline-functions, -funswitch-loops, -fpredictive-commoning, -fgcse-after-reload, -ftree-loop-vectorize, -ftree-slp-vectorize, -fvect-cost-model, -free-partial-pre и -fipa-cp-clone.
-O0
Сократите время компиляции и сделайте отладку ожидаемыми результатами. Это значение по умолчанию.
-Os
Оптимизируйте размер. -O разрешает все оптимизации -O2, которые обычно не увеличивают размер кода. Он также выполняет дальнейшую оптимизацию для уменьшения размера кода.
-Os Отключает следующие флаги оптимизации:
-falign-functions
-falign-jumps
-falign-loops
-falign-labels
-freorder-blocks
-freorder-blocks-and-partition
-fprefetch-loop-arrays
http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
Собственно, -O является сокращением длинного списка независимых оптимизаций. Если вы не знаете, что вам нужно, просто выберите -O3.
Ответ 4
-O3 оптимизируется для скорости, тогда как -O оптимизируется для пространства. Это означает, что -O3 даст вам быстрый исполняемый файл, но он может быть довольно большим, а -O дает вам меньший исполняемый файл, но он может быть медленнее.
Эффективность пространства и времени обычно является компромиссом. Более быстрые алгоритмы имеют тенденцию занимать больше места, где локальные алгоритмы (алгоритмы, которые не увеличивают использование пространства) имеют тенденцию быть менее эффективными.
Обычно современные компьютеры имеют много места в памяти, поэтому -O3 обычно предпочтительнее. Однако, если вы программируете что-то с низким уровнем ram (как небольшое устройство), вы можете предпочесть -O
Ответ 5
На самом деле невозможно ответить, простые правила состоят в том, чтобы использовать оптимизацию для скорости на критическом пути кода и оптимизировать размер для некритического кода, например, загрузки,...
Некоторые компиляторы могут работать в два прохода, чтобы решить это для вас, сначала создайте специальный исполняемый файл с поддержкой профилирования, запустите приложение для сбора данных, а вторая компиляция сможет решить на основе данных того, что Лучший. Он позволяет де виртуализировать, предсказать ветвь,...