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?
ve  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. değerleri C dili ile yazılmış kodları etkiler,  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   ve   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,  değerleri  '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  için farklı bir değer belirtmeye ihtiyaç duymamanız gerekir.

Hatalı düşünceler
ve  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!

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  ve   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  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  değerleri ile tekrar derlenmesini ve problemin halen devam edip etmediğinin incelenmesini isterler.

Temel
ve  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:

To get more details, including  and   values, use:

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


 * : Bu seviye (bir "O" harfinin ardından eklenmiş sıfır) tıpkı  kullanılmamış gibi tüm optimizasyon 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. Programdaki hataları yakalama 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. 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.

Önceden de belirttiğimiz gibi  önerilen optimizasyon seviyesidir. Eğer derlemeniz hata ile sonlandıysa ve  kullanmıyorsanız, öncelikle kullanarak tekrar deneyin. Hata oluştuğu durumlarda 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 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.

Ö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 getirisinin bir bedeli 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.

Ama -funroll-loops -fomg-optimize seçenekleri ile daha iyi performans alıyorum!
No, you only think you do because someone has convinced you that more flags are better. Aggressive flags will only hurt applications when used system-wide. Even the GCC manual says that using  and   will make 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.

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  or. 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?
Bazı kullanıcılar,   gibi yüksek optimizasyon seviyeleri ile daha iyi performans aldıklarını iddia etmekteler. Aslında 'ün üzerindeki hiçbir optimizasyon değerinin bir etkisi bulunmamakta. Derleyici yalnızca  seviyesini uygulamaktadır.

Need more proof? Examine the source code:

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

What about compiling outside the target machine?
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?
Çoğu zaman dosyasındaki CFLAGS ve CXXFLAGS değerlerinin  arasında tekrarlanan   değerlerini görebilirsiniz. Bu bazen hata ile bazen de bayrak değişiminin önüne geçmek için yapılan birşeydir.

Bayrak filtreleme/değişimi Portage içerisinde birçok uygulamada yapılmakta. Genellikle bir uygulamanın belirli bir  değeri ile çalışamadığı görüldüğünde ebuild üzerinde ilgili seçeneğin kaldırılması veya değiştirilmesi ile problem aşılıyor.

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:

Ancak bu akıllıca bir işlem değil. CFLAGS değerinin ebuild üzerinde filtrelenmesinin bir amacı var. Uygulamanın bu bayrak ile derlenmesinin güvenli olmadığına emin olunduktan sonra bu tür değişiklikler yapılmakta. Bu sebeple bu tür işlemler yapmamalısınız.

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ı


 * Chapter 5 of the Gentoo Installation Handbooks


 * man make.conf


 * Wikipedia


 * Gentoo Forumları