Сколько существует уровней оптимизации GCC?
сколько GCC уровни оптимизации существуют?
я попробовал на GCC -О1, ССЗ -О2, НКУ -О3, и gcc -О4
Если я использую действительно большое число, это не будет работать.
однако, я пробовал
gcc -O100
и он компилируется.
сколько существует уровней оптимизации?
4 ответа:
чтобы быть педантичным, есть 8 различных допустимых вариантов-O, которые вы можете дать gcc, хотя есть некоторые, которые означают одно и то же.
в оригинальной версии этого ответа говорилось, что было 7 вариантов. GCC с тех пор добавил
-Og
чтобы довести общее число до 8
-O
(то же, что и-O1
)-O0
(не оптимизируйте, по умолчанию, если нет уровня оптимизации указано)-O1
(минимально оптимизировать)-O2
(больше оптимального)-O3
(оптимизировать еще больше)-Ofast
(оптимизация очень агрессивно до точки нарушения стандартного соответствия)-Og
(оптимизировать процесс отладки. - Og включает оптимизации, которые не мешают отладке. Это должно быть уровень оптимизации выбора для стандартного цикла редактирования-компиляции-отладки, предлагая разумный уровень оптимизации при сохранении быстрой компиляции и хорошего опыта отладки.)-Os
(оптимизации по размеру.-Os
позволяет всем-O2
оптимизации, которые обычно не увеличивают размер кода. Он также выполняет дальнейшие оптимизации предназначен для уменьшения размера кода.-Os
отключает следующие флаги оптимизации:-falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -freorder-blocks-and-partition -fprefetch-loop-arrays -ftree-vect-loop-version
)также могут быть оптимизации для конкретной платформы, как отмечает @pauldoo, OS X имеет
-Oz
семь отдельных уровней:
-O0
(по умолчанию): нет оптимизация.
-O
или-O1
(то же самое): оптимизируйте, но не тратьте слишком много времени.
-O2
: оптимизация более агрессивно
-O3
: оптимизация наиболее агрессивно
-Ofast
: эквивалентно-O3 -ffast-math
.-ffast-math
триггеры не соответствуют стандартам с плавающей точкой процессы оптимизации. Это позволяет компилятору делать вид, что числа с плавающей запятой бесконечно точны, и что алгебра на них следует стандартным правилам алгебры действительных чисел. Это также говорит компилятору сказать оборудование для промывки denormals к нулю и лечить denormals как ноль, по крайней мере на некоторых процессоров, включая x86 и x86-64. Денормалы запускают медленный путь на многих FPU, и поэтому их обработка как ноль (который не запускает медленный путь) может быть большой выигрыш в производительности.
-Os
: оптимизация для размера кода. Это может фактически улучшить скорость в некоторых случаях, из-за лучшего поведения I-кэша.
-Og
: оптимизируйте, но не мешайте отладке. Это позволяет не стеснять производительность для отладочных сборок и предназначено для замены-O0
для отладки строит.есть также другие параметры, которые не включены ни одним из них, и должны быть включены отдельно. Оно также можно использовать опцию оптимизации, но отключить определенные флаги, включенные этой оптимизацией.
дополнительную информацию см. На веб-сайте GCC.
давайте интерпретируйте исходный код GCC 5.1 чтобы увидеть, что происходит на
-O100
так как это не ясно на странице man.мы сделаем вывод, что:
- все, что выше
-O3
доINT_MAX
это то же самое, что-O3
, но это может легко измениться в будущем, так что не полагаться на него.- GCC 5.1 выполняет неопределенное поведение, если вы вводите целые числа больше, чем
INT_MAX
.- аргумент может быть только есть цифры, или это не корректно. В частности, это исключает отрицательные целые числа, такие как
-O-1
сосредоточьтесь на подпрограммах
сначала помните, что GCC-это просто интерфейс для
cpp
,as
,cc1
,collect2
. Быстро./XXX --help
говорит, что толькоcollect2
иcc1
взять-O
, так что давайте сосредоточимся на них.и:
gcc -v -O100 main.c |& grep 100
выдает:
COLLECT_GCC_OPTIONS='-O100' '-v' '-mtune=generic' '-march=x86-64' /usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1 [[noise]] hello_world.c -O100 -o /tmp/ccetECB5.
так
-O
был направлены какcc1
иcollect2
.O в общем.опт
общие.опт - это формат описания конкретного параметра CLI GCC, описанный в внутренняя документация и переводится на C с помощью opth-gen. awk и optc-gen. awk.
содержит следующие интересные строки:
O Common JoinedOrMissing Optimization -O<number> Set optimization level to <number> Os Common Optimization Optimize for space rather than speed Ofast Common Optimization Optimize for speed disregarding exact standards compliance Og Common Optimization Optimize for debugging experience rather than speed or size
которые указывают все
O
параметры. Отмечать как-O<n>
находится в отдельной семье от другихOs
,Ofast
иOg
.когда мы строим, это создает
options.h
файл, который содержит:OPT_O = 139, /* -O */ OPT_Ofast = 140, /* -Ofast */ OPT_Og = 141, /* -Og */ OPT_Os = 142, /* -Os */
в качестве бонуса, в то время как мы находимся на применение grep к
\bO\n
внутриcommon.opt
мы видим строки:-optimize Common Alias(O)
, который учит нас, что
--optimize
(двойной тире, потому что он начинается с тире-optimize
на.opt
file) - это недокументированный псевдоним для-O
, который может быть использован в качестве--optimize=3
!где используется OPT_O
теперь мы рассмотрим более подробно:
git grep -E '\bOPT_O\b'
, который указывает нам на два файла:
давайте сначала отследим
opts.c
opts.c: default_options_optimization
все
opts.c
обычаи происходят внутри:default_options_optimization
.мы grep backtrack, чтобы увидеть, кто вызывает эту функцию, и мы видим, что единственный путь кода:
main.c:main
toplev.c:toplev::main
opts-global.c:decode_opts
opts.c:default_options_optimization
и
main.c
является точкой входаcc1
. Хорошо!первая часть этой функции:
- тут
integral_argument
которых звонкиatoi
в строке, соответствующейOPT_O
для разбора входного аргумента- сохраняет значение внутри
opts->x_optimize
здесьopts
этоstruct gcc_opts
.struct gcc_opts
после применение grep к зря, мы замечаем, что этот
struct
также генерируется вoptions.h
:struct gcc_options { int x_optimize; [...] }
здесь
x_optimize
исходит из строк:Variable int optimize
в настоящее время
common.opt
иoptions.c
:struct gcc_options global_options;
Итак, мы предполагаем, что это что содержит всю конфигурацию глобального состояния, и
int x_optimize
значение оптимизации.255-это внутренний максимум
in
opts.c:integral_argument
,atoi
применяется к входному аргументу, поэтомуINT_MAX
- это верхняя граница. И если вы положите что-нибудь большее, кажется, что GCC запускает c неопределенным поведением. Ай?
integral_argument
также тонко обертыванияatoi
и отвергает аргумент, если какой-либо символ не является цифрой. Поэтому отрицательные значения не изящно.на
opts.c:default_options_optimization
мы видим строку:if ((unsigned int) opts->x_optimize > 255) opts->x_optimize = 255;
так что уровень оптимизации усекается до
255
. Во время чтенияopth-gen.awk
я сталкивался:# All of the optimization switches gathered together so they can be saved and restored. # This will allow attribute((cold)) to turn on space optimization.
и на созданном
options.h
:struct GTY(()) cl_optimization { unsigned char x_optimize;
что объясняет, почему усечение: параметры также должны быть перенаправлены в
cl_optimization
, который используетchar
для экономии места. Так что 255-это внутренний максимум на самом деле.opts.c: maybe_default_options
на
opts.c:default_options_optimization
, мы встречаемmaybe_default_options
звучит интересно. Мы входим в него, а потомmaybe_default_option
где мы достигаем большой переключатель:switch (default_opt->levels) { [...] case OPT_LEVELS_1_PLUS: enabled = (level >= 1); break; [...] case OPT_LEVELS_3_PLUS: enabled = (level >= 3); break;
нет
>= 4
проверяет, что указывает на то, что3
является максимально возможным.тогда мы ищем определение
OPT_LEVELS_3_PLUS
наcommon-target.h
:enum opt_levels { OPT_LEVELS_NONE, /* No levels (mark end of array). */ OPT_LEVELS_ALL, /* All levels (used by targets to disable options enabled in target-independent code). */ OPT_LEVELS_0_ONLY, /* -O0 only. */ OPT_LEVELS_1_PLUS, /* -O1 and above, including -Os and -Og. */ OPT_LEVELS_1_PLUS_SPEED_ONLY, /* -O1 and above, but not -Os or -Og. */ OPT_LEVELS_1_PLUS_NOT_DEBUG, /* -O1 and above, but not -Og. */ OPT_LEVELS_2_PLUS, /* -O2 and above, including -Os. */ OPT_LEVELS_2_PLUS_SPEED_ONLY, /* -O2 and above, but not -Os or -Og. */ OPT_LEVELS_3_PLUS, /* -O3 and above. */ OPT_LEVELS_3_PLUS_AND_SIZE, /* -O3 and above and -Os. */ OPT_LEVELS_SIZE, /* -Os only. */ OPT_LEVELS_FAST /* -Ofast only. */ };
ха! Это сильный показатель что есть только 3 уровня.
opts.c: default_options_table
opt_levels
так интересно, что мы грэпOPT_LEVELS_3_PLUS
, иopts.c:default_options_table
:static const struct default_options default_options_table[] = { /* -O1 optimizations. */ { OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 }, [...] /* -O3 optimizations. */ { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 }, [...] }
вот здесь
-On
к конкретному отображению оптимизации, упомянутому в документах, кодируется. Мило!убедитесь, что больше нет использования для x_optimize
основное использование
x_optimize
должен был установить другие конкретные параметры оптимизации, такие как-fdefer_pop
как указано на справочной странице. Есть еще что-нибудь?мы
grep
, и найти еще несколько. Их количество невелико, и при ручном осмотре мы видим, что каждое использование не только вx_optimize >= 3
, так что наш вывод имеет.lto-обертка.c
теперь мы идем на второе появление
OPT_O
, который находился вlto-wrapper.c
.LTO значит оптимизирование времени соединения, которое как имя предполагает, что понадобится
-O
вариант, и будет связан сcollec2
(который в основном является компоновщиком).в самом деле, первая строка
lto-wrapper.c
говорит:/* Wrapper to call lto. Used by collect2 and the linker plugin.
в этом файле
OPT_O
вхождения, кажется, только нормализуют значениеO
пропустить его вперед, так что мы должны быть в порядке.
четыре (0-3): см. GCC 4.4.2 руководство. Все, что выше-это просто-O3, но в какой-то момент Вы будете переполнять предел размера переменной.