GCC optimization/tr

Bu sayfada kaynak kodu, güvenli ve mantıklı CFLAGS ve CXXFLAGS kulllanarak optimize etmekle ilgili bilgi verilmektedir. Ayrıca derlemeyi optimize etmenin arkasındaki genel mantığı da ele almaktadır.

CFLAGS ve CXXFLAGS nedir?
CFLAGS ve CXXFLAGS değerleri, GNU Compiler Collection tarafından kaynak kodu derlerken ne tür değişiklikler yapılması gerektiğini belirleyen ortam değişkenleridir. CFLAGS değerleri C dili ile yazılmış kodları etkiler, CXXFLAGS ise 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 ve CXXFLAGS iki şekilde kullanılabilir. İlk olarak, her uygulamaya özel olarak derleme sırasında automake tarafından üretilen Makefile dosyalarında bulunabilirler.

Ancak bu yöntem Portage içerisindeki paketleri kurarken uygulanmamalıdır. Bunun yerine dosyasındaki CFLAGS ve CXXFLAGS değerlerini ayarlamalısınız. Tüm paketler, burada seçtiğiniz yapılandırmaya göre derlenecektir.

/etc/portage/make.conf dosyasındaki CFLAGS değerleri

Gördüğünüz gibi, CXXFLAGS değerleri CFLAGS'a atanan değerlerin aynısını kullanmakta. Muhtemelen hatasız bir derleme için ihtiyacınız olan durum da budur. Normal şartlarda CXXFLAGS için farklı bir değer belirtmeye ihtiyaç duymamanız gerekir.

Hatalı düşünceler
CFLAGS ve CXXFLAGS değerleri daha küçük veya daha hızlı çalışan dosyalar üretmekte yardımcı olabilir. Ancak bazı durumlarda yavaşlama, boyut büyümesi, derlenen dosyanın istendiği gibi çalışmaması ve tabi ki derleme sırasında hatalara sebep olabilir!

CFLAGS değerleri sihirli değnek değildir; otomatik olarak sisteminizi daha ufak ve daha hızlı bir hale getiremezler. Gereğinden fazla ve gereksiz değerler eklemek sisteminizi çorbaya çevirebilir ve başladığınızdan daha kötü bir noktaya ulaştırabilir.

İnternette bulacağınız övgüler bir yana, agresif CFLAGS ve CXXFlags değerleri uygulamalarınıza yarardan çok zarar getirme eğilimindedir. Bu değerlerin var olma sebebinin özel amaçlarda özel yerlerde kullanılması olduğunu unutmayınız. Bir CFLAGS değerinin bir parça kod veya bir uygulama üzerinde işe yarıyor olması tüm sisteminizi bu flag kullanılarak derlemenizin faydanıza olacağı anlamına gelmez.

Hazır mısınız?
Karşılaşacağınız riskleri de bildiğinize göre artık bazı mantıklı ve güvenli değerleri incelemenin zamanı geldi. Bu değerler sisteminizi sağlıklı tutacak ve Bugzilla'ya raporlayacağınız hatalarda geliştiricilere yardımcı olacak değerlerdir. Geliştiriciler hata raporlarında genellikle (agresif değerlerin yazılıma zarar verebileceğini bildikleri için) problem oluşturan yazılımın basit CFLAGS değerleri ile tekrar derlenmesini ve problemin halen devam edip etmediğinin incelenmesini isterler.

Temel
CFLAGS ve CXXFLAGS kullanılmasının amacı sonuçta mümkün olduğu kadar güvenilir ve hızlı uygulamalara/sisteme sahip olmanız için kodları sisteminize uyumlu şekilde derlemektir. Bu seçeneklerden her CPU mimarisine göre en iyi çalışanlardan bahsedeceğiz. Ardından dikkat etmeniz gereken agresif seçeneklere de değineceğiz. yardım sayfasındaki tüm seçenekleri açıklamayacağız (ki yüzlerce var), yalnızca en bilinen ve temel bayrakları ele alacağız.

-march
İlk ve en önemli seçenek. Bu seçenek derleyiciye kodun 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ğeri ile derleyici sahip olduğunuz işlemcinin kapasitesine ve özelliklerine uygun bir kod üretecektir.

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

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

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

/etc/portage/make.conf: Pentium III

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

/etc/portage/make.conf: AMD64

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 farklı bir CPU'da çalışacak bir paket derliyorsanı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 yalnızca uyumlu  seçeneği olmadığında kullanılan seçeneklerdir. Bazı işlemci mimarileri  hatta   kullanımını gerektirebilir. Malesef '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. Yüksek optimizasyon kullandığınızda biraz daha yavaş ve RAM tüketen bir derleme sürecine sahip olabilirsiniz.

5 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:


 * : Bu seviye (bir "O" harfinin ardından eklenmiş sıfır) tıpkı  kullanılmamış gibi tüm optimiasyon seçeneklerini kapalı konuma getirir. Bu sayede derleme zamanı azalır ve hata ayıklamak kolaylaşır ancak bazı uygulamalar optimizasyon olmadan düzgün çalışamayacaktır. Hata ayıklama amacı dışında bu seçenek önerilmemektedir.


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


 * :  seçeneğinin bir üstü, özel bir ihtiyacınız yok ise tavsiye edilen optimizasyon seçeneği. ,   'in açtığı bayrakların yanı sıra 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.

Önceden de belirttiğimiz gibi,  önerilen optimizasyon seviyesidir. Eğer derlemeniz hata ile sonlandıysa ve  kullanmıyorsanız, öncelikle kullanarak tekrar deneyin. Hata durumlarında optimizasyonu azaltmayı, hatta kapatmayı deneyebilirsiniz.

-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 kullanmayın.

-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 hata ayıklamayı oldukça zorlaştırır.

Özel olarak Java ile yazılmış uygulamaların hata ayıklamasını neredeyse imkansız hale getirir. Yine de bu bayrak yalnızca Java kodlarını etkilememektedir. Yani işe yaramasının bir bedeki olarak problem oluşturan uygulamalarınızın hata kaydı çıktıları işe yaramaz duruma gelecektir. Hata ayıklama işlemine ihtiyacınız yok ise ve farklı hata ayıklama seçeneklerini ( gibi) kullanmıyorsanız   kullanmayı deneyebilirsiniz.

-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.

But I get better performance with -funroll-loops -fomg-optimize!
No, you only think you do because someone has convinced you that more flags are better. Aggressive flags will only hurt your applications when used system-wide. Even the  manual says that using   and   makes code larger and run more slowly. Yet for some reason, these two flags, along with ,   ,   , and similar flags, continue to be very popular among ricers who want the biggest bragging rights.

The truth of the matter is that they are dangerously aggressive flags. Take a good look around the Gentoo Forums and Bugzilla to see what those flags do: nothing good!

You don't 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 your code and get your bugs marked INVALID or WONTFIX.

You don't need dangerous flags like these. Don't use them. Stick to the basics: ,   , and.

What about -O levels higher than 3?
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.

Need more proof? Examine the  source code :

-O source code

As you can see, any value higher than 3 is treated as just.

What about redundant flags?
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.

The Gentoo Developer Manual outlines where and how flag filtering/replacing works.

It's possible to circumvent  filtering by redundantly listing the flags for a certain level, such as  , by doing things like:

Specifying redundant CFLAGS

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.

You will most likely continue to run into problems when you build a package with unacceptable flags. When you report your troubles on Bugzilla, the flags you use in will be readily visible and you will be told to recompile without those flags. Save yourself the trouble of recompiling by not using redundant flags in the first place! Don't just automatically assume that you know better than the developers.

What about LDFLAGS?
The Gentoo developers have already set basic, safe LDFLAGS in the base profiles, so you don't need to change them.

Can I use per-package flags?
Information on how to use per-package environment variables (including CFLAGS) is described in the Gentoo Handbook, "Per-Package Environment Variables".

Resources
The following resources are of some help in further understanding optimization:


 * The GCC online documentation


 * Chapter 5 of the Gentoo Installation Handbooks




 * Wikipedia


 * The Gentoo Forums

Acknowledgements
We would like to thank the following authors and editors for their contributions to this guide:


 * nightmorph