GCC optimization/tr

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

CFLAGS ve CXXFLAGS nedir?
CFLAGS ve CXXFLAGS değerleri, GNU Compiler Collection ( GCC ) 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ında CFLAGS ve CXXFLAGS değerlerini ayarlamalısınız. Tüm paketler, burada seçtiğiniz yapılandırmaya göre derlenecektir.

Örnekte gördüğünüz gibi, CXXFLAGS değerleri CFLAGS 'a atanan değerlerin aynısını kullanmakta. Çoğu sistemin hatasız bir derleme için ihtiyacı olan da bu olacaktır. 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 hatalı yapılandırma durumlarında 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 bir 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çlar" için "ö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 seçenek var), yalnızca en bilinen ve temel bayrakları ele alacağız.

-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 iki komut kullanılabilir:


 * 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ı