얼마나 많은 GCC 최적화 수준이 있습니까?
gcc -O1, gcc -O2, gcc -O3 및 gcc -O4를 시도했습니다.
정말 많은 수를 사용하면 작동하지 않습니다.
그러나 나는 시도했다
gcc -O100
그리고 그것은 컴파일되었습니다.
얼마나 많은 최적화 수준이 있습니까?
답변
현명하게 말하자면, gcc에 줄 수있는 유효한 -O 옵션이 8 가지 있지만 같은 의미를 갖는 옵션도 있습니다.
이 답변의 원래 버전에는 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
답변
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 common.opt
common.opt 는 내부 문서에 설명되어 있으며 opth-gen.awk 및 optc-gen.awk에 의해 C로 번역 된 GCC 특정 CLI 옵션 설명 형식 입니다.
다음과 같은 흥미로운 라인이 포함되어 있습니다.
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 */
보너스로, 우리가 \bO\n
내부를 탐색하는 동안 우리는 common.opt
다음과 같은 라인을 발견했습니다.
-optimize
Common Alias(O)
어떤 것을 우리에게 가르쳐 --optimize
(이중 대시가 대시로 시작하기 때문에 -optimize
온 .opt
파일)에 대한 문서화되지 않은 별칭 -O
으로 사용할 수 있습니다 --optimize=3
!
OPT_O가 사용되는 곳
이제 우리는 grep :
git grep -E '\bOPT_O\b'
두 개의 파일을 가리 킵니다.
먼저 추적 해보자 opts.c
opts.c : default_options_optimization
모든 opts.c
사용은 내부에서 발생합니다 : default_options_optimization
.
우리는이 함수를 호출하는 사람을 확인하기 위해 역 추적을했고, 유일한 코드 경로는 다음과 같습니다.
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
구조체 gcc_opts
헛되이 움켜 쥐고 나면 다음 위치 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는 내부 최대 값입니다.
에서 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
in 의 정의를 검색합니다 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
너무 흥미로워 서 우리는 grep 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를 더 이상 사용하지 않도록하십시오.
의 주요 용도 는 man 페이지에 설명 된 x_optimize
것과 같은 다른 특정 최적화 옵션을 설정 하는 것이 었습니다 -fdefer_pop
. 더 있나요?
우리 grep
는 몇 가지를 더 찾습니다. 그 수가 적고 수동 검사를 통해 모든 사용이 최대 a 만 수행하는 것을 알 수 x_optimize >= 3
있으므로 결론은 유효합니다.
lto-wrapper.c
이제 우리의 두 번째 발생에 대한 이동 OPT_O
에 있었다 lto-wrapper.c
.
LTO는 Link Time Optimization을 의미하며 이름에서 알 수 있듯이 -O
옵션 이 필요하며 collec2
기본적으로 링커에 연결됩니다 .
실제로 첫 번째 줄 lto-wrapper.c
은 다음 과 같이 말합니다.
/* Wrapper to call lto. Used by collect2 and the linker plugin.
이 파일에서 OPT_O
발생은 값을 정규화하여 O
전달하는 것처럼 보이므로 괜찮습니다.
답변
7 가지 수준 :
-
-O0
(기본값) : 최적화 없음. -
-O
또는-O1
(동일) : 최적화하되 너무 많은 시간을 소비하지 마십시오. -
-O2
:보다 적극적으로 최적화 -
-O3
: 가장 적극적으로 최적화 -
-Ofast
:-O3 -ffast-math
.-ffast-math
비표준 호환 부동 소수점 최적화를 트리거합니다. 이를 통해 컴파일러는 부동 소수점 숫자가 무한히 정확하고 그에 대한 대수가 실수 대수의 표준 규칙을 따르는 것처럼 가장 할 수 있습니다. 또한 적어도 x86 및 x86-64를 포함한 일부 프로세서에서 비정규를 0으로 플러시하고 비정규를 0으로 처리하도록 하드웨어에 지시하도록 컴파일러에 지시합니다. 비정규 화는 많은 FPU에서 느린 경로를 트리거하므로이를 0 (느린 경로를 트리거하지 않음)으로 처리하면 성능이 크게 향상 될 수 있습니다. -
-Os
: 코드 크기를 최적화합니다. 이것은 더 나은 I- 캐시 동작으로 인해 어떤 경우에는 실제로 속도를 향상시킬 수 있습니다. -
-Og
: 최적화하지만 디버깅을 방해하지 않습니다. 이것은 디버그 빌드에 대해 당황스럽지 않은 성능을 가능하게하며 디버그 빌드를 대체하기-O0
위한 것 입니다.
이들 중 어느 것도 활성화하지 않고 별도로 활성화해야하는 다른 옵션도 있습니다. 최적화 옵션을 사용할 수도 있지만이 최적화로 활성화 된 특정 플래그를 비활성화합니다.
자세한 내용은 GCC 웹 사이트를 참조하십시오.