Questa pagina fornisce una panoramica su come implementare un driver per l'API Neural Networks (NNAPI). Per ulteriori dettagli, consulta la documentazione disponibile nei file di definizione
HAL in
hardware/interfaces/neuralnetworks
.
Un esempio di implementazione del driver è disponibile in
frameworks/ml/nn/driver/sample
.
Per ulteriori informazioni sull'API Neural Networks, consulta la pagina relativa all'API Neural Networks.
Reti neurali HAL
L'HAL per le reti neurali (NN) definisce un'astrazione dei vari dispositivi, come le unità di elaborazione grafica (GPU) e gli elaboratori di segnale digitale (DSP), presenti in un prodotto (ad esempio uno smartphone o un tablet). I driver di questi
dispositivi devono essere conformi alla NN HAL. L'interfaccia è specificata nei file di definizione HAL in hardware/interfaces/neuralnetworks
.
Il flusso generale dell'interfaccia tra il framework e un driver è illustrato nella Figura 1.
Figura 1. Flusso delle reti neurali
Inizializzazione
Al momento dell'inizializzazione, il framework esegue query sul driver per verificare le sue funzionalità utilizzando IDevice::getCapabilities_1_3
.
La struttura @1.3::Capabilities
include tutti i tipi di dati e
rappresenta le prestazioni non rallentate utilizzando un vettore.
Per determinare come allocare i calcoli ai dispositivi disponibili, il framework utilizza le funzionalità per capire quanto velocemente e con quanta efficienza energetica ciascun driver può eseguire un'esecuzione. Per fornire queste informazioni, il conducente deve fornire valori standardizzati per le prestazioni in base all'esecuzione dei carichi di lavoro di riferimento.
Per determinare i valori che il driver restituisce in risposta a IDevice::getCapabilities_1_3
, utilizza l'app di benchmark NNAPI per misurare le prestazioni per i tipi di dati corrispondenti. I modelli MobileNet v1 e v2, asr_float
e tts_float
sono consigliati per misurare le prestazioni per valori in virgola mobile di 32 bit, mentre i modelli quantizzati MobileNet v1 e v2 sono consigliati per valori quantizzati di 8 bit. Per ulteriori informazioni, consulta
Android Machine Learning Test Suite.
In Android 9 e versioni precedenti, la struttura Capabilities
include informazioni sulle prestazioni dei driver
solo per i tensori quantizzati e in virgola mobile e non include
i tipi di dati più scalabili.
Nell'ambito della procedura di inizializzazione, il framework potrebbe richiedere ulteriori informazioni, utilizzando IDevice::getType
, IDevice::getVersionString
, IDevice:getSupportedExtensions
e IDevice::getNumberOfCacheFilesNeeded
.
Tra i riavvii del prodotto, il framework prevede che tutte le query descritte in questa sezione riportino sempre gli stessi valori per un determinato driver. In caso contrario, un'app che utilizza il driver potrebbe mostrare prestazioni ridotte o un comportamento errato.
Compilation
Il framework determina quali dispositivi utilizzare quando riceve una richiesta da un'app. In Android 10, le app possono rilevare e specificare i dispositivi tra cui scegliere il framework. Per ulteriori informazioni, consulta Rilevamento e assegnazione dei dispositivi.
Al momento della compilazione del modello, il framework invia il modello a ogni driver candidato chiamando IDevice::getSupportedOperations_1_3
.
Ogni driver restituisce un array di valori booleani che indicano le operazioni del modello supportate. Un conducente può stabilire di non poter
supportare una determinata operazione per vari motivi. Ad esempio:
- Il driver non supporta il tipo di dati.
- Il driver supporta solo operazioni con parametri di input specifici. Ad esempio, un driver potrebbe supportare le operazioni di convoluzione 3 x 3 e 5 x 5, ma non 7 x 7.
- Il driver ha vincoli di memoria che gli impediscono di gestire grafici o input di grandi dimensioni.
Durante la compilazione, l'input, l'output e gli operandi interni del modello, come descritto in OperandLifeTime
, possono avere dimensioni o ranking sconosciuti. Per maggiori informazioni, consulta
Forma di output.
Il framework chiede a ciascun driver selezionato di prepararsi a eseguire un sottoinsieme del modello chiamando IDevice::prepareModel_1_3
.
Ogni driver compila quindi il proprio sottoinsieme. Ad esempio, un driver potrebbe
generare codice o creare una copia riordinata dei pesi. Poiché può trascorrere una quantità di tempo significativa tra la compilazione del modello e l'esecuzione delle richieste, non è consigliabile assegnare risorse come grandi blocchi di memoria del dispositivo durante la compilazione.
Se l'operazione riesce, il conducente restituisce un handle @1.3::IPreparedModel
. Se il driver restituisce un codice di errore durante la preparazione del sottoinsieme del modello, il framework esegue l'intero modello sulla CPU.
Per ridurre il tempo utilizzato per la compilazione all'avvio di un'app, un driver può memorizzare nella cache gli elementi di compilazione. Per ulteriori informazioni, consulta la sezione Memorizzazione nella cache della compilazione.
Esecuzione
Quando un'app chiede al framework di eseguire una richiesta, per impostazione predefinita il framework chiama il metodo HAL IPreparedModel::executeSynchronously_1_3
per eseguire un'esecuzione sincrona su un modello preparato.
Una richiesta può anche essere eseguita in modo asincrono utilizzando il metodo execute_1_3
, il metodo executeFenced
(vedi Esecuzione vincolata) oppure può essere eseguita utilizzando un'esecuzione a burst.
Le chiamate di esecuzione sincrona migliorano le prestazioni e riducono il sovraccarico di threading rispetto alle chiamate asincrone perché il controllo viene restituito al processo dell'app solo al termine dell'esecuzione. Ciò significa che il conducente non ha bisogno di un meccanismo separato per notificare al processo dell'app il completamento di un'esecuzione.
Con il metodo execute_1_3
asincrono, il controllo torna al processo dell'app dopo l'avvio dell'esecuzione e il driver deve inviare una notifica al framework al termine dell'esecuzione, utilizzando @1.3::IExecutionCallback
.
Il parametro Request
passato al metodo execute elenca gli operandi di input e output utilizzati per l'esecuzione. La memoria che memorizza i dati dell'operando deve utilizzare l'ordine di riga principale con la prima dimensione che esegue l'iterazione più lenta e non deve avere spazi aggiuntivi alla fine di nessuna riga. Per ulteriori informazioni sui tipi di operandi, consulta Operandi.
Per i driver NN HAL 1.2 o versioni successive, quando una richiesta viene completata, lo stato di errore, la forma dell'output e le informazioni sui tempi vengono restituiti al framework. Durante l'esecuzione, gli operandi di output o interni del modello possono avere una o più dimensioni o un rango sconosciuti. Quando almeno un operando di output ha una dimensione o un ranking sconosciuti, il conducente deve restituire informazioni di output con dimensioni dinamiche.
Per i driver con NN HAL 1.1 o versioni precedenti, viene restituito solo lo stato di errore al termine di una richiesta. Le dimensioni per gli operandi di input e output devono essere completamente specificate per il completamento dell'esecuzione. Gli operandi interni possono avere una o più dimensioni sconosciute, ma devono avere un rango specificato.
Per le richieste degli utenti che interessano più driver, il framework è responsabile della prenotazione della memoria intermedia e della sequenza delle chiamate a ciascun driver.
È possibile avviare più richieste in parallelo sullo stesso
@1.3::IPreparedModel
.
Il driver può eseguire le richieste in parallelo o serializzare le esecuzioni.
Il framework può chiedere a un driver di mantenere più di un modello preparato. Ad esempio, prepara il modello m1
, prepara m2
, esegui la richiesta r1
su m1
, esegui r2
su m2
, esegui r3
su m1
, esegui r4
su m2
, rilascia (descritto in Pulizia) m1
e release m2
.
Per evitare una prima esecuzione lenta che potrebbe comportare una scarsa esperienza utente (ad esempio, un primo frame a scatti), il driver deve eseguire la maggior parte delle inizializzazioni nella fase di compilazione. L'inizializzazione alla prima esecuzione deve essere limitata alle azioni che influiscono negativamente sulla salute del sistema se eseguite in anticipo, ad esempio la prenotazione di buffer temporanei di grandi dimensioni o l'aumento della frequenza di clock di un dispositivo. I driver che possono preparare solo un numero limitato di modelli simultanei potrebbero dover eseguire l'inizializzazione alla prima esecuzione.
In Android 10 o versioni successive, qualora vengano eseguite in rapida successione più esecuzioni con lo stesso modello preparato, il client può scegliere di utilizzare un oggetto burst di esecuzione per comunicare tra i processi dell'app e del driver. Per ulteriori informazioni, consulta la sezione Esecuzioni a raffica e code di messaggi rapide.
Per migliorare le prestazioni per più esecuzioni in rapida successione, il driver può trattenere buffer temporanei o aumentare le frequenze di clock. È consigliabile creare un thread di monitoraggio per liberare le risorse se non vengono create nuove richieste dopo un determinato periodo di tempo.
Forma di output
Per le richieste in cui per uno o più operandi di output non sono state specificate tutte le dimensioni, il driver deve fornire un elenco di forme di output contenente le informazioni sulle dimensioni per ogni operando di output dopo l'esecuzione. Per scoprire di più
sulle dimensioni, consulta
OutputShape
.
Se un'esecuzione non va a buon fine a causa di un buffer di output di dimensioni insufficienti, il driver deve indicare quali operandi di output hanno dimensioni del buffer insufficienti nell'elenco delle forme di output e deve segnalare quante più informazioni dimensionali possibili, utilizzando zero per le dimensioni sconosciute.
Tempi
In Android 10, un'app può chiedere il tempo di esecuzione se l'app ha specificato un singolo dispositivo da utilizzare durante il processo di compilazione. Per
maggiori dettagli, vedi
MeasureTiming
e Rilevamento e assegnazione dei dispositivi.
In questo caso, un driver NN HAL 1.2 deve misurare la durata dell'esecuzione o segnalare UINT64_MAX
(per indicare che la durata non è disponibile) durante l'esecuzione di una richiesta. Il driver deve ridurre al minimo l'eventuale perdita di prestazioni derivante dalla misurazione della durata di esecuzione.
Il driver registra le seguenti durate in microsecondi nella struttura
Timing
:
- Tempo di esecuzione sul dispositivo: non è incluso il tempo di esecuzione nel driver, che viene eseguito sul processore host.
- Tempo di esecuzione nel driver: include il tempo di esecuzione sul dispositivo.
Queste durate devono includere il momento in cui l'esecuzione è sospesa, ad esempio quando l'esecuzione è stata prerilasciata da altre attività o quando è in attesa che una risorsa diventi disponibile.
Quando al driver non è stato chiesto di misurare la durata dell'esecuzione o quando si verifica un errore di esecuzione, il driver deve segnalare le durate come UINT64_MAX
. Anche quando al conducente è stato chiesto di misurare la durata
dell'esecuzione, può invece registrare UINT64_MAX
per il tempo sul dispositivo, il tempo
del conducente o entrambi. Quando il driver riporta entrambe le durate come un valore diverso da
UINT64_MAX
, il tempo di esecuzione nel driver deve essere uguale o superiore al tempo sul
dispositivo.
Esecuzione con recinzione
In Android 11, NNAPI consente alle esecuzioni di attendere un elenco di handle sync_fence
e, facoltativamente, di restituire un oggetto sync_fence
, che viene segnalato al completamento dell'esecuzione. In questo modo si riduce l'overhead per i modelli di piccole sequenze e i casi d'uso in streaming. L'esecuzione con recinzione consente inoltre un'interoperabilità più efficiente con altri componenti che possono segnalare o attendere sync_fence
. Per maggiori informazioni su sync_fence
, consulta
Framework di sincronizzazione.
In un'esecuzione con barriere, il framework chiama il metodo
IPreparedModel::executeFenced
per avviare un'esecuzione asincrona con barriere su un modello preparato con un
vettore di barriere di sincronizzazione da attendere. Se l'attività asincrona è stata completata prima del ritorno della chiamata, è possibile restituire un handle vuoto per sync_fence
. Deve essere restituito anche un oggetto IFencedExecutionCallback
per consentire al framework di eseguire query sulle informazioni relative allo stato e alla durata dell'errore.
Al termine di un'esecuzione, è possibile eseguire query sui due seguenti valori tempistiche che misurano la durata dell'esecuzione tramite IFencedExecutionCallback::getExecutionInfo
.
timingLaunched
: durata dal momento in cui viene chiamatoexecuteFenced
a quello in cuiexecuteFenced
indica il valoresyncFence
restituito.timingFenced
: la durata compresa tra il momento in cui tutti i limiti di sincronizzazione attendi dall'esecuzione vengono segnalati e il momento in cuiexecuteFenced
segnala il valore disyncFence
restituito.
Flusso di controllo
Per i dispositivi con Android 11 o versioni successive, NNAPI include due operazioni di flusso di controllo, IF
e WHILE
, che prendono altri modelli come argomenti ed eseguono in modo condizionale (IF
) o ripetuto (WHILE
). Per maggiori informazioni su come implementare questa funzionalità, consulta Flusso di controllo.
Qualità del servizio
In Android 11, la NNAPI offre una migliore qualità del servizio (QoS) consentendo a un'app di indicare le priorità relative dei suoi modelli, il tempo massimo previsto per la preparazione di un modello e il tempo massimo previsto per il completamento di un'esecuzione. Per ulteriori informazioni, consulta la pagina Qualità del servizio.
Pulizia
Quando un'app termina di utilizzare un modello preparato, il framework rilascia
il riferimento all'oggetto
@1.3::IPreparedModel
. Quando non viene più fatto riferimento all'oggetto IPreparedModel
, questo viene eliminato automaticamente nel servizio driver che lo ha creato. Le risorse specifiche del modello possono essere recuperate in questo momento nell'implementazione del driver del distruttore. Se il servizio driver vuole che l'oggetto IPreparedModel
venga
eliminato automaticamente quando non è più necessario dal client, non deve contenere
nessun riferimento all'oggetto IPreparedModel
dopo che l'oggetto IPreparedeModel
è stato restituito tramite
IPreparedModelCallback::notify_1_3
.
Utilizzo CPU
I driver devono utilizzare la CPU per configurare i calcoli. I driver non devono usare la CPU per eseguire calcoli grafici perché ciò interferisce con la capacità del framework di allocare correttamente il lavoro. Il conducente deve segnalare le parti che non è in grado di gestire al framework e lasciare che sia il framework a gestire il resto.
Il framework fornisce un'implementazione della CPU per tutte le operazioni NNAPI, ad eccezione di quelle definite dal fornitore. Per ulteriori informazioni, consulta la sezione Estensioni del fornitore.
Le operazioni introdotte in Android 10 (livello API 29) hanno un'implementazione della CPU di riferimento solo per verificare che i test CTS e VTS siano corretti. Le implementazioni ottimizzate incluse nei framework di machine learning mobile sono preferite all'implementazione della CPU NNAPI.
Funzioni di utilità
Il codebase NNAPI include funzioni di utilità che possono essere utilizzate dai servizi di conducenti.
Il file frameworks/ml/nn/common/include/Utils.h
contiene funzioni di utilità assortite, come quelle utilizzate per il logging e per la conversione tra diverse versioni NN HAL.
Vlogging:
VLOG
è una macro wrapper perLOG
di Android che registra il messaggio solo se il tag appropriato è impostato nella proprietàdebug.nn.vlog
.initVLogMask()
deve essere chiamato prima di qualsiasi chiamata aVLOG
. La macroVLOG_IS_ON
può essere impiegata per verificare seVLOG
è attualmente attivata, consentendo di saltare il codice di registrazione complicato se non è necessario. Il valore della proprietà deve essere uno dei seguenti:- Una stringa vuota, che indica che non deve essere eseguito alcun logging.
- Il token
1
oall
, che indica che tutti i log devono essere eseguiti. - Un elenco di tag, delimitati da spazi, virgole o due punti,
che indicano il logging da eseguire. I tag sono
compilation
,cpuexe
,driver
,execution
,manager
emodel
.
compliantWithV1_*
: restituiscetrue
se un oggetto HAL NN può essere convertito nello stesso tipo di una versione HAL diversa senza perdere informazioni. Ad esempio, la chiamata dicompliantWithV1_0
su unV1_2::Model
restituiscefalse
se il modello include i tipi di operazioni introdotti in NN HAL 1.1 o NN HAL 1.2.convertToV1_*
: converte un oggetto HAL NN da una versione all'altra. Viene registrato un avviso se la conversione comporta una perdita di informazioni (ovvero se la nuova versione del tipo non può rappresentare completamente il valore).Funzionalità: le funzioni
nonExtensionOperandPerformance
eupdate
possono essere utilizzate per contribuire a creare il campoCapabilities::operandPerformance
.Proprietà di query dei tipi:
isExtensionOperandType
,isExtensionOperationType
,nonExtensionSizeOfData
,nonExtensionOperandSizeOfData
,nonExtensionOperandTypeIsScalar
,tensorHasUnspecifiedDimensions
.
Il
file
frameworks/ml/nn/common/include/ValidateHal.h
contiene funzioni di utilità per verificare che un oggetto HAL NN sia valido
secondo la specifica della relativa versione HAL.
validate*
: restituiscetrue
se l'oggetto HAL NN è valido secondo la specifica della relativa versione HAL. I tipi di estensione e i tipi di OEM non vengono convalidati. Ad esempio,validateModel
restituiscefalse
se il modello contiene un'operazione che fa riferimento a un indice degli operandi che non esiste o un'operazione non supportata in quella versione dell'HAL.
Il file frameworks/ml/nn/common/include/Tracing.h
contiene macro per semplificare l'aggiunta di informazioni di systracing al codice delle reti neurali.
Ad esempio, vedi le chiamate della macro NNTRACE_*
nel driver di esempio.
Il
file frameworks/ml/nn/common/include/GraphDump.h
contiene una funzione di utilità per scaricare i contenuti di un Model
in formato grafico
per scopi di debug.
graphDump
: scrive una rappresentazione del modello in formato Graphviz (.dot
) nello stream specificato (se fornito) o in logcat (se non viene fornito alcun stream).
Convalida
Per testare l'implementazione di NNAPI, utilizza i test VTS e CTS inclusi nel framework Android. VTS esercita i tuoi driver direttamente (senza utilizzare il framework), mentre CTS li esercita indirettamente tramite il framework. Testano ogni metodo API e verificano che tutte le operazioni supportate dai conducenti funzionino correttamente e forniscano risultati che soddisfano i requisiti di precisione.
I requisiti di precisione in CTS e VTS per NNAPI sono i seguenti:
In virgola mobile: abs(expected - actual) <= atol + rtol * abs(expected); dove:
- Per fp32, atol = 1e-5f, rtol = 5.0f * 1.1920928955078125e-7
- Per fp16, atol = rtol = 5.0f * 0.0009765625f
Quantizzata: di sconto di uno (tranne per
mobilenet_quantized
, che è disattivato per tre)Booleano: corrispondenza esatta
Un modo in cui CTS testa NNAPI è generando grafici pseudocasuali fissi utilizzati per testare e confrontare i risultati di esecuzione di ciascun driver con l'implementazione di riferimento di NNAPI. Per i driver con NN HAL 1.2 o versioni successive, se i risultati non soddisfano i criteri di precisione, CTS segnala un errore e esegue il dump di un file di specifiche per il modello non riuscito in /data/local/tmp
per il debug.
Per ulteriori dettagli sui criteri di precisione, consulta
TestRandomGraph.cpp
e
TestHarness.h
.
Test di fuzzing
Lo scopo del test di fuzz è trovare arresti anomali, asserzioni, violazioni della memoria o comportamenti non definiti generali nel codice in test a causa di fattori come input imprevisti. Per i test di fuzzing NNAPI, Android utilizza test basati su libFuzzer, che sono efficienti per il fuzzing perché utilizzano la copertura delle righe degli scenari di test precedenti per generare nuovi input casuali. Ad esempio, libFuzzer favorisce gli scenari di test che vengono eseguiti su nuove righe di codice. In questo modo si riduce notevolmente il tempo necessario ai test per trovare il codice problematico.
Per eseguire fuzz test al fine di convalidare l'implementazione del driver, modifica frameworks/ml/nn/runtime/test/android_fuzzing/DriverFuzzTest.cpp
nell'utilità di test libneuralnetworks_driver_fuzzer
trovata in AOSP in modo da includere il codice del driver. Per maggiori informazioni sui test di fuzz NNAPI, consulta
frameworks/ml/nn/runtime/test/android_fuzzing/README.md
.
Sicurezza
Poiché i processi delle app comunicano direttamente con quelli del conducente,
i conducenti devono convalidare gli argomenti delle chiamate che ricevono. Questa convalida viene verificata da VTS. Il codice di convalida si trova in
frameworks/ml/nn/common/include/ValidateHal.h
.
I conducenti devono inoltre assicurarsi che le app non possano interferire con altre app quando utilizzano lo stesso dispositivo.
Test Suite di Android Machine Learning
Android Machine Learning Test Suite (MLTS) è un benchmark NNAPI incluso in CTS e VTS per convalidare l'accuratezza dei modelli reali sui dispositivi dei fornitori. Il benchmark valuta la latenza e l'accuratezza e confronta i risultati dei driver con quelli ottenuti utilizzando TF Lite in esecuzione sulla CPU per lo stesso modello e gli stessi set di dati. Ciò garantisce che l'accuratezza di un driver non sia peggiore dell'implementazione del riferimento della CPU.
Gli sviluppatori della piattaforma Android utilizzano anche gli MLTS per valutare la latenza e l'accuratezza dei driver.
Il benchmark NNAPI è disponibile in due progetti in AOSP:
platform/test/mlts/benchmark
(app di benchmark)platform/test/mlts/models
(modelli e set di dati)
Modelli e set di dati
Il benchmark NNAPI utilizza i seguenti modelli e set di dati.
- MobileNetV1 quantizzato in formato float e u8 in dimensioni diverse, eseguito su un piccolo sottoinsieme (1500 immagini) del set di dati Open Images Dataset v4.
- I dati MobileNetV2 sono in virgola mobile e u8 quantizzati in dimensioni diverse ed eseguono un piccolo sottoinsieme (1500 immagini) del set di dati Open Images v4.
- Modello acustico basato su memoria a lungo termine (LSTM) per la sintesi vocale, eseguito su un piccolo sottoinsieme dell'insieme CMU Arctic.
- Modello acustico basato su LSTM per il riconoscimento vocale automatico, eseguito su un piccolo sottoinsieme del set di dati LibriSpeech.
Per ulteriori informazioni, consulta
platform/test/mlts/models
.
Stress test
La Test Suite di Android Machine Learning include una serie di test di arresto anomalo per confermare la resilienza dei driver in condizioni di utilizzo gravose o nei casi secondari del comportamento dei clienti.
Tutti i test di arresto anomalo forniscono le seguenti funzionalità:
- Rilevamento di blocchi: se il client NNAPI si blocca durante un test, il test non va a buon fine con il motivo dell'errore
HANG
e la suite di test passa al test successivo. - Rilevamento di arresti anomali del client NNAPI: i test superano gli arresti anomali del client e i test non hanno esito positivo per il motivo dell'errore
CRASH
. - Rilevamento di arresti anomali del driver: i test possono rilevare un arresto anomalo del driver che causa un errore in una chiamata NNAPI. Tieni presente che potrebbero verificarsi arresti anomali nei processi del driver che non causano un errore NNAPI e non causano l'interruzione del test. Per risolvere questo tipo di errore, ti consigliamo di eseguire il comando
tail
nel log di sistema per errori o arresti anomali relativi al driver. - Targeting di tutti gli acceleratori disponibili: i test vengono eseguiti su tutti i driver disponibili.
Tutti i test di collisione hanno i seguenti quattro possibili risultati:
SUCCESS
: esecuzione completata senza un errore.FAILURE
: esecuzione non riuscita. In genere è causato da un errore durante il test di un modello e indica che il driver non è riuscito a compilare o eseguire il modello.HANG
: il processo di test non risponde.CRASH
: il processo di test ha avuto un arresto anomalo.
Per ulteriori informazioni sui test di stress e un elenco completo dei test di arresto anomalo, consulta
platform/test/mlts/benchmark/README.txt
.
Utilizza MTLS
Per utilizzare MLTS:
- Collega un dispositivo di destinazione alla tua workstation e assicurati che sia accessibile tramite adb.
Esporta la variabile di ambiente
ANDROID_SERIAL
del dispositivo di destinazione se è collegato più di un dispositivo. cd
nella directory di origine di primo livello di Android.source build/envsetup.sh lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available. ./test/mlts/benchmark/build_and_run_benchmark.sh
Al termine dell'esecuzione di un benchmark, i risultati vengono presentati come pagina HTML e trasmessi a
xdg-open
.
Per ulteriori informazioni, consulta
platform/test/mlts/benchmark/README.txt
.
Versioni HAL delle reti neurali
Questa sezione descrive le modifiche introdotte nelle versioni Android e Neural Reti HAL.
Android 11
Android 11 introduce NN HAL 1.3, che include le seguenti modifiche importanti.
- Supporto per la quantizzazione firmata a 8 bit in NNAPI. Aggiunge il tipo di operando
TENSOR_QUANT8_ASYMM_SIGNED
. I driver con NN HAL 1.3 che supportano operazioni con quantizzazione non firmata devono supportare anche le varianti firmate di queste operazioni. Quando eseguono versioni con e senza firma della maggior parte delle operazioni quantizzate, i driver devono produrre gli stessi risultati fino a un offset di 128. Esistono cinque eccezioni a questo requisito:CAST
,HASHTABLE_LOOKUP
,LSH_PROJECTION
,PAD_V2
eQUANTIZED_16BIT_LSTM
. L'operazioneQUANTIZED_16BIT_LSTM
non supporta gli operandi con segno e le altre quattro operazioni supportano la quantizzazione con segno, ma non richiedono che i risultati siano uguali. - Supporto per le esecuzioni protette in cui il framework chiama il metodo
IPreparedModel::executeFenced
per avviare un'esecuzione asincrona e protetta su un modello preparato con un vettore di restrizioni di sincronizzazione da attendere. Per maggiori informazioni, consulta Esecuzione vincolata. - Supporto per il flusso di controllo. Aggiunge le operazioni
IF
eWHILE
, che prendono altri modelli come argomenti ed eseguono in modo condizionale (IF
) o ripetuto (WHILE
). Per ulteriori informazioni, consulta Flusso di controllo. - Il miglioramento della qualità del servizio (QoS) in quanto le app possono indicare le priorità relative dei relativi modelli, il tempo massimo previsto per la preparazione di un modello e il tempo massimo previsto per il completamento di un'esecuzione. Per ulteriori informazioni, consulta Qualità del servizio.
- Supporto per i domini di memoria che forniscono interfacce di allocazione per i buffer gestiti dal driver. Ciò consente di passare le memorie native del dispositivo tra le esecuzioni, eliminando la copia e la trasformazione non necessarie dei dati tra esecuzioni consecutive sullo stesso driver. Per ulteriori informazioni, consulta Domini di memoria.
Android 10
Android 10 introduce NN HAL 1.2, che include le seguenti modifiche importanti.
- La struttura
Capabilities
include tutti i tipi di dati, inclusi quelli scalari, e rappresenta le prestazioni non rilassate utilizzando un vettore anziché campi denominati. - I metodi
getVersionString
egetType
consentono al framework di recuperare le informazioni sul tipo di dispositivo (DeviceType
) e sulla versione. Consulta Rilevamento e assegnazione dei dispositivi. - Il metodo
executeSynchronously
viene chiamato per impostazione predefinita per eseguire un'esecuzione in modo sincrono. Il metodoexecute_1_2
indica al framework di eseguire un'esecuzione in modo asincrono. Vedi Esecuzione. - Il parametro
MeasureTiming
perexecuteSynchronously
,execute_1_2
ed esecuzione burst specifica se il driver deve misurare la durata di esecuzione. I risultati sono riportati nella strutturaTiming
. Consulta la sezione Tempi. - Supporto per le esecuzioni in cui uno o più operandi di output hanno una dimensione o un ranking sconosciuti. Vedi Forma di output.
- Supporto per le estensioni del fornitore, ovvero raccolte di operazioni e tipi di dati definiti dal fornitore. Il conducente segnala le estensioni supportate con
il metodo
IDevice::getSupportedExtensions
. Vedi Estensioni del fornitore. - La possibilità per un oggetto burst di controllare un insieme di esecuzioni burst utilizzando code di messaggi rapide (FMQ) per comunicare tra i processi dell'app e del driver, riducendo la latenza. Consulta Esecuzioni raffica e code di messaggi rapide.
- Supporto per AHardwareBuffer per consentire al driver di eseguire esecuzioni senza copiare i dati. Vedi AHardwareBuffer.
- Supporto migliorato per la memorizzazione nella cache degli artefatti di compilazione al fine di ridurre il tempo utilizzato per la compilazione all'avvio di un'app. Vedi Memorizzazione nella cache della compilazione.
Android 10 introduce i seguenti tipi di operandi e operazioni.
-
ANEURALNETWORKS_BOOL
ANEURALNETWORKS_FLOAT16
ANEURALNETWORKS_TENSOR_BOOL8
ANEURALNETWORKS_TENSOR_FLOAT16
ANEURALNETWORKS_TENSOR_QUANT16_ASYMM
ANEURALNETWORKS_TENSOR_QUANT16_SYMM
ANEURALNETWORKS_TENSOR_QUANT8_SYMM
ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL
-
ANEURALNETWORKS_ABS
ANEURALNETWORKS_ARGMAX
ANEURALNETWORKS_ARGMIN
ANEURALNETWORKS_AXIS_ALIGNED_BBOX_TRANSFORM
ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM
ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN
ANEURALNETWORKS_BOX_WITH_NMS_LIMIT
ANEURALNETWORKS_CAST
ANEURALNETWORKS_CHANNEL_SHUFFLE
ANEURALNETWORKS_DETECTION_POSTPROCESSING
ANEURALNETWORKS_EQUAL
ANEURALNETWORKS_EXP
ANEURALNETWORKS_EXPAND_DIMS
ANEURALNETWORKS_GATHER
ANEURALNETWORKS_GENERATE_PROPOSALS
ANEURALNETWORKS_GREATER
ANEURALNETWORKS_GREATER_EQUAL
ANEURALNETWORKS_GROUPED_CONV_2D
ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT
ANEURALNETWORKS_INSTANCE_NORMALIZATION
ANEURALNETWORKS_LESS
ANEURALNETWORKS_LESS_EQUAL
ANEURALNETWORKS_LOG
ANEURALNETWORKS_LOGICAL_AND
ANEURALNETWORKS_LOGICAL_NOT
ANEURALNETWORKS_LOGICAL_OR
ANEURALNETWORKS_LOG_SOFTMAX
ANEURALNETWORKS_MAXIMUM
ANEURALNETWORKS_MINIMUM
ANEURALNETWORKS_NEG
ANEURALNETWORKS_NOT_EQUAL
ANEURALNETWORKS_PAD_V2
ANEURALNETWORKS_POW
ANEURALNETWORKS_PRELU
ANEURALNETWORKS_QUANTIZE
ANEURALNETWORKS_QUANTIZED_16BIT_LSTM
ANEURALNETWORKS_RANDOM_MULTINOMIAL
ANEURALNETWORKS_REDUCE_ALL
ANEURALNETWORKS_REDUCE_ANY
ANEURALNETWORKS_REDUCE_MAX
ANEURALNETWORKS_REDUCE_MIN
ANEURALNETWORKS_REDUCE_PROD
ANEURALNETWORKS_REDUCE_SUM
ANEURALNETWORKS_RESIZE_NEAREST_NEIGHBOR
ANEURALNETWORKS_ROI_ALIGN
ANEURALNETWORKS_ROI_POOLING
ANEURALNETWORKS_RSQRT
ANEURALNETWORKS_SELECT
ANEURALNETWORKS_SIN
ANEURALNETWORKS_SLICE
ANEURALNETWORKS_SPLIT
ANEURALNETWORKS_SQRT
ANEURALNETWORKS_TILE
ANEURALNETWORKS_TOPK_V2
ANEURALNETWORKS_TRANSPOSE_CONV_2D
ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM
ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN
Android 10 introduce aggiornamenti per molte operazioni esistenti. Gli aggiornamenti sono principalmente correlati a quanto segue:
- Supporto per il layout della memoria NCHW
- Supporto per tensori con rango diverso da 4 nelle operazioni di normalizzazione e softmax
- Supporto per le convoluzioni dilatate
- Supporto per input con quantizzazione mista in
ANEURALNETWORKS_CONCATENATION
L'elenco seguente mostra le operazioni modificate in Android 10. Per tutti i dettagli delle modifiche, consulta OperationCode nella documentazione di riferimento di NNAPI.
ANEURALNETWORKS_ADD
ANEURALNETWORKS_AVERAGE_POOL_2D
ANEURALNETWORKS_BATCH_TO_SPACE_ND
ANEURALNETWORKS_CONCATENATION
ANEURALNETWORKS_CONV_2D
ANEURALNETWORKS_DEPTHWISE_CONV_2D
ANEURALNETWORKS_DEPTH_TO_SPACE
ANEURALNETWORKS_DEQUANTIZE
ANEURALNETWORKS_DIV
ANEURALNETWORKS_FLOOR
ANEURALNETWORKS_FULLY_CONNECTED
ANEURALNETWORKS_L2_NORMALIZATION
ANEURALNETWORKS_L2_POOL_2D
ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION
ANEURALNETWORKS_LOGISTIC
ANEURALNETWORKS_LSH_PROJECTION
ANEURALNETWORKS_LSTM
ANEURALNETWORKS_MAX_POOL_2D
ANEURALNETWORKS_MEAN
ANEURALNETWORKS_MUL
ANEURALNETWORKS_PAD
ANEURALNETWORKS_RELU
ANEURALNETWORKS_RELU1
ANEURALNETWORKS_RELU6
ANEURALNETWORKS_RESHAPE
ANEURALNETWORKS_RESIZE_BILINEAR
ANEURALNETWORKS_RNN
ANEURALNETWORKS_ROI_ALIGN
ANEURALNETWORKS_SOFTMAX
ANEURALNETWORKS_SPACE_TO_BATCH_ND
ANEURALNETWORKS_SPACE_TO_DEPTH
ANEURALNETWORKS_SQUEEZE
ANEURALNETWORKS_STRIDED_SLICE
ANEURALNETWORKS_SUB
ANEURALNETWORKS_SVDF
ANEURALNETWORKS_TANH
ANEURALNETWORKS_TRANSPOSE
Android 9
NN HAL 1.1 viene introdotto in Android 9 e include le seguenti modifiche significative.
IDevice::prepareModel_1_1
include un parametroExecutionPreference
. Un conducente può utilizzarlo per modificare la propria preparazione, sapendo che l'app preferisce risparmiare la batteria o eseguirà il modello in chiamate successive rapide.- Sono state aggiunte nove nuove operazioni:
BATCH_TO_SPACE_ND
,DIV
,MEAN
,PAD
,SPACE_TO_BATCH_ND
,SQUEEZE
,STRIDED_SLICE
,SUB
,TRANSPOSE
. - Un'app può specificare che i calcoli con numeri in virgola mobile a 32 bit possono essere eseguiti
utilizzando l'intervallo e/o la precisione dei numeri in virgola mobile a 16 bit impostando
Model.relaxComputationFloat32toFloat16
sutrue
. Lo structCapabilities
ha il campo aggiuntivorelaxedFloat32toFloat16Performance
, che consente al driver di segnalare le sue prestazioni rilassate al framework.
Android 8.1
L'HAL iniziale di reti neurali (1.0) è stato rilasciato in Android 8.1. Per ulteriori informazioni, consulta /neuralnetworks/1.0/
.