Le système de construction Android pour Android 13 et versions antérieures prend en charge l'optimisation guidée par profil (PGO) de Clang sur les modules Android natifs dotés de règles de construction de modèles . Cette page décrit Clang PGO, comment générer et mettre à jour en permanence les profils utilisés pour PGO, et comment intégrer PGO au système de build (avec cas d'utilisation).
NB : Ce document décrit l'utilisation de PGO dans la plateforme Android. Pour en savoir plus sur l'utilisation de PGO à partir d'une application Android, visitez cette page .
À propos de Clang PGO
Clang peut effectuer une optimisation guidée par profil à l'aide de deux types de profils :
- Des profils basés sur l'instrumentation sont générés à partir d'un programme cible instrumenté. Ces profils sont détaillés et imposent une surcharge d'exécution élevée.
- Les profils basés sur l'échantillonnage sont généralement produits par des compteurs matériels d'échantillonnage. Ils imposent une faible surcharge d'exécution et peuvent être collectés sans aucune instrumentation ni modification du binaire. Ils sont moins détaillés que les profils basés sur l’instrumentation.
Tous les profils doivent être générés à partir d'une charge de travail représentative qui exerce le comportement typique de l'application. Alors que Clang prend en charge à la fois les versions AST ( -fprofile-instr-generate
) et LLVM IR ( -fprofile-generate)
, Android ne prend en charge que les versions LLVM IR pour les PGO basés sur l'instrumentation.
Les indicateurs suivants sont nécessaires pour créer la collection de profils :
-
-fprofile-generate
pour l'instrumentation basée sur l'IR. Avec cette option, le backend utilise une approche d'arbre couvrant minimal pondéré pour réduire le nombre de points d'instrumentation et optimiser leur placement sur des bords de faible poids (utilisez également cette option pour l'étape de liaison). Le pilote Clang transmet automatiquement le runtime de profilage (libclang_rt.profile- arch -android.a
) à l'éditeur de liens. Cette bibliothèque contient des routines pour écrire les profils sur le disque à la sortie du programme. -
-gline-tables-only
pour la collecte de profils basée sur l'échantillonnage afin de générer un minimum d'informations de débogage.
Un profil peut être utilisé pour PGO en utilisant -fprofile-use= pathname
ou -fprofile-sample-use= pathname
pour les profils basés sur l'instrumentation et basés sur l'échantillonnage respectivement.
Remarque : au fur et à mesure que des modifications sont apportées au code, si Clang ne peut plus utiliser les données de profil, il génère un avertissement -Wprofile-instr-out-of-date
.
Utiliser PGO
L'utilisation de PGO implique les étapes suivantes :
- Construisez la bibliothèque/l'exécutable avec l'instrumentation en passant
-fprofile-generate
au compilateur et à l'éditeur de liens. - Collectez des profils en exécutant une charge de travail représentative sur le binaire instrumenté.
- Post-traitez les profils à l'aide de l'utilitaire
llvm-profdata
(pour plus de détails, voir Gestion des fichiers de profil LLVM ). - Utilisez les profils pour appliquer PGO en transmettant
-fprofile-use=<>.profdata
au compilateur et à l'éditeur de liens.
Pour PGO sur Android, les profils doivent être collectés hors ligne et enregistrés avec le code pour garantir des versions reproductibles. Les profils peuvent être utilisés au fur et à mesure de l'évolution du code, mais doivent être régénérés périodiquement (ou chaque fois que Clang avertit que les profils sont obsolètes).
Collecter des profils
Clang peut utiliser des profils collectés en exécutant des tests de performance à l'aide d'une version instrumentée de la bibliothèque ou en échantillonnant des compteurs matériels lors de l'exécution du test de performance. Pour le moment, Android ne prend pas en charge l'utilisation de la collecte de profils basée sur l'échantillonnage. Vous devez donc collecter des profils à l'aide d'une version instrumentée :
- Identifiez un benchmark et l’ensemble des bibliothèques exercées collectivement par ce benchmark.
- Ajoutez des propriétés
pgo
au benchmark et aux bibliothèques (détails ci-dessous). - Produisez une version Android avec une copie instrumentée de ces bibliothèques en utilisant :
make ANDROID_PGO_INSTRUMENT=benchmark
benchmark
est un espace réservé qui identifie la collection de bibliothèques instrumentées lors de la construction. Les entrées représentatives réelles (et éventuellement un autre exécutable lié à une bibliothèque en cours d'évaluation) ne sont pas spécifiques à PGO et dépassent la portée de ce document.
- Flashez ou synchronisez la version instrumentée sur un appareil.
- Exécutez le benchmark pour collecter des profils.
- Utilisez l'outil
llvm-profdata
(discuté ci-dessous) pour post-traiter les profils et les préparer à être archivés dans l'arborescence source.
Utiliser des profils pendant la construction
Vérifiez les profils dans toolchain/pgo-profiles
dans une arborescence Android. Le nom doit correspondre à ce qui est spécifié dans la sous-propriété profile_file
de la propriété pgo
de la bibliothèque. Le système de construction transmet automatiquement le fichier de profil à Clang lors de la construction de la bibliothèque. La variable d'environnement ANDROID_PGO_DISABLE_PROFILE_USE
peut être définie sur true
pour désactiver temporairement PGO et mesurer ses avantages en termes de performances.
Pour spécifier des répertoires de profils supplémentaires spécifiques au produit, ajoutez-les à la variable make PGO_ADDITIONAL_PROFILE_DIRECTORIES
dans un BoardConfig.mk
. Si des chemins supplémentaires sont spécifiés, les profils de ces chemins remplacent ceux de toolchain/pgo-profiles
.
Lors de la génération d'une image de version à l'aide de la cible dist
à make
, le système de construction écrit les noms des fichiers de profil manquants dans $DIST_DIR/pgo_profile_file_missing.txt
. Vous pouvez vérifier ce fichier pour voir quels fichiers de profil ont été accidentellement supprimés (ce qui désactive silencieusement PGO).
Activer PGO dans les fichiers Android.bp
Pour activer PGO dans les fichiers Android.bp
pour les modules natifs, spécifiez simplement la propriété pgo
. Cette propriété possède les sous-propriétés suivantes :
Propriété | Description |
---|---|
instrumentation | Défini sur true pour PGO à l’aide de l’instrumentation. La valeur par défaut est false . |
sampling | Défini sur true pour PGO à l’aide de l’échantillonnage. La valeur par défaut est false . |
benchmarks | Liste de chaînes. Ce module est conçu pour le profilage si un benchmark de la liste est spécifié dans l'option de construction ANDROID_PGO_INSTRUMENT . |
profile_file | Fichier de profil (relatif à toolchain/pgo-profile ) à utiliser avec PGO. La build avertit que ce fichier n'existe pas en ajoutant ce fichier à $DIST_DIR/pgo_profile_file_missing.txt à moins que la propriété enable_profile_use soit définie sur false OU que la variable de build ANDROID_PGO_NO_PROFILE_USE soit définie sur true . |
enable_profile_use | Définissez sur false si les profils ne doivent pas être utilisés pendant la construction. Peut être utilisé pendant le bootstrap pour activer la collecte de profils ou pour désactiver temporairement PGO. La valeur par défaut est true . |
cflags | Liste des indicateurs supplémentaires à utiliser lors d'une build instrumentée. |
Exemple de module avec 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", } }
Si les benchmarks benchmark1
et benchmark2
exercent un comportement représentatif pour les bibliothèques libstatic1
, libstatic2
ou libshared1
, la propriété pgo
de ces bibliothèques peut également inclure les benchmarks. Le module defaults
dans Android.bp
peut inclure une spécification pgo
commune pour un ensemble de bibliothèques afin d'éviter de répéter les mêmes règles de construction pour plusieurs modules.
Pour sélectionner différents fichiers de profil ou désactiver sélectivement PGO pour une architecture, spécifiez les propriétés profile_file
, enable_profile_use
et cflags
par architecture. Exemple (avec architecture cible en gras ) :
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", } } } }
Pour résoudre les références à la bibliothèque d'exécution de profilage lors du profilage basé sur l'instrumentation, transmettez l'indicateur de build -fprofile-generate
à l'éditeur de liens. Les bibliothèques statiques instrumentées avec PGO, toutes les bibliothèques partagées et tout binaire dépendant directement de la bibliothèque statique doivent également être instrumentés pour PGO. Cependant, ces bibliothèques partagées ou exécutables n'ont pas besoin d'utiliser des profils PGO, et leur propriété enable_profile_use
peut être définie sur false
. En dehors de cette restriction, vous pouvez appliquer PGO à n’importe quelle bibliothèque statique, bibliothèque partagée ou exécutable.
Gérer les fichiers de profil LLVM
L'exécution d'une bibliothèque instrumentée ou d'un exécutable produit un fichier de profil nommé default_ unique_id _0.profraw
dans /data/local/tmp
(où unique_id
est un hachage numérique unique à cette bibliothèque). Si ce fichier existe déjà, le runtime de profilage fusionne le nouveau profil avec l'ancien lors de l'écriture des profils. Notez que /data/local/tmp
n'est pas accessible aux développeurs d'applications ; ils devraient plutôt utiliser quelque part comme /storage/emulated/0/Android/data/ packagename /files
. Pour modifier l'emplacement du fichier de profil, définissez la variable d'environnement LLVM_PROFILE_FILE
au moment de l'exécution.
L'utilitaire llvm-profdata
est ensuite utilisé pour convertir le fichier .profraw
(et éventuellement fusionner plusieurs fichiers .profraw
) en un fichier .profdata
:
llvm-profdata merge -output=profile.profdata <.profraw and/or .profdata files>
profile.profdata
peut ensuite être archivé dans l'arborescence source pour être utilisé pendant la construction.
Si plusieurs binaires/bibliothèques instrumentés sont chargés lors d'un test, chaque bibliothèque génère un fichier .profraw
distinct avec un ID unique distinct. En règle générale, tous ces fichiers peuvent être fusionnés en un seul fichier .profdata
et utilisés pour la construction de PGO. Dans les cas où une bibliothèque est exercée par un autre benchmark, cette bibliothèque doit être optimisée à l'aide des profils des deux benchmarks. Dans cette situation, l'option show
de llvm-profdata
est utile :
llvm-profdata merge -output=default_unique_id.profdata default_unique_id_0.profraw llvm-profdata show -all-functions default_unique_id.profdata
Pour mapper les unique_id à des bibliothèques individuelles, recherchez dans la sortie show
pour chaque unique_id un nom de fonction unique à la bibliothèque.
Étude de cas : PGO pour ART
L'étude de cas présente ART comme un exemple pertinent ; cependant, il ne s'agit pas d'une description précise de l'ensemble réel de bibliothèques profilées pour ART ou de leurs interdépendances.
Le compilateur avancé dex2oat
dans ART dépend de libart-compiler.so
, qui à son tour dépend de libart.so
. Le runtime ART est implémenté principalement dans libart.so
. Les benchmarks pour le compilateur et le runtime seront différents :
Référence | Bibliothèques profilées |
---|---|
dex2oat | dex2oat (exécutable), libart-compiler.so , libart.so |
art_runtime | libart.so |
- Ajoutez la propriété
pgo
suivante àdex2oat
,libart-compiler.so
:pgo: { instrumentation: true, benchmarks: ["dex2oat",], profile_file: "dex2oat.profdata", }
- Ajoutez la propriété
pgo
suivante àlibart.so
:pgo: { instrumentation: true, benchmarks: ["art_runtime", "dex2oat",], profile_file: "libart.profdata", }
- Créez des builds instrumentés pour les benchmarks
dex2oat
etart_runtime
en utilisant :make ANDROID_PGO_INSTRUMENT=dex2oat make ANDROID_PGO_INSTRUMENT=art_runtime
- Exécutez les benchmarks en exerçant
dex2oat
etart_runtime
pour obtenir :- Trois fichiers
.profraw
dedex2oat
(dex2oat_exe.profdata
,dex2oat_libart-compiler.profdata
etdexeoat_libart.profdata
), identifiés à l'aide de la méthode décrite dans Gestion des fichiers de profil LLVM . - Un seul
art_runtime_libart.profdata
.
- Trois fichiers
- Produisez un fichier profdata commun pour l'exécutable
dex2oat
etlibart-compiler.so
en utilisant :llvm-profdata merge -output=dex2oat.profdata \ dex2oat_exe.profdata dex2oat_libart-compiler.profdata
- Obtenez le profil pour
libart.so
en fusionnant les profils des deux benchmarks :llvm-profdata merge -output=libart.profdata \ dex2oat_libart.profdata art_runtime_libart.profdata
Les décomptes bruts pour
libart.so
des deux profils peuvent être disparates car les tests diffèrent par le nombre de cas de test et la durée pendant laquelle ils s'exécutent. Dans ce cas, vous pouvez utiliser une fusion pondérée :llvm-profdata merge -output=libart.profdata \ -weighted-input=2,dex2oat_libart.profdata \ -weighted-input=1,art_runtime_libart.profdata
La commande ci-dessus attribue deux fois le poids au profil de
dex2oat
. Le poids réel doit être déterminé en fonction des connaissances du domaine ou de l'expérimentation. - Vérifiez les fichiers de profil
dex2oat.profdata
etlibart.profdata
danstoolchain/pgo-profiles
pour les utiliser pendant la construction.
Vous pouvez également créer une seule version instrumentée avec toutes les bibliothèques instrumentées à l'aide de :
make ANDROID_PGO_INSTRUMENT=dex2oat,art_runtime (or) make ANDROID_PGO_INSTRUMENT=ALL
La deuxième commande crée tous les modules compatibles PGO pour le profilage.