System kompilacji Androida w wersji 13 lub starszej obsługuje optymalizację kierowaną przez profil (PGO) w narzędziu Clang w natywności natywnych modułów Androida, które mają reguły kompilacji blueprint. Na tej stronie opisaliśmy Clang PGO, ciągłe generowanie i aktualizowanie profili używanych w PGO oraz integrację PGO z systemem kompilacji (z przykladem zastosowania).
Uwaga: ten dokument opisuje korzystanie z PGO na platformie Android. Aby dowiedzieć się więcej o używaniu PGO w aplikacji na Androida, wejdź na tę stronę.
Informacje o Clang PGO
Clang może wykonywać optymalizację kierowaną przez profil za pomocą 2 typów profili:
- Profile oparte na pomiarach są generowane na podstawie zinstrumentowanego programu docelowego. Te profile są szczegółowe i wymagają dużych nakładów na czas wykonywania.
- Profile oparte na próbkowaniu są zwykle tworzone przez liczniki sprzętowe. Nie obciążają one procesora podczas działania i mogą być zbierane bez konieczności instrumentowania ani modyfikowania pliku binarnego. Są one mniej szczegółowe niż profile oparte na pomiarach.
Wszystkie profile powinny być generowane na podstawie reprezentatywnego obciążenia, które odzwierciedla typowe zachowanie aplikacji. Clang obsługuje zarówno profile oparte na AST (-fprofile-instr-generate
), jak i na LLVM IR (-fprofile-generate)
). Android obsługuje profile oparte na LLVM IR tylko w przypadku PGO z użyciem instrumentacji.
Aby móc tworzyć profile, musisz użyć tych flag:
-fprofile-generate
dla urządzeń wykorzystujących podczerwień. W przypadku tej opcji backend używa ważonego minimalnego drzewa rozpinającego, aby zmniejszyć liczbę punktów pomiarowych i zoptymalizować ich rozmieszczenie na krawędziach o niskiej wadze (używaj tej opcji również w przypadku kroku łączenia). Kompilator Clang automatycznie przekazuje środowisko wykonawcze do profilowania (libclang_rt.profile-arch-android.a
) do linkera. Biblioteka ta zawiera procedury zapisywania profili na dysku po zakończeniu pracy programu.-gline-tables-only
w przypadku zbierania profili na podstawie próbkowania, aby generować minimalne informacje debugowania.
Profil może być używany do PGO za pomocą -fprofile-use=pathname
lub -fprofile-sample-use=pathname
odpowiednio dla profili opartych na pomiarach i profili opartych na próbkowaniu.
Uwaga: jeśli po wprowadzeniu zmian w kodzie Clang nie może już korzystać z danych profilu, generuje ostrzeżenie -Wprofile-instr-out-of-date
.
Używanie PGO
Korzystanie z PGO obejmuje te kroki:
- Utwórz bibliotekę lub plik wykonywalny z użyciem instrumentacji, przekazując parametr
-fprofile-generate
do kompilatora i linkera. - Zbieraj profile, uruchamiając reprezentatywny zestaw zadań na zaimplementowanym binarnym pliku.
- Przeprowadź dodatkowe przetwarzanie profili za pomocą narzędzia
llvm-profdata
(szczegółowe informacje znajdziesz w artykule Praca z plikami profilu LLVM). - Użyj profili, aby zastosować PGO, przekazując parametr
-fprofile-use=<>.profdata
do kompilatora i linkera.
W przypadku PGO na Androidzie profile powinny być zbierane w trybie offline i sprawdzane wraz z kodem, aby zapewnić możliwość odtworzenia kompilacji. Profilów można używać w miarę ewolucji kodu, ale należy je okresowo odtwarzać (lub zawsze, gdy Clang ostrzega, że są nieaktualne).
Zbieranie profili
Clang może używać profili zebranych przez uruchomione benchmarki za pomocą biblioteki z instrukcjami lub próbkowania rejestrów sprzętowych podczas uruchamiania benchmarku. Obecnie Android nie obsługuje zbierania profili na podstawie próbkowania, dlatego musisz zbierać profile za pomocą wersji z instrumentacją:
- Określ punkt odniesienia i zbiór bibliotek, które są używane przez ten punkt odniesienia.
- Dodaj do zestawu danych i bibliotek właściwości
pgo
(szczegóły poniżej). - Utwórz wersję Androida z przeanalizowaną kopią tych bibliotek, korzystając z jednego z tych narzędzi:
make ANDROID_PGO_INSTRUMENT=benchmark
benchmark
to element zastępczy, który identyfikuje kolekcję bibliotek zinstrumentacją podczas kompilacji. Rzeczywiste reprezentatywne dane wejściowe (i być może inny plik wykonywalny, który łączy się z biblioteką, dla której wykonywane są testy porównawcze) nie są specyficzne dla PGO i nie są objęte zakresem tego dokumentu.
- Wgrywanie lub synchronizacja zmodyfikowanej wersji na urządzeniu.
- Uruchom test porównawczy, aby zebrać profile.
- Użyj narzędzia
llvm-profdata
(omówionego poniżej), aby przetworzyć profile i przygotować je do zacheckowania w drzewie źródeł.
Korzystanie z profili podczas kompilacji
Sprawdź profile w toolchain/pgo-profiles
w drzewie Androida. Nazwa powinna być zgodna z wartością podrzędnej właściwości profile_file
w przypadku właściwości pgo
biblioteki. Podczas kompilowania biblioteki system kompilacji automatycznie przekazuje plik profilu do Clanga. Zmienną środowiskową ANDROID_PGO_DISABLE_PROFILE_USE
można ustawić na wartość true
, aby tymczasowo wyłączyć PGO i zmierzyć korzyści dla skuteczności.
Aby podać dodatkowe katalogi profili związane z poszczególnymi produktami, dodaj je do zmiennej PGO_ADDITIONAL_PROFILE_DIRECTORIES
w sekcji BoardConfig.mk
. Jeśli zostaną określone dodatkowe ścieżki, profile na tych ścieżkach zastąpią te w pliku toolchain/pgo-profiles
.
Podczas generowania obrazu wersji za pomocą celu dist
w pliku make
system kompilacji zapisuje nazwy brakujących plików profilu w pliku $DIST_DIR/pgo_profile_file_missing.txt
. Możesz sprawdzić ten plik, aby zobaczyć, które pliki profilu zostały przypadkowo usunięte (co powoduje automatyczne wyłączenie PGO).
Włączanie PGO w plikach Android.bp
Aby włączyć PGO w plikach Android.bp
dla modułów natywnych, po prostu określ właściwość pgo
. Ta usługa ma te usługi podrzędne:
Usługa | Opis |
---|---|
instrumentation
|
Ustaw na true w przypadku PGO z wykorzystaniem pomiarów. Wartość domyślna to false . |
sampling
|
Ustaw na true , aby używać PGO z próbkowaniem. Wartość domyślna to false . |
benchmarks
|
Lista ciągów tekstowych. Ten moduł jest przeznaczony do profilowania, jeśli w opcji ANDROID_PGO_INSTRUMENT build
podany jest dowolny benchmark z listy. |
profile_file
|
Plik profilu (względnie do toolchain/pgo-profile ) do użycia z PGO. Kompilacja ostrzega, że ten plik nie istnieje, dodając ten plik do $DIST_DIR/pgo_profile_file_missing.txt
chyba że właściwość enable_profile_use jest ustawiona na
false LUB zmienna kompilacji ANDROID_PGO_NO_PROFILE_USE jest ustawiona na
true . |
enable_profile_use
|
Ustaw na false , jeśli nie chcesz używać profili podczas kompilacji. Można go używać podczas uruchamiania, aby włączyć zbieranie danych do profilu lub tymczasowo wyłączyć PGO. Wartość domyślna to true . |
cflags
|
Lista dodatkowych flag do użycia podczas kompilacji z instrumentacją. |
Przykład modułu z PGO:
cc_library { name: "libexample", srcs: [ "src1.cpp", "src2.cpp", ], static: [ "libstatic1", "libstatic2", ], shared: [ "libshared1", ] pgo: { instrumentation: true, benchmarks: [ "benchmark1", "benchmark2", ], profile_file: "example.profdata", } }
Jeśli punkty odniesienia benchmark1
i benchmark2
wykazują się reprezentatywnym zachowaniem w przypadku bibliotek libstatic1
,
libstatic2
lub libshared1
, właściwości tych bibliotek pgo
mogą również zawierać punkty odniesienia. Moduł defaults
w pliku Android.bp
może zawierać wspólną specyfikację pgo
dla zestawu bibliotek, aby uniknąć powtarzania tych samych reguł kompilacji dla wielu modułów.
Aby wybrać różne pliki profilu lub selektywnie wyłączyć PGO dla danej architektury, określ właściwości profile_file
, enable_profile_use
i cflags
dla każdej architektury. Przykład (z celem dotyczącym architektury w pogrubieniu):
cc_library { name: "libexample", srcs: [ "src1.cpp", "src2.cpp", ], static: [ "libstatic1", "libstatic2", ], shared: [ "libshared1", ], pgo: { instrumentation: true, benchmarks: [ "benchmark1", "benchmark2", ], } target: { android_arm: { pgo: { profile_file: "example_arm.profdata", } }, android_arm64: { pgo: { profile_file: "example_arm64.profdata", } } } }
Aby podczas profilowania na podstawie instrumentacji rozwiązywać odwołania do biblioteki profilowania w czasie wykonywania, przekaż linkerowi flagę kompilacji -fprofile-generate
. Biblioteki statyczne zinstrumentowane za pomocą PGO, wszystkie biblioteki współdzielone i wszystkie pliki binarne, które są bezpośrednio zależne od biblioteki statycznej, muszą być również zinstrumentowane za pomocą PGO. Takie udostępnione biblioteki lub pliki wykonywalne nie muszą jednak używać profili PGO, a właściwość enable_profile_use
może mieć wartość false
.
Poza tą restrykcją możesz zastosować PGO do dowolnej statycznej biblioteki, współdzielonej biblioteki lub pliku wykonywalnego.
Obsługa plików profilu LLVM
Wykonywanie zinstrumentowanej biblioteki lub pliku wykonywalnego powoduje wygenerowanie pliku profilu o nazwie default_unique_id_0.profraw
w folderze /data/local/tmp
(gdzie unique_id
to identyfikator numeryczny, który jest niepowtarzalny dla tej biblioteki). Jeśli ten plik już istnieje, podczas zapisywania profili środowisko uruchomieniowe profilowania scala nowy profil ze starym. Pamiętaj, że deweloperzy aplikacji nie mają dostępu do wartości /data/local/tmp
. Powinni zamiast tego używać wartości takich jak /storage/emulated/0/Android/data/packagename/files
.
Aby zmienić lokalizację pliku profilu, ustaw zmienną środowiskową LLVM_PROFILE_FILE
w czasie wykonywania.
Następnie za pomocą narzędzia llvm-profdata
konwertujesz plik .profraw
(i ewentualnie scalasz kilka plików .profraw
) na plik .profdata
:
llvm-profdata merge -output=profile.profdata <.profraw and/or .profdata files>
profile.profdata
można wtedy zaimportować do drzewa źródeł na potrzeby kompilacji.
Jeśli podczas testu porównawczego wczytywane są skompilowane biblioteki binarne, każda z nich generuje osobny plik .profraw
z osobnym identyfikatorem. Wszystkie te pliki można zwykle scalić w jeden plik .profdata
i używać go do tworzenia PGO. W przypadku biblioteki, która jest używana przez inny test porównawczy, należy ją zoptymalizować, korzystając z profili z obu testów porównawczych. W tej sytuacji przydatna jest opcja show
: llvm-profdata
:
llvm-profdata merge -output=default_unique_id.profdata default_unique_id_0.profraw llvm-profdata show -all-functions default_unique_id.profdata
Aby zmapować unique_id na poszczególne biblioteki, wyszukaj w wyniku show
dla każdego unique_id nazwę funkcji, która jest unikalna dla danej biblioteki.
Studium przypadku: PGO dla ART
Przypadek ten przedstawia ART jako przykład, ale nie jest to dokładny opis rzeczywistego zestawu bibliotek profilowanych pod kątem ART ani ich wzajemnych zależności.
Kompilator dex2oat
w ART zależy od libart-compiler.so
, który z kolei zależy od libart.so
. Środowisko wykonawcze ART jest wdrażane głównie w libart.so
. Benchmarki dla kompilatora i czasu wykonywania będą różne:
Benchmark | Profilowane biblioteki |
---|---|
dex2oat
|
dex2oat (plik wykonywalny), libart-compiler.so ,libart.so |
art_runtime
|
libart.so
|
- Dodaj do
dex2oat
,libart-compiler.so
tę właściwośćpgo
:pgo: { instrumentation: true, benchmarks: ["dex2oat",], profile_file: "dex2oat.profdata", }
- Dodaj do pliku
libart.so
tę właściwośćpgo
:pgo: { instrumentation: true, benchmarks: ["art_runtime", "dex2oat",], profile_file: "libart.profdata", }
- Utwórz kompilacje z instrumentacją na potrzeby testów porównawczych
dex2oat
iart_runtime
za pomocą:make ANDROID_PGO_INSTRUMENT=dex2oat make ANDROID_PGO_INSTRUMENT=art_runtime
- Uruchom testy porównawcze z użyciem
dex2oat
iart_runtime
, aby uzyskać:- 3 pliki
.profraw
zdex2oat
(dex2oat_exe.profdata
,dex2oat_libart-compiler.profdata
idexeoat_libart.profdata
), zidentyfikowane za pomocą metody opisanej w artykule Przetwarzanie plików profilu LLVM. - pojedynczy
art_runtime_libart.profdata
,
- 3 pliki
- Utwórz wspólny plik profdata dla pliku wykonywalnego
dex2oat
ilibart-compiler.so
za pomocą:llvm-profdata merge -output=dex2oat.profdata \ dex2oat_exe.profdata dex2oat_libart-compiler.profdata
- Uzyskaj profil
libart.so
, zliczając profile z tych 2 benchmarków:llvm-profdata merge -output=libart.profdata \ dex2oat_libart.profdata art_runtime_libart.profdata
Liczby
libart.so
z 2 profili mogą się różnić, ponieważ punkty odniesienia różnią się liczbą przypadków testowych i czasem ich trwania. W takim przypadku możesz użyć złączenia ważonego:llvm-profdata merge -output=libart.profdata \ -weighted-input=2,dex2oat_libart.profdata \ -weighted-input=1,art_runtime_libart.profdata
Powyższe polecenie przypisuje profilowi z adresu
dex2oat
podwójną wagę. Rzeczywista waga powinna być określana na podstawie wiedzy w danej dziedzinie lub eksperymentowania. - Sprawdź pliki profilu
dex2oat.profdata
ilibart.profdata
w folderzetoolchain/pgo-profiles
, aby użyć ich podczas kompilacji.
Możesz też utworzyć pojedynczą wersję z wszystkimi zinstrumentowanymi bibliotekami za pomocą:
make ANDROID_PGO_INSTRUMENT=dex2oat,art_runtime (or) make ANDROID_PGO_INSTRUMENT=ALL
Drugie polecenie tworzy wszystkie moduły z włączonym PGO na potrzeby profilowania.