Android Neural Networks API (NNAPI), Android cihazlarda makine öğrenimi için yoğun hesaplama gerektiren işlemleri çalıştırmak üzere tasarlanmış bir Android C API'sidir. NNAPI, sinir ağları oluşturup eğiten TensorFlow Lite ve Caffe2 gibi daha üst düzey makine öğrenimi çerçeveleri için temel bir işlev 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 cihazlardaki verileri önceden eğitilmiş, geliştirici tanımlı modellere uygulayarak çıkarım yapmayı destekler. Çıkarsama örnekleri arasında resimleri sınıflandırma, kullanıcı davranışını tahmin etme ve arama sorgusuna uygun yanıtları seçme yer alır.
Cihaz üzerinde çıkarım yapmanın birçok avantajı vardır:
- Gecikme: Ağ bağlantısı üzerinden istek gönderip yanıt beklemeniz gerekmez. Örneğin, bu durum bir kameradan gelen art arda gelen kareleri işleyen video uygulamaları için kritik olabilir.
- Kullanılabilirlik: Uygulama, ağ kapsamı dışındayken bile çalışır.
- Hız: Sinir ağı işlemeye özel yeni donanım, tek başına genel amaçlı bir CPU'dan önemli ölçüde daha hızlı hesaplama sağlar.
- Gizlilik: Veriler Android cihazdan çıkmaz.
- Maliyet: Tüm hesaplamalar Android cihazda yapıldığında sunucu çiftliğine gerek yoktur.
Geliştiricilerin göz önünde bulundurması gereken bazı avantajlar ve dezavantajlar da vardır:
- Sistem kullanımı: Yapay sinir ağlarının değerlendirilmesi çok fazla hesaplama gerektirir ve bu da pil gücünün kullanımını artırabilir. Uygulamanız için bu bir sorunsa, özellikle uzun süreli hesaplamalar söz konusu olduğunda pil sağlığını izlemeyi düşünmeniz gerekir.
- Uygulama boyutu: Modellerinizin boyutuna dikkat edin. Modeller birkaç megabaytlık alan kaplayabilir. APK'nıza büyük modeller eklemek kullanıcılarınızı olumsuz yönde etkileyecekse modelleri uygulama yüklendikten sonra indirebilir, daha küçük modeller kullanabilir veya hesaplamalarınızı bulutta çalıştırabilirsiniz. NNAPI, modelleri bulutta çalıştırma işlevi 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 çalışma zamanını anlama
NNAPI, geliştiricilerin modellerini cihaz dışında eğitmelerine ve Android cihazlarda dağıtmalarına olanak tanıyan makine öğrenimi kitaplıkları, çerçeveleri ve araçları tarafından çağrılmak üzere tasarlanmıştır. Uygulamalar genellikle NNAPI'yi doğrudan kullanmaz, bunun yerine daha üst düzey makine öğrenimi çerçevelerini kullanır. Bu çerçeveler de desteklenen cihazlarda donanım hızlandırmalı çıkarım işlemleri gerçekleştirmek için NNAPI'yi kullanabilir.
Android'in sinir ağı çalışma zamanı, uygulamanın gereksinimlerine ve Android cihazdaki donanım özelliklerine bağlı olarak, özel sinir ağı donanımı, grafik işlem birimleri (GPU'lar) ve dijital sinyal işlemcileri (DSP'ler) dahil olmak üzere mevcut cihaz üzerinde işlemcilere hesaplama iş yükünü verimli bir şekilde dağıtabilir.
Özel bir tedarikçi sürücüsü olmayan Android cihazlarda NNAPI çalışma zamanı, istekleri CPU'da yürütür.
Şekil 1'de NNAPI'nin üst düzey sistem mimarisi gösterilmektedir.
Neural Networks API programlama modeli
NNAPI'yi kullanarak hesaplama yapmak için öncelikle yapılacak hesaplamaları tanımlayan yönlendirilmiş bir grafik oluşturmanız gerekir. Bu hesaplama grafiği, giriş verilerinizle (ör. bir makine öğrenimi çerçevesinden aktarılan ağırlıklar ve önyargılar) birlikte 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üreci aracılığıyla öğrenilen sabit değerlerin hesaplama grafiği. Bu işlemler, sinir ağlarına özgüdür. Bunlar arasında 2 boyutlu (2D) konvolüsyon, mantıksal (sigmoid) aktivasyon, doğrusal 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, mesaj dizileri ve derlemelerde yeniden kullanılabilir.
NNAPI'de modeller
ANeuralNetworksModel
örneği olarak temsil edilir. - Derleme: Bir NNAPI modelini daha düşük düzeyli koda derleme yapılandırmasını temsil eder. Derleme oluşturma işlemi eşzamanlı bir işlemdir. Başarıyla oluşturulduktan sonra, iş parçacıkları ve yürütmeler arasında yeniden kullanılabilir. NNAPI'de her derleme bir
ANeuralNetworksCompilation
örneği olarak temsil edilir. - Bellek: Paylaşılan belleği, belleğe eşlenen dosyaları ve benzer bellek arabelleklerini temsil eder. Bellek arabelleği kullanmak, NNAPI çalışma zamanının sürücülere daha verimli bir şekilde veri aktarmasını sağlar. Uygulamalar genellikle bir modeli tanımlamak için gereken tüm tenzorları içeren bir paylaşılan bellek arabelleği oluşturur. Bir yürütme örneğinin giriş ve çıkışlarını depolamak için bellek arabelleklerini de kullanabilirsiniz. NNAPI'de her bellek arabelleği bir
ANeuralNetworksMemory
örneği olarak temsil edilir. Yürütme: NNAPI modelini bir giriş grubuna uygulamak ve sonuçları toplamak için kullanılan arayüz. Yürütme, eşzamanlı veya eşzamansız olarak yapılabilir.
Eşzamansız yürütme için 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österilmektedir.
Bu bölümün geri kalanında, NNAPI modelinizi hesaplama yapmak, modeli derlemek ve derlenmiş modeli yürütmek için ayarlamayla ilgili adımlar açıklanmaktadır.
Eğitim verilerine erişim sağlama
Eğitilmiş ağırlık ve önyargı verileriniz büyük olasılıkla bir dosyada depolanır. NNAPI çalışma zamanında bu verilere verimli bir erişim sağlamak için ANeuralNetworksMemory_createFromFd()
işlevini çağırıp açılan veri dosyasının dosya tanımlayıcısını ileterek bir ANeuralNetworksMemory
örneği oluşturun. Ayrıca, bellek koruma işaretlerini ve paylaşılan bellek bölgesinin dosyada başladığı ofseti de 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 kullanmak mümkündür.
Yerel donanım arabelleklerini kullanma
Model girişleri, çıkışları ve sabit operatör değerleri için yerel donanım arabelleklerini kullanabilirsiniz. Belirli durumlarda, 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 dokümanlarında listelenen kısıtlamalara bakın ve AHardwareBuffer
kullanan derlemelerin ve yürütme işlemlerinin beklendiği gibi davrandığından emin olmak için hedef cihazlarda önceden test edin. Hızlandırıcıyı belirtmek için cihaz atamasını kullanı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 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 AHardwareBuffer
nesnesine artık erişmesi gerekmediğinde ilgili ANeuralNetworksMemory
örneğini serbest bırakın:
ANeuralNetworksMemory_free(mem2);
Not:
AHardwareBuffer
parametresini yalnızca arabelleğin tamamı için kullanabilirsiniz;ARect
parametresiyle kullanamazsınız.- NNAPI çalışma zamanı arabelleği temizlemez. Yürütmeyi planlamadan önce giriş ve çıkış arabelleklerine erişilebildiğinden emin olmanız gerekir.
- Senkronizasyon çiti dosya tanımlayıcıları desteklenmez.
- Tedarikçiye özgü biçimler ve kullanım bitleri içeren bir
AHardwareBuffer
için, önbelleği temizlemekten istemcinin mi yoksa sürücünün mi sorumlu olacağını belirlemek tedarikçiye aittir.
Model
Model, NNAPI'deki temel hesaplama birimidir. Her model bir veya daha fazla operatör ve işlemle tanımlanır.
İşlemler
İşlemler, grafiği tanımlamak için kullanılan veri nesneleridir. Buna modelin giriş ve çıkışları, bir işlemden diğerine akan verileri içeren ara düğümler ve bu işlemlere iletilen sabitler dahildir.
NNAPI modellerine eklenebilecek iki tür operatör vardır: skalar ve tenzorlar.
Skalar, tek bir değeri temsil eder. NNAPI, boole, 16 bit kayan nokta, 32 bit kayan nokta, 32 bit tam sayı ve 32 bit tam sayı (imzalanmamış) 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 kesirli, 16 bit kesirli, 32 bit tam sayı ve 8 bit doğru/yanlış değerlerine sahip tenzorları destekler.
Örneğin, 3. şekil iki işlem içeren bir modeli temsil eder: artım ve ardından çarpma. Model, bir giriş tensörü alır ve bir çıkış tensörü oluşturur.
Yukarıdaki modelde yedi işleyen vardır. Bu operatörler, modele eklendikleri sıranın dizini tarafından dolaylı olarak tanımlanır. Eklenen ilk operatörün dizini 0, ikincinin dizini 1 olur ve bu şekilde devam eder. 1, 2, 3 ve 5 operatörleri sabit operatörlerdir.
İşlemleri ekleme sırası önemli değildir. Örneğin, model çıkış operatı ilk eklenen olabilir. Önemli olan, bir operand'a atıfta bulunurken doğru dizin değerini kullanmaktır.
İşlem öğelerinin türleri vardır. Bunlar modele eklenirken belirtilir.
Bir operant, bir modelin hem girişi hem de çıkışı olarak kullanılamaz.
Her operand, model girişi, sabit değer veya tam olarak bir işlemin çıkış operand'ı olmalıdır.
İşlem öğelerini kullanma hakkında daha fazla bilgi için İşlem öğeleri hakkında daha fazla bilgi başlıklı makaleyi inceleyin.
İşlemler
İşlem, gerçekleştirilecek hesaplamaları belirtir. Her işlem aşağıdaki unsurlardan oluşur:
- bir işlem türü (ör. toplama, çarpma, topoloji),
- İşlemin giriş için kullandığı operatörlerin dizinlerinin listesi ve
- İşlemin çıkış için kullandığı operatörlerin 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şlemi eklemeden önce, işlemin kullandığı veya ürettiği operandları modele eklemeniz gerekir.
İşlemleri ekleme sırası önemli değildir. NNAPI, işlemlerin yürütülme sırasını belirlemek için operatörler ve işlemlerin hesaplama grafiği tarafından oluşturulan bağımlılıklardan yararlanır.
NNAPI'nin 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_TENSOR_QUANT8_ASYMM
tensörleri ANEURALNETWORKS_PAD
işlemine aktarırken NNAPI'den elde edilen çıkış, TensorFlow Lite gibi daha üst düzey makine öğrenimi çerçevelerinden elde edilen çıkışla eşleşmeyebilir. Bunun yerine yalnızca ANEURALNETWORKS_TENSOR_FLOAT32
parametresini iletmeniz gerekir.
Sorun, Android 10 (API düzeyi 29) ve sonraki sürümlerde giderilmiştir.
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()
işlevini çağırarak operatörleri modelinize ekleyin. Veri türleriANeuralNetworksOperandType
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 bir eğitim sürecinden elde ettiği ağırlıklar ve önyargılar gibi sabit değerlere sahip operatörler için
ANeuralNetworksModel_setOperandValue()
veANeuralNetworksModel_setOperandValueFromMemory()
işlevlerini kullanın.Aşağıdaki örnekte, Eğitim verilerine erişim izni verme 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));Hesaplamak istediğiniz yönlendirilmiş grafikteki her işlem için
ANeuralNetworksModel_addOperation()
işlevini çağırarak işlemi modelinize ekleyin.Uygulamanız bu çağrının parametreleri olarak şunları sağlamalıdır:
- İşlem türü
- giriş değerlerinin sayısı
- Giriş operatörleri için dizin dizisi
- çıkış değerlerinin sayısı
- Çıkış operatörlerinin dizinleri dizisi
Bir operatörün 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 operatörleri giriş ve çıkış olarak değerlendirmesi 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,
ANeuralNetworksModel_relaxComputationFloat32toFloat16()
işlevini çağırarakANEURALNETWORKS_TENSOR_FLOAT32
değerinin IEEE 754 16 bit kayan nokta biçimi kadar düşük bir aralık veya hassasiyetle hesaplanmasına izin verilip verilmeyeceğini belirtin.Modelinizin tanımını tamamlamak için
ANeuralNetworksModel_finish()
numaralı telefonu arayın. Hata yoksa bu işlevANEURALNETWORKS_NO_ERROR
sonuç kodunu döndürür.ANeuralNetworksModel_finish(model);
Oluşturduğunuz modeli istediğiniz sayıda derleyebilir ve her derlemeyi istediğiniz sayıda çalıştırabilirsiniz.
Kontrol akışı
Kontrol 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 model içinde bu modellere referans veren işlevler 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 çalışacağını belirler ve ilgili sürücülerden yürütme işlemine hazırlanmalarını ister. Bu işlem, modelinizin çalışacağı işlemcilere özel makine kodunun oluşturulmasını içerebilir.
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);
İsterseniz hangi cihazlarda çalışacağını 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ı ve yürütme hızı arasında nasıl denge kuracağını belirleyebilirsiniz. Bunu yapmak için
ANeuralNetworksCompilation_setPreference()
numaralı telefonu arayabilirsiniz.// Ask to optimize for low power consumption ANeuralNetworksCompilation_setPreference(compilation, ANEURALNETWORKS_PREFER_LOW_POWER);
Belirtmeniz gereken tercihler şunlardır:
ANEURALNETWORKS_PREFER_LOW_POWER
: Pil tüketimini en aza indirecek şekilde yürütmeyi tercih edin. Bu, sık çalıştırılan derlemeler için istenilen bir durumdur.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 eder. Bu, varsayılan seçenektir.ANEURALNETWORKS_PREFER_SUSTAINED_SPEED
: Kareden kareye işleme yaparken olduğu gibi, art arda gelen karelerin aktarım hızını en üst düzeye çıkarmayı tercih edin.
İsteğe bağlı olarak
ANeuralNetworksCompilation_setCaching
çağrısını yaparak derleme önbelleğe almayı ayarlayabilirsiniz.// Set up compilation caching ANeuralNetworksCompilation_setCaching(compilation, cacheDir, token);
cacheDir
içingetCodeCacheDir()
kullanın. Belirtilentoken
, uygulamadaki her model için benzersiz olmalıdır.ANeuralNetworksCompilation_finish()
işlevini çağırarak derleme tanımını tamamlayın. Hata yoksa bu işlevANEURALNETWORKS_NO_ERROR
sonuç kodunu döndürür.ANeuralNetworksCompilation_finish(compilation);
Cihaz bulma ve atama
Android 10 (API düzeyi 29) ve sonraki sürümleri çalıştıran Android cihazlarda NNAPI, makine öğrenimi çerçeve kitaplıklarının ve uygulamalarının mevcut cihazlar hakkında bilgi edinmesine ve yürütme için kullanılacak cihazları belirtmesine olanak tanıyan işlevler sağlar. Mevcut cihazlar hakkında bilgi sağlamak, uygulamaların bilinen uyumsuzlukları önlemek için cihazda bulunan sürücülerin tam sürümünü almasına olanak tanır. Uygulamalara, bir modelin farklı bölümlerinin hangi cihazlarda çalışacağını belirtme olanağı sunarak uygulamaları dağıtıldığı Android cihaz için optimize edebilirsiniz.
Cihaz bulma
Mevcut cihaz sayısını öğrenmek için ANeuralNetworks_getDeviceCount
simgesini kullanın. Her cihaz için ANeuralNetworksDevice
örneğini ilgili cihazın referansı olarak ayarlamak üzere ANeuralNetworks_getDevice
kullanın.
Cihaz referansı aldıktan sonra aşağıdaki işlevleri kullanarak ilgili cihaz hakkında daha fazla bilgi edinebilirsiniz:
ANeuralNetworksDevice_getFeatureLevel
ANeuralNetworksDevice_getName
ANeuralNetworksDevice_getType
ANeuralNetworksDevice_getVersion
Cihaz ataması
Bir modelin hangi işlemlerinin belirli cihazlarda çalışabileceğini öğrenmek için ANeuralNetworksModel_getSupportedOperationsForDevices
simgesini kullanın.
Yürütme için hangi hızlandırıcıların kullanılacağını kontrol etmek üzere ANeuralNetworksCompilation_create
yerine ANeuralNetworksCompilation_createForDevices
çağrısı yapın.
Elde edilen ANeuralNetworksCompilation
nesnesini normal şekilde kullanın.
Sağlanan model, seçili cihazlar tarafından desteklenmeyen işlemler içeriyorsa işlev hata döndürür.
Birden fazla cihaz belirtilirse çalışmanın cihazlara dağıtılmasından çalışma zamanı sorumludur.
Diğer cihazlara benzer şekilde, NNAPI CPU uygulaması nnapi-reference
adında ve ANEURALNETWORKS_DEVICE_TYPE_CPU
türündeki bir ANeuralNetworksDevice
ile temsil edilir. ANeuralNetworksCompilation_createForDevices
çağrılırken model derleme ve yürütmeyle ilgili hata durumlarını işlemek için CPU uygulaması kullanılmaz.
Bir modeli, belirtilen cihazlarda çalışabilecek alt modellere ayırmak uygulamanın sorumluluğundadır. Manuel bölümlendirme yapması gerekmeyen uygulamalar, modeli hızlandırmak için mevcut tüm cihazları (CPU dahil) kullanmak üzere daha basit ANeuralNetworksCompilation_create
işlevini çağırmaya devam etmelidir. Model, ANeuralNetworksCompilation_createForDevices
kullanılarak belirttiğiniz cihazlar tarafından tam olarak desteklenemiyorsa 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ı, işi cihazlara dağıtır. Örneğin, ANeuralNetworksCompilation_createForDevices
için birden fazla cihaz sağlandıysa iş atanı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 olmak üzere mevcut tüm cihazlar dikkate alınır.
Dağıtım, modeldeki her işlem için kullanılabilir cihazlar listesinden, işlemi destekleyen ve müşteri tarafından belirtilen yürütme tercihine bağlı olarak en iyi performansı (ör. en hızlı yürütme süresi veya en düşük güç tüketimi) sunan cihazı seçerek yapılır. Bu bölümleme algoritması, farklı işlemciler arasındaki G/Ç'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
kullanırken dolaylı olarak) ortaya çıkan uygulamanın profilini oluşturmak önemlidir.
Modelinizin NNAPI tarafından nasıl bölümlendirildiğini anlamak için Android günlüklerinde bir mesaj olup olmadığını kontrol edin (ExecutionPlan
etiketiyle INFO 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 giriştir veya ANeuralNetworksCompilation_createForDevices
kullanılıyorsa ANeuralNetworks_getDeviceCount
ve ANeuralNetworks_getDevice
kullanılarak tüm cihazlar üzerinde iterasyon yapılırken döndürülen cihaz listesidir.
Mesaj (ExecutionPlan
etiketiyle INFO düzeyinde):
ModelBuilder::partitionTheWork: only one best device: device-name
Bu mesaj, grafiğin tamamının device-name
cihazında 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 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 nerede okuduğunu belirtin. Uygulamanız, sırasıyla
ANeuralNetworksExecution_setInput()
veyaANeuralNetworksExecution_setInputFromMemory()
işlevini çağırarak giriş değerlerini bir kullanıcı arabelleğinden ya da ayrılmış bir bellek alanından 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, sırasıyla
ANeuralNetworksExecution_setOutput()
veyaANeuralNetworksExecution_setOutputFromMemory()
işlevini çağırarak çıkış değerlerini bir kullanıcı arabelleğine ya da ayrılmış bir bellek alanına yazabilir.// Set the output float32 myOutput[3][4]; ANeuralNetworksExecution_setOutput(run1, 0, NULL, myOutput, sizeof(myOutput));
ANeuralNetworksExecution_startCompute()
işlevini çağırarak yürütmenin başlamasını planlayın. Hata yoksa bu işlevANEURALNETWORKS_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ıysa bu işlevANEURALNETWORKS_NO_ERROR
sonuç kodunu döndürür. Beklemede kalma işlemi, yürütmeyi başlatan iş parçacığından farklı bir iş parçacığında 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 derlenmiş 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);
Senkronize 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. Bir iş parçacığına bildirim gönderilmesi veya iş parçacığının uyandırılması ile bir CPU çekirdeğine bağlanması arasındaki en uzun gecikme 500 mikrosaniyeye kadar ulaşabilir.
Gecikmeyi azaltmak için uygulamayı, çalışma zamanında eşzamanlı bir çıkarım çağrısı yapmaya yönlendirebilirsiniz. Bu çağrı, çıkarım başlatıldıktan sonra değil, yalnızca çıkarım tamamlandıktan sonra döndürülür. Uygulama, çalışma zamanında eşzamanlı çıkarım çağrısı yapmak için ANeuralNetworksExecution_compute
yerine ANeuralNetworksExecution_startCompute
çağırır. ANeuralNetworksExecution_compute
'e yapılan bir arama ANeuralNetworksEvent
gerektirmez ve ANeuralNetworksEvent_wait
'e yapılan bir aramayla eşlenmez.
Ani 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 toplu yürütmeleri destekler. Seri yürütmeler, aynı derlemenin hızlı bir şekilde art arda gerçekleştiği bir yürütme dizisidir (ör. kamera yakalama karelerinde veya art arda gelen ses örneklerinde çalışanlar). ANeuralNetworksBurst
nesneleri, hızlandırıcılara kaynakların yürütmeler arasında yeniden kullanılabileceğini ve hızlandırıcıların ani artış süresi boyunca yüksek performanslı durumda kalması gerektiğini belirttiği için daha hızlı yürütmelerle sonuçlanabilir.
ANeuralNetworksBurst
, normal yürütme yolunda yalnızca küçük bir değişiklik yapar. Aşağıdaki kod snippet'inde gösterildiği gibi ANeuralNetworksBurst_create
kullanarak bir seri nesnesi oluşturursunuz:
// Create burst object to be reused across a sequence of executions ANeuralNetworksBurst* burst = NULL; ANeuralNetworksBurst_create(compilation, &burst);
Patlama yürütmeleri eşzamanlıdır. Ancak her çıkarım işlemini gerçekleştirmek için ANeuralNetworksExecution_compute
kullanmak yerine, ANeuralNetworksExecution_burstCompute
işlev çağrılarında çeşitli ANeuralNetworksExecution
nesnelerini aynı ANeuralNetworksBurst
ile eşleşirsiniz.
// 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 çitle çevrili yürütme
Android 11 ve sonraki sürümlerde NNAPI, ANeuralNetworksExecution_startComputeWithDependencies()
yöntemi aracılığıyla asenkron yürütmeyi planlamanın ek bir yolunu destekler. Bu yöntemi kullandığınızda yürütme, değerlendirmeye başlamadan önce tüm bağımlı etkinliklerin sinyallenmesini bekler. Yürütme tamamlandıktan ve çıkışlar kullanılmaya hazır olduktan sonra döndürülen etkinlik sinyallenir.
Etkinliğin yürütülmesini hangi cihazların üstlendiğine bağlı olarak, etkinlik bir senkronizasyon çiti ile desteklenmelidir. Etkinliği beklemek ve yürütmenin kullandığı kaynakları geri almak için ANeuralNetworksEvent_wait()
işlevini çağırmanız gerekir. ANeuralNetworksEvent_createFromSyncFenceFd()
kullanarak senkronizasyon çitlerini bir etkinlik nesnesine aktarabilir ve ANeuralNetworksEvent_getSyncFenceFd()
kullanarak senkronizasyon çitlerini bir etkinlik nesnesinden dışa aktarabilirsiniz.
Dinamik olarak boyutlandırılmış çıkışlar
Çıktının boyutunun giriş verilerine bağlı olduğu modelleri (yani boyutun model çalıştırma sırasında belirlenemediği modelleri) desteklemek için ANeuralNetworksExecution_getOutputOperandRank
ve ANeuralNetworksExecution_getOutputOperandDimensions
parametrelerini 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ölme işlemi sırasında bir hata oluşursa, sürücü bir modeli (modelin bir parçası) derleyemezse veya sürücü derlenmiş bir modeli (modelin bir parçası) 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 içeriyorsa (ör. TFLite) CPU yedek planını devre dışı bırakmak ve istemcinin optimize edilmiş işlem uygulamasıyla hataları ele almak avantajlı olabilir.
Android 10'da derleme ANeuralNetworksCompilation_createForDevices
kullanılarak gerçekleştirilirse CPU yedekleme devre dışı bırakılır.
Android P'de, sürücüde yürütme başarısız olursa NNAPI yürütme işlemi 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, tek bir bölüm için geri çekilir ve bu yine de başarısız olursa modelin tamamını CPU'da yeniden dener.
Bölme veya derleme başarısız olursa modelin tamamı CPU'da denenir.
Bazı işlemlerin CPU'da desteklenmediği durumlar vardır ve bu gibi durumlarda derleme veya yürütme, yedek yönteme geçmek yerine başarısız olur.
CPU yedekleme devre dışı bırakıldıktan sonra bile modelde CPU'da planlanmış işlemler olabilir. CPU, ANeuralNetworksCompilation_createForDevices
'e 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'nun çalışmadığından emin olmak için nnapi-reference
'ı cihaz listesinden hariç tutarken ANeuralNetworksCompilation_createForDevices
kullanın.
Android P'den itibaren, debug.nn.partition
mülkünü 2 olarak ayarlayarak YAPI YOKSA derlemelerinde yürütme sırasında yedeği devre dışı bırakmak mümkündür.
Anı alanları
Android 11 ve sonraki sürümlerde NNAPI, opak bellekler için ayırıcı arayüzleri sağlayan bellek alanlarını destekler. Bu sayede uygulamalar, cihaza özgü bellekleri yürütmeler arasında iletebilir. Böylece NNAPI, aynı sürücüde art arda yürütmeler gerçekleştirirken gereksiz yere veri kopyalama veya dönüştürme yapmaz.
Bellek alanı özelliği, çoğunlukla sürücüye dahil olan ve istemci tarafına sık sık erişmesi gerekmeyen tenzorlar için tasarlanmıştır. Bu tür tenzorlara örnek olarak sıralı modellerdeki durum tenzorları verilebilir. İstemci tarafında sık sık CPU erişimi gerektiren tenzorlar için bunun yerine paylaşılan bellek havuzlarını kullanın.
Saydam olmayan bir bellek ayırmak için aşağıdaki adımları uygulayın:
Yeni bir bellek tanımlayıcısı oluşturmak için
ANeuralNetworksMemoryDesc_create()
işlevini çağırın:// Create a memory descriptor ANeuralNetworksMemoryDesc* desc; ANeuralNetworksMemoryDesc_create(&desc);
ANeuralNetworksMemoryDesc_addInputRole()
veANeuralNetworksMemoryDesc_addOutputRole()
çağrılarını yaparak amaçlanan 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()
işlevini çağırarak bellek boyutlarını belirtin.// Specify the memory dimensions uint32_t dims[] = {3, 4}; ANeuralNetworksMemoryDesc_setDimensions(desc, 2, dims);
ANeuralNetworksMemoryDesc_finish()
işlevini çağırarak tanımlayıcı tanımını tamamlayın.ANeuralNetworksMemoryDesc_finish(desc);
Tanımlayıcıyı
ANeuralNetworksMemory_createFromDesc()
öğesine ileterek ihtiyacınız olan kadar bellek ayırın.// Allocate two opaque memories with the descriptor ANeuralNetworksMemory* opaqueMem; ANeuralNetworksMemory_createFromDesc(desc, &opaqueMem);
Artık ihtiyaç duymadığınız bellek tanımlayıcısını serbest bırakın.
ANeuralNetworksMemoryDesc_free(desc);
İstemci, oluşturulan ANeuralNetworksMemory
nesnesini yalnızca ANeuralNetworksMemoryDesc
nesnesinde belirtilen rollere göre ANeuralNetworksExecution_setInputFromMemory()
veya ANeuralNetworksExecution_setOutputFromMemory()
ile kullanabilir. Başlangıç ve uzunluk bağımsız değişkenleri, belleğin tamamının kullanıldığını belirten 0 olarak ayarlanmalıdır. İstemci, ANeuralNetworksMemory_copy()
kullanarak belleğin içeriğini açıkça ayarlayabilir veya ayıklayabilir.
Belirtilmemiş boyut veya rütbe rollerine sahip opak anılar oluşturabilirsiniz.
Bu durumda, bellek oluşturma işlemi temel sürücü tarafından desteklenmiyorsa ANEURALNETWORKS_OP_FAILED
durumuyla başarısız olabilir. İstemcinin, Ashmem veya BLOB modu AHardwareBuffer
tarafından desteklenen yeterince büyük bir arabellek ayırarak yedek mantığını uygulaması önerilir.
NNAPI'nin opak bellek nesnesine erişmesi gerekmediğinde ilgili ANeuralNetworksMemory
örneğini serbest bırakın:
ANeuralNetworksMemory_free(opaqueMem);
Performansı ölçün
Uygulamanızın performansını yürütme süresini ölçerek veya profil oluşturarak değerlendirebilirsiniz.
Yürütme süresi
Çalışma zamanı boyunca toplam yürütme süresini belirlemek istediğinizde senkronize yürütme API'sini kullanabilir ve çağrının ne kadar sürdüğünü ölçebilirsiniz. Yazılım yığınının daha düşük bir düzeyinde toplam yürütme süresini belirlemek istediğinizde ANeuralNetworksExecution_setMeasureTiming
ve ANeuralNetworksExecution_getDuration
değerlerini kullanarak şunları elde edebilirsiniz:
- hızlandırıcıda (ana işlemcide çalışan sürücüde değil) yürütme süresi
- hızlandırıcıdaki süre dahil olmak üzere sürücüdeki yürütme süresi.
Sürücünün 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 maliyetleri içermez.
Bu API'ler, sürücü veya hızlandırıcının çıkarım gerçekleştirmek için ayırdığı süreyi (muhtemelen bağlam geçişi nedeniyle kesintiye uğrayabilir) değil, gönderilen çalışma ile tamamlanan çalışma etkinlikleri arasındaki süreyi ölçer.
Örneğin, 1. çıkarım başlarsa sürücü 2. çıkarım yapmak için çalışmayı durdurur, ardından çalışmayı devam ettirerek 1. çıkarımı tamamlar. 1. çıkarım için yürütme süresi, 2. çıkarım yapmak üzere çalışmanın durdurulduğu zamanı içerir.
Bu zamanlama bilgileri, çevrimdışı kullanım için telemetri toplamak üzere bir uygulamanın üretim dağıtımı için yararlı olabilir. Uygulamayı daha yüksek performans sağlayacak şekilde değiştirmek için zamanlama verilerini kullanabilirsiniz.
Bu işlevi kullanırken aşağıdakileri göz önünde bulundurun:
- Zamanlama bilgilerinin toplanması performans maliyeti oluşturabilir.
- NNAPI çalışma zamanında ve IPC'de harcanan süre hariç olmak üzere, yalnızca sürücü kendisinde veya hızlandırıcıda harcanan süreyi hesaplayabilir.
- Bu API'leri yalnızca
numDevices = 1
ileANeuralNetworksCompilation_createForDevices
kullanılarak oluşturulmuş birANeuralNetworksExecution
ile kullanabilirsiniz. - Zamanlama bilgilerini bildirmek için sürücüye gerek yoktur.
Android Systrace ile uygulamanızın profilini oluşturma
Android 10'dan itibaren NNAPI, uygulamanızın profilini oluşturmak için kullanabileceğiniz systrace etkinliklerini otomatik olarak oluşturur.
NNAPI kaynağı, uygulamanız tarafından oluşturulan systrace etkinliklerini işlemek ve model yaşam döngüsünün farklı aşamalarında (örnek oluşturma, 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 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ü işlemi.
Profil oluşturma analizi verilerini oluşturma
$ANDROID_BUILD_TOP adresindeki AOSP kaynak ağacını kontrol ettiğinizi ve hedef uygulama olarak TFLite görüntü sınıflandırma örneğini kullandığınızı varsayarak aşağıdaki adımları uygulayarak NNAPI profilleme verilerini 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
dosyasına yazılacağını gösterir. Kendi uygulamanızın profilini oluştururken org.tensorflow.lite.examples.classification
değerini, uygulama manifestinizde belirtilen işlem adıyla değiştirmeniz gerekir.
Bu işlem, kabuk konsollarınızdan birini meşgul eder. enter
'ün sonlandırılmasını etkileşimli olarak beklediği için komutu arka planda çalıştırmayın.
- Systrace toplayıcısı başlatıldıktan sonra uygulamanızı başlatın ve karşılaştırma testinizi çalıştırın.
Bizim durumumuzda, Görüntü Sınıflandırma uygulamasını Android Studio'dan veya uygulama zaten yüklüyse doğrudan test telefonunuzun kullanıcı arayüzünden başlatabilirsiniz. NNAPI verileri oluşturmak için uygulama yapılandırma iletişim kutusunda hedef cihaz olarak NNAPI'yi seçerek uygulamayı NNAPI kullanacak şekilde yapılandırmanız gerekir.
Test tamamlandığında, 1. adımdan beri etkin olan konsol terminalinde
enter
tuşuna basarak systrace'i 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
: Alttaki bir katmana yapılan çağrıda yürütmeyi beklerken harcanan süre 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şamaların istatistikleri yerine yalnızca yürütme ve alt aşamalarını (yürütme başına süre olarak) yazdırır
- --json
: Çıktıyı JSON biçiminde oluşturur
Aşağıda çıkışa örnek verilmiş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 izlemesini 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 mevcutsa başarısız olabilir. Bu durum genellikle, systrace toplayıcıyı başlattığınızda önceki bir profil oluşturma oturumundaki bazı etkinlikler oluşturuluyorsa ortaya çıkar. Bu durumda, profil oluşturma işleminizi tekrar yapmanız gerekir.
Uygulama kodunuzun istatistiklerini systrace_parser çıktısına ekleme
parse_systrace uygulaması, yerleşik Android systrace işlevini temel alır. Özel etkinlik adlarıyla systrace API'yi (Java için, yerel uygulamalar için) kullanarak uygulamanızdaki belirli işlemler için izlemeler ekleyebilirsiniz.
Özel etkinliklerinizi uygulama yaşam döngüsünün aşamalarıyla ilişkilendirmek için etkinlik adınıza aşağıdaki dizelerden birini ekleyin:
[NN_LA_PI]
: İlklendirme 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
Aşağıda, Execution
aşaması için bir runInferenceModel
bölümü ve NNAPI izlemelerinde dikkate alınmayacak başka bölümler preprocessBitmap
içeren Application
katmanı ekleyerek TFLite görüntü sınıflandırması örnek kodunu nasıl değiştirebileceğinize dair bir örnek verilmiştir. runInferenceModel
bölümü, nnapi systrace ayrıştırıcısı tarafından işlenen systrace etkinliklerinin bir parçası olacaktır:
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, bir uygulamanın modellerinin göreceli önceliklerini, belirli bir modelin hazırlanması için beklenen maksimum süreyi ve belirli bir hesaplamanın tamamlanması için beklenen maksimum süreyi belirtmesine olanak tanıyarak daha iyi hizmet kalitesi (HK) sağlar. Android 11, uygulamaların yürütme son tarihlerinin kaçırılması gibi hataları anlamasını sağlayan ek NNAPI sonuç kodları da sunar.
Bir iş yükünün önceliğini ayarlama
Bir NNAPI iş yükünün önceliğini ayarlamak için ANeuralNetworksCompilation_finish()
'ı çağırmadan önce ANeuralNetworksCompilation_setPriority()
'ı çağırın.
Teslim tarihleri belirleme
Uygulamalar hem model derleme hem de çıkarım için son tarihler belirleyebilir.
- Derleme zaman aşımını ayarlamak için
ANeuralNetworksCompilation_finish()
'ı çağırmadan önceANeuralNetworksCompilation_setTimeout()
'ı çağırın. - Çıkarsama zaman aşımını ayarlamak için derlemeyi başlatmadan önce
ANeuralNetworksExecution_setTimeout()
işlevini çağırın.
İşlemler hakkında daha fazla bilgi
Aşağıdaki bölümde, operatörlerin kullanımıyla ilgili ileri seviye konular ele alınmaktadır.
Kesirli tensörler
Kuantize edilmiş tenzor, kayan noktalı değerlerden oluşan n boyutlu bir diziyi temsil etmenin kompakt bir yoludur.
NNAPI, 8 bit asimetrik olarak ölçülmüş tenzorları destekler. Bu tensörlerde her hücrenin değeri 8 bitlik bir tam sayı ile temsil edilir. Tensörle ilişkili bir ölçek ve sıfır noktası 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 şu şekildedir:
(cellValue - zeroPoint) * scale
Burada zeroPoint değeri 32 bitlik bir tam sayı, scale ise 32 bitlik bir kayan nokta değeridir.
32 bit kayan nokta değerlerinin yer aldığı tenzorlara kıyasla 8 bitlik kesirli tenzorların iki avantajı vardır:
- Eğitimli ağırlıklar 32 bit tenzorların dörtte birini kapladığından uygulamanız daha küçüktür.
- Hesaplamalar genellikle daha hızlı yürütülebilir. Bunun nedeni, bellekten alınması gereken daha az veri miktarı ve DSP'ler gibi işlemcilerin tam sayı matematik işlemlerini gerçekleştirmedeki verimliliğidir.
Kayan noktalı bir modeli kesirli bir modele dönüştürmek mümkün olsa da deneyimlerimiz, kesirli bir modeli doğrudan eğiterek daha iyi sonuçlar elde edildiğini gösteriyor. Nöral ağ, her bir değerin artan ayrıntı düzeyini telafi etmeyi öğrenir. Her kesikli tenör için ölçek ve sıfır noktası değerleri eğitim süreci sırasında belirlenir.
NNAPI'de, ANeuralNetworksOperandType
veri yapısının tür alanını ANEURALNETWORKS_TENSOR_QUANT8_ASYMM
olarak ayarlayarak kesirli tenör türlerini tanımlarsınız.
Ayrıca, söz konusu veri yapısında tensörün ölçeğini ve sıfır noktası değerini de belirtirsiniz.
NNAPI, 8 bit asimetrik kesirli tenzorlara ek olarak aşağıdakileri de destekler:
CONV/DEPTHWISE_CONV/TRANSPOSED_CONV
işlemlerinde ağırlıkları temsil etmek için kullanabileceğinizANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL
QUANTIZED_16BIT_LSTM
nesnesinin 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 bazı işlemler isteğe bağlı işlenenler alır. Modelde isteğe bağlı operatörün atlandığını belirtmek için ANeuralNetworksModel_setOperandValue()
işlevini çağırın. Bu işleve arabellek için NULL
ve uzunluk için 0 değerini iletin.
Operanın mevcut olup olmadığına dair karar her yürütme için değişiyorsa ANeuralNetworksExecution_setInput()
veya ANeuralNetworksExecution_setOutput()
işlevlerini kullanarak operanın atlandığını belirtirsiniz. Bu işlevlerde arabellek için NULL
ve uzunluk için 0 değerlerini gönderirsiniz.
Bilinmeyen rütbedeki tenzorlar
Android 9 (API düzeyi 28), bilinmeyen boyutlara ancak bilinen rütbeye (boyut sayısı) sahip model operatörlerini kullanıma sundu. Android 10 (API düzeyi 29), ANeuralNetworksOperandType'da gösterildiği gibi bilinmeyen rütbedeki tenzorları 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) olarak kullanılabilir.
Karşılaştırma, gecikmeyi 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 aynı çalışmayla karşılaştırır.
Karşılaştırmayı kullanmak için aşağıdakileri yapın:
Hedef bir Android cihazı bilgisayarınıza 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 üst düzey kaynak dizine 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
Bir karşılaştırma çalışması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
mülkünü (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ının oluşturulması ve derlenmesiexecution
: Model yürütmecpuexe
: NNAPI CPU uygulamasını kullanarak işlemlerin yürütülmesimanager
: 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 etiketle INFO düzeyinde günlük girişleri oluşturur.
NNAPI API bileşenleri, debug.nn.vlog
kontrollü mesajların yanı sıra her biri belirli bir günlük etiketi kullanan çeşitli düzeylerde başka günlük girişleri de sağlar.
Bileşenlerin listesini almak için aşağıdaki ifadeyi kullanarak kaynak ağaçta 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:
- BurstBuilder
- Geri aramalar
- CompilationBuilder
- CpuExecutor
- ExecutionBuilder
- ExecutionBurstController
- ExecutionBurstServer
- ExecutionPlan
- FibonacciDriver
- GraphDump
- IndexedShapeWrapper
- IonWatcher
- Müdür
- Bellek
- MemoryUtils
- MetaModel
- ModelArgumentInfo
- ModelBuilder
- NeuralNetworks
- OperationResolver
- İşlemler
- OperationsUtils
- PackageInfo
- TokenHasher
- TypeManager
- Utils
- ValidateHal
- VersionedInterfaces
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ğer tümünü devre dışı bırakmak için ANDROID_LOG_TAGS
değerini aşağıdaki gibi 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.
ANDROID_LOG_TAGS
değerini aşağıdaki komutu kullanarak 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 bir filtre olduğunu unutmayın. Ayrıntılı günlük bilgileri oluşturmak için debug.nn.vlog
mülkünü all
olarak ayarlamanız gerekir.