Bu makale, popülerliği ve yaygın kullanımıyla tanınan Intel C++ derleyicilerine odaklanarak derleyici optimizasyonlarının potansiyeline ışık tutmayı amaçlamaktadır.
Önemli Noktalar: Derleyici optimizasyonları nelerdir? | -Açık | Mimari hedeflendi | Prosedürlerarası Optimizasyon | -fno-aliasing | Derleyici Optimizasyon raporları
Herhangi bir derleyici, yüksek seviyeli kaynak kodunu düşük seviyeli makine koduna dönüştürmek için bir dizi adımı uygular. Bunlar sözcük analizi, sözdizimi analizi, anlamsal analiz, ara kod üretimi (veya IR), optimizasyon ve kod üretimini içerir.
Optimizasyon aşamasında derleyici, daha az kaynak kullanan veya daha hızlı yürütülen anlamsal olarak eşdeğer bir çıktıyı hedefleyerek bir programı dönüştürmenin yollarını titizlikle arar. Bu süreçte kullanılan teknikler , sabit katlama, döngü optimizasyonu, işlev satır içi oluşturma ve ölü kodun ortadan kaldırılmasını kapsar ancak bunlarla sınırlı değildir.
Geliştiriciler, derleme işlemi sırasında bir dizi derleyici bayrağı belirleyebilir; bu, hata ayıklama ve profil oluşturma bilgileri için GCC ile " -g" veya "-pg" gibi seçenekleri kullananların aşina olduğu bir uygulamadır. Devam ederken, uygulamamızı Intel C++ derleyicisiyle derlerken kullanabileceğimiz benzer derleyici bayraklarını tartışacağız. Bunlar kodunuzun verimliliğini ve performansını artırmanıza yardımcı olabilir.
u(x,y,t), t zamanında (x,y) noktasındaki sıcaklıktır.
Temel olarak, Jacobi yinelemelerini değişken boyutlardaki ızgaralar üzerinde (çözünürlük adını verdiğimiz) gerçekleştiren bir C++ kodlamasına sahibiz. Temel olarak, 500'lük bir ızgara boyutu, 500x500 boyutunda bir matrisin çözülmesi anlamına gelir, vb.
/* * One Jacobi iteration step */ void jacobi(double *u, double *unew, unsigned sizex, unsigned sizey) { int i, j; for (j = 1; j < sizex - 1; j++) { for (i = 1; i < sizey - 1; i++) { unew[i * sizex + j] = 0.25 * (u[i * sizex + (j - 1)] + // left u[i * sizex + (j + 1)] + // right u[(i - 1) * sizex + j] + // top u[(i + 1) * sizex + j]); // bottom } } for (j = 1; j < sizex - 1; j++) { for (i = 1; i < sizey - 1; i++) { u[i * sizex + j] = unew[i * sizex + j]; } } }
MFLOP/s, “Saniyede Milyon Kayan Nokta İşlemi” anlamına gelir. Kayan nokta işlemleri açısından bir bilgisayarın veya işlemcinin performansını ölçmek için kullanılan bir ölçüm birimidir. Kayan nokta işlemleri, kayan nokta biçiminde temsil edilen ondalık veya gerçek sayılarla matematiksel hesaplamaları içerir.
Not 1: Stabil bir sonuç sağlamak için çalıştırılabilir dosyayı her çözünürlük için 5 kez çalıştırıp MFLOP/s değerlerinin ortalamasını alıyorum.
Not 2: Intel C++ derleyicisindeki varsayılan optimizasyonun -O2 olduğunu unutmamak önemlidir. Bu nedenle kaynak kodunu derlerken -O0 değerini belirtmek önemlidir.
Bunlar, derleyici optimizasyonlarına başladığınızda en sık kullanılan derleyici bayraklarından bazılarıdır. İdeal durumda Ofast > O3 > O2 > O1 > O0 performansı. Ancak bu mutlaka gerçekleşmez. Bu seçeneklerin kritik noktaları şunlardır:
-O1:
-O2:
-O3:
-Ofast:
Tüm bu optimizasyonların temel kodumuzdan (“-O0” ile) çok daha hızlı olduğu açıkça görülmektedir. Yürütme çalışma süresi temel duruma göre 2-3 kat daha düşüktür. MFLOP/lar ne olacak?
Genel olarak, çok az da olsa, “-O3” en iyi performansı gösteriyor.
“ -Ofast ” (“ -no-prec-div -fp-model fast=2 ”) tarafından kullanılan ekstra işaretler herhangi bir ek hızlanma sağlamamaktadır.
Cevap stratejik derleyici bayraklarında yatıyor. " -xHost " ve daha kesin olarak " -xCORE-AVX512 " gibi seçeneklerle denemeler yapmak, makinenin yeteneklerinin tüm potansiyelini kullanmamıza ve optimum performans için optimizasyonları uyarlamamıza olanak sağlayabilir.
-xHost:
-xCORE-AVX512:
Hedef: Derleyiciye Intel Gelişmiş Vektör Uzantıları 512 (AVX-512) talimat setini kullanan kod oluşturmasını açıkça söyleyin.
Temel Özellikler: AVX-512, AVX2 gibi önceki sürümlere kıyasla daha geniş vektör kayıtları ve ek işlemler sunan gelişmiş bir SIMD (Tek Komut, Çoklu Veri) komut setidir. Bu bayrağın etkinleştirilmesi, derleyicinin optimize edilmiş performans için bu gelişmiş özelliklerden yararlanmasına olanak tanır.
Hususlar: Taşınabilirlik yine burada suçludur. AVX-512 talimatlarıyla oluşturulan ikili dosyalar, bu talimat setini desteklemeyen işlemcilerde en iyi şekilde çalışmayabilir. Hiç çalışmayabilirler!
Varsayılan olarak “ -xCORE-AVX512 ”, programın zmm kayıtlarının kullanımından büyük olasılıkla faydalanmayacağını varsayar. Derleyici, performans artışı garanti edilmediği sürece zmm kayıtlarını kullanmaktan kaçınır.
Zmm kayıtlarını kısıtlama olmadan kullanmayı planlıyorsanız " " yüksek olarak ayarlanabilir. Biz de bunu yapacağız.
Vay be!
Dikkate değer kısım, bu sonuçları herhangi bir önemli manuel müdahale olmadan, yalnızca uygulama derleme süreci sırasında bir avuç derleyici bayrağını dahil ederek elde etmiş olmamızdır.
Not: Donanımınız AVX-512'yi desteklemiyorsa endişelenmeyin. Intel C++ Derleyicisi AVX, AVX-2 ve hatta SSE için optimizasyonları destekler. bilmeniz gereken her şey var!
Halka arz, bir program içindeki farklı işlevler veya prosedürler arasındaki etkileşimlere odaklanan çok adımlı bir süreçtir. IPO, Yönlendirme ikamesi, Dolaylı çağrı dönüşümü ve Satır içi dahil olmak üzere birçok farklı türde optimizasyon içerebilir.
-ipo:
Hedef: Derleyicinin derleme sırasında bireysel kaynak dosyaların ötesinde tüm programı analiz etmesine ve optimize etmesine olanak tanıyarak prosedürler arası optimizasyona olanak tanır.
Temel Özellikler: - Tüm Program Optimizasyonu: " -ipo ", tüm program boyunca işlevler ve prosedürler arasındaki etkileşimleri dikkate alarak tüm kaynak dosyalar genelinde analiz ve optimizasyon gerçekleştirir. - İşlevler arası ve modüller arası optimizasyon: Bayrak, satır içi işlevleri ve senkronizasyonu kolaylaştırır farklı program bölümlerinde optimizasyonlar ve veri akışı analizi.
Hususlar: Ayrı bir bağlantı adımı gerektirir. “ -ipo ” ile derledikten sonra, son yürütülebilir dosyayı oluşturmak için belirli bir bağlantı adımına ihtiyaç vardır. Derleyici, bağlantı sırasında tüm program görünümünü temel alarak ek optimizasyonlar gerçekleştirir.
-ip:
Hedef: Derleyicinin ayrı bir bağlantı adımı gerektirmeden prosedürler arası bazı optimizasyonları gerçekleştirmesine olanak tanıyarak prosedürler arası analiz yayılımını etkinleştirir.
Temel Özellikler: - Analiz ve yayılım: " -ip ", derleyicinin derleme sırasında farklı işlevler ve modüller arasında araştırma ve veri yayılımı gerçekleştirmesini sağlar. Ancak tam program görünümünü gerektiren tüm optimizasyonları gerçekleştirmez. - Daha hızlı derleme: “ -ipo ”dan farklı olarak “ -ip ” ayrı bir bağlantı adımı gerektirmez, bu da derleme sürelerinin daha hızlı olmasını sağlar. Hızlı geri bildirimin gerekli olduğu geliştirme sırasında bu yararlı olabilir.
Dikkat Edilmesi Gerekenler: İşlev satır içi dahil olmak üzere yalnızca bazı sınırlı prosedürler arası optimizasyonlar gerçekleşir.
-ipo, ayrı bir bağlantı adımı içerdiğinden ancak daha uzun derleme sürelerine mal olduğundan genellikle daha kapsamlı prosedürler arası optimizasyon yetenekleri sağlar. [ ] -ip, ayrı bir bağlantı adımı gerektirmeden bazı prosedürler arası optimizasyonları gerçekleştiren, geliştirme ve test aşamalarına uygun hale getiren daha hızlı bir alternatiftir.[ ]
Yalnızca performanstan ve farklı optimizasyonlardan, derleme sürelerinden veya çalıştırılabilir dosyanın boyutundan bahsettiğimiz için bizi ilgilendirmiyor, " -ipo " konusuna odaklanacağız.
/* * One Jacobi iteration step */ void jacobi(double *u, double *unew, unsigned sizex, unsigned sizey) { int i, j; for (j = 1; j < sizex - 1; j++) { for (i = 1; i < sizey - 1; i++) { unew[i * sizex + j] = 0.25 * (u[i * sizex + (j - 1)] + // left u[i * sizex + (j + 1)] + // right u[(i - 1) * sizex + j] + // top u[(i + 1) * sizex + j]); // bottom } } for (j = 1; j < sizex - 1; j++) { for (i = 1; i < sizey - 1; i++) { u[i * sizex + j] = unew[i * sizex + j]; } } }
jacobi() işlevi, parametre olarak ikiye katlamak için birkaç işaretçi alır ve ardından iç içe geçmiş for döngüleri içinde bir şeyler yapar. Herhangi bir derleyici kaynak dosyada bu işlevi gördüğünde çok dikkatli olmalıdır.
U kullanarak yeniyi hesaplama ifadesi, 4 komşu u değerinin ortalamasını içerir. Peki ya siz ve Unew aynı konumu işaret ediyorsa? Bu, takma ad verilmiş işaretçilerin klasik sorunu haline gelecektir [ ].
Modern derleyiciler çok akıllıdır ve güvenliği sağlamak için takma adın mümkün olabileceğini varsayarlar. Ve bunun gibi senaryolarda, kodun anlamını ve çıktısını etkileyebilecek her türlü optimizasyondan kaçınırlar.
Bizim durumumuzda, u ve unew'in farklı hafıza konumları olduğunu ve farklı değerleri depolaması gerektiğini biliyoruz. Böylece derleyiciye burada herhangi bir takma ad olmayacağını kolayca bildirebiliriz.
İki yöntem var. Birincisi C “ ” anahtar sözcüğüdür . Ancak kodun değiştirilmesini gerektirir. Şimdilik bunu istemiyoruz.
Basit bir şey var mı? “ -fno-alias ”ı deneyelim.
-fno-takma ad:
Hedef: Derleyiciye programda takma ad kullanmamasını söyleyin.
Temel Özellikler: Takma ad olmadığı varsayıldığında, derleyici kodu daha serbestçe optimize edebilir, bu da potansiyel olarak performansı artırabilir.
Dikkat Edilmesi Gerekenler: Geliştiricinin bu bayrağı kullanırken dikkatli olması gerekir; çünkü herhangi bir yersiz takma ad kullanılması durumunda program beklenmedik çıktılar verebilir.
Artık elimizde bir şey var!!!
Montaj kodunun (burada paylaşılmasa da) ve oluşturulan derleme optimizasyon raporunun ( aşağıya bakın) daha yakından incelenmesi, derleyicinin ve konusundaki ustaca uygulamasını ortaya çıkarır. Bu dönüşümler, derleyici direktiflerinin kod verimliliği üzerindeki önemli etkisini ortaya koyarak yüksek derecede optimize edilmiş performansa katkıda bulunur.
Intel C++ derleyicisi, kullanıcıların optimizasyon amacıyla yapılan tüm ayarlamaları özetleyen bir optimizasyon raporu oluşturmasına olanak tanıyan değerli bir özellik sağlar [ ]. Bu kapsamlı rapor, derleyicinin kod içinde uyguladığı optimizasyonların ayrıntılı bir listesini sunan YAML dosya formatında kaydedilir. Ayrıntılı bir açıklama için “ ” hakkındaki resmi belgelere bakın.
Benzer şekilde Intel C++ derleyicileri (ve tüm popüler olanlar) pragma direktiflerini de destekler ki bunlar çok güzel özelliklerdir. ivdep, paralel, simd, vektör vb. gibi bazı pragmaları kontrol etmeye değer.