Сколько существует уровней оптимизации 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на.optfile) - это недокументированный псевдоним для-O, который может быть использован в качестве--optimize=3!где используется OPT_O
теперь мы рассмотрим более подробно:
git grep -E '\bOPT_O\b', который указывает нам на два файла:
давайте сначала отследим
opts.copts.c: default_options_optimization
все
opts.cобычаи происходят внутри:default_options_optimization.мы grep backtrack, чтобы увидеть, кто вызывает эту функцию, и мы видим, что единственный путь кода:
main.c:maintoplev.c:toplev::mainopts-global.c:decode_optsopts.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, но в какой-то момент Вы будете переполнять предел размера переменной.