GCC Optimizasyonu

From Gentoo Wiki
Jump to: navigation, search
This page is a translated version of the page GCC optimization and the translation is 55% complete.

Outdated translations are marked like this.
Other languages:
English • ‎Türkçe • ‎español • ‎français • ‎italiano • ‎português do Brasil • ‎русский • ‎中文(中国大陆)‎ • ‎日本語 • ‎한국어

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.

Tanıtım

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

Because such a large proportion of the packages that make up most Gentoo systems are written in C and C++, these are two variables administrators will definitely want to set correctly as they will greatly influence the way much of the system is built.

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.

CODE /etc/portage/make.conf dosyasındaki CFLAGS değerleri
CFLAGS="-march=athlon64 -O2 -pipe"
CXXFLAGS="${CFLAGS}"
Önemli
USE bayrakları için birden fazla satır kullanmanız mümkünken, CFLAGS için birden fazla satır tanımı özellikle cmake ile yapılan derlemelerde sorun çıkaracaktır. Bu sebeple CFLAGS tanımının tek satırda olduğuna emin olun. Bkz. bug #500034

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

Tip
Safe CFLAGS article might help beginners start optimizing their systems.

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!

Remember, the global CFLAGS configured in /etc/portage/make.conf will be applied to every package on the system so administrators typically only set general, widely-applicable options. Individual packages further modify these options either in the ebuild or the build system itself to generate the final set of flags used when invoking the compiler.

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.

Optimizasyon

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

Not
Bir seçeneğin tam olarak ne yaptığından emin değilseniz, GCC yardım sayfasının ilgili bölümüne bakın. Anlamazsanız Google'ı veya GCC e-posta listelerini deneyin.

-march

İlk ve en önemli seçenek -march. 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. -march değerinin yardımı ile derleyici sahip olduğunuz işlemcinin kapasitesine ve özelliklerine uygun bir kod üretecektir.

-march= is an ISA selection option; it tells the compiler that it may use the instructions from the ISA. On an Intel/AMD64 platform with -march=native -O2 or lower OPT level, the code will likely end up with AVX instructions used but using shorter SSE XMM registers. To take full advantage of AVX YMM registers, the -ftree-vectorize, -O3 or -Ofast options should be used as well[1].

-ftree-vectorize is an optimization option (default at -O3 and -Ofast), which attempts to vectorize loops using the selected ISA if possible. The reason it isn't enabled at -O2 is that it doesn't always improve code, it can make code slower as well, and usually makes the code larger; it really depends on the loop etc.

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

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

user $cat /proc/cpuinfo

or even install app-portage/cpuid2cpuflags and add the available CPU-specific options to the /etc/portage/package.use/00cpuflags file, which the tool does through e.g. the CPU_FLAGS_X86 variable:

user $cpuid2cpuflags
CPU_FLAGS_X86: aes avx avx2 f16c fma3 mmx mmxext popcnt sse sse2 sse3 sse4_1 sse4_2 ssse3
root #echo "*/* $(cpuid2cpuflags)" >> /etc/portage/package.use/00cpuflags

march ve mtune dahil, seçenekler hakkında daha fazla detay için iki komut kullanılabilir:

user $gcc -c -Q -march=native --help=target
user $gcc -### -march=native /usr/include/stdlib.h

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

FILE /etc/portage/make.confPentium III örneği
CFLAGS="-march=pentium3"
CXXFLAGS="${CFLAGS}"

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

FILE /etc/portage/make.confAMD64 örneği
CFLAGS="-march=athlon64"
CXXFLAGS="${CFLAGS}"

Hangi tür işlemciye sahip olduğunuzdan veya işlemciniz için ne kullanacağınızdan halen emin değilseniz -march=native 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!

Warning
distcc ile derleme yaparken make.conf içerisindeki CFLAGS veya CXXFLAGS değerlerinde -march=native veya -mtune=native değerlerini 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 -march=native 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 -march=native kullanarak derlediğiniz bir paket VIA C3 işlemci üzerinde çalışamayacaktır.

Ayrıca -mtune ve -mcpu bayraklarını da kullanabilirsiniz. Bunlar normalde sadece uyumlu -march seçeneği bulunmadığında kullanılan seçeneklerdir; bazı işlemci mimarileri -mtune hatta -mcpu 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 -march 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 -march kullanın. -mtune ve -mcpu seçeneklerini yalnızca daha eski işlemcilere (i386 ve i486 gibi) uyumlu paketler derleme amacındaysanız değerlendirin. -mcpu 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) -mtune veya -mcpu seçeneklerine ihtiyaç duyabilir. Bu mimarilerde bu seçenekler, x86/x86-64 mimarideki -march seçeneğinin yaptığı görevi yapmaktadır. Emin olmak için GCC yardım sayfasını incelediğinize emin olunuz.

Not
Daha fazla -march/ -mtune/ -mcpu tavsiyesi için lütfen Gentoo Kurulum Belgesinin 5. bölümünü inceleyin. Ayrıca GCC'nin mimariye özel belgeleri de özellikle -march, -mcpu ve -mtune arasındaki farkları anlamada yardımcı olabilir.

-O

Warning
Using -O3 or -Ofast may cause some packages to break during the compilation.
Note
To print all packages that were built with specified CFLAGS/CXXFLAGS it's possible to use the following command: grep Ofast /var/db/pkg/*/*/CFLAGS

Gelecek seçeneğimiz -O. 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ı -O ayarı bulunmaktadır: -O0 , -O1 , -O2 , -O3 ,-Os, -Og ve -Ofast. /etc/portage/make.conf dosyasında bunlardan yalnızca birini kullanmalısınız.

-O0 istisna olmak üzere, tüm -O 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:

  • -O0 : Bu seviye (bir "O" harfinin ardından eklenmiş sıfır) tıpkı -O 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.
  • -O1 : 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.
  • -O2 : -O1 seçeneğinin bir üstü ve özel bir ihtiyacınız yok ise tavsiye edilen optimizasyon seçeneğidir. -O2, -O1'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.
  • -O3 : 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. -O3'ün ayrıca bazı paketleri çalışmaz hale getirdiği bilinmektedir. Bu yüzden kullanımı tavsiye edilmemektedir.
  • -Os : Bu seçenek üretilen kodun boyutunu optimize eder. Boyutta büyümeye sebep olmayacak tüm -O2 seçeneklerini açar. Çok az disk alanı ve/veya işlemcisinde ufak önbellekleri bulunan bilgisayarlarda kullanışlı olabilir.
  • -Og: GCC 4.8'de yeni bir optimizasyon seviyesi olarak -Og 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 -O0'dan daha rahat bir ortam sağlamaktadır. -Og uygulamak otomatik olarak -g'yi aktif hale getirmez, yalnızca hata ayıklamayı zorlaştıran optimizasyonları etkisiz hale getirir.
  • -Ofast: GCC 4.7 ile gelen bir seçenektir, -O3 üzerine -ffast-math, -fno-protect-parens ve -fstack-arrays ekler. Bu seçenek tavsiye edilen standartların dışında olduğu için tavsiye edilmemektedir.

Önceden de belirttiğimiz gibi -O2 önerilen optimizasyon seviyesidir. Eğer derlemeniz hata ile sonlandıysa ve -O2 kullanmıyorsanız, öncelikle kullanarak tekrar deneyin. Hata oluştuğu durumlarda optimizasyonu azaltmayı (-O1), hatta kapatmayı (-O0 -g2 -ggdb) deneyebilirsiniz.

-pipe

Bir başka sık kullanılan bayrak da -pipe'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) -O seçeneğinin her seviyesinde (-O0 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 (-ggdb gibi) kullanmıyorsanız -fomit-frame-pointer kullanmayı deneyebilirsiniz.

Önemli
-fomit-frame-pointer seçeneğini benzeri olan -momit-leaf-frame-pointer ile kullanmayın. Ayrıca -momit-leaf-frame-pointer seçeneğinin performans üzerinde negatif etkisi olduğu bilinmektedir.

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

Önemli
cat /proc/cpuinfo komutunu çalıştırarak işlemcinizin bu bayrakları desteklediğine emin olun. Aldığınız çıktı işlemcinizin hangilerini desteklediğini gösterecektir. pni seçeneğinin SSE3 ile aynı anlama geldiğini hatırlatmak isteriz.

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

Not
Aktifleştirilen işlemci bayrakları ile ilgili GCC notlarını inceleyebilirsiniz. Eğer bir seçenek listelenmişse, özel olarak eklemenize gerek bulunmayacak ve doğru -march ayarı ile gelecektir.

Optimizasyon SSS

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. GCC dahi belgelerinde -funroll-loops ve -funroll-all-loops seçeneklerinin boyutu büyüttüğüne ve yavaşlamaya sebep olduğuna dikkat çekiyor. Ancak bu iki seçenek halen -ffast-math , -fforce-mem , -fforce-addr 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.

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: -march , -O ve -pipe .

Peki ya 3'ten büyük -O seviyeleri?

Bazı kullanıcılar -O4, -O9 gibi yüksek optimizasyon seviyeleri ile daha iyi performans aldıklarını iddia etmekteler. Aslında -O3'ün üzerindeki hiçbir optimizasyon değerinin bir etkisi bulunmamakta. Derleyici yalnızca -O3 seviyesini uygulamaktadır.

Kanıt mı istiyorsunuz? Kaynak kodunu inceleyin:

CODE -O kaynak kodu
if (optimize >= 3)
    {
      flag_inline_functions = 1;
      flag_unswitch_loops = 1;
      flag_gcse_after_reload = 1;
      /* Allow even more virtual operators.  */
      set_param_value ("max-aliased-vops", 1000);
      set_param_value ("avg-aliased-vops", 3);
    }

Gördüğünüz gibi, 3'den büyük değerler -O3 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 -march=native) 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 -march parameter doesn't get a native 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 -march parameter, which is derived from the GCC's CHOST when not explicitly provided in the command line.

Peki ihtiyaç fazlası bayraklar?

Çoğu zaman /etc/portage/make.conf dosyasındaki CFLAGS ve CXXFLAGS değerlerinin arasında tekrarlanan -O 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 -O 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 -O değerleri kullanarak belirli bir seviye için filtreleme işleminden kurtulmak mümkün. Örneğin -O3 için:

CODE Gereksiz CFLAGS belirtme
CFLAGS="-O3 -finline-functions -funswitch-loops"

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ştirdikleri için herhangi bir değişiklik yapmanıza gerek bulunmamaktadır.

Her paket için ayrı bayrak kullanabilir miyim?

Uyarı
Her paket için farklı bayrak kullanımı hata ayıklama ve destek almanızı zorlaştıracaktır. Hata raporu açtığınızda bu özelliği kullanıyorsanız tüm detayları iletmeyi unutmayın.

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.

See also

Kaynaklar

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

  • man make.conf komutu

References

  1. GNU GCC Bugzilla, AVX/AVX2 no ymm registers used in a trivial reduction. Retrieved on 2017/07/18.

This page is based on a document formerly found on our main website gentoo.org.