Profilgestützte Optimierung

Profilgestützte Optimierung ist eine bekannte Compiler-Optimierung, . In PGO werden Laufzeitprofile aus den Ausführungen eines Programms vom um optimale Entscheidungen über Inlining und Code-Layout zu treffen. Dies führt zu verbesserte Leistung und reduzierte Codegröße.

PGO kann mit den folgenden Schritten in Ihrer Anwendung oder Bibliothek bereitgestellt werden: 1. Identifizieren Sie eine repräsentative Arbeitslast. 2. Profile erfassen. 3. Profile in einem Release-Build verwenden

Schritt 1: Repräsentative Arbeitslast identifizieren

Bestimmen Sie zuerst eine repräsentative Benchmark oder Arbeitslast für Ihre Anwendung. Dies ist ein wichtiger Schritt, da die aus der Arbeitslast erfassten Profile die heißen und kalten Regionen im Code enthalten. Bei Verwendung der Profile führt der Compiler aggressive Optimierungen durchzuführen und sich in besonders beliebten Regionen zu positionieren. Der Compiler kann sich auch dafür entscheiden, die Codegröße von selten genutzten Regionen zu reduzieren, die Leistung.

Das Identifizieren einer guten Arbeitslast ist auch hilfreich, um die Leistung in allgemein.

Schritt 2: Profile erfassen

Die Profilerfassung umfasst drei Schritte: – nativen Code mit Instrumentierung erstellen, – die instrumentierte App auf dem Gerät ausführen und Profile generieren – Zusammenführen/Nachverarbeiten der Profile auf dem Host

Instrumentierten Build erstellen

Die Profile werden erfasst, indem die Arbeitslast aus Schritt 1 auf einem den instrumentierten Build der Anwendung. Um einen instrumentierten Build zu generieren, fügen Sie -fprofile-generate zu den Compiler- und Verknüpfungs-Flags. Dieses Flag sollte gesteuert wird, da das Flag während einer Standard-Build

Profile erstellen

Führen Sie als Nächstes die instrumentierte App auf dem Gerät aus und generieren Sie Profile. Profile werden im Arbeitsspeicher erfasst, wenn die instrumentierte Binärdatei ausgeführt wird und beim Beenden in eine Datei geschrieben. Mit atexit registrierte Funktionen sind jedoch nicht in einer Android-App aufgerufen wird – die App bricht ab.

Die Anwendung/Arbeitslast muss zusätzliche Arbeit leisten, um einen Pfad für die Profildatei festzulegen. und dann explizit einen Profilschreibvorgang auslösen.

  • Um den Pfad der Profildatei festzulegen, rufen Sie __llvm_profile_set_filename(PROFILE_DIR "/default-%m.profraw %m ist hilfreich wenn es mehrere gemeinsam genutzte Bibliotheken gibt. %m` wird zu einem eindeutigen Modul erweitert. Signatur für diese Bibliothek, was zu einem separaten Profil pro Bibliothek führt. Weitere Informationen finden Sie unter hier für weitere nützliche Musterspezifizierer. PROFILE_DIR ist ein Verzeichnis, die über die App geschrieben werden können. Demo ansehen zur Ermittlung dieses Verzeichnisses während der Laufzeit.
  • Rufen Sie zum expliziten Auslösen eines Profilschreibvorgangs die Methode __llvm_profile_write_file auf. .
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;
}

Hinweis: Das Generieren der Profildatei ist einfacher, wenn die Arbeitslast eine eigenständige Binärdatei ist: legen Sie einfach die Umgebungsvariable LLVM_PROFILE_FILE auf %t/default-%m.profraw bevor die Binärdatei ausgeführt wird.

Nachbearbeitung von Profilen

Die Profildateien liegen im .profraw-Format vor. Sie müssen zuerst von mit adb pull auf das Gerät. Verwenden Sie nach dem Abruf das Dienstprogramm llvm-profdata in NDK zur Konvertierung von .profraw in .profdata, das dann an den Compiler.

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

llvm-profdata und clang aus demselben NDK-Release verwenden, um Version zu vermeiden Die Formate der Profildatei stimmen nicht überein.

Schritt 3: Profile zum Erstellen der Anwendung verwenden

Verwenden Sie das Profil aus dem vorherigen Schritt während eines Release-Builds Ihres -Anwendung hinzu, indem Sie -fprofile-use=<>.profdata an den Compiler und den Linker übergeben. Die Profile können auch dann verwendet werden, wenn sich der Code weiterentwickelt – der Clang-Compiler kann diese Funktion tolerieren. Die Quelle stimmt mit den Profilen leicht nicht überein.

Hinweis: Bei den meisten Bibliotheken werden die Profile in der Regel in allen Architekturen verwendet. Beispielsweise können Profile, die aus dem Arm64-Build der Bibliothek generiert wurden, für alle Architekturen. Allerdings müssen architekturspezifische Codepfade in der Bibliothek (Verzweigung oder x86- oder 32-Bit- oder 64-Bit-Version), separate Profile die für jede Konfiguration verwendet werden sollen.

Zusammenfassung

https://github.com/DanAlbert/ndk-samples/tree/pgo/pgo zeigt eine End-to-End-Demo zur Verwendung von PGO über eine App. Sie bietet zusätzliche die in diesem Dokument bereits überflogen sind.

  • Der CMake-Build Regeln wie Sie eine CMake-Variable einrichten, die nativen Code mit Instrumentierung erstellt. Ist keine Build-Variable festgelegt, wird nativer Code mithilfe der bisherigen von PGO-Profilen.
  • Bei einem instrumentierten Build pgodemo.cpp schreibt die Profile die Ausführung von Arbeitslasten.
  • Ein beschreibbarer Speicherort für die Profile wird zur Laufzeit abgerufen in Hauptaktivität.kt mit applicationContext.cacheDir.toString().
  • Wenn du Profile vom Gerät abrufen möchtest, ohne dass adb root erforderlich ist, verwende die adb Rezept hier.