Android Neural Networks API (NNAPI), Android cihazlarda makine öğrenimi için yoğun işlem gücü 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çeveleri için temel bir işlevsellik katmanı sağlamak üzere 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 önceden eğitilmiş, geliştirici tarafından tanımlanmış modellere veri uygulayarak çıkarımı destekler. Çıkarım örnekleri arasında görüntüleri sınıflandırmak, kullanıcı davranışlarını tahmin etmek ve bir arama sorgusu için uygun yanıtları seçmek yer alır.
Cihaz üzerinde çıkarım birçok avantaj sağlar:
- Gecikme: Bir ağ bağlantısı üzerinden 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ının 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 kıyasla çok daha hızlı hesaplama sağlar.
- Gizlilik: Veriler Android cihazdan dışarı çıkmaz.
- Maliyet: Tüm hesaplamalar Android cihazda yapıldığında sunucu çiftliğine 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 işlem gerektirdiği için pil gücü kullanımını artırabilir. Uygulamanız açısından sorun yaratıyorsa, özellikle de uzun süreli hesaplamalar söz konusuysa pil sağlığını izlemeyi düşünmelisiniz.
- Uygulama boyutu: Modellerinizin boyutuna dikkat edin. Modeller birkaç megabayt yer kaplayabilir. APK'nızda büyük modelleri paket haline 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ırmak için 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'nin, geliştiricilerin modellerini cihaz dışında eğitip Android cihazlara dağıtmasını sağlayan makine öğrenimi kitaplıkları, çerçeveler ve araçlar tarafından çağrılması amaçlanmıştır. Uygulamalar genellikle doğrudan NNAPI'yi değil, daha üst düzey makine öğrenimi çerçevelerini kullanır. Buna karşılık 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 gerekliliklerine 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 sürücüsü bulunmayan Android cihazlarda NNAPI çalışma zamanı, istekleri CPU üzerinde yürütür.
Şekil 1'de NNAPI için üst düzey sistem mimarisi gösterilmektedir.

Neural Networks API'si 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 (örneğin, bir makine öğrenimi çerçevesinden aktarılan ağırlıklar ve yanlılıklar) birleştirildiğ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) etkinleştirme, düzeltilmiş doğrusal (ReLU) aktivasyon ve daha fazlası yer alır. Model oluşturma işlemi 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 derlemek için kullanılan bir yapılandırmayı temsil eder. Derleme oluşturma, eşzamanlı bir işlemdir. Başarılı bir şekilde oluşturulduktan sonra, iş parçacığı 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, hafıza eşlenmiş dosyaları ve benzer bellek arabelleklerini temsil eder. Bellek arabelleği kullanmak, NNAPI çalışma zamanı verilerini 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 paylaşılan bir 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 bir bellek arabelleği bir
ANeuralNetworksMemory
örneği olarak temsil edilir. Yürütme: NNAPI modelini bir giriş kümesine 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.

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ğitilmiş ağırlıklar ve ağırlıklandırma verileriniz büyük olasılıkla bir dosyada depolanır. NNAPI çalışma zamanına bu verilere verimli erişim sağlamak için ANeuralNetworksMemory_createFromFd()
işlevini çağırıp açık veri dosyasının dosya tanımlayıcısını ileterek bir ANeuralNetworksMemory
örneği oluşturun. Ayrıca, bellek koruma bayrakları ve paylaşılan bellek bölgesinin dosyada başladığı yerde 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 kullanmamıza rağmen 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 tümünü desteklemeyebilir. Bu sınırlama nedeniyle, ANeuralNetworksMemory_createFromAHardwareBuffer
referans belgelerinde listelenen kısıtlamalara bakın ve AHardwareBuffer
kullanan derlemelerin ve yürütmelerin beklendiği gibi davrandığından emin olmak için hızlandırıcıyı belirtmek için cihaz atamasını kullanarak hedef cihazlarda önceden test yapın.
NNAPI çalışma zamanının bir AHardwareBuffer
nesnesine erişmesine izin vermek için ANeuralNetworksMemory_createFromAHardwareBuffer
işlevini çağırarak ve aşağıdaki kod örneğinde gösterildiği gibi AHardwareBuffer
nesnesini ileterek 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 tampon için kullanabilirsiniz.ARect
parametresiyle kullanamazsınız.- NNAPI çalışma zamanı arabelleği boşaltmaz. Yürütmeyi planlamadan önce giriş ve çıkış arabelleklerine erişilebildiğinden 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 mü 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ımlamada kullanılan veri nesneleridir. Bunlar arasında modelin giriş ve çıkışları, bir işlemden diğerine akan verilerin bulunduğu ara düğümler ve bu işlemlere aktarılan sabit değerler yer alır.
NNAPI modellerine eklenebilen iki işlem türü vardır: skalarlar 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örleri içerir. Tensörler n boyutlu dizilerdir. NNAPI; 16 bit kayan nokta, 32 bit kayan nokta, 8 bit nicelleştirilmiş, 16 bit sayısal, 32 bit tam sayı ve 8 bit boole değerlerine sahip tensörleri destekler.
Örneğin, Şekil 3, iki işlemli bir modeli temsil eder: toplama ve ardından bir çarpma işlemi. Model, bir giriş tensörü alır ve bir çıkış tensörü üretir.

Yukarıdaki modelin yedi işleneni vardır. Bu işlenenler, modele eklendikleri sıranın diziniyle örtülü olarak tanımlanır. Eklenen ilk işlenenin dizini 0, ikincisinin dizini 1 ve bu şekilde devam eder. İşlem gören 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ğerinin kullanılmasıdı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şlem gören bir model girişi, sabit değer ya da tam olarak bir işlemin çıkış işleneni olmalıdır.
İşlem görenlerin kullanımı hakkında daha fazla bilgi için İşlem görenler hakkında daha fazla bilgi bölümüne bakın.
İşlemler
İşlem, gerçekleştirilecek hesaplamaları belirtir. Her işlem şu öğelerden oluşur:
- işlem türü (ör. 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ş 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ıklardan yararlanır.
NNAPI'nın desteklediği işlemler aşağıdaki tabloda özetlenmiştir:
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 iletilirken, NNAPI'den elde edilen çı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
sınavını geçmelisiniz.
Bu sorun, Android 10 (API düzeyi 29) ve sonraki sürümlerde çözülmüştür.
Model oluşturma
Aşağıdaki örnekte, Şekil 3'te bulunan iki işlemli modeli oluşturuyoruz.
Modeli oluşturmak için aşağıdaki adımları uygulayın:
Boş bir model tanımlamak için
ANeuralNetworksModel_create()
işlevini çağırın.ANeuralNetworksModel* model = NULL; ANeuralNetworksModel_create(&model);
ANeuralNetworks_addOperand()
yöntemini çağırarak işlenenleri modelinize 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 6Uygulamanızın eğitim sürecinden elde ettiği ağırlıklar ve ağırlıklandırma gibi sabit değerlere sahip olan işlenenler için
ANeuralNetworksModel_setOperandValue()
veANeuralNetworksModel_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 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));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
- çıkış değerlerinin sayısı
- çıkış işlem görenleri 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);ANeuralNetworksModel_identifyInputsAndOutputs()
işlevini çağırarak modelin hangi işlenenleri giriş ve çıkışları olarak işlemesi 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);
İsteğe bağlı olarak,
ANEURALNETWORKS_TENSOR_FLOAT32
içinANeuralNetworksModel_relaxComputationFloat32toFloat16()
yöntemini çağırarak IEEE 754 16 bit kayan nokta biçiminin aralığı veya hassasiyetiyle hesaplanmasına izin verilip verilmeyeceğini belirtin.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, bu modeli istediğiniz sayıda derleyebilir ve her derlemeyi istediğiniz sayıda çalıştırabilirsiniz.
Kontrol akışı
Denetim akışını bir NNAPI modeline dahil etmek için aşağıdakileri yapın:
İlgili yürütme alt grafiklerini (
IF
ifadesi içinthen
veelse
alt grafikleri,WHILE
döngüsü içincondition
vebody
alt grafikleri) bağımsızANeuralNetworksModel*
modelleri olarak oluşturun:ANeuralNetworksModel* thenModel = makeThenModel(); ANeuralNetworksModel* elseModel = makeElseModel();
Kontrol akışını içeren modelde bu modellere referans veren 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);
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ırlanmaları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:
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.
İsteğe bağlı olarak, çalışma zamanının pil gücü kullanımı ile yürütme hızı arasında nasıl bir denge kurduğunu 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
: Yürütmeyi, pil tüketimini en aza indirecek şekilde tercih edin. Bu, sık yürütülen derlemeler için tercih edilir.ANEURALNETWORKS_PREFER_FAST_SINGLE_ANSWER
: Daha fazla güç tüketimine neden olsa bile tek bir yanıtı mümkün olduğunca hızlı 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.
İsteğe bağlı olarak,
ANeuralNetworksCompilation_setCaching
yöntemini çağırarak derlemenin önbelleğe alınmasını da ayarlayabilirsiniz.// Set up compilation caching ANeuralNetworksCompilation_setCaching(compilation, cacheDir, token);
cacheDir
içingetCodeCacheDir()
kullanın. Belirtilentoken
, uygulama içindeki her model için benzersiz olmalıdır.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 almasına ve yürütme için kullanılacak cihazları belirtmesine olanak tanıyan işlevler sağlar. Kullanılabilir cihazlar hakkında bilgi vermek, uygulamaların bilinen uyumsuzlukları önlemek için cihazdaki sürücülerin tam sürümlerini almasına olanak tanır. Uygulamalara, bir modelin farklı bölümlerini hangi cihazların çalıştıracağını belirtme olanağı verilerek 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
kullanın. Her cihazda bu cihaza referans vermek üzere bir ANeuralNetworksDevice
örneği ayarlamak için ANeuralNetworks_getDevice
öğesini kullanın.
Bir cihaz referansı aldıktan sonra, aşağıdaki işlevleri kullanarak söz konusu cihazla ilgili ek bilgileri öğrenebilirsiniz:
ANeuralNetworksDevice_getFeatureLevel
ANeuralNetworksDevice_getName
ANeuralNetworksDevice_getType
ANeuralNetworksDevice_getVersion
Cihaz ataması
Bir modelin hangi işlemlerinin belirli cihazlarda çalıştırılabileceğini keşfetmek 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 işin cihazlara dağıtılmasından çalışma zamanı sorumludur.
Diğer cihazlara benzer şekilde NNAPI CPU uygulaması da nnapi-reference
adında ve ANEURALNETWORKS_DEVICE_TYPE_CPU
türünde bir ANeuralNetworksDevice
ile temsil edilir. ANeuralNetworksCompilation_createForDevices
çağrısı yapılırken model derleme ve yürütme hata durumlarını yönetmek için CPU uygulaması kullanılmaz.
Bir modeli, belirtilen cihazlarda çalışabilecek alt modellere ayırmak uygulamanın sorumluluğudur. Manuel bölümlendirme gerektirmeyen uygulamalar, modeli hızlandırmak amacıyla mevcut tüm cihazları (CPU dahil) kullanmak için 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ümlendirme
Model için birden fazla cihaz mevcut olduğunda NNAPI çalışma zamanı, çalışmayı cihazlar arasında 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 tüm mevcut 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) bildirecek şekilde, kullanılabilir cihazlar listesinden seçim yapılır. Bu bölümlendirme algoritması, farklı işlemciler arasındaki KS'nin neden olduğu olası verimsizlikleri hesaba katmaz. Bu nedenle, birden fazla işlemci belirtirken (ANeuralNetworksCompilation_createForDevices
kullanırken açıkça 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 bir mesajla ilgili Android günlüklerine bakın (ExecutionPlan
etiketiyle bilgi düzeyinde):
ModelBuilder::findBestDeviceForEachOperation(op-name): device-index
op-name
, grafikteki işlemin açıklayıcı adıdır ve device-index
, cihaz listesindeki aday cihazın dizinidir.
Bu liste, ANeuralNetworksCompilation_createForDevices
işlevine sağlanan girdidir veya ANeuralNetworksCompilation_createForDevices
kullanılıyorsa ANeuralNetworks_getDeviceCount
ve ANeuralNetworks_getDevice
kullanılarak tüm cihazlar üzerinden iterasyon yapıldığında 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
adlı cihazda tüm grafiğin hızlandırıldığını gösterir.
Uygulama
Yürütme adımı, modeli bir dizi girişe 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 aşağıdaki adımları uygulayın:
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);
Uygulamanızın hesaplama için giriş değerlerini okuduğu yeri belirtin. Uygulamanız,
ANeuralNetworksExecution_setInput()
veyaANeuralNetworksExecution_setInputFromMemory()
kodunu sırayla çağırarak 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));
Uygulamanızın çıkış değerlerini nereye yazacağını belirtin. Uygulamanız,
ANeuralNetworksExecution_setOutput()
veyaANeuralNetworksExecution_setOutputFromMemory()
kodunu sırayla ç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));
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);
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 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);
İ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 çalıştırıldığı zaman ile nihayetinde CPU çekirdeğine bağlandığı zaman arasındaki en uzun gecikme 500 mikrosaniyeye kadar çıkabilir.
Gecikmeyi iyileştirmek için bunun yerine bir uygulamayı çalışma zamanına eşzamanlı bir çıkarım çağrısı yapması için yönlendirebilirsiniz. Bu çağrı, bir çıkarım başladıktan sonra dönmek yerine yalnızca çıkarım tamamlandığında döndürülür. Uygulama, çalışma zamanına eşzamansız bir çıkarım çağrısı için ANeuralNetworksExecution_startCompute
yöntemini çağırmak yerine, çalışma zamanına eşzamanlı bir çağrı yapmak için ANeuralNetworksExecution_compute
yöntemini çağırır. ANeuralNetworksExecution_compute
numarasına yapılan bir çağrı ANeuralNetworksEvent
almaz ve ANeuralNetworksEvent_wait
numarasına yapılan bir çağrıyla eşleştirilmez.
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 üzerinden seri yürütmeyi destekler. Seri çekim yürütmeler, aynı derlemenin hızlı bir şekilde art arda yürütülmesinden oluşan bir dizidir (örneğin, kamera çekimindeki karelerde veya ardışık ses örneklerinde çalışı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 patlama süresince yüksek performans durumunda kalması gerektiğini belirttiğinden daha hızlı yürütmeyle sonuçlanabilir.
ANeuralNetworksBurst
normal yürütme yolunda yalnızca küçük bir değişiklik sağlar. Aşağıdaki kod snippet'inde gösterildiği gibi ANeuralNetworksBurst_create
kullanarak seri bir nesne oluşturabilirsiniz:
// Create burst object to be reused across a sequence of executions ANeuralNetworksBurst* burst = NULL; ANeuralNetworksBurst_create(compilation, &burst);
Seri işlem yürütmeler eşzamanlıdır. Ancak her çıkarımı gerçekleştirmek için ANeuralNetworksExecution_compute
kullanmak yerine, ANeuralNetworksExecution_burstCompute
işlevine yapılan çağrılarda çeşitli ANeuralNetworksExecution
nesnelerini aynı ANeuralNetworksBurst
ile 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ırlanmış yürütme
Android 11 ve sonraki sürümlerde NNAPI, ANeuralNetworksExecution_startComputeWithDependencies()
yöntemi aracılığıyla eşzamansız yürütmeyi programlamanın ek bir yolunu da destekler. Bu yöntemi kullandığınızda yürütme, değerlendirmeye başlamadan önce bağlı tüm etkinliklere sinyal verilmesini bekler. Yürütme tamamlandıktan ve çıkışlar kullanılmaya 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, ANeuralNetworksEvent_getSyncFenceFd()
kullanarak da bir etkinlik nesnesindeki senkronizasyon çitlerini dışa aktarabilirsiniz.
Dinamik olarak boyutlandırılmış çıkışlar
Çıkış boyutunun giriş verilerine bağlı olduğu (yani, model yürütme anı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());
Temizleme
Temizleme adımı, hesaplamanız için kullanılan dahili kaynakların serbest bırakılmasını kapsar.
// Cleanup ANeuralNetworksCompilation_free(compilation); ANeuralNetworksModel_free(model); ANeuralNetworksMemory_free(mem1);
Hata yönetimi ve CPU yedeği
Bölümlendirme sırasında hata oluşursa, bir sürücü bir modelin (parça) derleyemezse veya derlenmiş (bir parça) modeli çalıştıramazsa 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 işlemek 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üdeki yürütme başarısız olursa NNAPI yürütmesi CPU'ya geri 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 üzerinde 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 üzerinde planlanmış işlemler olabilir. CPU, ANeuralNetworksCompilation_createForDevices
adlı iş ortağına sağlanan işlemciler listesinde yer alıyorsa ve bu işlemleri destekleyen tek veya bu işlemler için en iyi performansı talep eden işlemciyse birincil (yedek olmayan) yürütücü olarak seçilir.
CPU yürütmesi yapılmadığı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 olarak ayarlayarak HATA AYIKLAMA derlemelerinde yürütme zamanı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 anıları yürütmeler 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ı ö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şimi gereken tensörler için bunun yerine paylaşılan bellek havuzlarını kullanın.
Opak bellek ayırmak için aşağıdaki adımları uygulayın:
Yeni bir bellek açıklayıcı oluşturmak için
ANeuralNetworksMemoryDesc_create()
işlevini çağırın:// Create a memory descriptor ANeuralNetworksMemoryDesc* desc; ANeuralNetworksMemoryDesc_create(&desc);
ANeuralNetworksMemoryDesc_addInputRole()
veANeuralNetworksMemoryDesc_addOutputRole()
özelliklerini ç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);
İ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);
ANeuralNetworksMemoryDesc_finish()
yöntemini çağırarak açıklayıcı tanımını tamamlayın.ANeuralNetworksMemoryDesc_finish(desc);
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);
Artık ihtiyaç duymadığınızda bellek açıklayıcıyı boşaltın.
ANeuralNetworksMemoryDesc_free(desc);
İstemci, oluşturulan ANeuralNetworksMemory
nesnesini ANeuralNetworksMemoryDesc
nesnesinde belirtilen rollere göre yalnızca 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ça 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 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çün
Yürütme süresini ölçerek veya profil çıkararak 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 harcadığı 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
kullanarak şunları alabilirsiniz:
- hızlandırıcıda (ana makine işlemcisinde çalışan sürücüde değil) yürütme süresini gösterir.
- yürütme süresini kontrol eder.
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 çıkarımı yapmak için ayırdığı ve muhtemelen bağlam geçişi nedeniyle kesintiye uğradığı süre yerine, gönderilen iş ile tamamlanan iş etkinlikleri arasındaki süreyi ölçer.
Örneğin, çıkarım 1 başlarsa sürücü, çıkarım 2'yi gerçekleştirmek için çalışmayı durdurur, ardından devam edip 1 çıkarımı tamamlarsa çıkarım 1 için yürütme süresi, çıkarım 2'yi gerçekleştirmek 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 faydalı olabilir. Zamanlama verilerini kullanarak uygulamayı daha yüksek performans sağlayacak ş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 sürücü kendi içinde veya hızlandırıcıda harcanan süreyi hesaplayabilir.
- Bu API'leri yalnızca
numDevices = 1
ileANeuralNetworksCompilation_createForDevices
ile oluşturulan birANeuralNetworksExecution
ile kullanabilirsiniz. - Zamanlama bilgilerini bildirebilmek için herhangi bir sürücüye gerek yoktur.
Android Systrace ile uygulamanızın profilini çıkarın
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ıyla birlikte sunulur. Uygulamanızın bölündüğü katmanlar şunlardır:
Application
: ana uygulama koduRuntime
: NNAPI Çalışma ZamanıIPC
: NNAPI Çalışma Zamanı ile Sürücü kodu arasındaki işlemler arası iletişimDriver
: Hızlandırıcı sürücüsü işlemi.
Profil oluşturma analizi verilerini oluşturma
$ANDROID_BUILD_TOP konumundaki AOSP kaynak ağacını incelediğinizi ve hedef uygulama olarak TFLite resim sınıflandırma örneğini kullandığınız varsayıldığında, NNAPI profil oluşturma verilerini aşağıdaki adımları uygulayarak oluşturabilirsiniz:
- Aşağıdaki komutla Android systrace'i 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, izlerin 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, kabuk konsollarınızdan birini meşgul eder. Komut etkileşimli olarak bir enter
öğesinin sonlandırılmasını beklediğinden komutu arka planda çalıştırmayın.
- 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, Android Studio'dan veya uygulama zaten yüklenmişse doğrudan test telefonunuzun kullanıcı arayüzünden Image Classification uygulamasını 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.
Test tamamlandığında, 1. adımdan itibaren etkin durumdaki konsol terminalinde
enter
tuşuna basarak sistemi sonlandırın.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'ten 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 başına süre olarak) yazdırır
- --json
: çıktıyı JSON biçiminde oluşturur
Çı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, ilişkili bir bölüm başlangıç etkinliği olmadan izlemede yer alıyorsa başarısız olabilir. Bu durum genellikle, systrace toplayıcıyı başlattığınızda önceki profil çıkarma oturumundan bazı etkinlikler oluşturuluyorsa ortaya çıkar. Bu durumda, profil oluşturma işlemini tekrar çalıştırmanız gerekir.
Uygulama kodunuz için systrace_parser çıkışına istatistikler 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üzeyindeki etkinlik[NN_LA_PC]
: Derleme için uygulama düzeyinde etkinlik[NN_LA_PE]
: Yürütme için uygulama düzeyindeki etkinlik
Execution
aşaması için runInferenceModel
bölümü ve NNAPI izlerinde dikkate alınmayacak başka bölümleri preprocessBitmap
içeren Application
katmanı ekleyerek TFLite resim 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ı 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 ListrecognizeImage(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 ilgili modellerinin göreceli önceliklerini, belirli bir modeli hazırlamak için beklenen maksimum süreyi ve belirli bir hesaplamayı tamamlamak için beklenen maksimum süreyi belirtmesine olanak tanıyarak daha iyi hizmet kalitesi (HK) sağlar. Android 11'de, uygulamaların teslim tarihlerinin kaçırılması gibi hataları anlamasını sağlayan ek NNAPI sonuç kodları da sunulmaktadır.
İş yükünün önceliğini ayarlama
NNAPI iş yükünün önceliğini ayarlamak için ANeuralNetworksCompilation_finish()
çağrısı yapmadan önce ANeuralNetworksCompilation_setPriority()
numaralı telefonu arayın.
Son tarihler belirleyin
Uygulamalar hem model derleme hem de çıkarım için son tarihler belirleyebilir.
- Derleme zaman aşımını ayarlamak için
ANeuralNetworksCompilation_finish()
çağrısı yapmadan önceANeuralNetworksCompilation_setTimeout()
numaralı telefonu arayın. - Çıkarım zaman aşımını ayarlamak için derlemeyi başlatmadan önce
ANeuralNetworksExecution_setTimeout()
çağrısı yapın.
İş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.
Niceliklendirilmiş tensörler
Niceleş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örlerde her hücrenin değeri 8 bitlik bir tam sayı ile temsil edilir. Tensörle ilişkilendirilen şey ölçek ve sıfır puandır. Bunlar, 8 bit tam sayıları temsil edilen kayan nokta değerlerine dönüştürmek için kullanılır.
Formül şöyledir:
(cellValue - zeroPoint) * scale
Bu örnekte sıfırPoint değeri 32 bitlik bir tam sayı ve ölçek, 32 bitlik bir kayan nokta değeridir.
32 bitlik kayan nokta değerlerinin tensörleriyle karşılaştırıldığında, 8 bit ölçülebilir tensörlerin iki avantajı vardır:
- Eğitilmiş 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 yapma konusunda DSP 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 modeli doğrudan eğiterek 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 için ö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 nicel tensör türlerini tanımlarsınız.
Ayrıca bu veri yapısındaki tensörün ölçeğini ve sıfırPoint değerini de belirtirsiniz.
NNAPI, 8 bit asimetrik ölçülmüş tensörlere ek olarak aşağıdakileri destekler:
- Ağırlıkları
CONV/DEPTHWISE_CONV/TRANSPOSED_CONV
işlemlerine temsil etmek için kullanabileceğinizANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL
. QUANTIZED_16BIT_LSTM
'in dahili durumu için kullanabileceğinizANEURALNETWORKS_TENSOR_QUANT16_ASYMM
.ANEURALNETWORKS_TENSOR_QUANT8_SYMM
,ANEURALNETWORKS_DEQUANTIZE
için giriş olabilir.
İ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.
İşlenen öğenin mevcut olup olmadığıyla ilgili karar her yürütme için farklılık gösteriyorsa ANeuralNetworksExecution_setInput()
veya ANeuralNetworksExecution_setOutput()
işlevlerini kullanarak işlenenin atlandığını belirtirsiniz ve arabellek için NULL
, uzunluk için 0 değerini iletirsiniz.
Sıralaması bilinmeyen tensörler
Android 9 (API düzeyi 28) bilinmeyen boyutların model işlenenlerini kullanıma sundu ancak sıralama (boyut sayısı) bilinen sıralamaya sahip. Android 10 (API düzeyi 29), ANeuralNetworkOperandType bölümünde 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:
Bilgisayarınıza bir hedef Android cihaz bağlayın, bir terminal penceresi açın ve cihaza adb üzerinden erişilebildiğinden emin olun.
Birden fazla Android cihaz bağlıysa hedef cihaz
ANDROID_SERIAL
ortam değişkenini dışa aktarın.Android'in en üst düzey kaynak dizinine gidin.
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
adresine iletilen bir HTML sayfası olarak sunulur.
NNAPI günlükleri
NNAPI, sistem günlüklerinde yararlı 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 oluşturmacompilation
: Model yürütme planı ve derleme oluşturmaexecution
: Model yürütmecpuexe
: İşlemlerin NNAPI CPU uygulamasını kullanarak yürütmemanager
: NNAPI uzantıları, mevcut arayüzler ve özelliklerle ilgili bilgilerall
veya1
: 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ştirildikten sonra ayrıntılı günlük kaydı, aşama veya bileşen adına ayarlanmış bir etiket ile INFO (Bilgi) düzeyinde günlük girişleri oluşturur.
NNAPI API bileşenleri, debug.nn.vlog
tarafından denetlenen mesajların yanı sıra, her biri belirli bir günlük etiketi kullanan çeşitli düzeylerde diğer günlük girişleri 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 Derleme Oluşturucu
- Geri çağırma işlevleri
- Derleme Oluşturucu
- CPUExecutor
- Yürütme Oluşturucu
- Yürütme Seri İşlem Denetleyicisi
- Yürütme BurstSunucusu
- Yürütme Planı
- FibonacciSürücü
- Grafik Dökümü
- Dizine Eklenen Şekil Sarmalayıcı
- Ionİzleyici
- Yönetici
- Bellek
- MemoryUtil'ler
- MetaModel
- Model Argüman Bilgisi
- Model Oluşturucu
- NeuralAğlar
- İşlem Çözücü
- İşlemler
- İşlem Yardımcı Araçları
- Paket Bilgileri
- TokenHasher (Jeton Karesi)
- Tür Yöneticisi
- Yardımcı Programlar
- 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. Yine de ayrıntılı günlük bilgileri oluşturmak için debug.nn.vlog
özelliğini all
olarak ayarlamanız gerekir.