Ile jest poziomów optymalizacji GCC?
Ile jest poziomów optymalizacji GCC ?
Próbowałem gcc-O1, gcc-O2, gcc-O3 i gcc-O4Jeśli użyję naprawdę dużej liczby, to nie zadziała.
Jednak próbowałem
gcc -O100
I skompilował się.
Ile jest poziomów optymalizacji?
4 answers
Aby być pedantycznym, istnieje 8 różnych opcji valid-O, które możesz dać gcc, chociaż są pewne, które znaczą to samo.
W oryginalnej wersji tej odpowiedzi stwierdzono, że było 7 opcji. GCC dodał -Og
, aby doprowadzić całość do 8
-
-O
(to samo co-O1
) -
-O0
(nie Optymalizuj, domyślnie, jeśli nie określono poziomu optymalizacji) -
-O1
(optimize minimalnie) -
-O2
(optimize more) -
-O3
(optimize even more) -
-Ofast
(optymalizacja bardzo agresywnie do punktu złamania zgodności standardowej) -
-Og
(Optimize debugging experience. -Og umożliwia optymalizacje, które nie zakłócają debugowania. Powinno być wybór optymalizacji dla standardowego cyklu edycji-kompilacji-debugowania, oferujący rozsądny poziom optymalizacji przy zachowaniu szybkiej kompilacji i dobrego debugowanie.) -
-Os
(optymalizacja pod kątem rozmiaru.-Os
włącza wszystkie optymalizacje-O2
, które zazwyczaj nie zwiększają rozmiaru kodu. Wykonuje również dalsze optymalizacje zaprojektowany w celu zmniejszenia rozmiaru kodu.-Os
wyłącza następujące flagi optymalizacji:-falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -freorder-blocks-and-partition -fprefetch-loop-arrays -ftree-vect-loop-version
)
Mogą być również optymalizacje specyficzne dla platformy, jak zauważa @pauldoo, OS X ma -Oz
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-03 12:00:54
Siedem różnych poziomów:
-O0
(domyślnie): brak optymalizacji.-O
lub-O1
(to samo): optymalizować, ale nie spędzać zbyt wiele czasu.-
-O2
: Optymalizuj bardziej agresywnie -
-O3
: Optymalizacja najbardziej agresywnie -Ofast
: odpowiednik-O3 -ffast-math
.-ffast-math
uruchamia niestandardowe optymalizacje zmiennoprzecinkowe. Pozwala to kompilatorowi udawać, że liczby zmiennoprzecinkowe są nieskończenie precyzyjne, a algebra na nich spełnia standardowe reguły algebry liczb rzeczywistych. Dodatkowo kompilator każe sprzętowi spłukiwać denormale do zera i traktować denormale jako zero, przynajmniej na niektórych procesorach, w tym x86 i x86-64. Denormale wyzwalają powolną ścieżkę na wielu FPU, więc traktowanie ich jako zera (co nie powoduje powolnej ścieżki) może być dużą wygraną wydajności.-Os
: optymalizacja pod kątem rozmiaru kodu. Może to rzeczywiście poprawić prędkość w niektórych przypadki, ze względu na lepsze zachowanie I-cache.-Og
: Optymalizuj, ale nie przeszkadzaj w debugowaniu. Pozwala to na bezawaryjną wydajność debugowania kompilacji i ma zastąpić-O0
dla debugowania kompilacji.
Istnieją również inne opcje, które nie są włączone przez żadną z nich i muszą być włączone oddzielnie. Możliwe jest również użycie opcji optymalizacji, ale wyłączenie określonych FLAG włączonych przez tę optymalizację.
Aby uzyskać więcej informacji, zobacz stronę GCC.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-27 09:24:27
Zinterpretujmy kod źródłowy GCC 5.1, aby zobaczyć, co się stanie na -O100
, ponieważ nie jest to jasne na stronie podręcznika.
Wnioskujemy, że:
- wszystko powyżej
-O3
doINT_MAX
jest tym samym co-O3
, Ale To może się łatwo zmienić w przyszłości, więc nie polegaj na tym. - GCC 5.1 uruchamia nieokreślone zachowanie, jeśli wpiszesz liczby całkowite większe niż
INT_MAX
. - argument może mieć tylko cyfry, w przeciwnym razie nie powiedzie się. W szczególności, to wyklucza ujemne liczby całkowite, takie jak
-O-1
Skup się na podprogramach
Najpierw pamiętaj, że GCC to tylko front-end dla cpp
, as
, cc1
, collect2
. Szybki ./XXX --help
mówi, że tylko collect2
i cc1
biorą -O
, więc skupmy się na nich.
I:
gcc -v -O100 main.c |& grep 100
Daje:
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.
Więc -O
został przekazany zarówno cc1
, jak i collect2
.
O wspólne.opt
Pospolite.opt jest GCC format opisu opcji CLI opisany w wewnętrznej dokumentacji i przetłumaczony na język C przez opth-gen. awki optc-gen. awk.
Zawiera następujące interesujące wiersze:
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
Które określają wszystkie opcje {[33] }. Zauważ, że -O<n>
jest w oddzielnej rodzinie od innych Os
, Ofast
i Og
.
Kiedy budujemy, generujemy options.h
plik zawierający:
OPT_O = 139, /* -O */
OPT_Ofast = 140, /* -Ofast */
OPT_Og = 141, /* -Og */
OPT_Os = 142, /* -Os */
Jako bonus, podczas gdy my jesteśmy grepping dla \bO\n
Wewnątrz common.opt
zauważamy linie:
-optimize
Common Alias(O)
Co uczy nas, że --optimize
(podwójne myślenie, ponieważ zaczyna się od myślnika -optimize
na pliku .opt
) jest nieudokumentowanym aliasem dla -O
, który może być użyty jako --optimize=3
!
Gdzie używa się OPT_O
Teraz grep:
git grep -E '\bOPT_O\b'
Co wskazuje na dwa pliki:
Let ' s first track dół opts.c
Opts.c: default_options_optimization
Wszystkie opts.c
zastosowania dzieją się wewnątrz: default_options_optimization
.
Grep backtrack, aby zobaczyć, kto wywołuje tę funkcję, i widzimy, że jedyną ścieżką kodu jest:
main.c:main
toplev.c:toplev::main
opts-global.c:decode_opts
opts.c:default_options_optimization
I main.c
jest punktem wejścia cc1
. Dobrze!
Pierwsza część tej funkcji:
- does
integral_argument
which callsatoi
na łańcuchu odpowiadającymOPT_O
do analizy argumentu wejściowego - przechowuje wartość wewnątrz
opts->x_optimize
gdzieopts
jeststruct gcc_opts
.
Struct gcc_opts
Po wygrawerowaniu na próżno zauważamy, że to struct
jest również generowane w options.h
:
struct gcc_options {
int x_optimize;
[...]
}
Gdzie x_optimize
pochodzi z linii:
Variable
int optimize
Obecny w common.opt
, a ten options.c
:
struct gcc_options global_options;
Więc domyślamy się, że to jest to, co zawiera całą konfigurację stan globalny, a int x_optimize
jest wartością optymalizacji.
255 jest wewnętrznym maksimum
W opts.c:integral_argument
, atoi
jest stosowany do argumentu wejściowego, więc INT_MAX
jest górną granicą. A jeśli umieścisz coś większego, to wygląda na to, że GCC uruchamia C undefined behavior. AUĆ?
integral_argument
również cienko zawija atoi
i odrzuca argument, jeśli jakikolwiek znak nie jest cyfrą. Więc wartości ujemne zawodzą z wdziękiem.
Powrót do opts.c:default_options_optimization
, widzimy linia:
if ((unsigned int) opts->x_optimize > 255)
opts->x_optimize = 255;
, aby poziom optymalizacji został skrócony do 255
. Podczas czytania opth-gen.awk
natknąłem się na:
# All of the optimization switches gathered together so they can be saved and restored.
# This will allow attribute((cold)) to turn on space optimization.
I na wygenerowanym options.h
:
struct GTY(()) cl_optimization
{
unsigned char x_optimize;
Co wyjaśnia, dlaczego okrojenie: opcje muszą być również przekazane do cl_optimization
, który używa char
, aby zaoszczędzić miejsce. Więc 255 to wewnętrzne maksimum.
Opts.c: maybe_default_options
Wracając do opts.c:default_options_optimization
, natykamy się {[79] } co brzmi interesująco. My wpisujemy go, a następnie maybe_default_option
gdzie dochodzimy do dużego przełącznika:
switch (default_opt->levels)
{
[...]
case OPT_LEVELS_1_PLUS:
enabled = (level >= 1);
break;
[...]
case OPT_LEVELS_3_PLUS:
enabled = (level >= 3);
break;
Nie ma >= 4
kontroli, która wskazuje, że 3
jest największa z możliwych.
Następnie szukamy definicji OPT_LEVELS_3_PLUS
w 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. */
};
Ha! Jest to silny wskaźnik, że istnieją tylko 3 poziomy.
Opts.c: default_options_table
opt_levels
jest tak interesujące, że grep OPT_LEVELS_3_PLUS
i natknąć się 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 },
[...]
}
Więc tutaj -On
do specyficznego mapowania optymalizacji wymienionego w dokumentach jest zakodowany. Nieźle!
Upewnij się, że nie ma więcej zastosowań dla x_optimize
Głównym zastosowaniem x_optimize
było ustawienie innych specyficznych opcji optymalizacji, takich jak -fdefer_pop
, zgodnie z dokumentacją na stronie podręcznika. Jest ich więcej?
My grep
, i znaleźć kilka więcej. Liczba jest niewielka, a po ręcznej kontroli widzimy, że każde użycie robi co najwyżej x_optimize >= 3
, więc nasz wniosek trzyma.
Lto-owijarka.c
Teraz przejdziemy do drugiego wystąpienia OPT_O
, które było w lto-wrapper.c
.
LTO oznacza optymalizację czasu połączenia, która, jak sama nazwa wskazuje, będzie wymagać opcji -O
i będzie połączona z collec2
(która jest w zasadzie linkerem).
W rzeczywistości pierwsza linijka lto-wrapper.c
mówi:
/* Wrapper to call lto. Used by collect2 and the linker plugin.
W tym pliku zdarzenia OPT_O
wydają się normalizować tylko wartość O
, aby przekazać ją do przodu, więc powinniśmy być dobrze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-25 16:40:30
Cztery (0-3): patrz instrukcja GCC 4.4.2 . Wszystko wyższe to tylko-O3, ale w pewnym momencie przekroczysz limit zmiennej wielkości.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-22 12:17:48