Profil odaklı optimizasyon (PGO), iyi bilinen bir derleyici optimizasyon tekniğidir. PGO'da, derleyici, satır içi yerleştirme ve kod düzeni hakkında en uygun seçimleri yapmak için programın çalıştırılmalarından elde edilen çalışma zamanı profillerini kullanır. Bu, performansın iyileşmesine ve kod boyutunun azalmasına yol açar.
PGO, aşağıdaki adımlarla uygulamanıza veya kitaplığınıza dağıtılabilir: 1. Temsil edici bir iş yükü belirleyin. 2. Profilleri toplayın. 3. Sürüm derlemesinde profilleri kullanın.
1. Adım: Temsilci İş Yükü Belirleme
Öncelikle, uygulamanız için temsili bir karşılaştırma veya iş yükü belirleyin. İş yükünden toplanan profiller koddaki yoğun ve az kullanılan bölgeleri tanımladığından bu adım kritik öneme sahiptir. Derleyici, profilleri kullanırken yoğun kullanılan bölgelerde agresif optimizasyonlar ve satır içi yerleştirme yapar. Derleyici, performanstan ödün vermeden soğuk bölgelerin kod boyutunu azaltmayı da tercih edebilir.
İyi bir iş yükünü belirlemek, genel performansı takip etmek için de yararlıdır.
2. Adım: Profilleri toplayın
Profil toplama işlemi üç adımdan oluşur: - enstrümantasyonlu yerel kod oluşturma, - araçlı uygulamayı cihazda çalıştırma ve profil oluşturma ve - ana makinede profilleri birleştirme/son işleme.
Enstrümante Edilmiş Derleme Oluşturma
Profiller, 1. adımdaki iş yükünün uygulamanın enstrümante edilmiş bir derlemesinde çalıştırılmasıyla toplanır. Enstrümante edilmiş bir derleme oluşturmak için derleyici ve bağlayıcı işaretlerine -fprofile-generate
ekleyin. Varsayılan derleme sırasında bu işarete ihtiyaç duyulmadığı için ayrı bir derleme değişkeni tarafından kontrol edilmelidir.
Profil Oluştur
Ardından, enstrümante edilmiş uygulamayı cihazda çalıştırın ve profiller oluşturun.
Profiller, enstrümante edilmiş ikili çalıştırıldığında bellekte toplanır ve çıkışta bir dosyaya yazılır. Ancak, atexit
işlevine kaydedilen işlevler bir Android uygulamasında çağrılmaz. Uygulama hemen kapatılır.
Uygulamanın/iş yükünün, profil dosyası için bir yol belirlemek ve ardından profil yazma işlemini açıkça tetiklemek üzere ek işlem yapması gerekir.
- Profil dosyası yolunu ayarlamak için
__llvm_profile_set_filename(PROFILE_DIR "/default-%m.profraw
yöntemini çağırın.%m
, birden fazla paylaşılan kitaplık olduğunda kullanışlıdır.%m
, ilgili kitaplık için benzersiz bir modül imzasına genişler. Bu da kitaplık başına ayrı bir profil oluşturur. Diğer yararlı kalıp belirteçleri için buraya göz atın.PROFILE_DIR
, uygulamadan yazılabilen bir dizindir. Bu dizini çalışma zamanında algılamak için demo bölümüne bakın. - Profil yazma işlemini açıkça tetiklemek için
__llvm_profile_write_file
işlevini çağırın.
extern "C" {
extern int __llvm_profile_set_filename(const char*);
extern int __llvm_profile_write_file(void);
}
#define PROFILE_DIR "<location-writable-from-app>"
void workload() {
// ...
// run workload
// ...
// set path and write profiles after workload execution
__llvm_profile_set_filename(PROFILE_DIR "/default-%m.profraw");
__llvm_profile_write_file();
return;
}
Not: İş yükü bağımsız bir ikili programsa profil dosyası oluşturmak daha kolaydır. İkili programı çalıştırmadan önce LLVM_PROFILE_FILE
ortam değişkenini %t/default-%m.profraw
olarak ayarlamanız yeterlidir.
İşlem Sonrası Profilleri
Profil dosyaları .profraw biçimindedir. Önce adb pull
kullanılarak cihazdan getirilmelidir. Getirme işleminden sonra, .profraw
değerinden .profdata
değerine dönüştürmek için NDK'daki llvm-profdata
yardımcı programını kullanın. Bu yardımcı programı, daha sonra derleyiciye iletilebilir.
$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-profdata \
merge --output=pgo_profile.profdata \
<list-of-profraw-files>
Profil dosyası biçimlerinin sürüm uyuşmazlığını önlemek için aynı NDK sürümünden llvm-profdata
ve clang
kullanın.
3. Adım Uygulama Oluşturmak İçin Profilleri Kullanma
Derleyiciye ve bağlayıcıya -fprofile-use=<>.profdata
'ü ileterek uygulamanızın sürüm derlemesi sırasında önceki adımdaki profili kullanın. Profiller, kod gelişirken bile kullanılabilir. Clang derleyicisi, kaynak ile profiller arasında küçük bir uyuşmazlığa izin verebilir.
Not: Genel olarak, çoğu kitaplık için profiller mimarilerde ortaktır. Örneğin, kitaplığın arm64 derlemesinden oluşturulan profiller tüm mimariler için kullanılabilir. Kitaplıkta mimariye özgü kod yolları varsa (arm yerine x86, 32 bit veya 64 bit) bu tür her yapılandırma için ayrı profiller kullanılması gerektiğini unutmayın.
Özet
https://github.com/DanAlbert/ndk-samples/tree/pgo/pgo, PGO'yu bir uygulamadan kullanmayla ilgili uçtan uca bir demo gösterir. Bu dokümanda gözden geçirilmeyen ek ayrıntılar sağlanır.
- CMake derleme kuralları, araçlarla yerel kod oluşturan bir CMake değişkeninin nasıl ayarlanacağını gösterir. Derleme değişkeni ayarlanmadığında yerel kod, daha önce oluşturulmuş PGO profilleri kullanılarak optimize edilir.
- Araçlı bir derlemede pgodemo.cpp, profillerin iş yükü yürütme olduğunu yazar.
- MainActivity.kt'de çalışma zamanında
applicationContext.cacheDir.toString()
kullanılarak profiller için yazılabilir bir konum elde edilir. adb root
uygulamasını gerektirmeden cihazdan profil almak için buradakiadb
tarifini kullanın.