Utilizza l'ottimizzazione guidata dal profilo

Il sistema di compilazione per Android 13 e versioni precedenti supporta l'utilizzo della guida al profilo di Clang ottimizzazione (PGO) su moduli Android nativi con build di progetto le regole del caso. In questa pagina viene descritto Clang PGO, che spiega come generare e aggiornare continuamente profili utilizzati per PGO e come integrare PGO con il sistema di compilazione (con questo caso d'uso).

Nota: questo documento descrive l'utilizzo di PGO nella piattaforma Android. Per informazioni sull'utilizzo PGO da un'app Android, visita questa pagina.

Informazioni su Clang PGO

Clang può eseguire l'ottimizzazione guidata dal profilo utilizzando due tipi di profili:

  • I profili basati sulla strumentazione sono generati da una programma target strumentato. Questi profili sono dettagliati e impongono un l'overhead del runtime.
  • I profili basati sul campionamento sono generalmente prodotti di campionamento dei contatori hardware. Imporranno un overhead di runtime basso e possono essere raccolti senza alcuna strumentazione o modifica al file binario. Loro sono meno dettagliate rispetto ai profili basati sulla strumentazione.

Tutti i profili devono essere generati da un carico di lavoro rappresentativo il comportamento tipico dell'app. Anche se Clang supporta Basato su AST (-fprofile-instr-generate) e LLVM IR (-fprofile-generate), Android supporta solo le porte LLVM basate su IR per basato su strumentazione.

Per creare la raccolta dei profili sono necessari i seguenti flag:

  • -fprofile-generate per la strumentazione basata su IR. Con questo , il backend utilizza un approccio ad albero di spanning minimo ponderato per ridurre il numero di punti di strumentazione e ottimizzare il loro posizionamento (utilizza questa opzione anche per il passaggio del collegamento). The Clang il driver supera automaticamente il runtime di profilazione (libclang_rt.profile-arch-android.a) al linker. Questa libreria contiene routine per scrivere i profili su disco in base al programma .
  • -gline-tables-only per la raccolta dei profili basata sul campionamento per generare informazioni di debug minime.

È possibile usare un profilo per PGO usando -fprofile-use=pathname o -fprofile-sample-use=pathname per i dati basati su strumentazione e profili basati sul campionamento.

Nota:man mano che vengono apportate modifiche al codice, se Clang non può utilizzare i dati del profilo, questo genera Avviso -Wprofile-instr-out-of-date.

Usa PGO

L'utilizzo di PGO prevede i seguenti passaggi:

  1. Crea la libreria/eseguibile con la strumentazione passando -fprofile-generate al compilatore e al linker.
  2. Raccogli i profili eseguendo un carico di lavoro rappresentativo sul binario strumentato.
  3. Completa l'elaborazione dei profili utilizzando l'utilità llvm-profdata (per maggiori dettagli, consulta Gestione delle VM LLVM file del profilo).
  4. Utilizza i profili per applicare l'autorizzazione PGO superando -fprofile-use=<>.profdata al compilatore e Linker.

Per PGO in Android, i profili devono essere raccolti offline e registrati insieme al codice per garantire build riproducibili. I profili possono essere utilizzati il codice si evolve, ma deve essere rigenerato periodicamente (o ogni volta che Clang avvisa che i profili sono obsoleti).

Raccogliere i profili

Clang può utilizzare i profili raccolti eseguendo benchmark utilizzando un della libreria o campionando i contatori hardware quando il benchmark viene eseguito. Al momento, Android non supporta l'uso di modelli basati sul campionamento raccolta di profili, pertanto devi raccogliere i profili utilizzando una build:

  1. Identificare un benchmark e l'insieme di biblioteche collettivamente esercitate a quel benchmark.
  2. Aggiungi proprietà pgo al benchmark e alle librerie (dettagli di seguito).
  3. Produce una build Android con una copia instrumentata di queste librerie con:
    make ANDROID_PGO_INSTRUMENT=benchmark

benchmark è un segnaposto che identifica di librerie strumentate durante la creazione. Il rappresentante effettivo di input (ed eventualmente un altro eseguibile che collega a una libreria benchmark) non sono specifiche per PGO e non rientrano nell'ambito di queste documento.

  1. Esegui il flashing o la sincronizzazione della build con strumentazione su un dispositivo.
  2. Esegui il benchmark per raccogliere i profili.
  3. Usa lo strumento llvm-profdata (considerato di seguito) a post-elaborare i profili e renderli pronti per essere registrati nell'origine. albero di Natale.

Utilizza i profili durante la creazione

Controlla i profili in toolchain/pgo-profiles su un Android albero di Natale. Il nome deve corrispondere a quello specificato nel profile_file proprietà secondaria della proprietà pgo per nella libreria. Il sistema di compilazione passa automaticamente il file del profilo a Clang. durante la creazione della biblioteca. ANDROID_PGO_DISABLE_PROFILE_USE di ambiente può essere impostata su true per disattivare temporaneamente PGO e misurarne i vantaggi in termini di rendimento.

Per specificare ulteriori directory del profilo specifiche del prodotto, aggiungile a la variabile make PGO_ADDITIONAL_PROFILE_DIRECTORIES in una BoardConfig.mk. Se vengono specificati percorsi aggiuntivi, i profili in questi percorsi sostituiscono quelli in toolchain/pgo-profiles.

Quando generi un'immagine di release utilizzando il target dist per make, il sistema di compilazione scrive i nomi dei file di profilo mancanti a $DIST_DIR/pgo_profile_file_missing.txt. Puoi controllare per vedere quali file del profilo sono stati eliminati per errore (operazione che disattiva PGO).

Attiva PGO nei file Android.bp

Per attivare PGO nei file Android.bp per i moduli nativi, è sufficiente specificare la proprietà pgo. Questa proprietà ha quanto segue proprietà secondarie:

Proprietà Descrizione
instrumentation Imposta su true per PGO utilizzando la strumentazione. Il valore predefinito è false.
sampling Imposta su true per PGO utilizzando il campionamento. Il valore predefinito è false.
benchmarks Elenco di stringhe. Questo modulo è realizzato per la profilazione di eventuali benchmark nell'elenco è specificato nella build ANDROID_PGO_INSTRUMENT .
profile_file File del profilo (relativo a toolchain/pgo-profile) da utilizzare con PGO. La build avvisa che il file non esiste aggiungendo questo file in $DIST_DIR/pgo_profile_file_missing.txt a meno che la proprietà enable_profile_use sia impostata su false OPPURE La variabile di build ANDROID_PGO_NO_PROFILE_USE è impostata su true.
enable_profile_use Imposta su false se non è necessario utilizzare profili durante creare. Può essere utilizzato durante il bootstrap per attivare la raccolta del profilo o per disattivare temporaneamente PGO. Il valore predefinito è true.
cflags Elenco di flag aggiuntivi da utilizzare durante una build instrumentata.

Esempio di modulo con 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",
    }
}

Se i benchmark benchmark1 e benchmark2 applicare un comportamento rappresentativo delle biblioteche libstatic1, libstatic2, o libshared1, la pgo di queste librerie possono includere anche i benchmark. La defaults modulo in Android.bp può includere un pgo per un insieme di librerie per evitare di ripetere i valori le stesse regole di build per più moduli.

Per selezionare diversi file di profilo o disattivare selettivamente PGO per un specifica l'profile_file, enable_profile_use e cflags proprietà per dell'architettura. Esempio (con architettura di destinazione in grassetto):

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",
              }
         }
    }
}

Per risolvere i riferimenti alla libreria di runtime di profilazione durante profilazione basata su strumentazione, passare il flag di build -fprofile-generate al linker. Librerie statiche instrumentate con PGO, tutte le librerie condivise e qualsiasi programma binario che dipende direttamente la libreria statica deve essere anche strumentata per PGO. Tuttavia, tali elementi per le librerie o gli eseguibili non hanno bisogno di utilizzare profili PGO e i relativi La proprietà enable_profile_use può essere impostata su false. Al di fuori di questa limitazione, puoi applicare PGO a qualsiasi libreria statica, condivisa o eseguibile.

Gestire i file del profilo LLVM

L'esecuzione di una libreria con strumenti o di un eseguibile produce un file di profilo chiamato default_unique_id_0.profraw in /data/local/tmp (dove unique_id è un hash numerico univoco per questa libreria). Se il file esiste già, il runtime di profilazione unisce il nuovo profilo a quello precedente durante la scrittura i profili. Tieni presente che /data/local/tmp non è accessibile all'app sviluppatori; da usare, ad esempio, /storage/emulated/0/Android/data/packagename/files in alternativa. Per modificare la posizione del file del profilo, imposta LLVM_PROFILE_FILE di ambiente in fase di runtime.

llvm-profdata viene utilizzata per convertire il file .profraw (ed eventualmente unisci più file .profraw) in un file .profdata file:

  llvm-profdata merge -output=profile.profdata <.profraw and/or .profdata files>

È quindi possibile eseguire il check-in di profile.profdata nell'origine da usare durante la creazione.

Se durante un benchmark vengono caricati più file binari/librerie con strumenti, ogni libreria genera un file .profraw separato con un univoco. In genere, tutti questi file possono essere uniti .profdata e utilizzato per la build PGO. Nei casi in cui una libreria viene esercitata da un altro benchmark, la libreria deve essere ottimizzata utilizzando i profili di entrambi i benchmark. In questa situazione, show l'opzione llvm-profdata è utile:

  llvm-profdata merge -output=default_unique_id.profdata default_unique_id_0.profraw
llvm-profdata show -all-functions default_unique_id.profdata

Per mappare unique_id a singole librerie, cerca nella Output show per ogni unique_id per il nome di una funzione che è univoco per la libreria.

Case study: PGO per ART

Il case study presenta l'ART come esempio di facile immedesimazione: ma non è Una descrizione accurata dell'insieme effettivo di biblioteche profilate per ART o le loro interdipendenze.

Il compilatore dex2oat in anticipo in ART dipende da libart-compiler.so, che a sua volta dipende libart.so. Il runtime ART è implementato principalmente libart.so. I benchmark per il compilatore e il runtime diverso:

Benchmark Librerie profilate
dex2oat dex2oat (eseguibile), libart-compiler.so, libart.so
art_runtime libart.so
  1. Aggiungi la seguente proprietà pgo a dex2oat, libart-compiler.so:
        pgo: {
            instrumentation: true,
            benchmarks: ["dex2oat",],
            profile_file: "dex2oat.profdata",
        }
  2. Aggiungi la seguente proprietà pgo a libart.so:
        pgo: {
            instrumentation: true,
            benchmarks: ["art_runtime", "dex2oat",],
            profile_file: "libart.profdata",
        }
  3. Crea build con strumenti per dex2oat e art_runtime benchmark che utilizzano:
        make ANDROID_PGO_INSTRUMENT=dex2oat
        make ANDROID_PGO_INSTRUMENT=art_runtime
  4. In alternativa, crea un'unica build con strumenti con tutte le librerie instrumentate con:

        make ANDROID_PGO_INSTRUMENT=dex2oat,art_runtime
        (or)
        make ANDROID_PGO_INSTRUMENT=ALL

    Il secondo comando crea tutti i moduli abilitati per PGO la profilazione.

  5. Esegui i benchmark con l'allenamento dex2oat e art_runtime per ottenere:
      .
    • Tre file .profraw da dex2oat (dex2oat_exe.profdata, dex2oat_libart-compiler.profdata e dexeoat_libart.profdata), identificato utilizzando il metodo descritta in Gestione del profilo LLVM .
    • Un singolo art_runtime_libart.profdata.
  6. Produci un file profdata comune per l'eseguibile dex2oat e libart-compiler.so con:
    llvm-profdata merge -output=dex2oat.profdata \
        dex2oat_exe.profdata dex2oat_libart-compiler.profdata
  7. Ottieni il profilo per libart.so unendo i profili dei due benchmark:
    llvm-profdata merge -output=libart.profdata \
        dex2oat_libart.profdata art_runtime_libart.profdata

    I conteggi non elaborati di libart.so dei due profili potrebbero essere perché i benchmark differiscono nel numero di scenari di test e durata massima di esecuzione. In questo caso, puoi utilizzare un'unione ponderata:

    llvm-profdata merge -output=libart.profdata \
        -weighted-input=2,dex2oat_libart.profdata \
        -weighted-input=1,art_runtime_libart.profdata

    Il comando precedente assegna il doppio del peso al profilo da dex2oat. La ponderazione effettiva deve essere determinata in base al dominio conoscenza o sperimentazione.

  8. Controlla i file del profilo dex2oat.profdata e libart.profdata in toolchain/pgo-profiles per durante la creazione.