Profil odaklı optimizasyonu kullanma

Android 13 ve önceki sürümler için Android derleme sistemi, blueprint derleme kurallarına sahip yerel Android modüllerinde Clang'ın profil odaklı optimizasyonunu (PGO) kullanmayı destekler. Bu sayfada Clang PGO, PGO için kullanılan profillerin sürekli olarak nasıl oluşturulacağı ve güncelleneceği ve PGO'nun derleme sistemiyle nasıl entegre edileceği (kullanım alanıyla birlikte) açıklanmaktadır.

Not: Bu dokümanda, PGO'nun Android platformunda kullanımı açıklanmaktadır. Android uygulamasından PGO'yu kullanma hakkında bilgi edinmek için bu sayfayı ziyaret edin.

Clang PGO hakkında

Clang, iki tür profil kullanarak profile dayalı optimizasyon gerçekleştirebilir:

  • Enstrümantasyona dayalı profiller, enstrümante edilmiş bir hedef programdan oluşturulur. Bu profiller ayrıntılıdır ve çalışma zamanında yüksek bir yükü beraberinde getirir.
  • Örneklemeye dayalı profiller genellikle donanım sayaçları örneklenerek oluşturulur. Bunlar, çalışma zamanında düşük bir yükü yükler ve ikili dosyada herhangi bir enstrümantasyon veya değişiklik yapılmadan toplanabilir. Bu profiller, enstrümantasyon tabanlı profillere kıyasla daha az ayrıntılıdır.

Tüm profiller, uygulamanın tipik davranışını gösteren temsili bir iş yükünden oluşturulmalıdır. Clang hem AST tabanlı (-fprofile-instr-generate) hem de LLVM IR tabanlı (-fprofile-generate)) profilleri desteklese de Android, enstrümantasyon tabanlı PGO için yalnızca LLVM IR tabanlı profilleri destekler.

Profil koleksiyonu için derleme işleminde aşağıdaki işaretler gereklidir:

  • -fprofile-generate kızılötesi tabanlı enstrümasyon için. Bu seçenekte arka uç, instrumentasyon noktalarının sayısını azaltmak ve bunların yerleşimini düşük ağırlıklı kenarlara göre optimize etmek için ağırlıklı minimum kapsayıcı ağaç yaklaşımını kullanır (bu seçeneği bağlantı adımı için de kullanın). Clang sürücüsü, profil oluşturma çalışma zamanını (libclang_rt.profile-arch-android.a) bağlayıcıya otomatik olarak iletir. Bu kitaplık, programdan çıktığınızda profilleri diske yazma rutinlerini içerir.
  • -gline-tables-only için örneklemeye dayalı profil toplama

Bir profil, sırasıyla -fprofile-use=pathname veya -fprofile-sample-use=pathname kullanılarak instrumentasyon tabanlı ve örnekleme tabanlı profiller için PGO'da kullanılabilir.

Not: Kodda değişiklik yapıldığında Clang artık profil verilerini kullanamazsa -Wprofile-instr-out-of-date uyarısı oluşturur.

PGO'yu kullanma

PGO'yu kullanma adımları şunlardır:

  1. Derleyiciye ve bağlayıcıya -fprofile-generate ileterek kitaplığı/yürütülebilir dosyayı enstrümantasyonla derleyin.
  2. Enstrümante edilmiş ikili dosyada temsili bir iş yükü çalıştırarak profiller toplayın.
  3. llvm-profdata yardımcı programını kullanarak profilleri son işleme tabi tutun (ayrıntılar için LLVM profil dosyalarını işleme başlıklı makaleyi inceleyin).
  4. Derleyiciye ve bağlayıcıya -fprofile-use=<>.profdata ileterek PGO'yu uygulamak için profilleri kullanın.

Android'de PGO için profiller çevrimdışı olarak toplanmalı ve yeniden üretilebilir derlemeler sağlamak amacıyla kodla birlikte kontrol edilmelidir. Profiller, kod geliştikçe kullanılabilir ancak düzenli aralıklarla (veya Clang, profillerin güncel olmadığı konusunda uyarı verdiğinde) yeniden oluşturulmalıdır.

Profil toplama

Clang, kitaplığın enstrümante edilmiş bir derlemesini kullanarak veya karşılaştırma çalıştırıldığında donanım sayaçları örnekleyerek karşılaştırma çalıştırarak toplanan profilleri kullanabilir. Android şu anda örneklemeye dayalı profil toplamayı desteklemediğinden, enstrümante edilmiş bir derleme kullanarak profilleri toplamanız gerekir:

  1. Bir karşılaştırma ölçütünü ve bu karşılaştırma ölçütünün toplu olarak kullandığı kitaplık grubunu tanımlayın.
  2. Karşılaştırmaya ve kitaplıklara pgo mülkleri ekleyin (ayrıntılar aşağıdadır).
  3. Aşağıdakileri kullanarak bu kitaplıkların enstrümante edilmiş bir kopyasıyla Android derlemesi oluşturun:
    make ANDROID_PGO_INSTRUMENT=benchmark

benchmark, derleme sırasında enstrümante edilen kitaplık koleksiyonunu tanımlayan bir yer tutucusudur. Gerçek temsili girişler (ve muhtemelen karşılaştırma yapılan bir kitaplığa bağlantı veren başka bir yürütülebilir dosya) PGO'ya özel değildir ve bu dokümanın kapsamı dışındadır.

  1. Enstrümante edilmiş derlemeyi bir cihaza yükleyin veya senkronize edin.
  2. Profil toplamak için karşılaştırmayı çalıştırın.
  3. Profilleri son işleme tabi tutmak ve kaynak ağacına eklenmeye hazır hale getirmek için llvm-profdata aracını (aşağıda açıklanmıştır) kullanın.

Derleme sırasında profilleri kullanma

Android ağacında toolchain/pgo-profiles içindeki profilleri kontrol edin. Ad, kitaplığın pgo mülkünün profile_file alt mülkünde belirtilen adla eşleşmelidir. Derleme sistemi, kitaplığı derlerken profil dosyasını otomatik olarak Clang'a iletir. ANDROID_PGO_DISABLE_PROFILE_USE ortam değişkeni, PGO'yu geçici olarak devre dışı bırakmak ve performans avantajını ölçmek için true olarak ayarlanabilir.

Ürüne özel ek profil dizinleri belirtmek için bunları PGO_ADDITIONAL_PROFILE_DIRECTORIES make değişkenine BoardConfig.mk ekleyin. Ek yollar belirtilirse bu yollardaki profiller, toolchain/pgo-profiles içindeki profilleri geçersiz kılar.

dist hedefi make için kullanılarak bir sürüm resmi oluşturulurken derleme sistemi, eksik profil dosyalarının adlarını $DIST_DIR/pgo_profile_file_missing.txt dosyasına yazar. Hangi profil dosyalarının yanlışlıkla bırakıldığını görmek için bu dosyayı kontrol edebilirsiniz (bu işlem, PGO'yu sessizce devre dışı bırakır).

Android.bp dosyalarında PGO'yu etkinleştirme

Yerel modüller için Android.bp dosyalarında PGO'yu etkinleştirmek isterseniz pgo özelliğini belirtmeniz yeterlidir. Bu mülkün aşağıdaki alt mülkleri vardır:

Mülk Açıklama
instrumentation Enstrümantasyon kullanarak PGO için true olarak ayarlayın. Varsayılan değer: false.
sampling Örnekleme kullanarak PGO için true olarak ayarlayın. Varsayılan değer: false.
benchmarks Dize listesi. Bu modül, listedeki herhangi bir karşılaştırma ANDROID_PGO_INSTRUMENT derleme seçeneğinde belirtilirse profil oluşturmak için oluşturulur.
profile_file PGO ile kullanılacak profil dosyası (toolchain/pgo-profile'e göre). Derleme, enable_profile_use mülkü false olarak ayarlanmadığı VEYA ANDROID_PGO_NO_PROFILE_USE derleme değişkeni true olarak ayarlanmadığı sürece bu dosyayı $DIST_DIR/pgo_profile_file_missing.txt'e ekleyerek bu dosyanın mevcut olmadığı konusunda uyarı verir.
enable_profile_use Derleme sırasında profiller kullanılmaması gerekiyorsa false olarak ayarlayın. Profil toplamayı etkinleştirmek veya PGO'yu geçici olarak devre dışı bırakmak için önyükleme sırasında kullanılabilir. Varsayılan değer true'tir.
cflags Enstrümante edilmiş derleme sırasında kullanılacak ek işaretlerin listesi.

PGO içeren modül örneği:

cc_library {
    name: "libexample",
    srcs: [
        "src1.cpp",
        "src2.cpp",
    ],
    static: [
        "libstatic1",
        "libstatic2",
    ],
    shared: [
        "libshared1",
    ]
    pgo: {
        instrumentation: true,
        benchmarks: [
            "benchmark1",
            "benchmark2",
        ],
        profile_file: "example.profdata",
    }
}

benchmark1 ve benchmark2 karşılaştırmaları libstatic1, libstatic2 veya libshared1 kitaplıkları için temsili davranış sergilerse bu kitaplıkların pgo mülkü de karşılaştırmaları içerebilir. Android.bp içindeki defaults modülü, birkaç modül için aynı derleme kurallarının tekrarlanmasını önlemek amacıyla bir kitaplık grubu için ortak bir pgo spesifikasyonu içerebilir.

Farklı profil dosyaları seçmek veya bir mimari için PGO'yu seçerek devre dışı bırakmak amacıyla mimari başına profile_file, enable_profile_use ve cflags özelliklerini belirtin. Örnek (mimari hedefi kalın olarak gösterilmiştir):

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

Enstrümantasyon tabanlı profilleme sırasında profilleme çalışma zamanındaki kitaplığa yapılan referansları çözmek için -fprofile-generate yapı işaretini bağlayıcıya iletin. PGO ile enstrümante edilmiş statik kitaplıklar, tüm paylaşılan kitaplıklar ve doğrudan statik kitaplığa bağlı olan tüm ikili programlar da PGO için enstrümante edilmelidir. Ancak bu tür paylaşılan kütüphanelerin veya yürütülebilir dosyaların PGO profillerini kullanması gerekmez ve enable_profile_use mülkleri false olarak ayarlanabilir. Bu kısıtlamanın dışında, PGO'yu herhangi bir statik kitaplığa, paylaşılan kitaplığa veya yürütülebilir dosyaya uygulayabilirsiniz.

LLVM profil dosyalarını işleme

Enstrümante edilmiş bir kitaplığın veya yürütülebilir dosyanın yürütülmesi, /data/local/tmp adlı bir profil dosyası oluşturur (unique_id, bu kitaplığa özgü sayısal bir karmadır).default_unique_id_0.profraw Bu dosya zaten mevcutsa profil oluşturma çalışma zamanı, profilleri yazarken yeni profili eski profille birleştirir. Uygulama geliştiricilerin /data/local/tmp adresine erişemediğini unutmayın. Bunun yerine /storage/emulated/0/Android/data/packagename/files gibi bir adres kullanmaları gerekir. Profil dosyasının konumunu değiştirmek için LLVM_PROFILE_FILE ortam değişkenini çalışma zamanında ayarlayın.

Ardından, .profraw dosyasını (ve muhtemelen birden fazla .profraw dosyasını) .profdata dosyasına dönüştürmek için llvm-profdata yardımcı programı kullanılır:

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

profile.profdata daha sonra derleme sırasında kullanılmak üzere kaynak ağaca kaydedilebilir.

Bir karşılaştırma sırasında birden fazla enstrümante edilmiş ikili/kitaplık yüklenirse her kitaplık ayrı bir benzersiz kimliğe sahip ayrı bir .profraw dosyası oluşturur. Genellikle bu dosyaların tümü tek bir .profdata dosyasında birleştirilebilir ve PGO derlemesi için kullanılabilir. Bir kitaplığın başka bir karşılaştırma tarafından kullanıldığı durumlarda, söz konusu kitaplık her iki karşılaştırmadan alınan profiller kullanılarak optimize edilmelidir. Bu durumda llvm-profdata'ın show seçeneği faydalıdır:

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

unique_id'leri ayrı kitaplıklarla eşlemek için her unique_id için show çıkışında, kitaplığa özgü bir işlev adı arayın.

Örnek olay: ART için PGO

Kasus çalışmasında, ART'nin anlaşılır bir örneği sunulmaktadır. Ancak bu örnek, ART için profil oluşturulan gerçek kitaplık grubu veya bu kitaplıkların birbirine bağımlılıkları hakkında doğru bir açıklama değildir.

ART'taki dex2oat derleyici, libart-compiler.so'e bağlıdır. libart-compiler.so ise libart.so'ye bağlıdır. ART çalışma zamanı temel olarak libart.so'te uygulanır. Derleyici ve çalışma zamanı için karşılaştırmalar farklı olacaktır:

Benchmark Profil oluşturulmuş kitaplıklar
dex2oat dex2oat (yürütülebilir), libart-compiler.so, libart.so
art_runtime libart.so
  1. Aşağıdaki pgo mülkünü dex2oat'a ekleyin: libart-compiler.so
        pgo: {
            instrumentation: true,
            benchmarks: ["dex2oat",],
            profile_file: "dex2oat.profdata",
        }
  2. libart.so özelliğine aşağıdaki pgo özelliğini ekleyin:
        pgo: {
            instrumentation: true,
            benchmarks: ["art_runtime", "dex2oat",],
            profile_file: "libart.profdata",
        }
  3. Aşağıdakileri kullanarak dex2oat ve art_runtime karşılaştırmaları için enstrümante edilmiş derlemeler oluşturun:
        make ANDROID_PGO_INSTRUMENT=dex2oat
        make ANDROID_PGO_INSTRUMENT=art_runtime
  4. Alternatif olarak, aşağıdakiler kullanılarak tüm kitaplıkların enstrümante edildiği tek bir enstrümante edilmiş derleme oluşturabilirsiniz:

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

    İkinci komut, profil oluşturma için tüm PGO özellikli modülleri oluşturur.

  5. Aşağıdakileri elde etmek için dex2oat ve art_runtime'ü kullanarak karşılaştırmaları çalıştırın:
    • LLVM profil dosyalarını yönetme bölümünde açıklanan yöntem kullanılarak tanımlanan, dex2oat'daki üç .profraw dosyası (dex2oat_exe.profdata, dex2oat_libart-compiler.profdata ve dexeoat_libart.profdata).
    • Tek bir art_runtime_libart.profdata.
  6. Aşağıdakileri kullanarak dex2oat yürütülebilir dosyası ve libart-compiler.so için ortak bir profdata dosyası oluşturun:
    llvm-profdata merge -output=dex2oat.profdata \
        dex2oat_exe.profdata dex2oat_libart-compiler.profdata
  7. İki karşılaştırmadaki profilleri birleştirerek libart.so için profili elde edin:
    llvm-profdata merge -output=libart.profdata \
        dex2oat_libart.profdata art_runtime_libart.profdata

    Karşılaştırmalar, test örnekleri sayısı ve çalıştırılma süresi açısından farklı olduğundan, iki profildeki libart.so için ham sayım farklı olabilir. Bu durumda, ağırlıklı bir birleştirme kullanabilirsiniz:

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

    Yukarıdaki komut, dex2oat kaynağından gelen profile iki kat ağırlık atar. Gerçek ağırlık, alan bilgisine veya denemeye göre belirlenmelidir.

  8. Derleme sırasında kullanmak için dex2oat.profdata ve libart.profdata profil dosyalarını toolchain/pgo-profiles içine kopyalayın.