ระดับการเพิ่มประสิทธิภาพGCCมีกี่ระดับ?
ฉันลอง gcc -O1, gcc -O2, gcc -O3 และ gcc -O4
ถ้าฉันใช้จำนวนมากมันจะไม่ได้ผล
อย่างไรก็ตามฉันได้พยายามแล้ว
gcc -O100
และรวบรวม
ระดับการเพิ่มประสิทธิภาพมีกี่ระดับ?
ระดับการเพิ่มประสิทธิภาพGCCมีกี่ระดับ?
ฉันลอง gcc -O1, gcc -O2, gcc -O3 และ gcc -O4
ถ้าฉันใช้จำนวนมากมันจะไม่ได้ผล
อย่างไรก็ตามฉันได้พยายามแล้ว
gcc -O100
และรวบรวม
ระดับการเพิ่มประสิทธิภาพมีกี่ระดับ?
3
ก็เหมือนกับ3
(ตราบใดที่มันไม่int
ล้น) ดูคำตอบของฉัน
-fomit-stack-pointer
จะเปลี่ยนรหัสที่สร้างขึ้น
คำตอบ:
เพื่อความอวดดีมีตัวเลือก -O ที่ถูกต้อง 8 แบบที่คุณสามารถมอบให้กับ 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
-Oz
ตั้งค่าเพิ่มเติมซึ่ง "ปรับขนาดให้เหมาะสมยิ่งขึ้นกว่าเดิม-Os
": developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/…
-Og
ซึ่งเป็นตัวเลือกการเพิ่มประสิทธิภาพทั้งหมดที่ไม่รบกวนการดีบัก
ลองตีความซอร์สโค้ดของ GCC 5.1
เราจะพยายามทำความเข้าใจว่าเกิดอะไรขึ้น-O100
เนื่องจากยังไม่ชัดเจนในหน้าคน
เราจะสรุปได้ว่า:
-O3
ขึ้นไปINT_MAX
ก็เหมือนกับ-O3
แต่สิ่งนั้นอาจเปลี่ยนแปลงได้ง่ายในอนาคตดังนั้นอย่าพึ่งพามันINT_MAX
.-O-1
มุ่งเน้นไปที่โปรแกรมย่อย
ครั้งแรกจำได้ว่า GCC เป็นเพียง front-end สำหรับ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เป็นรูปแบบคำอธิบาย GCC ที่เฉพาะเจาะจงตัวเลือก CLI อธิบายไว้ในเอกสาร internalsและแปลไปที่ 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 */
เป็นโบนัสในขณะที่เรากำลังโลภ\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
.
เรา 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
a struct gcc_opts
.โครงสร้าง gcc_opts
หลังจาก grepping ในไร้สาระเราสังเกตเห็นว่าเรื่องนี้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: might_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 อีกต่อไป
การใช้งานหลักx_optimize
คือการตั้งค่าตัวเลือกการเพิ่มประสิทธิภาพเฉพาะอื่น ๆ เช่น-fdefer_pop
ตามที่ระบุไว้ใน man page มีอีกมั้ย?
เราgrep
และพบอีกสองสามอย่าง จำนวนน้อยและจากการตรวจสอบด้วยตนเองเราจะเห็นว่าทุกการใช้งานทำเพียง a มากที่สุดx_optimize >= 3
เท่านั้นดังนั้นข้อสรุปของเราจึงมี
lto-wrapper.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
การส่งต่อไปข้างหน้าเป็นปกติดังนั้นเราควรจะสบายดี
เจ็ดระดับที่แตกต่างกัน:
-O0
(ค่าเริ่มต้น): ไม่มีการปรับให้เหมาะสม
-O
หรือ-O1
(สิ่งเดียวกัน): เพิ่มประสิทธิภาพ แต่อย่าใช้เวลามากเกินไป
-O2
: เพิ่มประสิทธิภาพในเชิงรุกมากขึ้น
-O3
: ปรับให้เหมาะสมที่สุด
-Ofast
: เทียบเท่ากับ-O3 -ffast-math
. -ffast-math
ทริกเกอร์การเพิ่มประสิทธิภาพจุดลอยตัวที่ไม่เป็นไปตามมาตรฐาน สิ่งนี้ช่วยให้คอมไพเลอร์สามารถแสร้งทำเป็นว่าตัวเลขทศนิยมนั้นมีความแม่นยำไม่สิ้นสุดและพีชคณิตนั้นเป็นไปตามกฎมาตรฐานของพีชคณิตจำนวนจริง นอกจากนี้ยังบอกคอมไพเลอร์ให้บอกฮาร์ดแวร์ให้ล้าง denormals เป็นศูนย์และถือว่า denormals เป็นศูนย์อย่างน้อยในโปรเซสเซอร์บางตัวเช่น x86 และ x86-64 Denormals ทำให้เกิดเส้นทางที่ช้าใน FPU จำนวนมากดังนั้นการปฏิบัติต่อพวกเขาเป็นศูนย์ (ซึ่งไม่ทำให้เกิดเส้นทางที่ช้า) อาจเป็นชัยชนะที่ยิ่งใหญ่
-Os
: ปรับขนาดโค้ดให้เหมาะสม สิ่งนี้สามารถปรับปรุงความเร็วได้จริงในบางกรณีเนื่องจากพฤติกรรมของ I-cache ดีขึ้น
-Og
: เพิ่มประสิทธิภาพ แต่ไม่รบกวนการดีบัก สิ่งนี้เปิดใช้งานประสิทธิภาพที่ไม่น่าอายสำหรับบิวด์ดีบักและมีจุดมุ่งหมายเพื่อแทนที่-O0
สำหรับการดีบักบิวด์
นอกจากนี้ยังมีตัวเลือกอื่น ๆ ที่ไม่ได้เปิดใช้งานโดยตัวเลือกเหล่านี้และต้องเปิดใช้งานแยกกัน นอกจากนี้ยังสามารถใช้ตัวเลือกการเพิ่มประสิทธิภาพ แต่ปิดใช้งานแฟล็กเฉพาะที่เปิดใช้งานโดยการเพิ่มประสิทธิภาพนี้
สำหรับข้อมูลเพิ่มเติมโปรดดูเว็บไซต์ GCC
-O100
คอมไพล์ล่ะ?
atoi
พฤติกรรมที่ไม่ได้กำหนดมากขึ้นตามด้วย255
ขีด จำกัด ภายใน
man gcc
Cygwin (12000 เส้นคี่) คุณสามารถค้นหา-O
และค้นหาทุกคำตอบด้านล่างได้