Profil Kılavuzlu Optimizasyon

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 buradaki adb tarifini kullanın.