Optymalizacja oparta na profilu

Optymalizacja oparta na profilu to dobrze znany mechanizm optymalizacji za pomocą tej metody. W programie PGO profile środowiska wykonawczego z wykonań programu są wykorzystywane przez kompilatora, aby wybrać optymalny układ treści i kodu. Prowadzi to do poprawiono wydajność i zmniejszył rozmiar kodu.

PGO można wdrożyć w aplikacji lub bibliotece, wykonując te czynności: 1. Identyfikowanie reprezentatywnego zbioru zadań. 2. Utwórz profile. 3. Użyj profili w kompilacji wersji.

Krok 1. Zidentyfikuj reprezentatywne zadanie

Najpierw określ reprezentatywny punkt odniesienia lub zbiór zadań dla swojej aplikacji. Jest to kluczowy krok, ponieważ profile zebrane z zadania identyfikują gorące i zimne regiony w kodzie. Podczas korzystania z profili kompilator przeprowadzić agresywne optymalizacje i wbudować w treści w najpopularniejszych regionach. Kompilator mogą też zmniejszyć rozmiar kodu w przypadku zimnych regionów, a jednocześnie wymienić skuteczność reklam.

Dobrze dobrane zadanie pomaga też śledzić wydajność ogólne.

Krok 2. Zbierz profile

Zbieranie profilu obejmuje 3 kroki: - tworzenia natywnego kodu z użyciem instrumentacji, - uruchamianie aplikacji instrumentalnej na urządzeniu i generowanie profili; - scalanie/konieczne przetwarzanie profili na hoście.

Utwórz kompilację instrumentalną

Profile są zbierane przez uruchomienie zadania z kroku 1 w z instrumentowaną kompilację aplikacji. Aby wygenerować kompilację instrumentalną, dodaj -fprofile-generate do flag kompilatora i tagu łączącego. Ta flaga powinna być kontrolowane przez osobną zmienną kompilacji, ponieważ flaga nie jest potrzebna podczas kompilację domyślną.

Wygeneruj profile

Następnie uruchom aplikację z instrumentami na urządzeniu i wygeneruj profile. Profile są zbierane w pamięci po uruchomieniu instrumentowanego pliku binarnego zapisane w pliku przy wyjściu. Jednak funkcje zarejestrowane za pomocą funkcji atexit nie są w aplikacji na Androida – aplikacja po prostu się wyłącza.

Aplikacja lub zbiór zadań musi wykonać dodatkową pracę, aby ustawić ścieżkę do pliku profilu a następnie bezpośrednio aktywować zapis profilu.

  • Aby ustawić ścieżkę pliku profilu, wywołaj __llvm_profile_set_filename(PROFILE_DIR "/default-%m.profraw Pole %m jest przydatne w przypadku wielu bibliotek udostępnionych. %m` rozwija się do unikalnego modułu dla tej biblioteki, co powoduje utworzenie osobnego profilu dla każdej biblioteki. Zobacz tutaj innych przydatnych specyfikatorów wzorców. PROFILE_DIR to katalog, w którym które można zapisać w aplikacji. Zobacz prezentację do wykrywania tego katalogu w czasie działania.
  • Aby bezpośrednio aktywować zapis profilu, wywołaj funkcję __llvm_profile_write_file .
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;
}

Uwaga: wygenerowanie pliku profilu jest łatwiejsze, jeśli zbiór zadań to samodzielny plik binarny – ustaw zmienną środowiskową LLVM_PROFILE_FILE na %t/default-%m.profraw przed uruchomieniem pliku binarnego.

Profile końcowe

Pliki profili mają format .profraw. Najpierw należy je pobrać z urządzenia za pomocą usługi adb pull. Po pobraniu użyj narzędzia llvm-profdata w NDK do skonwertowania z .profraw na .profdata, które można następnie przekazać do funkcji kompilatora.

$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-profdata \
    merge --output=pgo_profile.profdata \
    <list-of-profraw-files>

Aby uniknąć wersji, użyj llvm-profdata i clang z tej samej wersji NDK niezgodność formatów plików profilu.

Krok 3. Użyj profili do utworzenia aplikacji

Użyj profilu z poprzedniego kroku podczas kompilacji aplikacji, przekazując parametr -fprofile-use=<>.profdata do kompilatora i tagu łączącego. można używać nawet w miarę rozwoju kodu – kompilator Clang toleruje niezgodność między źródłem a profilami.

Uwaga: w większości bibliotek profile są wspólne dla wszystkich architektur. Na przykład profili wygenerowanych na podstawie kompilacji biblioteki arm64 można używać do: dla wszystkich architektur. Zastrzeżenie polega na tym, że w przypadku obiektów architektonicznych ścieżki kodu w bibliotece (wersje x86 lub 32-bitowe albo 64-bitowe), osobne profile należy stosować w każdej z tych konfiguracji.

Podsumowanie

https://github.com/DanAlbert/ndk-samples/tree/pgo/pgo zawiera kompleksową prezentację korzystania z programu PGO w aplikacji. Zapewnia szczegóły skrócone w tym dokumencie.

  • Funkcja CMake jak skonfigurować zmienną CMake, która tworzy kod natywny za pomocą instrumentacji. Jeśli zmienna kompilacji nie jest ustawiona, kod natywny jest optymalizowany przy użyciu poprzednio profili PGO.
  • W wersji instrumentalnej pgodemo.cpp, zapisuje, że profile są wykonywane przez zadania.
  • Możliwe do zapisu lokalizacja profili jest uzyskiwana w czasie działania w MainActivity.kt za pomocą funkcji applicationContext.cacheDir.toString().
  • Aby pobrać profile z urządzenia bez konieczności użycia funkcji adb root, użyj funkcji adb przepis tutaj.