En iyi uygulamaları iyileştirme
Bu belgede, Visual Studio'da C++ programlarını iyileştirmeye yönelik bazı en iyi yöntemler açıklanmaktadır.
Derleyici ve Bağlayıcı Seçenekleri
Profil destekli iyileştirme
Visual Studio, profil destekli iyileştirmeyi (PGO) destekler. Bu iyileştirme, uygulamanın daha sonra en iyi duruma getirilmesini sağlamak için bir uygulamanın izlemeli sürümünün eğitim yürütmelerinden profil verilerini kullanır. PGO kullanmak zaman alabilir, bu nedenle her geliştiricinin kullandığı bir şey olmayabilir, ancak ürünün son sürümü için PGO kullanmanızı öneririz. Daha fazla bilgi için bkz . Profil Destekli İyileştirmeler.
Ayrıca, Tüm Program İyileştirmesi (Bağlantı Zaman Kodu Oluşturma olarak da bilinir) ve /O1
ve /O2
iyileştirmeleri geliştirilmiştir. Genel olarak, bu seçeneklerden biriyle derlenen bir uygulama, önceki derleyiciyle derlenen uygulamadan daha hızlı olacaktır.
Daha fazla bilgi için bkz /GL
. (Tüm Program İyileştirme) ve /O1
/O2
(Boyutu Küçült, Hızı En Üst Düzeye Çıkar).
Kullanılacak iyileştirme düzeyi
Mümkünse, son sürüm derlemeleri Profil Destekli İyileştirmeler ile derlenmelidir. İzlemeli derlemeleri çalıştırmak için altyapı yetersiz olduğundan veya senaryolara erişemediğinden dolayı PGO ile derleme yapmak mümkün değilse, Tüm Program İyileştirmesi ile derlemenizi öneririz.
Anahtar /Gy
da çok kullanışlıdır. Her işlev için ayrı bir COMDAT oluşturur ve başvurulmayan COMDAT'ları ve COMDAT katlamasını kaldırma konusunda bağlayıcıya daha fazla esneklik sağlar. Kullanmanın /Gy
tek dezavantajı, hata ayıklama sırasında sorunlara neden olabilmesidir. Bu nedenle, genellikle kullanılması önerilir. Daha fazla bilgi için bkz /Gy
. (İşlev Düzeyi Bağlamayı Etkinleştirme).
64 bit ortamlarda bağlantı için bağlayıcı seçeneğinin /OPT:REF,ICF
kullanılması önerilir ve 32 bit ortamlarda /OPT:REF
kullanılması önerilir. Daha fazla bilgi için bkz . /OPT (İyileştirmeler).
Ayrıca, iyileştirilmiş sürüm derlemelerinde bile hata ayıklama sembolleri oluşturmanız kesinlikle önerilir. Oluşturulan kodu etkilemez ve gerekirse uygulamanızda hata ayıklamayı çok daha kolay hale getirir.
Kayan nokta anahtarları
Derleyici /Op
seçeneği kaldırıldı ve kayan nokta iyileştirmeleriyle ilgili aşağıdaki dört derleyici seçeneği eklendi:
Seçenek | Açıklama |
---|---|
/fp:precise |
Bu varsayılan öneridir ve çoğu durumda kullanılmalıdır. |
/fp:fast |
Performans, örneğin oyunlarda son derece önemliyse önerilir. Bu, en hızlı performansa neden olur. |
/fp:strict |
Hassas kayan nokta özel durumları ve IEEE davranışı isteniyorsa önerilir. Bu en yavaş performansa neden olur. |
/fp:except[-] |
veya /fp:precise ile /fp:strict birlikte kullanılabilir, ancak kullanılamaz/fp:fast . |
Daha fazla bilgi için bkz /fp
. (Kayan Nokta Davranışını Belirtme).
İyileştirme declspecs
Bu bölümde, performansa yardımcı olmak için programlarda kullanılabilecek iki declspec'e bakacağız: __declspec(restrict)
ve __declspec(noalias)
.
restrict
Declspec yalnızca işaretçi döndüren işlev bildirimlerine uygulanabilir, örneğin__declspec(restrict) void *malloc(size_t size);
declspec restrict
, sarmalanmamış işaretçiler döndüren işlevlerde kullanılır. Bu anahtar sözcük, geçerli programda zaten kullanımda olan bir işaretçi değerini hiçbir zaman döndürmeyeceğinden C-Runtime Kitaplığı uygulaması malloc
için kullanılır (boşaltıldıktan sonra bellek kullanma gibi geçersiz bir şey yapmazsanız).
restrict
declspec, derleyiciye derleyici iyileştirmeleri gerçekleştirmek için daha fazla bilgi verir. Derleyicinin belirlemesi en zor şeylerden biri, hangi işaretçilerin diğer işaretçileri diğer adlarıyla kullandığıdır ve bu bilgilerin kullanılması derleyiciye büyük ölçüde yardımcı olur.
Bunun derleyicinin doğrulanacağı bir şey değil, derleyiciye verilen bir söz olduğunu belirtmek gerekir. Programınız bu restrict
declspec'i uygunsuz bir şekilde kullanıyorsa, programınızın davranışı yanlış olabilir.
Daha fazla bilgi için bkz. restrict
.
noalias
Declspec yalnızca işlevlere de uygulanır ve işlevin yarı saf bir işlev olduğunu gösterir. Yarı saf işlev yalnızca yerellere, bağımsız değişkenlere ve bağımsız değişkenlerin birinci düzey dolaylılarına başvuran veya değiştiren işlevdir. Bu declspec derleyiciye verilen bir vaattir ve işlev genel değerlere veya işaretçi bağımsız değişkenlerinin ikinci düzey dizinlerine başvuruda bulunursa derleyici uygulamayı bozan kod oluşturabilir.
Daha fazla bilgi için bkz. noalias
.
İyileştirme pragmaları
Ayrıca kodu iyileştirmeye yardımcı olmak için birkaç yararlı pragma vardır. İlk olarak şu konuyu ele #pragma optimize
alacağız:
#pragma optimize("{opt-list}", on | off)
Bu pragma, belirli bir iyileştirme düzeyini işlev temelinde ayarlamanıza olanak tanır. Bu, belirli bir işlev iyileştirmeyle derlendiğinde uygulamanızın kilitlendiği nadir durumlar için idealdir. Tek bir işlev için iyileştirmeleri kapatmak için bunu kullanabilirsiniz:
#pragma optimize("", off)
int myFunc() {...}
#pragma optimize("", on)
Daha fazla bilgi için bkz. optimize
.
Satır içi, derleyicinin gerçekleştirdiği en önemli iyileştirmelerden biridir ve burada bu davranışı değiştirmeye yardımcı olan birkaç pragmadan bahsediyoruz.
#pragma inline_recursion
, uygulamanın özyinelemeli bir çağrıyı satır içi olarak sıralayabilmesini isteyip istemediğinizi belirtmek için yararlıdır. Varsayılan olarak kapalıdır. Küçük işlevlerin basit özyinelemeleri için bunu açabilirsiniz. Daha fazla bilgi için bkz. inline_recursion
.
Inlining derinliğini sınırlamak için bir diğer yararlı pragma da şeklindedir #pragma inline_depth
. Bu genellikle bir programın veya işlevin boyutunu sınırlamaya çalıştığınız durumlarda kullanışlıdır. Daha fazla bilgi için bkz. inline_depth
.
__restrict
ve __assume
Visual Studio'da performansa yardımcı olabilecek birkaç anahtar sözcük vardır: __restrict ve __assume.
İlk olarak, ve iki farklı şey olduğu __restrict
__declspec(restrict)
belirtilmelidir. Bir şekilde ilişkili olsalar da semantikleri farklıdır. __restrict
veya gibi const
volatile
bir tür niteleyicidir, ancak yalnızca işaretçi türleri için kullanılır.
ile __restrict
değiştirilen bir işaretçi, __restrict işaretçisi olarak adlandırılır. __restrict işaretçisi, yalnızca __restrict işaretçisi aracılığıyla erişilebilen bir işaretçidir. Başka bir deyişle, __restrict işaretçisi tarafından işaret edilen verilere erişmek için başka bir işaretçi kullanılamaz.
__restrict
Microsoft C++ iyileştiricisi için güçlü bir araç olabilir, ancak bunu büyük bir dikkatle kullanın. Düzgün kullanılmadıysa, iyileştirici uygulamanızı bozacak bir iyileştirme gerçekleştirebilir.
ile __assume
bir geliştirici derleyiciye bazı değişkenlerin değeri hakkında varsayımlarda bulunmasını söyleyebilir.
Örneğin __assume(a < 5);
, iyileştiriciye bu kod satırında değişkenin a
5'ten küçük olduğunu söyler. Bu da derleyiciye verilen bir sözdür. a
Programda bu noktada aslında 6 ise, derleyici iyileştirildikten sonra programın davranışı beklediğiniz gibi olmayabilir. __assume
en çok switch deyimleri ve/veya koşullu ifadeler öncesinde yararlıdır.
ile ilgili bazı sınırlamalar __assume
vardır. İlk olarak, gibi __restrict
yalnızca bir öneridir, bu nedenle derleyici bunu yoksaymak için serbesttir. Ayrıca, __assume
şu anda yalnızca sabitlere karşı değişken eşitsizlikleriyle çalışır. Sembolik eşitsizlikleri yaymıyor, örneğin, varsay(b < ).
İç destek
İç bilgiler, derleyicinin çağrı hakkında iç bilgiye sahip olduğu işlev çağrılarıdır ve bir kitaplıktaki bir işlevi çağırmak yerine bu işlev için kod yayar. intrin.h> üst bilgi dosyası<, desteklenen donanım platformlarının her biri için tüm kullanılabilir iç bilgileri içerir.
İç bilgi, programcıya derlemeyi kullanmak zorunda kalmadan kodun derinliklerine inebilme olanağı verir. İç bilgileri kullanmanın çeşitli avantajları vardır:
Kodunuz daha taşınabilir. Birçok iç bilgi birden çok CPU mimarisinde kullanılabilir.
Kodunuz daha kolay okunur çünkü kod hala C/C++ dilinde yazılmıştır.
Kodunuz derleyici iyileştirmelerinden yararlanır. Derleyici daha iyi hale geldiğinde, iç kod oluşturma iyileşir.
Daha fazla bilgi için bkz . Derleyici İç Bilgileri.
Özel durumlar
Özel durumlar kullanılarak ilişkilendirilmiş bir performans isabeti vardır. Derleyicinin belirli iyileştirmeleri gerçekleştirmesini engelleyen deneme blokları kullanılırken bazı kısıtlamalar uygulanır. x86 platformlarında, kod yürütme sırasında oluşturulması gereken ek durum bilgileri nedeniyle deneme bloklarından ek performans düşüşü vardır. 64 bit platformlarda deneme blokları performansı o kadar düşürmez, ancak özel durum oluşturulduktan sonra işleyiciyi bulma ve yığını geri sarma işlemi pahalı olabilir.
Bu nedenle, gerçekten ihtiyaç duymayan koda try/catch blokları eklemekten kaçınmanız önerilir. Özel durumlar kullanmanız gerekiyorsa, mümkünse zaman uyumlu özel durumlar kullanın. Daha fazla bilgi için bkz . Yapılandırılmış Özel Durum İşleme (C/C++).
Son olarak, yalnızca istisnai durumlar için özel durumlar oluşturur. Genel denetim akışı için özel durumlar kullanmak büyük olasılıkla performansı olumsuz etkileyebilir.