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 funkcjiadb
przepis tutaj.