Questa pagina fornisce una panoramica su come implementare un driver 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 GPU (Graphics Processing Unit) e i processori di segnali digitali (DSP),
presenti all'interno di 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 comprendere la velocità e l'efficienza energetica di ogni driver per 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 a 32 bit, mentre i modelli quantizzati MobileNet v1 e v2 sono consigliati per valori quantizzati a 8 bit. Per maggiori informazioni, consulta
Test Suite di Android Machine Learning.
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 del processo di inizializzazione, il framework può eseguire query su 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 quel driver potrebbe presentare prestazioni ridotte o comportamenti errati.
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 da cui il framework sceglie. 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. Ecco alcuni esempi:
- Il driver non supporta il tipo di dati.
- Il driver supporta solo le 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 indica a ogni 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 gli artefatti di compilazione. Per ulteriori informazioni, consulta la sezione Compilation memorizzazione nella cache.
Attuazione
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 l'overhead del thread 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 Esecuzione elenca gli operandi di input e output utilizzati per l'esecuzione. La memoria in cui sono archiviati i dati degli operandi deve utilizzare l'ordine principale delle righe e la prima dimensione deve ripetere la dimensione più lenta e non avere spaziatura interna alla fine di ogni riga. Per ulteriori informazioni sui tipi di operandi,
consulta la pagina
Operandi.
Per i driver NN HAL 1.2 o successivi, quando una richiesta viene completata, al framework vengono restituiti lo stato di errore, la forma di output e le informazioni sulle tempistiche. Durante l'esecuzione, gli operandi di output o interni del modello possono avere una o più dimensioni sconosciute o rango sconosciuto. 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 completamento della richiesta. Affinché l'esecuzione venga completata correttamente, le dimensioni degli operandi di input e output devono essere completamente specificate. 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 sulla stessa @1.3::IPreparedModel
.
Il driver può eseguire le richieste in parallelo o serializzare le esecuzioni.
Il framework può chiedere al conducente di tenere 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 un'esperienza utente scadente (ad esempio, lo stuttering del primo frame), il driver deve eseguire la maggior parte delle inizializzazioni nella fase di compilazione. L'inizializzazione alla prima esecuzione dovrebbe essere limitata ad azioni che incidono negativamente sull'integrità del sistema se eseguite in anticipo, come la prenotazione di buffer temporanei di grandi dimensioni o l'aumento della frequenza di clock di un dispositivo. I driver in grado di preparare solo un numero limitato di modelli simultanei potrebbero dover eseguire la propria 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ò mantenere i buffer temporanei o aumentare le frequenze di clock. Ti consigliamo di creare un thread di watchdog per rilasciare risorse se non vengono create nuove richieste dopo un periodo di tempo prestabilito.
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 riesce a causa di un buffer di output ridotto, il driver deve indicare quali operandi di output hanno dimensioni del buffer insufficienti nell'elenco di forme di output e deve riportare quante più informazioni dimensionali possibile, utilizzando zero per le dimensioni sconosciute.
Sincronizzazione
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 riporta le seguenti durate in microsecondi nella struttura di Timing
:
- Tempo di esecuzione sul dispositivo:non include 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 è 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 se
si verifica un errore di esecuzione, 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 conducente indica entrambe le durate come un valore diverso da
UINT64_MAX
, il tempo di esecuzione nel driver deve essere uguale o superiore a quello sul
dispositivo.
Esecuzione protetta
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. Questo riduce l'overhead per i modelli
di piccole sequenze e i casi d'uso relativi ai flussi di dati. L'esecuzione vincolata 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 protetta, 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. Se l'attività asincrona viene completata prima
della chiamata, è possibile restituire un handle vuoto per sync_fence
. È necessario restituire anche
un oggetto IFencedExecutionCallback
per consentire al framework
di eseguire query sulle informazioni relative allo stato e alla durata degli errori.
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 cuiexecuteFenced
viene chiamato al momento 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, la NNAPI
include due operazioni del flusso di controllo, IF
e WHILE
, che prendono altri modelli
come argomenti e li eseguono in modo condizionale (IF
) o ripetutamente (WHILE
). Per
maggiori informazioni su come eseguire questa operazione, 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 maggiori 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 dovrebbero utilizzare la CPU per eseguire calcoli grafici perché questo 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 maggiori informazioni, consulta la pagina relativa alle 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 preferibili 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 relativa aLOG
di Android che registra il messaggio solo se è impostato il tag appropriato nella proprietàdebug.nn.vlog
.initVLogMask()
deve essere chiamato prima di qualsiasi chiamata al numeroVLOG
. La macroVLOG_IS_ON
può essere utilizzata per verificare seVLOG
è attualmente abilitato, consentendo di saltare il codice di logging 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 acompliantWithV1_0
su unV1_2::Model
restituiscefalse
se il modello include tipi di operazioni introdotti in NN HAL 1.1 o NN HAL 1.2.convertToV1_*
: converte un oggetto NN HAL da una versione a un'altra. Se la conversione genera una perdita di informazioni (ovvero se la nuova versione del tipo non può rappresentare completamente il valore), viene registrato un avviso.Funzionalità: le funzioni
nonExtensionOperandPerformance
eupdate
possono essere utilizzate per 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 convalidare la validità di un oggetto NN HAL in base alla specifica della versione HAL.
validate*
: restituiscetrue
se l'oggetto NN HAL è valido secondo le specifiche della 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 eseguire il dump dei contenuti di un elemento Model
in forma grafica a scopo di debug.
graphDump
: scrive una rappresentazione del modello in formato Graphviz (.dot
) nel flusso specificato (se fornito) o nel logcat (se non viene fornito alcun flusso).
Convalida
Per testare l'implementazione di NNAPI, utilizza i test VTS e CTS inclusi nel framework Android. VTS esercita i conducenti direttamente (senza utilizzare il framework), mentre CTS li esercita indirettamente attraverso 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:
Valore con virgola mobile: AB(previsto - effettivo) <= atol + rtol * AB(previsto); 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 NNAPI. Per i conducenti con NN HAL 1.2 o versioni successive, se i risultati non soddisfano i criteri di precisione, CTS segnala un errore ed esegue il dump di un file di specifica per il modello in errore in /data/local/tmp
per il debug.
Per ulteriori dettagli sui criteri di precisione, consulta
TestRandomGraph.cpp
e
TestHarness.h
.
Test fuzz
Lo scopo dei test fuzz è trovare arresti anomali, asserzioni, violazioni della memoria o comportamenti generici non definiti nel codice sottoposto a test a causa di fattori come input imprevisti. Per i test di fuzz NNAPI, Android utilizza test basati su libFuzzer, che sono efficienti nel fuzzing perché utilizzano la copertura a linee 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 i risultati utilizzando TF Lite in esecuzione sulla CPU, per lo stesso modello e gli stessi set di dati. Ciò garantisce che la precisione di un driver non sia peggiore dell'implementazione del riferimento della CPU.
Gli sviluppatori di piattaforme Android utilizzano anche MLTS per valutare la latenza e l'accuratezza dei driver.
Il benchmark NNAPI è disponibile in due progetti in AOSP:
platform/test/mlts/benchmark
(app 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.
- I dati MobileNetV1 sono in virgola mobile e u8 quantizzati in dimensioni diverse ed eseguono un piccolo sottoinsieme (1500 immagini) del set di dati Open Images v4.
- MobileNetV2 è in virgola mobile e u8 quantificato in dimensioni diverse ed eseguito su un piccolo sottoinsieme (1500 immagini) del set di dati Open Images v4.
- Modello acustico basato su LSTM (Long Short-Term Memory). Per la sintesi vocale, viene eseguito su un piccolo sottoinsieme dell'Artico CMU.
- Modello acustico basato su LSTM per il riconoscimento vocale automatico, eseguito su un piccolo sottoinsieme del set di dati LibriSpeech.
Per maggiori informazioni, vedi
platform/test/mlts/models
.
Test di stress
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 offrono le seguenti funzionalità:
- Rilevamento dei blocchi: se il client NNAPI si blocca durante un test, quest'ultimo non va a buon fine e 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 la mancata riuscita 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 arresto anomalo hanno i seguenti quattro risultati possibili:
SUCCESS
: esecuzione completata senza un errore.FAILURE
: esecuzione non riuscita. In genere è causato da un errore durante il test di un modello, che indica che il driver non è riuscito a compilare o eseguire il modello.HANG
: il processo di test non risponde.CRASH
: arresto anomalo del processo di test.
Per ulteriori informazioni sui test di stress e per un elenco completo dei test di arresti anomali, vedi
platform/test/mlts/benchmark/README.txt
.
Utilizzo di MLTS
Per utilizzare MLTS:
- Connetti un dispositivo di destinazione alla workstation e assicurati che sia raggiungibile tramite adb.
Esporta la variabile di ambiente del dispositivo di destinazione
ANDROID_SERIAL
se è connesso più di un dispositivo. cd
nella directory di origine di primo livello 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 maggiori informazioni, vedi
platform/test/mlts/benchmark/README.txt
.
Versioni HAL per le 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 le operazioni con quantizzazione non firmata devono supportare anche le relative varianti con firma. 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 firmati e le altre quattro operazioni supportano la quantizzazione firmata, ma non richiedono che i risultati siano gli stessi. - 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 e li eseguono in modo condizionale (IF
) o ripetutamente (WHILE
). Per saperne di più, 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 la sezione Qualità del servizio.
- Supporto per i domini di memoria che forniscono interfacce allocator per i buffer gestiti dal driver. Ciò consente di passare le memorie native dei dispositivi tra le esecuzioni, eliminando la copia e la trasformazione non necessarie dei dati tra esecuzioni consecutive sullo stesso driver. Per maggiori informazioni, vedi Domini di memoria.
Android 10
Android 10 introduce NN HAL 1.2, che include le seguenti modifiche importanti.
- Lo struct
Capabilities
include tutti i tipi di dati, inclusi i tipi di dati scalari, e rappresenta le prestazioni non rallentate utilizzando un vettore anziché un campo con nome. - 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 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. - Possibilità di un oggetto burst di controllare un insieme di esecuzioni di burst tramite code di messaggi rapide (FMQ) per comunicare tra app e processi 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 Compilazione nella cache.
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 legati a quanto segue:
- Supporto del layout della memoria NCHW
- Supporto per tensori con ranking diverso da 4 nelle operazioni softmax e di normalizzazione
- Supporto per le convoluzioni dilate
- Supporto per input con quantizzazione mista in
ANEURALNETWORKS_CONCATENATION
L'elenco che segue 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 importanti.
IDevice::prepareModel_1_1
include un parametroExecutionPreference
. Un conducente può usare questa funzionalità per regolare la sua preparazione, sapendo che l'app preferisce risparmiare batteria o eseguirà il modello in rapide chiamate successive.- 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 è possibile eseguire i calcoli in virgola mobile a 32 bit utilizzando l'intervallo in virgola mobile a 16 bit e/o la precisione impostando
Model.relaxComputationFloat32toFloat16
sutrue
. Lo structCapabilities
ha il campo aggiuntivorelaxedFloat32toFloat16Performance
, che consente al driver di segnalare le prestazioni rilassate al framework.
Android 8.1
L'HAL iniziale per reti neurali (1.0) è stato rilasciato in Android 8.1. Per scoprire di più, visita la pagina
/neuralnetworks/1.0/
.