Profil Kılavuzlu Optimizasyon

Profil yönlendirmeli optimizasyon (PGO) iyi bilinen bir derleyici optimizasyon tekniğidir. PGO'da bir programın yürütmesinden alınan çalışma zamanı profilleri, satır içine alma ve kod düzeni hakkında optimum seçimler yapmak için derleyici tarafından kullanılır. Bu sayede performans artar ve kod boyutu küçülür.

PGO, aşağıdaki adımlarla uygulamanıza veya kitaplığınıza dağıtılabilir: 1. Temsili bir iş yükü tanımlayın. 2. Profilleri topla. 3. Sürüm derlemesinde profilleri kullanın.

1. Adım: Temsili İş Yükü Tanımlama

Öncelikle, uygulamanız için temsili bir karşılaştırma veya iş yükü belirleyin. İş yükünden toplanan profiller kodda sıcak ve soğuk bölgeleri tanımladığından bu kritik bir adımdır. Derleyici, profilleri kullanırken agresif optimizasyonlar gerçekleştirir ve sıcak bölgeleri satır içine alır. Derleyici, performanstan ödün vermeden soğuk bölgelerin kod boyutunu azaltmayı da tercih edebilir.

İyi bir iş yükünü tanımlamak, performansı genel olarak takip etmek için de faydalıdır.

2. Adım: Profilleri toplayın

Profil toplama işlemi üç adımdan oluşur: - araçlarla yerel kod oluşturma, - araçlı uygulamayı cihazda çalıştırma ve profiller oluşturma ve - profilleri ana makinede birleştirme/işleme sonrası.

Enstrümanlı Derleme Oluşturma

Profiller, 1. adımdaki iş yükü uygulamanın yapılandırılmış bir derlemesinde çalıştırılarak toplanır. Enstrümanlı bir derleme oluşturmak için derleyici ve bağlayıcı işaretlerine -fprofile-generate ekleyin. Varsayılan derleme sırasında işaret gerekli olmadığından bu işaret, ayrı bir derleme değişkeni tarafından kontrol edilmelidir.

Profil Oluştur

Ardından, göstergeli uygulamayı cihazda çalıştırın ve profiller oluşturun. Profiller, izlemeli ikili program çalıştırıldığında bellekte toplanır ve çıkışta bir dosyaya yazılır. Ancak atexit ile kaydedilen işlevler bir Android uygulamasında çağrılmaz; uygulama sadece sonlandırılır.

Uygulamanın/iş yükünün, profil dosyasına bir yol belirlemek ve daha sonra açık bir şekilde profil yazmayı tetiklemek için fazladan işlem yapması gerekir.

  • Profil dosyasının yolunu ayarlamak için __llvm_profile_set_filename(PROFILE_DIR "/default-%m.profraw numaralı telefonu arayın. %m, birden fazla paylaşılan kitaplık olduğunda yararlıdır. %m`, ilgili kitaplık için benzersiz bir modül imzasına genişler ve böylece her kitaplık için ayrı bir profil elde edilir. Diğer faydalı kalıp belirleyiciler için buraya bakın. PROFILE_DIR, uygulamadan yazılabilen bir dizindir. Çalışma zamanında bu dizini algılamak için demo bölümüne bakın.
  • Bir profil yazma işlemini açık bir şekilde 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ının oluşturulması daha basittir. İkili dosyayı ç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. Bunların öncelikle adb pull kullanılarak cihazdan alınması gerekir. 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 öğelerini kullanın.

3. Adım: Uygulama Oluşturmak için Profilleri Kullanma

-fprofile-use=<>.profdata öğesini derleyiciye ve bağlayıcıya geçirerek 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 ve profiller arasındaki küçük uyuşmazlıkları tolere edebilir.

Not: Genel olarak, çoğu kitaplık için profiller farklı mimarilerde ortaktır. Ör. kitaplığın arm64 derlemesinden oluşturulan profiller tüm mimarilerde kullanılabilir. Dikkat edilmesi gereken nokta, kitaplıkta mimariye özel kod yolları varsa (arm-x86 ya da 32 bit veya 64 bit) bu tür her yapılandırma için ayrı profiller kullanılmasıdır.

Her şeyi bir araya getirmek

https://github.com/DanAlbert/ndk-samples/tree/pgo/pgo adresinde, bir uygulamadan PGO kullanımı ile ilgili uçtan uca bir demo gösterilmektedir. Bu belgede kısaca gözden geçirilen ek ayrıntılara yer verilmiştir.

  • 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, önceden oluşturulmuş PGO profilleri kullanılarak optimize edilir.
  • Gelişmiş bir derlemede pgodemo.cpp, profillerin iş yükü yürütme olduğunu yazar.
  • Profillerin yazılabilir konumu, çalışma zamanında applicationContext.cacheDir.toString() kullanılarak MainActivity.kt dosyasında elde edilir.
  • adb root gerektirmeden cihazdan profil almak için buradaki adb tarifini kullanın.