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 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. CFLAGS are for code written in C, while CXXFLAGS are 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 automake.

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.

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
The goal behind using 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 we'll stick with combinations known to work well. Ideally, they are the best available for any CPU architecture. We'll mention the aggressive flags later so you know what to look out for. We won't discuss every option listed on the gcc manual (there are hundreds), but we'll cover the basic, most common flags.

-march
The first and most important option is. This tells the compiler what code it should produce for your processor architecture (or arch); it says that it should produce code for a certain kind of CPU. Different CPUs have different capabilities, support different instruction sets, and have different ways of executing code. The  flag will instruct the compiler to produce code specifically for your CPU, with all its capabilities, features, instruction sets, quirks, and so on.

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:

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

Also available are the  and   flags. These flags are normally only used when there is no available  option; certain processor architectures may require   or even. Unfortunately, gcc 's behavior isn't very consistent with how each flag behaves from one architecture to the next.

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.

Only non-x86/x86-64 CPUs (such as Sparc, Alpha, and PowerPC) may require  or   instead of. On these architectures,  /   will sometimes behave just like   (on x86/x86-64)... but with a different flag name. Again, gcc 's behavior and flag naming just isn't consistent across architectures, so be sure to check the gcc manual to determine which one you should use for your system.

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

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


 * : 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 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
This is a very common flag designed to reduce generated code size. It is turned on at all levels of  (except  ) on architectures where doing so does not interfere with debugging (such as x86-64), but you may need to activate it yourself by adding it to your flags. Though the gcc manual does not specify all architectures it is turned on by using, you will need to explicitly activate it on x86, with gcc up to version 4.6 or when using. However, using this flag will make debugging hard to impossible.

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

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 your applications when used system-wide. Even the gcc 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.

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.

Bu seçenekleri CFLAGS veya CXXFLAGS içerisinde sistem genelinde kullanmak sisteminize zarar vermenin yanı sıra raporladığınız hataların INVALID (geçersiz) veya WONTFIX (çözülmeyecek) olarak işaretlenmesine sebep olacaktır.

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?
Gentoo geliştiricileri zaten gerekli ve güvenli LDFLAGS değerlerini profillerin içine yerleştirmiştir. Bu yüzden herhangi bir değişiklik yapmanıza gerek bulunmamaktadır.

Her paket için ayrı bayrak kullanabilir miyim?
Her paket için ayrı ortam değişkenini (CFLAGS dahil) nasıl kullanabileceğiniz ile ilgili bilgi Gentoo El Kitabı, "Per-Package Environment Variables" bölümünde bulunmaktadır.

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


 * Wikipedia


 * Gentoo Forumları