Kaç tane GCC optimizasyon seviyesi var?
Gcc -O1, gcc -O2, gcc -O3 ve gcc -O4'ü denedim
Gerçekten büyük bir sayı kullanırsam işe yaramaz.
Ancak denedim
gcc -O100
ve derlendi.
Kaç optimizasyon seviyesi var?
Kaç tane GCC optimizasyon seviyesi var?
Gcc -O1, gcc -O2, gcc -O3 ve gcc -O4'ü denedim
Gerçekten büyük bir sayı kullanırsam işe yaramaz.
Ancak denedim
gcc -O100
ve derlendi.
Kaç optimizasyon seviyesi var?
3
aynı olandan daha büyük herhangi bir şey (taşmadığı 3
sürece int
). Cevabımı gör .
-fomit-stack-pointer
üretilen kodu değiştirecek.
Yanıtlar:
Bilgiçlik taslamak gerekirse, gcc'ye verebileceğiniz 8 farklı geçerli -O seçeneği vardır, ancak aynı anlama gelenler de vardır.
Bu cevabın orijinal versiyonu 7 seçenek olduğunu belirtti. GCC o zamandan beri -Og
toplamı 8'e çıkarmak için ekledi
Gönderen adam sayfası:
-O
(Aynı -O1
)-O0
(optimizasyon yapma, optimizasyon seviyesi belirtilmemişse varsayılan)-O1
(minimum düzeyde optimize edin)-O2
(daha fazla optimize edin)-O3
(daha fazla optimize edin)-Ofast
(standart uyumluluğu bozma noktasına kadar çok agresif bir şekilde optimize edin)-Og
(Hata ayıklama deneyimini optimize edin. -Og, hata ayıklamayı engellemeyen optimizasyonları mümkün kılar. Hızlı derlemeyi ve iyi bir hata ayıklama deneyimini korurken makul bir optimizasyon düzeyi sunan, standart düzenleme-derleme-hata ayıklama döngüsü için tercih edilen optimizasyon seviyesi olmalıdır. )-Os
(. Boyut optimize -Os
tüm sağlayan -O2
.. Aynı zamanda kod boyutunu azaltmak için tasarlanmış ileri optimizasyonlar gerçekleştirir tipik kod boyutunu artırmaz optimizasyonlar
-Os
aşağıdaki optimizasyon bayrakları devre dışı bırakır: -falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -freorder-blocks-and-partition -fprefetch-loop-arrays -ftree-vect-loop-version
)@Pauldoo'nun belirttiği gibi, platforma özel optimizasyonlar da olabilir, OS X'in -Oz
-Oz
, "boyut için daha agresif bir şekilde optimize et" olan ek bir ayar vardır -Os
: developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/…
-Og
ayıklama karışmaz tüm optimizasyon seçenekleri olan
GCC 5.1'in kaynak kodunu yorumlayalım
-O100
Man sayfasında net olmadığı için neler olduğunu anlamaya çalışacağız .
Şu sonuca varacağız:
-O3
için yukarı INT_MAX
aynıdır -O3
, ama bu kolayca gelecekte değişebilir bu yüzden güvenmeyin.INT_MAX
.-O-1
Alt programlara odaklanın
İlk GCC için sadece bir ön uç olduğunu unutmayın cpp
, as
, cc1
, collect2
. Hızlı bir ./XXX --help
sadece bunu söyler collect2
ve cc1
alır -O
, o yüzden onlara odaklanalım.
Ve:
gcc -v -O100 main.c |& grep 100
verir:
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.
bu yüzden -O
her ikisine de iletildi cc1
ve collect2
.
O ortak. Opt
common.opt tarif edilen bir GCC belirli CLI seçenek açıklama biçimi iç donanım belgelerine göre C ve çevrilmiş opth-gen.awk ve optc-gen.awk .
Aşağıdaki ilginç satırları içerir:
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
tüm O
seçenekleri belirtir . Nasıl Not -O<n>
diğerinden ayrı ailede olduğu Os
, Ofast
ve Og
.
Oluşturduğumuzda, bu options.h
, şunları içeren bir dosya oluşturur :
OPT_O = 139, /* -O */
OPT_Ofast = 140, /* -Ofast */
OPT_Og = 141, /* -Og */
OPT_Os = 142, /* -Os */
Bonus olarak, \bO\n
içeriye girerken common.opt
şu satırları görüyoruz:
-optimize
Common Alias(O)
olanı bize öğretir --optimize
(çift çizgi bir çizgi ile başlar, çünkü -optimize
üzerinde .opt
dosyası) için bir belgesiz takma -O
olarak kullanılabilir --optimize=3
!
OPT_O'nun kullanıldığı yerler
Şimdi grep:
git grep -E '\bOPT_O\b'
bu da bizi iki dosyaya işaret ediyor:
Önce takip edelim opts.c
opts.c: default_options_optimization
Tüm opts.c
kullanımlar içeride olur: default_options_optimization
.
Bu işlevi kimin çağırdığını görmek için geriye doğru izleriz ve tek kod yolunun şu olduğunu görürüz:
main.c:main
toplev.c:toplev::main
opts-global.c:decode_opts
opts.c:default_options_optimization
ve main.c
giriş noktasıdır cc1
. İyi!
Bu işlevin ilk bölümü:
integral_argument
çağrıları atoi
karşılık gelen dize üzerinde OPT_O
giriş argüman ayrıştırmak içinopts->x_optimize
olduğu yerde saklar .opts
struct gcc_opts
struct gcc_opts
Boşuna uğraştıktan sonra, bunun şu struct
anda da üretildiğini fark ettik options.h
:
struct gcc_options {
int x_optimize;
[...]
}
x_optimize
çizgiler nereden geliyor:
Variable
int optimize
mevcut common.opt
ve şu options.c
:
struct gcc_options global_options;
bu nedenle, tüm konfigürasyon genel durumunu içeren şeyin bu int x_optimize
olduğunu ve optimizasyon değerinin bu olduğunu tahmin ediyoruz .
255 dahili bir maksimumdur
in opts.c:integral_argument
, atoi
girdi bağımsız değişkenine uygulanır, dolayısıyla INT_MAX
bir üst sınır da uygulanır. Ve daha büyük bir şey koyarsanız, GCC C tanımsız davranışı çalıştırıyor gibi görünüyor. Ah?
integral_argument
ayrıca atoi
herhangi bir karakter rakam değilse, argümanı ince bir şekilde sarar ve reddeder. Yani negatif değerler zarafetle başarısız olur.
Geri dönelim opts.c:default_options_optimization
, şu satırı görüyoruz:
if ((unsigned int) opts->x_optimize > 255)
opts->x_optimize = 255;
optimizasyon düzeyinin kısaltılması için 255
. Okurken opth-gen.awk
karşılaştım:
# All of the optimization switches gathered together so they can be saved and restored.
# This will allow attribute((cold)) to turn on space optimization.
ve oluşturulan options.h
:
struct GTY(()) cl_optimization
{
unsigned char x_optimize;
Bu, neden kesmenin nedenini açıklar: seçenekler de yönlendirilmelidir cl_optimization
, bu char
da yer kazanmak için a kullanır . Yani 255 aslında dahili bir maksimumdur.
opts.c: might_default_options
Geri opts.c:default_options_optimization
döndüğümüzde, maybe_default_options
hangi kulağa ilginç geldiğini görüyoruz . Giriyoruz ve sonra maybe_default_option
büyük bir anahtara ulaşıyoruz:
switch (default_opt->levels)
{
[...]
case OPT_LEVELS_1_PLUS:
enabled = (level >= 1);
break;
[...]
case OPT_LEVELS_3_PLUS:
enabled = (level >= 3);
break;
Bunun mümkün olan en büyük >= 4
olduğunu gösteren hiçbir kontrol yoktur 3
.
Sonra tanımında aramak OPT_LEVELS_3_PLUS
içinde 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! Bu, yalnızca 3 seviye olduğunun güçlü bir göstergesidir.
opts.c: default_options_table
opt_levels
o kadar ilginç ki grep OPT_LEVELS_3_PLUS
ve karşımıza çıkıyor 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 },
[...]
}
bu nedenle -On
, belgelerde belirtilen belirli optimizasyon eşlemesinin kodlandığı yer burasıdır . Güzel!
X_optimize için başka kullanım olmadığından emin olun
Ana kullanımı , man sayfasında belgelendiği x_optimize
gibi diğer belirli optimizasyon seçeneklerini ayarlamaktı -fdefer_pop
. Daha var mı
Biz grep
ve birkaç tane daha buluyoruz. Sayı küçüktür ve manuel incelemede her kullanımın yalnızca en fazla a yaptığını görüyoruz x_optimize >= 3
, dolayısıyla sonucumuz geçerlidir.
lto-wrapper.c
Şimdi OPT_O
, içinde olan ikinci oluşumuna gidiyoruz lto-wrapper.c
.
LTO, adından da anlaşılacağı gibi bir -O
seçeneğe ihtiyaç duyacak ve bağlantılı olacak collec2
(temelde bir bağlayıcıdır) Bağlantı Süresi Optimizasyonu anlamına gelir .
Aslında, ilk satır şunu lto-wrapper.c
söylüyor:
/* Wrapper to call lto. Used by collect2 and the linker plugin.
Bu dosyada, OPT_O
olaylar sadece O
onu iletmenin değerini normalleştiriyor gibi görünüyor , bu yüzden iyi olmalıyız.
Yedi farklı seviye:
-O0
(varsayılan): Optimizasyon yok.
-O
veya -O1
(aynı şey): Optimize edin, ancak çok fazla zaman harcamayın.
-O2
: Daha agresif bir şekilde optimize edin
-O3
: En agresif şekilde optimize edin
-Ofast
: Eşdeğeri -O3 -ffast-math
. -ffast-math
standartlarla uyumlu olmayan kayan nokta optimizasyonlarını tetikler. Bu, derleyicinin kayan nokta sayılarının sonsuz derecede hassas olduğunu ve üzerlerindeki cebirin gerçek sayı cebirinin standart kurallarını izlediğini varsaymasına olanak tanır. Ayrıca derleyiciye, donanıma denormalleri sıfırlamasını ve en azından x86 ve x86-64 dahil olmak üzere bazı işlemcilerde normalleri sıfır olarak değerlendirmesini söylemesini söyler. Denormals, birçok FPU'da yavaş bir yol tetikler ve bu nedenle onları sıfır olarak ele almak (bu yavaş yolu tetiklemez) büyük bir performans kazanımı olabilir.
-Os
: Kod boyutu için optimize edin. Bu, daha iyi I-önbellek davranışı nedeniyle bazı durumlarda hızı gerçekten artırabilir.
-Og
: Optimize edin, ancak hata ayıklamaya müdahale etmeyin. Bu, hata ayıklama yapıları için utanç verici olmayan performans sağlar ve bunun yerini alması amaçlanmıştır.-O0
.
Bunların hiçbiri tarafından etkinleştirilmeyen ve ayrıca etkinleştirilmesi gereken başka seçenekler de vardır. Bir optimizasyon seçeneği kullanmak da mümkündür, ancak bu optimizasyonla etkinleştirilen belirli bayrakları devre dışı bırakabilirsiniz.
Daha fazla bilgi için GCC web sitesine bakın.
-O100
derleme yapılıyor?
Dört (0-3): GCC 4.4.2 kılavuzuna bakın . Daha yüksek bir değer sadece -O3'tür, ancak bir noktada değişken boyut sınırını aşarsınız.
atoi
tanımlanmamış davranışa ve ardından bir 255
iç sınıra güveniyor gibi görünüyor .
man gcc
Cygwin'de (12000 tek satır) bile,-O
aşağıda belirtilen her şeyi arayabilir ve bulabilirsiniz.