Neural Networks API

Android Neural Networks API (NNAPI), Android cihazlarda makine öğrenimi için yoğun işlem gerektiren işlemleri çalıştırmak üzere tasarlanmış bir Android C API'sidir. NNAPI, nöral ağlar oluşturup eğiten TensorFlow Lite ve Caffe2 gibi üst düzey makine öğrenimi çerçevelerine temel bir işlevsellik katmanı sunmak için tasarlanmıştır. API, Android 8.1 (API düzeyi 27) veya sonraki sürümleri çalıştıran tüm Android cihazlarda kullanılabilir.

NNAPI, Android cihazlardan daha önce eğitilmiş, geliştirici tarafından tanımlanmış modellere veri uygulayarak çıkarım yapılmasını destekler. Çıkarım örnekleri arasında görüntüleri sınıflandırmak, kullanıcı davranışını tahmin etmek ve bir arama sorgusu için uygun yanıtları seçmek yer alır.

Cihaz üzerinde çıkarım yapmanın birçok avantajı vardır:

  • Gecikme: Ağ bağlantısı üzerinden bir istek göndermenize ve yanıt beklemenize gerek yoktur. Örneğin bu, bir kameradan gelen ardışık kareleri işleyen video uygulamaları için kritik olabilir.
  • Kullanılabilirlik: Uygulama, ağ kapsamı dışında olsa bile çalışır.
  • Hız: Nöral ağ işlemeye özel yeni donanım, tek başına genel amaçlı bir CPU'ya göre önemli ölçüde daha hızlı hesaplama sağlar.
  • Gizlilik: Veriler Android cihazdan dışarı çıkmaz.
  • Maliyet: Tüm hesaplamalar Android cihazda yapıldığında sunucu grubuna gerek yoktur.

Geliştiricilerin göz önünde bulundurması gereken bazı ödünler de vardır:

  • Sistem kullanımı: Nöral ağların değerlendirilmesi, çok fazla hesaplama gerektirdiğinden pil gücü kullanımını artırabilir. Uygulamanız için sorun söz konusuysa pil sağlığını izlemeyi düşünebilirsiniz. Özellikle uzun süreli hesaplamalar için bu durum geçerlidir.
  • Uygulama boyutu: Modellerinizin boyutuna dikkat edin. Modeller birkaç megabayt yer kaplayabilir. APK'nızda büyük modelleri paket hâline getirmek kullanıcılarınızı aşırı şekilde etkilerse uygulama yüklendikten sonra modelleri indirmeyi, daha küçük modeller kullanmayı veya hesaplamalarınızı bulutta çalıştırmayı düşünebilirsiniz. NNAPI, modelleri bulutta çalıştırmaya yönelik herhangi bir işlev sağlamaz.

NNAPI'nin nasıl kullanılacağına dair bir örnek görmek için Android Neural Networks API örneğine bakın.

Neural Networks API'nin çalışma zamanını anlama

NNAPI, geliştiricilerin modellerini cihaz dışında eğitip Android cihazlara dağıtmasını sağlayan makine öğrenimi kitaplıkları, çerçeveleri ve araçları tarafından çağrılmak üzere tasarlanmıştır. Uygulamalar genellikle doğrudan NNAPI'yi değil, daha üst düzey makine öğrenimi çerçevelerini kullanır. Bu çerçeveler, desteklenen cihazlarda donanım hızlandırmalı çıkarım işlemleri gerçekleştirmek için NNAPI'yi kullanabilir.

Android'in nöral ağ çalışma zamanı, uygulamanın gereksinimlerine ve Android cihazdaki donanım özelliklerine bağlı olarak, hesaplama iş yükünü özel nöral ağ donanımı, grafik işleme birimleri (GPU'lar) ve dijital sinyal işlemcileri (DSP'ler) dahil olmak üzere mevcut cihaz üzerindeki işlemcilere etkili bir şekilde dağıtabilir.

Özel tedarikçi firma sürücüsü bulunmayan Android cihazlarda NNAPI çalışma zamanı, istekleri CPU'da yürütür.

Şekil 1, NNAPI için üst düzey sistem mimarisini göstermektedir.

Şekil 1. Android Neural Networks API için sistem mimarisi

Neural Networks API programlama modeli

NNAPI kullanarak hesaplamalar yapmak için öncelikle gerçekleştirilecek hesaplamaları tanımlayan yönlendirilmiş bir grafik oluşturmanız gerekir. Bu hesaplama grafiği, giriş verilerinizle birlikte (örneğin, bir makine öğrenimi çerçevesinden aktarılan ağırlıklar ve önyargılar) bir araya geldiğinde, NNAPI çalışma zamanı değerlendirmesi için modeli oluşturur.

NNAPI, dört ana soyutlama kullanır:

  • Model: Matematiksel işlemlerin ve bir eğitim sürecinden öğrenilen sabit değerlerin hesaplama grafiği. Bu işlemler nöral ağlara özeldir. Bunlar arasında 2 boyutlu (2D) evrim, mantıksal (sigmoid) aktivasyon, düzeltilmiş doğrusal (ReLU) aktivasyon ve daha fazlası yer alır. Model oluşturma eşzamanlı bir işlemdir. Başarıyla oluşturulduktan sonra ileti dizileri ve derlemelerde yeniden kullanılabilir. NNAPI'de bir model ANeuralNetworksModel örneği olarak temsil edilir.
  • Derleme: NNAPI modelini alt düzey kodda derlemeye yönelik bir yapılandırmayı temsil eder. Derleme oluşturmak eşzamanlı bir işlemdir. Başarılı bir şekilde oluşturulduktan sonra, ileti dizileri ve yürütme işlemlerinde yeniden kullanılabilir. NNAPI'de her derleme bir ANeuralNetworksCompilation örneği olarak temsil edilir.
  • Bellek: Paylaşılan belleği, bellek eşlenmiş dosyaları ve benzer bellek arabelleklerini temsil eder. Bellek arabelleği kullanmak, NNAPI çalışma zamanının verileri sürücülere daha verimli bir şekilde aktarmasını sağlar. Uygulamalar genellikle bir modeli tanımlamak için gereken her tensörü içeren tek bir paylaşılan bellek arabelleği oluşturur. Bir yürütme örneğinin giriş ve çıkışlarını depolamak için bellek arabellekleri de kullanabilirsiniz. NNAPI'de her bellek arabelleği bir ANeuralNetworksMemory örneği olarak temsil edilir.
  • Yürütme: Bir giriş grubuna NNAPI modeli uygulamak ve sonuçları toplamak için kullanılan arayüz. Yürütme eşzamanlı veya eşzamansız olarak gerçekleştirilebilir.

    Eşzamansız yürütmede birden fazla iş parçacığı aynı yürütmeyi bekleyebilir. Bu yürütme tamamlandığında tüm iş parçacıkları serbest bırakılır.

    NNAPI'de her yürütme bir ANeuralNetworksExecution örneği olarak temsil edilir.

Şekil 2'de temel programlama akışı gösterilmiştir.

Şekil 2. Android Neural Networks API için programlama akışı

Bu bölümün geri kalanında, NNAPI modelinizi hesaplama gerçekleştirmek, modeli derlemek ve derlenen modeli yürütmek için ayarlama adımları açıklanmaktadır.

Eğitim verilerine erişim sağlama

Eğitilen ağırlıklar ve ağırlıklandırmalar muhtemelen bir dosyada depolanır. NNAPI çalışma zamanının bu verilere verimli bir şekilde erişmesini sağlamak için ANeuralNetworksMemory_createFromFd() işlevini çağırarak ve açılan veri dosyasının dosya tanımlayıcısını ileterek bir ANeuralNetworksMemory örneği oluşturun. Ayrıca, bellek koruma işaretleri ve paylaşılan bellek bölgesinin dosyada başladığı bir ofset belirtirsiniz.

// Create a memory buffer from the file that contains the trained data
ANeuralNetworksMemory* mem1 = NULL;
int fd = open("training_data", O_RDONLY);
ANeuralNetworksMemory_createFromFd(file_size, PROT_READ, fd, 0, &mem1);

Bu örnekte tüm ağırlıklarımız için yalnızca bir ANeuralNetworksMemory örneği kullansak da birden fazla dosya için birden fazla ANeuralNetworksMemory örneği kullanılabilir.

Yerel donanım arabellekleri kullan

Model girişleri, çıkışlar ve sabit işlem gören değerleri için yerel donanım arabellekleri kullanabilirsiniz. Belirli durumlarda, bir NNAPI hızlandırıcısı sürücünün verileri kopyalamasına gerek kalmadan AHardwareBuffer nesnelerine erişebilir. AHardwareBuffer birçok farklı yapılandırmaya sahiptir ve her NNAPI hızlandırıcı bu yapılandırmaların tamamını desteklemeyebilir. Bu sınırlama nedeniyle, ANeuralNetworksMemory_createFromAHardwareBuffer referans dokümanlarında listelenen kısıtlamalara bakın ve AHardwareBuffer kullanan derleme ve yürütmelerin beklendiği gibi davrandığından emin olmak için hızlandırıcıyı belirtmek üzere cihaz atama özelliğini kullanarak hedef cihazlarda önceden test yapın.

NNAPI çalışma zamanının bir AHardwareBuffer nesnesine erişmesine izin vermek için aşağıdaki kod örneğinde gösterildiği gibi ANeuralNetworksMemory_createFromAHardwareBuffer işlevini çağırıp AHardwareBuffer nesnesini geçirerek bir ANeuralNetworksMemory örneği oluşturun:

// Configure and create AHardwareBuffer object
AHardwareBuffer_Desc desc = ...
AHardwareBuffer* ahwb = nullptr;
AHardwareBuffer_allocate(&desc, &ahwb);

// Create ANeuralNetworksMemory from AHardwareBuffer
ANeuralNetworksMemory* mem2 = NULL;
ANeuralNetworksMemory_createFromAHardwareBuffer(ahwb, &mem2);

NNAPI'nin artık AHardwareBuffer nesnesine erişmesi gerekmediğinde karşılık gelen ANeuralNetworksMemory örneğini serbest bırakın:

ANeuralNetworksMemory_free(mem2);

Not:

  • AHardwareBuffer öğesini yalnızca arabelleğin tamamı için kullanabilirsiniz; ARect parametresiyle kullanamazsınız.
  • NNAPI çalışma zamanı, arabelleği boşaltmaz. Yürütmeyi planlamadan önce giriş ve çıkış arabelleklerinin erişilebilir olduğundan emin olmanız gerekir.
  • Senkronizasyon çit dosyası açıklayıcıları için destek sunulmaz.
  • Tedarikçi firmaya özel biçimlere ve kullanım bitlerine sahip bir AHardwareBuffer için önbelleğin temizlenmesinden istemcinin mi yoksa sürücünün mi sorumlu olduğunu belirlemek tedarikçi firmanın uygulamasına bağlıdır.

Model

Model, NNAPI'deki hesaplamanın temel birimidir. Her model, bir veya daha fazla işlenen ve işlemle tanımlanır.

İşlem görenler

İşlem görenler, grafiği tanımlamakta kullanılan veri nesneleridir. Bunlar arasında modelin giriş ve çıkışları, bir işlemden diğerine akan verileri içeren ara düğümler ve bu işlemlere aktarılan sabit değerler bulunur.

NNAPI modellerine eklenebilecek iki tür işlenen vardır: skalerler ve tensörler.

Skaler tek bir değeri temsil eder. NNAPI, boole, 16 bit kayan nokta, 32 bit kayan nokta, 32 bit tam sayı ve işaretlenmemiş 32 bit tam sayı biçimlerinde skaler değerleri destekler.

NNAPI'deki çoğu işlem tensör içerir. Tensörler, n boyutlu dizilerdir. NNAPI, 16 bit kayan nokta, 32 bit kayan nokta, 8 bit ölçülen, 16 bit ölçülmüş, 32 bit tam sayı ve 8 bit boole değerlerine sahip tensörleri destekler.

Örneğin, Şekil 3'te iki işlem bulunan bir model gösterilmektedir: bir toplama ve ardından bir çarpma. Model, giriş tensörü alır ve bir çıkış tensörü üretir.

Şekil 3. NNAPI modeli için işlenenler örneği

Yukarıdaki modelin yedi işleneni vardır. Bu işlenenler, modele eklendikleri sıra diziniyle örtülü olarak tanımlanır. Eklenen ilk işlenenin dizini 0, ikincisinin dizini 1 olur ve bu böyle devam eder. İşlem gerçekleştirenler 1, 2, 3 ve 5 sabit işlenenlerdir.

İşlem görenleri ekleme sıranız önemli değildir. Örneğin, model çıkış işleneni eklenen ilk öğe olabilir. Önemli olan, bir işlenene atıfta bulunurken doğru dizin değerini kullanmaktır.

İşlem görenlerin türleri vardır. Bunlar, modele eklendiğinde belirtilir.

İşlem gören bir modelin hem girişi hem çıkışı olarak kullanılamaz.

Her işlenenin model girişi, sabit veya tam olarak bir işlemin çıkış işleneni olması gerekir.

İşlenenlerin kullanımı hakkında daha fazla bilgi için İşleme alınanlar hakkında daha fazla bilgi bölümüne bakın.

İşlemler

İşlem, gerçekleştirilecek hesaplamaları belirtir. Her işlem aşağıdaki öğelerden oluşur:

  • işlem türü (örneğin, toplama, çarpma, konvolüsyon),
  • işlemin giriş için kullandığı işlenenlerin dizinlerinin listesi ve
  • işlemin çıkış için kullandığı işlenenlerin dizinlerinin listesi.

Bu listelerdeki sıra önemlidir. Her işlem türünün beklenen girişleri ve çıkışları için NNAPI API referansına bakın.

Bir işlemin tükettiği veya ürettiği işlenenleri, işlemi eklemeden önce modele eklemeniz gerekir.

İşlemleri hangi sırayla eklediğiniz önemli değildir. NNAPI, işlemlerin yürütülme sırasını belirlemek için işlenenlerin ve işlemlerin hesaplama grafiğinde oluşturulan bağımlılıklara dayanır.

NNAPI'nin desteklediği işlemler aşağıdaki tabloda özetlenmiştir:

Kategori İşlemler
Element olarak matematik işlemleri
Tensor manipülasyonu
Görüntü işlemleri
Arama işlemleri
Normalleştirme işlemleri
Konvolüsyon işlemleri
Havuz oluşturma işlemleri
Etkinleştirme işlemleri
Diğer işlemler

API düzeyi 28'de bilinen sorun: Android 9 (API düzeyi 28) ve sonraki sürümlerde kullanılabilen ANEURALNETWORKS_PAD işlemine ANEURALNETWORKS_TENSOR_QUANT8_ASYMM tensörleri iletirken NNAPI'den gelen çıkış, TensorFlow Lite gibi daha üst düzey makine öğrenimi çerçevelerinin çıktılarıyla eşleşmeyebilir. Bunun yerine yalnızca ANEURALNETWORKS_TENSOR_FLOAT32 kartını geçmeniz gerekir. Bu sorun, Android 10 (API düzeyi 29) ve sonraki sürümlerde çözüldü.

Model oluşturma

Aşağıdaki örnekte, şekil 3'te bulunan iki işlemli modeli oluştururuz.

Modeli oluşturmak için aşağıdaki adımları uygulayın:

  1. Boş bir model tanımlamak için ANeuralNetworksModel_create() işlevini çağırın.

    ANeuralNetworksModel* model = NULL;
    ANeuralNetworksModel_create(&model);
    
  2. ANeuralNetworks_addOperand() yöntemini çağırarak modelinize işlenenleri ekleyin. Veri türleri, ANeuralNetworksOperandType veri yapısı kullanılarak tanımlanır.

    // In our example, all our tensors are matrices of dimension [3][4]
    ANeuralNetworksOperandType tensor3x4Type;
    tensor3x4Type.type = ANEURALNETWORKS_TENSOR_FLOAT32;
    tensor3x4Type.scale = 0.f;    // These fields are used for quantized tensors
    tensor3x4Type.zeroPoint = 0;  // These fields are used for quantized tensors
    tensor3x4Type.dimensionCount = 2;
    uint32_t dims[2] = {3, 4};
    tensor3x4Type.dimensions = dims;

    // We also specify operands that are activation function specifiers ANeuralNetworksOperandType activationType; activationType.type = ANEURALNETWORKS_INT32; activationType.scale = 0.f; activationType.zeroPoint = 0; activationType.dimensionCount = 0; activationType.dimensions = NULL;

    // Now we add the seven operands, in the same order defined in the diagram ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 0 ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 1 ANeuralNetworksModel_addOperand(model, &activationType); // operand 2 ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 3 ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 4 ANeuralNetworksModel_addOperand(model, &activationType); // operand 5 ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 6
  3. Uygulamanızın eğitim sürecinden elde ettiği ağırlıklar ve ağırlıklar gibi sabit değerlere sahip işlenenler için ANeuralNetworksModel_setOperandValue() ve ANeuralNetworksModel_setOperandValueFromMemory() işlevlerini kullanın.

    Aşağıdaki örnekte, Eğitim verilerine erişim sağlama bölümünde oluşturduğumuz bellek arabelleğine karşılık gelen eğitim veri dosyasından alınan sabit değerler belirledik.

    // In our example, operands 1 and 3 are constant tensors whose values were
    // established during the training process
    const int sizeOfTensor = 3 * 4 * 4;    // The formula for size calculation is dim0 * dim1 * elementSize
    ANeuralNetworksModel_setOperandValueFromMemory(model, 1, mem1, 0, sizeOfTensor);
    ANeuralNetworksModel_setOperandValueFromMemory(model, 3, mem1, sizeOfTensor, sizeOfTensor);

    // We set the values of the activation operands, in our example operands 2 and 5 int32_t noneValue = ANEURALNETWORKS_FUSED_NONE; ANeuralNetworksModel_setOperandValue(model, 2, &noneValue, sizeof(noneValue)); ANeuralNetworksModel_setOperandValue(model, 5, &noneValue, sizeof(noneValue));
  4. Yönlendirilen grafikteki hesaplamak istediğiniz her işlem için ANeuralNetworksModel_addOperation() işlevini çağırarak işlemi modelinize ekleyin.

    Bu çağrının parametresi olarak uygulamanız şunları sağlamalıdır:

    • işlem türü
    • giriş değerlerinin sayısı
    • giriş işlenenleri için dizin dizisi
    • çıktı değerlerinin sayısı
    • çıkış işlenenleri için dizin dizisi

    Bir işlenenin, aynı işlemin hem girişi hem de çıkışı için kullanılamayacağını unutmayın.

    // We have two operations in our example
    // The first consumes operands 1, 0, 2, and produces operand 4
    uint32_t addInputIndexes[3] = {1, 0, 2};
    uint32_t addOutputIndexes[1] = {4};
    ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_ADD, 3, addInputIndexes, 1, addOutputIndexes);

    // The second consumes operands 3, 4, 5, and produces operand 6 uint32_t multInputIndexes[3] = {3, 4, 5}; uint32_t multOutputIndexes[1] = {6}; ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_MUL, 3, multInputIndexes, 1, multOutputIndexes);
  5. ANeuralNetworksModel_identifyInputsAndOutputs() işlevini çağırarak modelin hangi işlenenleri giriş ve çıkış olarak ele alması gerektiğini belirleyin.

    // Our model has one input (0) and one output (6)
    uint32_t modelInputIndexes[1] = {0};
    uint32_t modelOutputIndexes[1] = {6};
    ANeuralNetworksModel_identifyInputsAndOutputs(model, 1, modelInputIndexes, 1 modelOutputIndexes);
    
  6. İsteğe bağlı olarak, ANEURALNETWORKS_TENSOR_FLOAT32'in ANeuralNetworksModel_relaxComputationFloat32toFloat16() yöntemini çağırarak IEEE 754 16 bit kayan nokta biçimi kadar düşük bir aralık veya hassasiyetle hesaplanmasına izin verilip verilmeyeceğini belirtin.

  7. Modelinizin tanımını tamamlamak için ANeuralNetworksModel_finish() numaralı telefonu arayın. Hata yoksa bu işlev, ANEURALNETWORKS_NO_ERROR sonuç kodunu döndürür.

    ANeuralNetworksModel_finish(model);
    

Bir model oluşturduktan sonra, bunu istediğiniz sayıda derleyebilir ve her derlemeyi istediğiniz sayıda çalıştırabilirsiniz.

Kontrol akışı

Bir NNAPI modeline denetim akışı eklemek için aşağıdakileri yapın:

  1. İlgili yürütme alt grafiklerini (IF ifadesi için then ve else alt grafikleri, WHILE döngüsü için condition ve body alt grafikleri) bağımsız ANeuralNetworksModel* modelleri olarak oluşturun:

    ANeuralNetworksModel* thenModel = makeThenModel();
    ANeuralNetworksModel* elseModel = makeElseModel();
    
  2. Kontrol akışını içeren model içinde bu modellere referansta bulunan işlenenler oluşturun:

    ANeuralNetworksOperandType modelType = {
        .type = ANEURALNETWORKS_MODEL,
    };
    ANeuralNetworksModel_addOperand(model, &modelType);  // kThenOperandIndex
    ANeuralNetworksModel_addOperand(model, &modelType);  // kElseOperandIndex
    ANeuralNetworksModel_setOperandValueFromModel(model, kThenOperandIndex, &thenModel);
    ANeuralNetworksModel_setOperandValueFromModel(model, kElseOperandIndex, &elseModel);
    
  3. Kontrol akışı işlemini ekleyin:

    uint32_t inputs[] = {kConditionOperandIndex,
                         kThenOperandIndex,
                         kElseOperandIndex,
                         kInput1, kInput2, kInput3};
    uint32_t outputs[] = {kOutput1, kOutput2};
    ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_IF,
                                      std::size(inputs), inputs,
                                      std::size(output), outputs);
    

Derleme

Derleme adımı, modelinizin hangi işlemcilerde yürütüleceğini belirler ve ilgili sürücülerden yürütmeye hazırlamalarını ister. Buna, modelinizin üzerinde çalışacağı işlemcilere özel makine kodu oluşturulması da dahil olabilir.

Bir modeli derlemek için aşağıdaki adımları uygulayın:

  1. Yeni bir derleme örneği oluşturmak için ANeuralNetworksCompilation_create() işlevini çağırın.

    // Compile the model
    ANeuralNetworksCompilation* compilation;
    ANeuralNetworksCompilation_create(model, &compilation);
    

    İsteğe bağlı olarak, hangi cihazlarda yürütüleceğini açıkça seçmek için cihaz atamasını kullanabilirsiniz.

  2. İsteğe bağlı olarak, çalışma zamanının pil gücü kullanımı ve yürütme hızı arasında nasıl denge sağlayacağını etkileyebilirsiniz. Bu işlemi ANeuralNetworksCompilation_setPreference() numaralı telefonu arayarak yapabilirsiniz.

    // Ask to optimize for low power consumption
    ANeuralNetworksCompilation_setPreference(compilation, ANEURALNETWORKS_PREFER_LOW_POWER);
    

    Belirtebileceğiniz tercihler şunları içerir:

    • ANEURALNETWORKS_PREFER_LOW_POWER: Uygulamayı pil kullanımını en aza indirecek şekilde kullanmayı tercih edin. Sık sık yürütülen derlemeler için bu tercih edilir.
    • ANEURALNETWORKS_PREFER_FAST_SINGLE_ANSWER: Daha fazla güç tüketimine neden olsa bile mümkün olduğunca hızlı bir şekilde tek bir yanıt döndürmeyi tercih edin. Bu varsayılan seçenektir.
    • ANEURALNETWORKS_PREFER_SUSTAINED_SPEED: Kameradan gelen ardışık karelerin işlenmesinde olduğu gibi, ardışık karelerin işleme hızını en üst düzeye çıkarmayı tercih edin.
  3. İsteğe bağlı olarak, ANeuralNetworksCompilation_setCaching yöntemini çağırarak derlemeyi önbelleğe almayı ayarlayabilirsiniz.

    // Set up compilation caching
    ANeuralNetworksCompilation_setCaching(compilation, cacheDir, token);
    

    cacheDir için getCodeCacheDir() kullanın. Belirtilen token, uygulamadaki her model için benzersiz olmalıdır.

  4. ANeuralNetworksCompilation_finish() yöntemini çağırarak derlemenin tanımını sonlandırın. Hata yoksa bu işlev ANEURALNETWORKS_NO_ERROR sonuç kodunu döndürür.

    ANeuralNetworksCompilation_finish(compilation);
    

Cihaz bulma ve atama

NNAPI, Android 10 (API düzeyi 29) ve sonraki sürümleri çalıştıran Android cihazlarda makine öğrenimi çerçeve kitaplıklarının ve uygulamalarının kullanılabilir cihazlar hakkında bilgi edinmesine ve yürütme için kullanılacak cihazları belirtmesine olanak tanıyan işlevler sağlar. Kullanılabilir cihazlar hakkında bilgi sağlamak, bilinen uyumsuzlukları önlemek için uygulamaların cihazda bulunan sürücülerin tam sürümünü almasına olanak tanır. Uygulamalara, bir modelin farklı bölümlerini hangi cihazların çalıştıracağını belirtme olanağı sunulduğunda uygulamalar dağıtıldıkları Android cihaz için optimize edilebilir.

Cihaz bulma

Kullanılabilir cihazların sayısını öğrenmek için ANeuralNetworks_getDeviceCount değerini kullanın. Her cihazda bu cihazın referansına bir ANeuralNetworksDevice örneği ayarlamak için ANeuralNetworks_getDevice kullanın.

Bir cihaz referansına sahip olduğunuzda, aşağıdaki işlevleri kullanarak söz konusu cihaz hakkında ek bilgi edinebilirsiniz:

Cihaz ataması

Bir modelin hangi işlemlerinin belirli cihazlarda çalıştırılabileceğini öğrenmek için ANeuralNetworksModel_getSupportedOperationsForDevices aracını kullanın.

Yürütme işleminde hangi hızlandırıcıların kullanılacağını kontrol etmek için ANeuralNetworksCompilation_create yerine ANeuralNetworksCompilation_createForDevices yöntemini çağırın. Ortaya çıkan ANeuralNetworksCompilation nesnesini normal şekilde kullanın. Sağlanan model, seçili cihazlar tarafından desteklenmeyen işlemler içeriyorsa işlev bir hata döndürür.

Birden fazla cihaz belirtilirse çalışmanın cihazlar arasında dağıtılmasından çalışma zamanı sorumlu olur.

Diğer cihazlara benzer şekilde, NNAPI CPU uygulaması nnapi-reference adında ve ANEURALNETWORKS_DEVICE_TYPE_CPU türünde bir ANeuralNetworksDevice ile temsil edilir. ANeuralNetworksCompilation_createForDevices çağrılırken, model derleme ve yürütme ile ilgili hata durumlarını yönetmek için CPU uygulaması kullanılmaz.

Bir modeli, belirtilen cihazlarda çalışabilen alt modeller halinde bölümlendirmek uygulamanın sorumluluğudur. Manuel bölümlendirme yapması gerekmeyen uygulamalar, modeli hızlandırmak için mevcut tüm cihazları (CPU dahil) kullanmak üzere daha basit olan ANeuralNetworksCompilation_create'ı çağırmaya devam etmelidir. Model, ANeuralNetworksCompilation_createForDevices kullanarak belirttiğiniz cihazlar tarafından tam olarak desteklenemediyse ANEURALNETWORKS_BAD_DATA döndürülür.

Model bölümlendirmesi

Model için birden fazla cihaz varsa NNAPI çalışma zamanı, çalışmayı cihazlara dağıtır. Örneğin, ANeuralNetworksCompilation_createForDevices adlı iş ortağına birden fazla cihaz sağlandıysa çalışma ayrılırken belirtilen tüm cihazlar dikkate alınır. CPU cihazı listede yoksa CPU yürütmenin devre dışı bırakılacağını unutmayın. ANeuralNetworksCompilation_create kullanılırken CPU dahil mevcut tüm cihazlar dikkate alınır.

Dağıtım, modeldeki işlemlerin her biri için işlemi destekleyen ve en iyi performansı (istemci tarafından belirtilen yürütme tercihine bağlı olarak en hızlı yürütme süresi veya en düşük güç tüketimi) bildirerek kullanılabilir cihazlar listesinden seçim yapılır. Bu bölümlendirme algoritması, farklı işlemciler arasındaki IO'nun neden olduğu olası verimsizlikleri dikkate almaz. Bu nedenle, birden fazla işlemci belirtirken (ANeuralNetworksCompilation_createForDevices kullanılırken açık bir şekilde veya ANeuralNetworksCompilation_create kullanarak dolaylı olarak) ortaya çıkan uygulamanın profilini çıkarmak önemlidir.

Modelinizin NNAPI tarafından nasıl bölümlendiğini anlamak için Android günlüklerinde bir mesaj olup olmadığını kontrol edin (ExecutionPlan etiketiyle bilgi düzeyinde):

ModelBuilder::findBestDeviceForEachOperation(op-name): device-index

op-name, grafikteki işlemin açıklayıcı adı; device-index ise cihaz listesindeki aday cihazın dizinidir. Bu liste, ANeuralNetworksCompilation_createForDevices için sağlanan giriştir veya ANeuralNetworksCompilation_createForDevices kullanılıyorsa ANeuralNetworks_getDeviceCount ve ANeuralNetworks_getDevice kullanan tüm cihazlar üzerinden iterasyon yaparken döndürülen cihazların listesidir.

Mesaj (ExecutionPlan etiketiyle bilgi düzeyinde):

ModelBuilder::partitionTheWork: only one best device: device-name

Bu mesaj, device-name cihazında tüm grafiğin hızlandırıldığını gösterir.

Uygulama

Yürütme adımı, modeli bir giriş grubuna uygular ve hesaplama çıkışlarını uygulamanızın ayırdığı bir veya daha fazla kullanıcı arabelleğine ya da bellek alanına depolar.

Derlenmiş bir modeli yürütmek için şu adımları uygulayın:

  1. Yeni bir yürütme örneği oluşturmak için ANeuralNetworksExecution_create() işlevini çağırın.

    // Run the compiled model against a set of inputs
    ANeuralNetworksExecution* run1 = NULL;
    ANeuralNetworksExecution_create(compilation, &run1);
    
  2. Uygulamanızın, hesaplama için giriş değerlerini nerede okuduğunu belirtin. Uygulamanız, sırasıyla ANeuralNetworksExecution_setInput() veya ANeuralNetworksExecution_setInputFromMemory() yöntemini çağırarak bir kullanıcı arabelleğinden veya ayrılmış bellek alanından giriş değerlerini okuyabilir.

    // Set the single input to our sample model. Since it is small, we won't use a memory buffer
    float32 myInput[3][4] = { ...the data... };
    ANeuralNetworksExecution_setInput(run1, 0, NULL, myInput, sizeof(myInput));
    
  3. Uygulamanızın çıkış değerlerini nereye yazacağını belirtin. Uygulamanız sırasıyla ANeuralNetworksExecution_setOutput() veya ANeuralNetworksExecution_setOutputFromMemory() yöntemini çağırarak kullanıcı arabelleğine veya ayrılmış bellek alanına çıkış değerleri yazabilir.

    // Set the output
    float32 myOutput[3][4];
    ANeuralNetworksExecution_setOutput(run1, 0, NULL, myOutput, sizeof(myOutput));
    
  4. ANeuralNetworksExecution_startCompute() işlevini çağırarak yürütmeyi başlayacak şekilde planlayın. Hata yoksa bu işlev ANEURALNETWORKS_NO_ERROR sonuç kodunu döndürür.

    // Starts the work. The work proceeds asynchronously
    ANeuralNetworksEvent* run1_end = NULL;
    ANeuralNetworksExecution_startCompute(run1, &run1_end);
    
  5. Yürütmenin tamamlanmasını beklemek için ANeuralNetworksEvent_wait() işlevini çağırın. Yürütme başarılı olduysa bu işlev, ANEURALNETWORKS_NO_ERROR sonuç kodunu döndürür. Yürütmeyi başlatandan farklı bir iş parçacığında bekleme işlemi yapılabilir.

    // For our example, we have no other work to do and will just wait for the completion
    ANeuralNetworksEvent_wait(run1_end);
    ANeuralNetworksEvent_free(run1_end);
    ANeuralNetworksExecution_free(run1);
    
  6. İsteğe bağlı olarak, yeni bir ANeuralNetworksExecution örneği oluşturmak için aynı derleme örneğini kullanarak derlenen modele farklı bir giriş grubu uygulayabilirsiniz.

    // Apply the compiled model to a different set of inputs
    ANeuralNetworksExecution* run2;
    ANeuralNetworksExecution_create(compilation, &run2);
    ANeuralNetworksExecution_setInput(run2, ...);
    ANeuralNetworksExecution_setOutput(run2, ...);
    ANeuralNetworksEvent* run2_end = NULL;
    ANeuralNetworksExecution_startCompute(run2, &run2_end);
    ANeuralNetworksEvent_wait(run2_end);
    ANeuralNetworksEvent_free(run2_end);
    ANeuralNetworksExecution_free(run2);
    

Eşzamanlı yürütme

Eşzamansız yürütme, iş parçacıklarını oluşturmak ve senkronize etmek için zaman harcar. Ayrıca, gecikme çok değişken olabilir. İş parçacığının bildirildiği veya uyandırıldığı zaman ile nihayetinde CPU çekirdeğine bağlandığı zaman arasında 500 mikrosaniyeye ulaşan en uzun gecikmeler.

Gecikmeyi iyileştirmek için bir uygulamayı, çalışma zamanına eşzamanlı çıkarım çağrısı yapacak şekilde yönlendirebilirsiniz. Bu çağrı, çıkarım başlatıldığında değil, yalnızca çıkarım tamamlandığında geri döndürülür. Uygulama, çalışma zamanına eşzamansız bir çıkarım çağrısı yapmak için ANeuralNetworksExecution_startCompute yerine ANeuralNetworksExecution_compute yöntemini çağırarak çalışma zamanına eşzamanlı bir çağrı yapar. ANeuralNetworksExecution_compute numaralı telefona yapılan bir arama ANeuralNetworksEvent işlemi yapmaz ve ANeuralNetworksEvent_wait numarasına yapılan bir aramayla eşlenmez.

Seri işlem yürütmeler

NNAPI, Android 10 (API düzeyi 29) ve sonraki sürümleri çalıştıran Android cihazlarda ANeuralNetworksBurst nesnesi aracılığıyla seri işlem yürütmeleri destekler. Seri çekim yürütmeler, aynı derlemenin hızlı bir şekilde gerçekleştirilen bir derleme dizisidir. Örneğin, bir kamera çekiminin karelerinde veya ardışık ses örneklerinde yürütülür. ANeuralNetworksBurst nesnelerinin kullanılması, hızlandırıcılara kaynakların yürütmeler arasında yeniden kullanılabileceğini ve hızlandırıcıların seri işlem süresince yüksek performans durumunda kalması gerektiğini belirttiğinden daha hızlı yürütmeye yol açabilir.

ANeuralNetworksBurst, normal yürütme yolunda yalnızca küçük bir değişiklik getirir. Aşağıdaki kod snippet'inde gösterildiği gibi ANeuralNetworksBurst_create kullanarak seri çekim nesne oluşturursunuz:

// Create burst object to be reused across a sequence of executions
ANeuralNetworksBurst* burst = NULL;
ANeuralNetworksBurst_create(compilation, &burst);

Seri işleme işlemleri eşzamanlıdır. Bununla birlikte, her çıkarımı gerçekleştirmek için ANeuralNetworksExecution_compute kullanmak yerine, ANeuralNetworksExecution_burstCompute işlevine yapılan çağrılarda aynı ANeuralNetworksBurst ile çeşitli ANeuralNetworksExecution nesnelerini eşlersiniz.

// Create and configure first execution object
// ...

// Execute using the burst object
ANeuralNetworksExecution_burstCompute(execution1, burst);

// Use results of first execution and free the execution object
// ...

// Create and configure second execution object
// ...

// Execute using the same burst object
ANeuralNetworksExecution_burstCompute(execution2, burst);

// Use results of second execution and free the execution object
// ...

Artık ihtiyaç duyulmadığında ANeuralNetworksBurst nesnesini ANeuralNetworksBurst_free ile serbest bırakın.

// Cleanup
ANeuralNetworksBurst_free(burst);

Eşzamansız komut sıraları ve sınırlı yürütme

NNAPI, Android 11 ve sonraki sürümlerde ANeuralNetworksExecution_startComputeWithDependencies() yöntemi aracılığıyla eşzamansız yürütmeyi planlamak için ek bir yöntem destekler. Bu yöntemi kullandığınızda yürütme işlemi, değerlendirmeye başlamadan önce bağlı tüm etkinliklerin sinyalini bekler. Yürütme tamamlandığında ve çıkışlar tüketilmeye hazır olduğunda döndürülen etkinlik için sinyal gönderilir.

Yürütme işlemini hangi cihazların yönettiğine bağlı olarak etkinlik bir senkronizasyon sınırı ile desteklenebilir. Etkinliği beklemek ve yürütmenin kullandığı kaynakları geri kazanmak için ANeuralNetworksEvent_wait() yöntemini çağırmanız gerekir. Senkronizasyon çitlerini ANeuralNetworksEvent_createFromSyncFenceFd() ile bir etkinlik nesnesine içe aktarabilir ve ANeuralNetworksEvent_getSyncFenceFd() kullanarak etkinlik nesnesindeki senkronizasyon sınırlarını dışa aktarabilirsiniz.

Dinamik olarak boyutlandırılmış çıkışlar

Çıkış boyutunun giriş verilerine bağlı olduğu (yani, model yürütme zamanında boyutun belirlenemediği) modelleri desteklemek için ANeuralNetworksExecution_getOutputOperandRank ve ANeuralNetworksExecution_getOutputOperandDimensions özelliklerini kullanın.

Aşağıdaki kod örneğinde bunun nasıl yapılacağı gösterilmektedir:

// Get the rank of the output
uint32_t myOutputRank = 0;
ANeuralNetworksExecution_getOutputOperandRank(run1, 0, &myOutputRank);

// Get the dimensions of the output
std::vector<uint32_t> myOutputDimensions(myOutputRank);
ANeuralNetworksExecution_getOutputOperandDimensions(run1, 0, myOutputDimensions.data());

Temizle

Temizleme adımı, hesaplamanız için kullanılan dahili kaynakların serbest bırakılmasını sağlar.

// Cleanup
ANeuralNetworksCompilation_free(compilation);
ANeuralNetworksModel_free(model);
ANeuralNetworksMemory_free(mem1);

Hata yönetimi ve CPU yedeği

Bölümlendirme sırasında veya bir sürücü bir modeli (a parçası) derleyemezse veya sürücü derlenmiş (bir parçası) modeli yürütemezse NNAPI, bir veya daha fazla işlemin kendi CPU uygulamasına geri dönebilir.

NNAPI istemcisi, işlemin optimize edilmiş sürümlerini (ör. TFLite) içeriyorsa CPU yedeğini devre dışı bırakmak ve hataları istemcinin optimize edilmiş işlem uygulamasıyla ele almak avantajlı olabilir.

Android 10'da, derleme ANeuralNetworksCompilation_createForDevices kullanılarak yapılırsa CPU yedeği devre dışı bırakılır.

Android P'de, sürücüde yürütme başarısız olursa NNAPI yürütmesi tekrar CPU'ya döner. Bu durum, Android 10'da ANeuralNetworksCompilation_createForDevices yerine ANeuralNetworksCompilation_create kullanıldığında da geçerlidir.

İlk yürütme işlemi bu tek bölüm için geri alınır ve bu da başarısız olursa modelin tamamını CPU üzerinde yeniden dener.

Bölümlendirme veya derleme başarısız olursa modelin tamamı CPU'da denenir.

Bazı işlemlerin CPU'da desteklenmediği ve bu gibi durumlarda derlemenin veya yürütmenin geri çekilmek yerine başarısız olacağı durumlar vardır.

CPU yedeğini devre dışı bıraktıktan sonra bile modelde CPU için planlanmış işlemler olabilir. CPU, ANeuralNetworksCompilation_createForDevices sağlayıcısına sağlanan işlemciler listesindeyse ve bu işlemleri destekleyen tek işlemciyse ya da bu işlemler için en iyi performansı iddia eden işlemciyse birincil (yedek olmayan) yürütücü olarak seçilir.

CPU yürütme işlemi olmadığından emin olmak için nnapi-reference öğesini cihaz listesinden hariç tutarken ANeuralNetworksCompilation_createForDevices kullanın. Android P'den başlayarak, debug.nn.partition özelliğini 2 değerine ayarlayarak HATA AYIKLAMA derlemelerinde yürütme sırasında yedeği devre dışı bırakmak mümkündür.

Bellek alanları

NNAPI, Android 11 ve sonraki sürümlerde opak anılar için ayırıcı arayüzler sağlayan bellek alan adlarını destekler. Bu, uygulamaların cihazda yerel anlarıları yürütme işlemleri arasında iletmesine olanak tanır. Böylece NNAPI, aynı sürücüde ardışık yürütmeler gerçekleştirirken verileri gereksiz yere kopyalamaz veya dönüştürmez.

Bellek alan adı özelliği, çoğunlukla sürücüde dahili olan ve istemci tarafına sık sık erişilmesi gerektirmeyen tensörler için tasarlanmıştır. Bu tür tensörlere örnek olarak dizi modellerindeki durum tensörleri verilebilir. İstemci tarafında sık CPU erişimine ihtiyaç duyan tensörler için bunun yerine paylaşılan bellek havuzlarını kullanın.

Opak bellek tahsis etmek için aşağıdaki adımları uygulayın:

  1. Yeni bir bellek açıklayıcısı oluşturmak için ANeuralNetworksMemoryDesc_create() işlevini çağırın:

    // Create a memory descriptor
    ANeuralNetworksMemoryDesc* desc;
    ANeuralNetworksMemoryDesc_create(&desc);
    
  2. ANeuralNetworksMemoryDesc_addInputRole() ve ANeuralNetworksMemoryDesc_addOutputRole() çağırarak istenen tüm giriş ve çıkış rollerini belirtin.

    // Specify that the memory may be used as the first input and the first output
    // of the compilation
    ANeuralNetworksMemoryDesc_addInputRole(desc, compilation, 0, 1.0f);
    ANeuralNetworksMemoryDesc_addOutputRole(desc, compilation, 0, 1.0f);
    
  3. İsteğe bağlı olarak, ANeuralNetworksMemoryDesc_setDimensions() yöntemini çağırarak bellek boyutlarını belirtin.

    // Specify the memory dimensions
    uint32_t dims[] = {3, 4};
    ANeuralNetworksMemoryDesc_setDimensions(desc, 2, dims);
    
  4. ANeuralNetworksMemoryDesc_finish() çağrısı yaparak açıklayıcı tanımını tamamlayın.

    ANeuralNetworksMemoryDesc_finish(desc);
    
  5. Açıklayıcıyı ANeuralNetworksMemory_createFromDesc()'e ileterek ihtiyaç duyduğunuz kadar anı ayırın.

    // Allocate two opaque memories with the descriptor
    ANeuralNetworksMemory* opaqueMem;
    ANeuralNetworksMemory_createFromDesc(desc, &opaqueMem);
    
  6. Artık ihtiyaç duymadığınız bellekte açıklayıcıyı boşaltın.

    ANeuralNetworksMemoryDesc_free(desc);
    

İstemci, oluşturulan ANeuralNetworksMemory nesnesini yalnızca ANeuralNetworksMemoryDesc nesnesinde belirtilen rollere göre ANeuralNetworksExecution_setInputFromMemory() veya ANeuralNetworksExecution_setOutputFromMemory() ile kullanabilir. Ofset ve uzunluk bağımsız değişkenleri, tüm belleğin kullanıldığını belirtmek için 0 olarak ayarlanmalıdır. Ayrıca istemci, ANeuralNetworksMemory_copy() kullanarak belleğin içeriğini açık bir şekilde ayarlayabilir veya çıkarabilir.

Belirtilmemiş boyut veya sıralama rolleriyle opak anılar oluşturabilirsiniz. Bu durumda, temel sürücü tarafından desteklenmiyorsa bellek oluşturma işlemi ANEURALNETWORKS_OP_FAILED durumunda başarısız olabilir. İstemcinin, Ashmem veya BLOB modu AHardwareBuffer tarafından desteklenen ve yeterince büyük bir arabellek tahsis ederek yedek mantığı uygulaması önerilir.

NNAPI'nin artık opak bellek nesnesine erişmesi gerekmediğinde karşılık gelen ANeuralNetworksMemory örneğini serbest bırakın:

ANeuralNetworksMemory_free(opaqueMem);

Performans ölçme

Yürütme süresini ölçerek veya profil oluşturarak uygulamanızın performansını değerlendirebilirsiniz.

Yürütme süresi

Çalışma zamanı boyunca toplam yürütme süresini belirlemek istediğinizde eşzamanlı yürütme API'sini kullanabilir ve çağrının aldığı süreyi ölçebilirsiniz. Daha düşük bir yazılım yığını düzeyinde toplam yürütme süresini belirlemek istediğinizde, ANeuralNetworksExecution_setMeasureTiming ve ANeuralNetworksExecution_getDuration araçlarını kullanarak şunları elde edebilirsiniz:

  • hızlandırıcıda (ana makine işlemcisinde çalışan sürücüde değil) yürütme süresini test eder.
  • hızlandırıcıda geçen süre de dahil olmak üzere sürücüdeki yürütme süresidir.

Sürücüdeki yürütme süresi, çalışma zamanının kendisi ve çalışma zamanının sürücüyle iletişim kurması için gereken IPC gibi ek yükleri hariç tutar.

Bu API'ler, bir sürücünün veya hızlandırıcının bağlam değişikliği nedeniyle kesintiye uğratılmış çıkarımı gerçekleştirmeye ayırdığı süre yerine, gönderilen çalışma ile tamamlanan iş etkinlikleri arasındaki süreyi ölçer.

Örneğin, çıkarım 1 başlarsa ve sürücü 2. çıkarımı yapmak için işi durdurur, ardından devam edip 1. çıkarımı tamamlarsa çıkarım 1 için yürütme süresi, 2. çıkarımı yapmak için işin durdurulduğu süreyi içerir.

Bu zamanlama bilgileri, çevrimdışı kullanım için telemetri toplamak üzere bir uygulamanın üretim dağıtımında yararlı olabilir. Zamanlama verilerini kullanarak uygulamayı daha yüksek performans gösterecek şekilde değiştirebilirsiniz.

Bu işlevi kullanırken aşağıdakileri göz önünde bulundurun:

  • Zamanlama bilgilerini toplamanın bir performans maliyeti olabilir.
  • NNAPI çalışma zamanında ve IPC'de harcanan süre hariç olmak üzere, yalnızca bir sürücü kendi içinde veya hızlandırıcıda harcanan süreyi hesaplayabilir.
  • Bu API'leri yalnızca numDevices = 1 ile ANeuralNetworksCompilation_createForDevices ile oluşturulan bir ANeuralNetworksExecution ile kullanabilirsiniz.
  • Zamanlama bilgilerini raporlayabilmek için herhangi bir sürücüye gerek yoktur.

Android Systrace ile uygulamanızın profilini oluşturun

NNAPI, Android 10'dan itibaren uygulamanızın profilini çıkarmak için kullanabileceğiniz systrace etkinliklerini otomatik olarak oluşturur.

NNAPI Kaynağı, uygulamanız tarafından oluşturulan sistem etkinliklerini işlemek ve model yaşam döngüsünün farklı aşamalarında (Hazırlık, Hazırlık, Derleme Yürütme ve Sonlandırma) ve uygulamaların farklı katmanlarında harcanan süreyi gösteren bir tablo görünümü oluşturmak için bir parse_systrace yardımcı programı içerir. Uygulamanızın bölündüğü katmanlar şunlardır:

  • Application: ana uygulama kodu
  • Runtime: NNAPI Çalışma Zamanı
  • IPC: NNAPI Çalışma Zamanı ile Sürücü kodu arasındaki işlemler arası iletişim
  • Driver: Hızlandırıcı sürücü işlemi.

Profil oluşturma analiz verilerini oluşturma

$ANDROID_BUILD_TOP olan AOSP kaynak ağacını incelediğinizi ve hedef uygulama olarak TFLite görüntü sınıflandırma örneğini kullandığınızı varsayarsak NNAPI profil oluşturma verilerini aşağıdaki adımları uygulayarak oluşturabilirsiniz:

  1. Android systrace'i aşağıdaki komutla başlatın:
$ANDROID_BUILD_TOP/external/chromium-trace/systrace.py  -o trace.html -a org.tensorflow.lite.examples.classification nnapi hal freq sched idle load binder_driver

-o trace.html parametresi, izlemelerin trace.html içine yazılacağını belirtir. Kendi uygulamanızın profilini oluştururken org.tensorflow.lite.examples.classification öğesini uygulama manifestinizde belirtilen işlem adıyla değiştirmeniz gerekir.

Bu işlem, kabuk konsollarınızdan birini meşgul eder. Komutun etkileşimli bir şekilde enter sonlandırılması beklendiğinden komutu arka planda çalıştırmayın.

  1. Sistem izleme toplayıcı başlatıldıktan sonra uygulamanızı başlatın ve karşılaştırma testinizi çalıştırın.

Örneğimizde, Image Classification uygulamasını Android Studio'dan veya uygulama zaten yüklenmişse doğrudan test telefonunuzun kullanıcı arayüzünden başlatabilirsiniz. Bazı NNAPI verileri oluşturmak için uygulama yapılandırma iletişim kutusunda NNAPI'yi hedef cihaz olarak seçerek uygulamayı NNAPI'yi kullanacak şekilde yapılandırmanız gerekir.

  1. Test tamamlandığında, 1. adımdan itibaren etkin durumdaki konsol terminalinde enter tuşuna basarak sistemi sonlandırın.

  2. Kümülatif istatistikler oluşturmak için systrace_parser yardımcı programını çalıştırın:

$ANDROID_BUILD_TOP/frameworks/ml/nn/tools/systrace_parser/parse_systrace.py --total-times trace.html

Ayrıştırıcı aşağıdaki parametreleri kabul eder: - --total-times: Bir alt katmana yapılan çağrının yürütülmesini beklerken harcanan süre de dahil olmak üzere bir katmanda harcanan toplam süreyi gösterir - --print-detail: systrace'den toplanan tüm etkinlikleri yazdırır - --per-execution: tüm aşamalardaki istatistikler yerine yalnızca yürütmeyi ve alt aşamalarını (yürütme sürelerine göre) yazdırır - --json: çıktıyı JSON biçiminde üretir

Çıkışın bir örneği aşağıda gösterilmiştir:

===========================================================================================================================================
NNAPI timing summary (total time, ms wall-clock)                                                      Execution
                                                           ----------------------------------------------------
              Initialization   Preparation   Compilation           I/O       Compute      Results     Ex. total   Termination        Total
              --------------   -----------   -----------   -----------  ------------  -----------   -----------   -----------   ----------
Application              n/a         19.06       1789.25           n/a           n/a         6.70         21.37           n/a      1831.17*
Runtime                    -         18.60       1787.48          2.93         11.37         0.12         14.42          1.32      1821.81
IPC                     1.77             -       1781.36          0.02          8.86            -          8.88             -      1792.01
Driver                  1.04             -       1779.21           n/a           n/a          n/a          7.70             -      1787.95

Total                   1.77*        19.06*      1789.25*         2.93*        11.74*        6.70*        21.37*         1.32*     1831.17*
===========================================================================================================================================
* This total ignores missing (n/a) values and thus is not necessarily consistent with the rest of the numbers

Toplanan etkinlikler tam bir uygulama izlemeyi temsil etmiyorsa ayrıştırıcı başarısız olabilir. Özellikle, bir bölümün sonunu işaretlemek için oluşturulan systrace etkinlikleri, izde ilişkili bir bölüm başlangıç etkinliği olmadan bulunuyorsa başarısız olabilir. Bu durum genellikle, systrace toplayıcıyı başlattığınızda önceki bir profil çıkarma oturumuna ait bazı etkinlikler oluşturuluyorsa ortaya çıkar. Bu durumda, profil oluşturma işlemini tekrar çalıştırmanız gerekir.

Uygulama kodunuza ait istatistikleri systrace_parser çıkışına ekleyin

ayrıştırma_systrace uygulaması, yerleşik Android systrace işlevine dayanır. Özel etkinlik adlarıyla systrace API'yi (Java için, yerel uygulamalar için) kullanarak uygulamanızdaki belirli işlemler için izler ekleyebilirsiniz.

Özel etkinliklerinizi Uygulama yaşam döngüsünün aşamalarıyla ilişkilendirmek için etkinlik adınızın başına aşağıdaki dizelerden birini ekleyin:

  • [NN_LA_PI]: Başlatma için uygulama düzeyinde etkinlik
  • [NN_LA_PP]: Hazırlık için uygulama düzeyinde etkinlik
  • [NN_LA_PC]: Derleme için uygulama düzeyinde etkinlik
  • [NN_LA_PE]: Yürütme için uygulama düzeyinde etkinlik

Execution aşaması için runInferenceModel bölümü ve NNAPI izlerinde dikkate alınmayacak başka bölümler preprocessBitmap içeren Application katmanı ekleyerek TFLite görüntü sınıflandırma örnek kodunu nasıl değiştirebileceğinize dair bir örneği burada bulabilirsiniz. runInferenceModel bölümü, nnapi systrace ayrıştırıcısı tarafından işlenen systrace etkinliklerinin bir parçası olur:

Kotlin

/** Runs inference and returns the classification results. */
fun recognizeImage(bitmap: Bitmap): List {
   // This section won’t appear in the NNAPI systrace analysis
   Trace.beginSection("preprocessBitmap")
   convertBitmapToByteBuffer(bitmap)
   Trace.endSection()

   // Run the inference call.
   // Add this method in to NNAPI systrace analysis.
   Trace.beginSection("[NN_LA_PE]runInferenceModel")
   long startTime = SystemClock.uptimeMillis()
   runInference()
   long endTime = SystemClock.uptimeMillis()
   Trace.endSection()
    ...
   return recognitions
}

Java

/** Runs inference and returns the classification results. */
public List recognizeImage(final Bitmap bitmap) {

 // This section won’t appear in the NNAPI systrace analysis
 Trace.beginSection("preprocessBitmap");
 convertBitmapToByteBuffer(bitmap);
 Trace.endSection();

 // Run the inference call.
 // Add this method in to NNAPI systrace analysis.
 Trace.beginSection("[NN_LA_PE]runInferenceModel");
 long startTime = SystemClock.uptimeMillis();
 runInference();
 long endTime = SystemClock.uptimeMillis();
 Trace.endSection();
  ...
 Trace.endSection();
 return recognitions;
}

Hizmet kalitesi

Android 11 ve sonraki sürümlerde NNAPI, uygulamaların modellerinin göreli önceliklerini, belirli bir modeli hazırlamak için beklenen maksimum süreyi ve belirli bir hesaplamayı tamamlaması için beklenen maksimum süreyi belirtmesini sağlayarak daha iyi hizmet kalitesi (HK) sağlar. Android 11, uygulamaların kaçırılan yürütme son tarihleri gibi hataları anlamasını sağlayan ek NNAPI sonuç kodları da sunar.

İş yükünün önceliğini ayarlama

Bir NNAPI iş yükünün önceliğini ayarlamak için ANeuralNetworksCompilation_finish() çağrısı yapmadan önce ANeuralNetworksCompilation_setPriority() çağrısı yapın.

Teslim tarihleri belirleme

Uygulamalar hem model derleme hem de çıkarım için son tarihler belirleyebilir.

İşlem görenler hakkında daha fazla bilgi

Aşağıdaki bölümde, işlenenlerin kullanımıyla ilgili ileri düzey konular ele alınmaktadır.

Nicelleştirilmiş tensörler

Nicelleştirilmiş tensör, n boyutlu bir kayan nokta değerleri dizisini temsil etmenin kompakt bir yoludur.

NNAPI, 8 bit asimetrik ölçülmüş tensörleri destekler. Bu tensörler için her hücrenin değeri 8 bitlik bir tam sayı ile temsil edilir. Tensörle ilişkilendirilen bir ölçek ve sıfır puan değeri vardır. Bunlar, 8 bitlik tam sayıları temsil edilen kayan nokta değerlerine dönüştürmek için kullanılır.

Formül şöyledir:

(cellValue - zeroPoint) * scale

sıfırPoint değeri 32 bitlik bir tam sayı ve ölçek de 32 bitlik bir kayan nokta değeridir.

32 bitlik kayan nokta değerlerinin tensörleriyle karşılaştırıldığında, 8 bitlik tensörlerin iki avantajı vardır:

  • Eğitilen ağırlıklar, 32 bit tensör boyutunun dörtte birini aldığından uygulamanız daha küçüktür.
  • Hesaplamalar çoğu zaman daha hızlı yürütülebilir. Bunun nedeni, bellekten getirilmesi gereken veri miktarının daha az olması ve tam sayı matematiği yaparken TTP'ler gibi işlemcilerin verimliliğidir.

Bir kayan nokta modelini ölçülmüş bir modele dönüştürmek mümkün olsa da deneyimlerimiz, nicel bir modelin doğrudan eğitilmesiyle daha iyi sonuçlar elde edildiğini göstermiştir. Aslında nöral ağ, her bir değerin artan ayrıntı düzeyini dengelemeyi öğrenir. Ölçülen her tensörün ölçek ve sıfırPoint değerleri, eğitim sürecinde belirlenir.

NNAPI'de, ANeuralNetworksOperandType veri yapısının tür alanını ANEURALNETWORKS_TENSOR_QUANT8_ASYMM olarak ayarlayarak ölçülmüş tensör türlerini tanımlarsınız. Bu veri yapısında tensörün ölçeğini ve zeroPoint değerini de belirtirsiniz.

NNAPI, 8 bit asimetrik nicelenmiş tensörlere ek olarak aşağıdakileri destekler:

İsteğe bağlı işlenenler

ANEURALNETWORKS_LSH_PROJECTION gibi birkaç işlem, isteğe bağlı işlenenleri alır. Modelde isteğe bağlı işlenenin atlandığını belirtmek için ANeuralNetworksModel_setOperandValue() işlevini çağırarak arabellek için NULL ve uzunluk için 0 değerini iletin.

İşlenenin mevcut olup olmadığıyla ilgili karar her yürütme için değişiyorsa ANeuralNetworksExecution_setInput() veya ANeuralNetworksExecution_setOutput() işlevlerini kullanarak işlenenin atlandığını belirtirsiniz ve arabellek için NULL, uzunluk için 0 değerini geçirin.

Sıralaması bilinmeyen tensörler

Android 9 (API düzeyi 28), bilinmeyen boyutların model işlenenlerini kullanıma sunmuştur ancak sıralamayı (boyut sayısı) bilinir. Android 10 (API düzeyi 29), ANeural NetworksLDAPType'da gösterildiği gibi bilinmeyen sıralamaya sahip tensörleri kullanıma sundu.

NNAPI karşılaştırması

NNAPI karşılaştırması, AOSP'de platform/test/mlts/benchmark (karşılaştırma uygulaması) ve platform/test/mlts/models (modeller ve veri kümeleri) üzerinde mevcuttur.

Karşılaştırma, gecikme ve doğruluğu değerlendirir ve sürücüleri, aynı modeller ve veri kümeleri için CPU'da çalışan Tensorflow Lite kullanılarak yapılan işle karşılaştırır.

Karşılaştırmayı kullanmak için aşağıdakileri yapın:

  1. Bilgisayarınıza bir hedef Android cihaz bağlayın, bir terminal penceresi açın ve cihaza adb üzerinden erişilebildiğinden emin olun.

  2. Birden fazla Android cihaz bağlıysa hedef cihaz ANDROID_SERIAL ortam değişkenini dışa aktarın.

  3. Android'in üst düzey kaynak dizinine gidin.

  4. Aşağıdaki komutları çalıştırın:

    lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available
    ./test/mlts/benchmark/build_and_run_benchmark.sh
    

    Karşılaştırma çalıştırmasının sonunda, sonuçları xdg-open öğesine iletilen bir HTML sayfası olarak sunulur.

NNAPI günlükleri

NNAPI, sistem günlüklerinde faydalı teşhis bilgileri oluşturur. Günlükleri analiz etmek için logcat yardımcı programını kullanın.

debug.nn.vlog özelliğini (adb shell kullanarak) boşluk, iki nokta veya virgülle ayrılmış aşağıdaki değer listesine ayarlayarak belirli aşamalar veya bileşenler için ayrıntılı NNAPI günlük kaydını etkinleştirin:

  • model: Model derleme
  • compilation: Model yürütme planı ve derlemesi oluşturma
  • execution: Model yürütme
  • cpuexe: NNAPI CPU uygulamasını kullanarak işlemleri yürütme
  • manager: NNAPI uzantıları, kullanılabilir arayüzler ve özelliklerle ilgili bilgiler
  • all veya 1: Yukarıdaki tüm öğeler

Örneğin, tam ayrıntılı günlük kaydını etkinleştirmek için adb shell setprop debug.nn.vlog all komutunu kullanın. Ayrıntılı günlük kaydını devre dışı bırakmak için adb shell setprop debug.nn.vlog '""' komutunu kullanın.

Etkinleştirildiğinde, ayrıntılı günlük kaydı, aşama veya bileşen adına ayarlanmış bir etiketle bilgi düzeyinde günlük girişleri oluşturur.

debug.nn.vlog tarafından denetlenen mesajların yanı sıra NNAPI API bileşenleri, her biri belirli bir günlük etiketini kullanan çeşitli düzeylerde diğer günlük girişlerini sağlar.

Bileşenlerin listesini almak için, aşağıdaki ifadeyi kullanarak kaynak ağacında arama yapın:

grep -R 'define LOG_TAG' | awk -F '"' '{print $2}' | sort -u | egrep -v "Sample|FileTag|test"

Bu ifade şu anda aşağıdaki etiketleri döndürüyor:

  • Seri Geliştirme Aracı
  • Geri Aramalar
  • Derleme Oluşturucu
  • CPUYürütücü
  • Yürütme Oluşturucu
  • YürütmeBurstDenetleyicisi
  • YürütmeBurst Sunucusu
  • Yürütme Planı
  • FibonacciSürücü
  • Grafik Dökümü
  • Dizine EklenmişŞekilSarmalayıcı
  • Ionİzleyici
  • Yönetici
  • Bellek
  • MemoryUtil'ler
  • MetaModel
  • ModelArgumentBilgileri
  • Model Oluşturucu
  • Sinir Ağları
  • İşlem Çözücü
  • İşlemler
  • İşlem Yardımcı Araçları
  • Paket Bilgileri
  • Jeton Karıştırıcı
  • Tür Yöneticisi
  • Yardımcı araçlar
  • DoğrulamaHal
  • Sürümlü Arayüzler

logcat tarafından gösterilen günlük mesajlarının düzeyini kontrol etmek için ANDROID_LOG_TAGS ortam değişkenini kullanın.

NNAPI günlük mesajlarının tamamını göstermek ve diğerlerini devre dışı bırakmak için ANDROID_LOG_TAGS öğesini aşağıdaki şekilde ayarlayın:

BurstBuilder:V Callbacks:V CompilationBuilder:V CpuExecutor:V ExecutionBuilder:V ExecutionBurstController:V ExecutionBurstServer:V ExecutionPlan:V FibonacciDriver:V GraphDump:V IndexedShapeWrapper:V IonWatcher:V Manager:V MemoryUtils:V Memory:V MetaModel:V ModelArgumentInfo:V ModelBuilder:V NeuralNetworks:V OperationResolver:V OperationsUtils:V Operations:V PackageInfo:V TokenHasher:V TypeManager:V Utils:V ValidateHal:V VersionedInterfaces:V *:S.

Aşağıdaki komutu kullanarak ANDROID_LOG_TAGS değerini ayarlayabilirsiniz:

export ANDROID_LOG_TAGS=$(grep -R 'define LOG_TAG' | awk -F '"' '{ print $2 ":V" }' | sort -u | egrep -v "Sample|FileTag|test" | xargs echo -n; echo ' *:S')

Bunun yalnızca logcat için geçerli olan bir filtre olduğunu unutmayın. Ayrıntılı günlük bilgisi oluşturmak için yine de debug.nn.vlog özelliğini all olarak ayarlamanız gerekir.