GCC optimization/tr

This guide provides an introduction to optimizing compiled code using safe, sane CFLAGS and CXXFLAGS. It also as describes the theory behind optimizing in general.

CFLAGS ve CXXFLAGS nedir?
CFLAGS and CXXFLAGS are environment variables that are used to tell the GNU Compiler Collection (GCC) what kinds of switches to use when compiling source code. The CFLAGS variable is used for compiling code written in C, while the CXXFLAGS variable is for code written in C++.

Derlenen programın üreteceği hata ayıklama (debug) mesajlarının yoğunluğunu düşürebilir, hata durumunda gösterilecek uyarı mesajlarını artırabilir ve elbette üretilen kodun sisteminiz için optimize edilmesini sağlayabilirler. GCC yardım sayfasında kullanılabilecek seçenekler ve açıklamaları bulunmaktadır.

Nasıl kullanılırlar?
CFLAGS and CXXFLAGS can be used in two ways. First, they can be used per-program with Makefiles generated by the program.

However, this should not be done when installing packages found in the Portage tree. Instead, for Gentoo-based machines, set the CFLAGS and CXXFLAGS variables in This way all packages will be compiled using the options specified in

As seen in the example above the CXXFLAGS variable is set to use all the options present in CFLAGS. Most every system should be configured in this manner; additional options for CXXFLAGS are extremely rare in common use cases.

Hatalı düşünceler
While CFLAGS and CXXFLAGS can be very effective means of getting source code to produce smaller and/or faster binaries, they can also impair the function of the code, bloat its size, slow down its execution time. Setting them incorrectly can even cause compilation failures!

CFLAGS are not a magic bullet; they will not automatically make the system run faster or reduce the size of binaries on the disk. Adding too many flags in an attempt to optimize (or "rice") the system is a sure recipe for failure. The point of diminishing returns is reached rather quickly when dealing with CFLAGS.

Despite the boasts and brags found on the internet, aggressive CFLAGS and CXXFLAGS are far more likely to harm binaries than to do any good. Keep in mind the flags are designed to be used at specific places for specific purposes. Few flags work as intended globally.

Hazır mısınız?
Being aware of the risks involved, take a look at some sane, safe optimizations. These will hold in good stead and will be endearing to developers the next time a problem is reported on Bugzilla. (Developers will usually request the user to recompile a package with minimal CFLAGS to see if the problem persists. Remember: aggressive flags can ruin code!)

Temel
The goal behind CFLAGS and CXXFLAGS is to create code tailor-made to your system; it should function perfectly while being lean and fast, if possible. Sometimes these conditions are mutually exclusive, so this guide will stick to combinations known to work well. Ideally, they are the best available for any CPU architecture. For informational purposes, aggressive flag use will be covered later. Not every option listed on the GCC manual (there are hundreds) will be discussed, but basic, most common flags will be reviewed.

-march
İlk ve en önemli seçenek. Bu seçenek derleyiciye derleme sonucunda hangi işlemci mimarisine uygun kod üretileceğini belirtir. Farklı işlemcilerin farklı özellikleri, çalışma yöntemleri ve desteklediği değerler bulunmaktadır. değerinin yardımı ile derleyici sahip olduğunuz işlemcinin kapasitesine ve özelliklerine uygun bir kod üretecektir.

dosyasındaki  değeri mimari seçeneğinizi iletse de,   halen daha uyumlu kod üretmek için kullanılabilir. x86 ve x86-64 işlemciler (diğerleri gibi)  bayrağından faydalanabilir.

Ne tür bir işlemciniz var? Öğrenmek için aşağıdaki komutu çalıştırabilirsiniz:

ve  dahil, seçenekler hakkında daha fazla detay için:


 * The second command will show the compiler directives for building the header file, but without actually performing the steps and instead showing them on the screen . The final output line is the command that holds all the optimization options and architecture selection:

Şimdi de  değerini iş başında görelim. Aşağıdaki örnek eski bir Pentium III işlemci için:

Şimdi de 64-bit bir işlemci için bir örnek:

Hangi tür işlemciye sahip olduğunuzdan veya işlemciniz için ne kullanacağınızdan halen emin değilseniz  kullanın. Bu değeri kullanarak, GCC'nin işlemcinizi otomatik olarak tanıyarak en uyumlu değerleri kendi belirlemesini sağlayabilirsiniz. Ancak oluşacak paketi farklı bir CPU'da çalıştırmak üzere bir derleme yapıyorsanız bu seçeneği kullanmayın!

Yani bir bilgisayarda derleme yapıp derlediğiniz paketleri farklı bir bilgisayarda (mesela daha eski ve yavaş bir cihazda) çalıştırmak istiyorsanız  kullanmamalısınız. "Native" (doğal) seçeneği derlemenin sonunda üretilen kodun yalnızca derlendiği işlemci türünde çalışabileceği anlamına gelir. AMD Athlon 64 işlemci üzerinde  kullanarak derlediğiniz bir paket VIA C3 işlemci üzerinde çalışamayacaktır.

Ayrıca  ve   bayraklarını da kullanabilirsiniz. Bunlar normalde sadece uyumlu  seçeneği bulunmadığında kullanılan seçeneklerdir; bazı işlemci mimarileri   hatta   kullanımını gerektirebilir. Malesef GCC'nin her bayrak için davranışı bir mimariden diğerine farklılık göstermektedir.

x86 ve x86-64 işlemcilerde  kullandığınızda sonuç olarak işlemciniz ile tam uyumlu kodlar alırsınız, yani üretilen paketler farklı veya daha eski işlemcilerde çalışmaz. Paketleri yalnızca derlediğiniz sistemde kullanacaksanız  kullanın. ve  seçeneklerini yalnızca daha eski işlemcilere (i386 ve i486 gibi) uyumlu paketler derleme amacındaysanız değerlendirin. seçeneği kullanıldığında birçok gerekli değeri (ABI gibi) dikkate almadığı için, bu seçeneği x86 ve x86-64 sistemlerde kullanmayın.

Sadece x86/x86-64 olmayan işlemciler (Sparc, Alpha ve PowerPC gibi)  veya   seçeneklerine ihtiyaç duyabilir. Bu mimarilerde bu seçenekler, x86/x86-64 mimarideki  seçeneğinin yaptığı görevi yapmaktadır. Emin olmak için GCC yardım sayfasını incelediğinize emin olunuz.

-O
Gelecek seçeneğimiz. Bu seçenek genel optimizasyon değerini kontrol etmekte. Bu değeri değiştirmek, özellikle yüksek değerlerde derleme sürecini biraz daha yavaş hale getirip, RAM tüketimini artırabilir.

7 farklı  ayarı bulunmaktadır:   ,   ,   ,   , ,   ve. dosyasında bunlardan yalnızca birini kullanmalısınız.

istisna olmak üzere, tüm  seçenekleri bazı farklı optimizasyon bayraklarını aktifleştirmektedir. Detay için GCC'nin optimizasyon seçenekleri sayfasını inceleyebilirsiniz.

Optimiasyon seviyelerinin yaptıklarına bir göz atalım:


 * : This level (that is the letter "O" followed by a zero) turns off optimization entirely and is the default if no  level is specified in CFLAGS or CXXFLAGS . This reduces compilation time and can improve debugging info, but some applications will not work properly without optimization enabled. This option is not recommended except for debugging purposes.


 * : En temel optimizasyon seviyesidir. Derleme süresini çok yükseltmeden daha hızlı ve daha ufak kodlar üretir. Basit bir seçenektir ancak genellikle her zaman güvenlidir diyebiliriz.


 * :  seçeneğinin bir üstü ve özel bir ihtiyacınız yok ise tavsiye edilen optimizasyon seçeneğidir. ,   'in açtığı bayrakları da açıp, üzerine bazı bayraklar açmaktadır. Bu seçenekle yine derleyici derleme zamanını fazla uzatmadan güvenli ve hızlı kod üretmeye çalışacaktır.


 * : Mümkün olan en üst düzey optimizasyondur. Derleme süresini ve kullanılan RAM'i artırma pahasına daha fazla optimizasyon yapar. Sonuçta daha hızlı bir sistem garanti etmez, hatta fazla kaynak tüketiminden dolayı bazı durumlarda daha yavaş bir sonuçla karşılaşabilirsiniz. 'ün ayrıca bazı paketleri çalışmaz hale getirdiği bilinmektedir. Bu yüzden kullanımı tavsiye edilmemektedir.


 * : Bu seçenek üretilen kodun boyutunu optimize eder. Boyutta büyümeye sebep olmayacak tüm  seçeneklerini açar. Çok az disk alanı ve/veya işlemcisinde ufak önbellekleri bulunan bilgisayarlarda kullanışlı olabilir.


 * : GCC 4.8'de yeni bir optimizasyon seviyesi olarak   tanıtıldı. Çalıştırma hızından çok ödün vermeden, hızlı bir derleme ile hata ayıklama modunda çalışmak için kullanılmaktadır. Geliştirme için genel olarak  'dan daha rahat bir ortam sağlamaktadır.   uygulamak otomatik olarak  'yi aktif hale getirmez, yalnızca hata ayıklamayı zorlaştıran optimizasyonları etkisiz hale getirir.


 * : GCC 4.7 ile gelen bir seçenektir,  üzerine ,   ve   ekler. Bu seçenek tavsiye edilen standartların dışında olduğu için tavsiye edilmemektedir.

As previously mentioned,  is the recommended optimization level. If package compilation fails and while not using, try rebuilding with that option. As a fallback option, try setting the CFLAGS and CXXFLAGS to a lower optimization level, such as  or even   (for error reporting and checking for possible problems).

-pipe
Bir başka sık kullanılan bayrak da 'dır. Derleme sonrası üretilen kodda bir değişikliğe sebep olmaz ancak derleme işleminin daha hızlı gerçekleştirilmesini sağlar. Derleyiciye, derleme sırasında geçici dosyalar kullanmak yerine pipe kullanmasını belirtir. Bu işlem daha fazla RAM kullanımına sebep olduğu için, eğer cihazınızda RAM sıkıntısı yaşıyorsanız ve derleme sırasında problem oluşuyor ise bu seçeneği kullanmayabilirsiniz.

-fomit-frame-pointer
Bu da üretilen kodun azaltılmasını sağlayan yaygın bir seçenektir. Hata ayıklamayı zorlaştırmadığı platformlarda (x86-64 gibi)  seçeneğinin her seviyesinde (  hariç) otomatik olarak açılır. GCC belgeleri her mimari için bu durumu netleştirmemektedir ancak x86 üzerinde kendiniz ekleyerek açmanız gerektiği bilinmektedir. Bu seçeneği kullanmak uygulamalarda oluşan hataları yakalamayı oldukça zorlaştırır.

In particular, it makes troubleshooting applications written in Java much harder, though Java is not the only code affected by using this flag. So while the flag can help, it also makes debugging harder; backtraces in particular will be useless. When not doing software debugging and no other debugging-related CFLAGS such as  have been used, then try using.

-msse, -msse2, -msse3, -mmmx, -m3dnow
Bu bayraklar x86 ve x86-64 mimarilerinde bulunan SSE, SSE2, SSE3 , MMX ve 3DNow! seçeneklerini aktifleştirmek için bulunmaktadır. Bu seçenekler çokluortam, oyun ve diğer birçok matematiksel işlem içeren uygulamada performansı yükseltmektedir ve güncel işlemcilerin çoğunda bulunmaktadır.

Doğru  değerini kullandığınız sürece normal şartlarda bu seçenekleri  dosyasına eklemenize gerek bulunmamakta. Örneğin  seçeneği zaten içerisinde   barındırmakta. Bazı yeni VIA ve Amd64 işlemcilerde 'ın kapsamadığı seçenekler (sse3 gibi) bulunabilmekte. Bu tür durumlarda  kodunun çıktısına bakarak gerekli eklemeyi yapmanız gerekecektir.

Ama -funroll-loops -fomg-optimize seçenekleri ile daha iyi performans alıyorum!
Hayır. Sadece birisi sizi daha fazla seçenek eklemenin daha iyi olduğu konusuna inandırdığı için öyle düşünüyorsunuz. Agresif bayraklar sistem genelinde kullanıldığında yalnızca uygulamalarınıza zarar verecektir. dahi belgelerinde  ve   seçeneklerinin boyutu büyüttüğüne ve yavaşlamaya sebep olduğuna dikkat çekiyor. Ancak bu iki seçenek halen ,   ,   ve benzeri seçeneklerle birlikte övgü kaynağı olmaya devam ediyor.

Aslında bunlar tehlikeli derecede agresif seçenekler. Bu seçeneklerin kullanımı ile ilgili Gentoo Forumları ve Bugzilla'ya göz attığınızda pek iyi bir manzara ile karşılaşmayacaksınız.

You do not need to use those flags globally in CFLAGS or CXXFLAGS. They will only hurt performance. They may make you sound like you have a high-performance system running on the bleeding edge, but they don't do anything but bloat the code and get your bugs marked INVALID or WONTFIX.

Genelde böyle zararlı bayraklara ihtiyacınız olmaz. O yüzden kullanmayın. Güvenlileri deneyin: ,   ve.

Peki ya 3'ten büyük -O seviyeleri?
Some users boast about even better performance obtained by using,  , and so on, but the reality is that   levels higher than 3 have no effect. The compiler may accept CFLAGS like, but it actually doesn't do anything with them. It only performs the optimizations for, nothing more.

Kanıt mı istiyorsunuz? Kaynak kodunu inceleyin:

Gördüğünüz gibi, 3'den büyük değerler  muamelesi görmekte.

Ya hedef bilgisayar haricinde derleme yapıyorsak?
Some readers might wonder if compiling outside the target machine with a strictly inferior CPU or GCC sub-architecture will result in inferior optimization results (compared to a native compilation). The answer is simple: No. Regardless of the actual hardware on which the compilation takes place and the CHOST for which GCC was built, as long as the same arguments are used (except for ) and the same version of GCC is used (although minor version might be different), the resulting optimizations are strictly the same.

To exemplify, if Gentoo is installed on a machine whose GCC's CHOST is i686-pc-linux-gnu, and a Distcc server is setup on another computer whose GCC's CHOST is i486-linux-gnu, then there is no need to be afraid that the results would be less optimal because of the strictly inferior sub-architecture of the remote compiler and/or hardware. The result would be as optimized as a native build, as long as the same options are passed to both compilers (and the  parameter doesn't get a   argument). In this particular case the target architecture needs to be specified explicitly as explained in Distcc and -march=native.

The only difference in behavior between two GCC versions built targeting different sub-architectures is the implicit default argument for the  parameter, which is derived from the GCC's CHOST when not explicitly provided in the command line.

Peki ihtiyaç fazlası bayraklar?
Oftentimes CFLAGS and CXXFLAGS that are turned on at various  levels are specified redundantly in. Sometimes this is done out of ignorance, but it is also done to avoid flag filtering or flag replacing.

Flag filtering/replacing is done in many of the ebuilds in the Portage tree. It is usually done because packages fail to compile at certain  levels, or when the source code is too sensitive for any additional flags to be used. The ebuild will either filter out some or all CFLAGS and CXXFLAGS, or it may replace  with a different level.

Gentoo geliştirici belgelerinde bu işlem detaylı olarak anlatılmakta.

Gereksiz  değerleri kullanarak belirli bir seviye için filtreleme işleminden kurtulmak mümkün. Örneğin  için:

However, this is not a smart thing to do. CFLAGS are filtered for a reason! When flags are filtered, it means that it is unsafe to build a package with those flags. Clearly, it is not safe to compile your whole system with  if some of the flags turned on by that level will cause problems with certain packages. Therefore, you shouldn't try to "outsmart" the developers who maintain those packages. Trust the developers. Flag filtering and replacing is done for your benefit! If an ebuild specifies alternative flags, then don't try to get around it.

Desteklenmeyen seçenekler kullandığınızda problemler yaşamanız ve hata raporu ilettiğinizde bu seçenekleri değiştirerek tekrar derleme yapma talebiyle karşılaşmanız kaçınılmazdır. Zaman kaybetmemek için gereksiz bayrak kullanımından kaçının.

Peki ya LDFLAGS?
The Gentoo developers have already set basic, safe LDFLAGS in the base profiles, so they do not need to be changed.

Her paket için ayrı bayrak kullanabilir miyim?
Information on how to use per-package environment variables (including CFLAGS ) is described in the Gentoo Handbook, "Per-Package Environment Variables".

Kaynaklar
Aşağıdaki kaynaklar optimizasyon ile ilgili daha fazla bilgi almanıza yardımcı olabilir:


 * GCC online dökümanları


 * Gentoo Kurulum Belgeleri 5. bölümü


 * man make.conf komutu


 * Wikipedia


 * Gentoo Forumları