Esta página oferece uma visão geral de como implementar um driver da API Neural Networks (NNAPI, na sigla em inglês). Para mais detalhes, consulte a documentação encontrada nos arquivos de definição
do HAL em
hardware/interfaces/neuralnetworks
.
Um exemplo de implementação de driver está em
frameworks/ml/nn/driver/sample
.
Para mais informações sobre a API Neural Networks, consulte API Neural Networks.
HAL de redes neurais
A HAL de redes neurais (NN) define uma abstração dos vários dispositivos,
como unidades de processamento gráfico (GPUs) e processadores de sinal digital (DSPs),
que estão em um produto (por exemplo, um smartphone ou tablet). Os drivers para esses
dispositivos precisam estar em conformidade com a NN HAL. A interface é especificada nos arquivos de definição
HAL em
hardware/interfaces/neuralnetworks
.
O fluxo geral da interface entre o framework e um driver é mostrado na Figura 1.
Figura 1. Fluxo de redes neurais
Inicialização
Na inicialização, o framework consulta o driver para saber os recursos dele usando
IDevice::getCapabilities_1_3
.
A estrutura @1.3::Capabilities
inclui todos os tipos de dados e
representa a performance não relaxada usando um vetor.
Para determinar como alocar cálculos para os dispositivos disponíveis, o framework usa os recursos para entender a rapidez e a eficiência energética de cada driver na execução. Para fornecer essas informações, o driver precisa fornecer números de desempenho padronizados com base na execução das cargas de trabalho de referência.
Para determinar os valores que o driver retorna em resposta a
IDevice::getCapabilities_1_3
, use o app de comparação da NNAPI para medir o
desempenho dos tipos de dados correspondentes. Os modelos MobileNet v1 e v2, asr_float
e tts_float
são recomendados para medir o desempenho de valores de ponto flutuante
de 32 bits, e os modelos quantizados MobileNet v1 e v2 são
recomendados para valores quantizados de 8 bits. Para mais informações, consulte
Pacote de testes de machine learning do Android.
No Android 9 e versões anteriores, a estrutura Capabilities
inclui informações de desempenho
do driver apenas para tensores de ponto flutuante e quantizados e não inclui
tipos de dados escalares.
Como parte do processo de inicialização, o framework pode consultar mais informações
usando
IDevice::getType
,
IDevice::getVersionString
,
IDevice:getSupportedExtensions
e
IDevice::getNumberOfCacheFilesNeeded
.
Entre as reinicializações do produto, o framework espera que todas as consultas descritas nesta seção sempre informem os mesmos valores para um determinado driver. Caso contrário, um app que usa esse driver pode apresentar desempenho reduzido ou comportamento incorreto.
Compilação
O framework determina quais dispositivos usar ao receber uma solicitação de um app. No Android 10, os apps podem descobrir e especificar os dispositivos que o framework escolhe. Para ver mais informações, consulte Descoberta e atribuição de dispositivos.
No momento da compilação do modelo, o framework envia o modelo para cada driver candidato
chamando
IDevice::getSupportedOperations_1_3
.
Cada driver retorna uma matriz de booleanos indicando quais operações do modelo são compatíveis. Um driver pode determinar que não pode
oferecer suporte a uma determinada operação por vários motivos. Exemplo:
- O driver não oferece suporte ao tipo de dados.
- O driver só é compatível com operações com parâmetros de entrada específicos. Por exemplo, um driver pode ser compatível com operações de convolução 3x3 e 5x5, mas não 7x7.
- O driver tem restrições de memória que impedem o processamento de gráficos ou entradas grandes.
Durante a compilação, a entrada, a saída e os operandos internos do modelo, conforme
descrito em
OperandLifeTime
,
podem ter dimensões ou classificação desconhecidas. Para mais informações, consulte
Formato de saída.
O framework instrui cada driver selecionado a se preparar para executar um subconjunto do
modelo chamando
IDevice::prepareModel_1_3
.
Cada driver compila o subconjunto. Por exemplo, um driver pode
gerar código ou criar uma cópia reordenada dos pesos. Como pode haver um
tempo significativo entre a compilação do modelo e a
execução das solicitações, recursos como grandes blocos de memória do dispositivo não podem
ser atribuídos durante a compilação.
Em caso de sucesso, o driver retorna um identificador
@1.3::IPreparedModel
. Se o driver retornar um código de falha ao preparar o subconjunto do
modelo, o framework executará todo o modelo na CPU.
Para reduzir o tempo usado na compilação quando um app é iniciado, um driver pode armazenar artefatos de compilação em cache. Para mais informações, consulte Compilação em cache.
Execução
Quando um app solicita que o framework execute uma solicitação, ele chama
o método
HAL
IPreparedModel::executeSynchronously_1_3
por padrão para realizar uma execução síncrona em um modelo preparado.
Uma solicitação também pode ser executada de forma assíncrona usando o método
execute_1_3
,
o método
executeFenced
(consulte Execução protegida)
ou usando uma
execução em rajada.
As chamadas de execução síncrona melhoram o desempenho e reduzem a sobrecarga de linha de execução em comparação com as chamadas assíncronas, porque o controle é retornado ao processo do app somente após a conclusão da execução. Isso significa que o driver não precisa de um mecanismo separado para notificar o processo do app de que uma execução foi concluída.
Com o método execute_1_3
assíncrono, o controle retorna ao
processo do app após o início da execução, e o driver precisa notificar
o framework quando a execução for concluída usando o
@1.3::IExecutionCallback
.
O parâmetro Request
transmitido ao método de execução lista os operandos de entrada e saída usados para a execução. A memória que armazena os dados do operando precisa
usar a ordem de linha principal com a primeira dimensão iterando a mais lenta e não ter
espaçamento no final de nenhuma linha. Para mais informações sobre os tipos de operandos,
consulte
Operandos.
Para drivers NN HAL 1.2 ou mais recentes, quando uma solicitação é concluída, o status do erro, o formato da saída e as informações de tempo são retornados ao framework. Durante a execução, os operandos de saída ou internos do modelo podem ter uma ou mais dimensões ou uma classificação desconhecida. Quando pelo menos um operando de saída tem uma dimensão ou classificação desconhecida, o driver precisa retornar informações de saída dimensionadas dinamicamente.
Para drivers com NN HAL 1.1 ou anterior, somente o status de erro é retornado quando uma solicitação é concluída. As dimensões para operandos de entrada e saída precisam ser totalmente especificadas para que a execução seja concluída. Os operandos internos podem ter uma ou mais dimensões desconhecidas, mas precisam ter a classificação especificada.
Para solicitações de usuários que abrangem vários drivers, o framework é responsável por reservar a memória intermediária e sequenciar as chamadas para cada driver.
Várias solicitações podem ser iniciadas em paralelo no mesmo
@1.3::IPreparedModel
.
O driver pode executar solicitações em paralelo ou serializar as execuções.
O framework pode solicitar que um driver mantenha mais de um modelo preparado. Por
exemplo, prepare o modelo m1
, prepare m2
, execute a solicitação r1
em m1
, execute
r2
em m2
, execute r3
em m1
, execute r4
em m2
, libere (descrito em
Limpeza) m1
e libere m2
.
Para evitar uma primeira execução lenta que pode resultar em uma experiência ruim para o usuário (por exemplo, a primeira renderização lenta de frame), o driver precisa realizar a maioria das inicializações na fase de compilação. A inicialização na primeira execução precisa ser limitada a ações que afetam negativamente a integridade do sistema quando executadas com antecedência, como reservar grandes buffers temporários ou aumentar a taxa de relógio de um dispositivo. Drivers que podem preparar apenas um número limitado de modelos simultâneos podem precisar fazer a inicialização na primeira execução.
No Android 10 ou versões mais recentes, em casos em que várias execuções com o mesmo modelo preparado são executadas em sucessão rápida, o cliente pode usar um objeto de execução em rajada para se comunicar entre os processos do app e do driver. Para mais informações, consulte Execuções de burst e filas rápidas de mensagens.
Para melhorar o desempenho de várias execuções em rápida sucessão, o driver pode manter buffers temporários ou aumentar as taxas de clock. É recomendável criar uma linha de execução de guardião para liberar recursos se nenhuma nova solicitação for criada após um período fixo.
Forma de saída
Para solicitações em que um ou mais operandos de saída não têm todas as dimensões
especificadas, o driver precisa fornecer uma lista de formas de saída contendo as
informações de dimensão para cada operando de saída após a execução. Para mais
informações sobre dimensões, consulte
OutputShape
.
Se uma execução falhar devido a um buffer de saída pequeno, o driver precisará indicar quais operandos de saída têm tamanho de buffer insuficiente na lista de formas de saída e informar o máximo possível de informações dimensionais, usando zero para dimensões desconhecidas.
Marcação de tempo
No Android 10, um app pode solicitar o tempo
de execução se tiver especificado um único dispositivo para usar durante o processo de compilação. Para
detalhes, consulte
MeasureTiming
e Descoberta e atribuição de dispositivos.
Nesse caso, um
driver do HAL 1.2 de NN precisa medir a duração da execução ou informar UINT64_MAX
(para
indicar que a duração está indisponível) ao executar uma solicitação. O driver
precisa minimizar qualquer penalidade de desempenho resultante da medição da duração
da execução.
O driver informa as seguintes durações em microssegundos na
estrutura
Timing
:
- Tempo de execução no dispositivo: não inclui o tempo de execução no driver, que é executado no processador host.
- Tempo de execução no driver:inclui o tempo de execução no dispositivo.
Essas durações precisam incluir o tempo em que a execução é suspensa, por exemplo, quando a execução foi interrompida por outras tarefas ou quando ela está aguardando a disponibilidade de um recurso.
Quando o driver não for solicitado a medir a duração da execução ou quando
houver um erro de execução, ele precisará informar as durações como
UINT64_MAX
. Mesmo que o motorista precise medir a duração
da execução, ele pode informar UINT64_MAX
para o tempo no dispositivo, o tempo no
motorista ou ambos. Quando o driver informa as duas durações como um valor diferente de
UINT64_MAX
, o tempo de execução no driver precisa ser igual ou superior ao tempo no
dispositivo.
Execução cercada
No Android 11, a NNAPI permite que as execuções aguardem uma
lista de gerenciadores sync_fence
e, opcionalmente, retornem um objeto sync_fence
, que
é sinalizado quando a execução é concluída. Isso reduz a sobrecarga para modelos de sequência pequena e casos de uso de streaming. Essa execução também permite a interoperabilidade
mais eficiente com outros componentes que podem sinalizar ou esperar por
sync_fence
. Para mais informações sobre sync_fence
, consulte
Framework de sincronização.
Em uma execução restrita, o framework chama o método
IPreparedModel::executeFenced
para iniciar uma execução assíncrona e isolada em um modelo preparado com um
vetor de limites de sincronização para aguardar. Se a tarefa assíncrona for concluída antes
da chamada retornar, um identificador vazio poderá ser retornado para sync_fence
. Um
objeto IFencedExecutionCallback
também precisa ser retornado para permitir que o framework
consulte informações de duração e status de erro.
Após a conclusão de uma execução, os dois valores de
tempo a seguir,
que medem a duração da execução, podem ser consultados usando
IFencedExecutionCallback::getExecutionInfo
.
timingLaunched
: duração do momento em que oexecuteFenced
é chamado até o momento em que oexecuteFenced
indica osyncFence
retornado.timingFenced
: duração do momento em que todos os limites de sincronização que a execução aguarda são sinalizados até o momento em queexecuteFenced
sinaliza osyncFence
retornado.
Fluxo de controle
Para dispositivos com Android 11 ou versões mais recentes, a NNAPI
inclui duas operações de fluxo de controle, IF
e WHILE
, que usam outros modelos
como argumentos e os executam condicionalmente (IF
) ou repetidamente (WHILE
). Para
mais informações sobre como implementar isso, consulte
Fluxo de controle.
Qualidade de serviço
No Android 11, a NNAPI inclui uma qualidade de serviço (QoS) melhorada ao permitir que um app indique as prioridades relativas dos modelos, o tempo máximo esperado para que um modelo seja preparado e o tempo máximo esperado para que uma execução seja concluída. Para mais informações, consulte Qualidade de serviço.
Limpeza
Quando um app termina de usar um modelo preparado, o framework libera
a referência para o
objeto
@1.3::IPreparedModel
. Quando o objeto IPreparedModel
não é mais referenciado, ele é
destruído automaticamente no serviço de driver que o criou. Os recursos específicos
do modelo podem ser recuperados no momento na implementação do
destrutor pelo driver. Se o serviço do driver quiser que o objeto IPreparedModel
seja
destruído automaticamente quando não for mais necessário para o cliente, ele não poderá conter
nenhuma referência ao objeto IPreparedModel
depois que o objeto IPreparedeModel
for retornado por
IPreparedModelCallback::notify_1_3
.
Uso da CPU
Espera-se que os drivers usem a CPU para configurar cálculos. Os drivers não podem usar a CPU para fazer cálculos de gráfico, porque isso interfere na capacidade do framework de alocar trabalho corretamente. O driver precisa informar as partes que não pode processar ao framework e deixar que ele processe o resto.
O framework fornece uma implementação de CPU para todas as operações da NNAPI, exceto as definidas pelo fornecedor. Para mais informações, consulte Extensões de fornecedor.
As operações introduzidas no Android 10 (nível 29 da API) têm apenas uma implementação de CPU de referência para verificar se os testes CTS e VTS estão corretos. As implementações otimizadas incluídas em frameworks de aprendizado de máquina para dispositivos móveis são preferidas em relação à implementação da CPU da NNAPI.
Funções utilitárias
O código-base da NNAPI inclui funções de utilitário que podem ser usadas por serviços de driver.
O arquivo
frameworks/ml/nn/common/include/Utils.h
contém várias funções utilitárias, como as usadas para registro e
para conversão entre diferentes versões do HAL de IA.
VLogging:
VLOG
é uma macro de wrapper em torno doLOG
do Android que só registra a mensagem se a tag apropriada estiver definida na propriedadedebug.nn.vlog
.initVLogMask()
precisa ser chamado antes de qualquer chamada paraVLOG
. A macroVLOG_IS_ON
pode ser usada para verificar seVLOG
está ativado no momento, permitindo que códigos complicados de geração de registros sejam pulados se não forem necessários. O valor da propriedade precisa ser um dos seguintes:- Uma string vazia, indicando que nenhum registro será feito.
- O token
1
ouall
, indicando que todos os registros precisam ser feitos. - Uma lista de tags, delimitadas por espaços, vírgulas ou dois-pontos, indicando qual registro será feito. As tags são
compilation
,cpuexe
,driver
,execution
,manager
emodel
.
compliantWithV1_*
: retornatrue
se um objeto da HAL de NN puder ser convertido para o mesmo tipo de uma versão diferente da HAL sem perder informações. Por exemplo, chamarcompliantWithV1_0
em umV1_2::Model
retornafalse
se o modelo incluir tipos de operação introduzidos no NN HAL 1.1 ou NN HAL 1.2.convertToV1_*
: converte um objeto da NN HAL de uma versão em outra. Um aviso é registrado se a conversão resultar em perda de informações, ou seja, se a nova versão do tipo não puder representar totalmente o valor.Recursos: as funções
nonExtensionOperandPerformance
eupdate
podem ser usadas para ajudar a criar o campoCapabilities::operandPerformance
.Consultar propriedades de tipos:
isExtensionOperandType
,isExtensionOperationType
,nonExtensionSizeOfData
,nonExtensionOperandSizeOfData
,nonExtensionOperandTypeIsScalar
,tensorHasUnspecifiedDimensions
.
O arquivo
frameworks/ml/nn/common/include/ValidateHal.h
contém funções utilitárias para validar se um objeto NN HAL é válido
de acordo com a especificação da versão da HAL.
validate*
: retornatrue
se o objeto da HAL HAL for válido de acordo com a especificação da versão da HAL. Os tipos de OEM e de extensão não são validados. Por exemplo,validateModel
retornafalse
se o modelo contém uma operação que faz referência a um índice de operando que não existe ou uma operação que não tem suporte nessa versão da HAL.
O arquivo
frameworks/ml/nn/common/include/Tracing.h
contém macros para simplificar a adição de informações de
systracing ao código de redes neurais.
Para conferir um exemplo, consulte as invocações de macro NNTRACE_*
no
driver de exemplo.
O arquivo
frameworks/ml/nn/common/include/GraphDump.h
contém uma função utilitária para despejar o conteúdo de um Model
em formato gráfico
para fins de depuração.
graphDump
: grava uma representação do modelo no formato Graphviz (.dot
) no fluxo especificado (se fornecido) ou no logcat (se nenhum stream for fornecido).
Validação
Para testar a implementação da NNAPI, use os testes VTS e CTS incluídos na estrutura do Android. O VTS exercita os impulsionadores diretamente (sem usar o framework), enquanto o CTS os exercita indiretamente por meio do framework. Eles testam cada método da API e verificam se todas as operações com suporte dos drivers funcionam corretamente e fornecem resultados que atendem aos requisitos de precisão.
Os requisitos de precisão no CTS e VTS para a NNAPI são os seguintes:
Ponto flutuante: abs(esperado - real) <= atol + rtol * abs(esperado); em que:
- Para fp32, atol = 1e-5f, rtol = 5,0f * 1,1920928955078125e-7
- Para fp16, atol = rtol = 5.0f * 0,0009765625f
Quantized:separado por um (exceto para
mobilenet_quantized
, que é dividido em três)Booleano: correspondência exata
Uma maneira de o CTS testar a NNAPI é gerar gráficos pseudoaleatórios fixos
usados para testar e comparar os resultados de execução de cada driver com a
implementação de referência da NNAPI. Para drivers com NN HAL 1.2 ou mais recente, se os
resultados não atenderem aos critérios de precisão, o CTS vai informar um erro e fazer o descarte de um
arquivo de especificação do modelo com falha em /data/local/tmp
para depuração.
Para mais detalhes sobre os critérios de precisão, consulte
TestRandomGraph.cpp
e
TestHarness.h
.
Teste de fuzz
O objetivo do teste de fuzz é encontrar falhas, declarações, violações de memória ou comportamento geral indefinido no código em teste devido a fatores como entradas inesperadas. Para testes de fuzz da NNAPI, o Android usa testes baseados na libFuzzer, que são eficientes em fuzzing porque usam a cobertura de linha de casos de teste anteriores para gerar novas entradas aleatórias. Por exemplo, o libFuzzer favorece casos de teste executados em novas linhas de código. Isso reduz bastante o tempo que os testes levam para encontrar códigos problemáticos.
Para fazer testes de fuzz e validar a implementação do driver, modifique
frameworks/ml/nn/runtime/test/android_fuzzing/DriverFuzzTest.cpp
no utilitário de teste libneuralnetworks_driver_fuzzer
encontrado no AOSP para incluir
o código do driver. Para mais informações sobre testes de fuzz da NNAPI, consulte
frameworks/ml/nn/runtime/test/android_fuzzing/README.md
.
Segurança
Como os processos do app se comunicam diretamente com o processo de um driver,
eles precisam validar os argumentos das chamadas que recebem. Essa validação
é verificada pelo VTS. O código de validação está em
frameworks/ml/nn/common/include/ValidateHal.h
.
Os drivers também precisam garantir que os apps não interfiram em outros quando usados no mesmo dispositivo.
Conjunto de testes de aprendizado de máquina do Android
O Android Machine Learning Test Suite (MLTS) é um comparativo de mercado da NNAPI incluído no CTS e VTS para validar a precisão de modelos reais em dispositivos do fornecedor. O comparativo de mercado avalia a latência e a precisão e compara os resultados dos drivers com os resultados usando o TF Lite em execução na CPU, para o mesmo modelo e conjuntos de dados. Isso garante que a precisão de um driver não seja pior do que a implementação de referência da CPU.
Os desenvolvedores de plataformas Android também usam o MLTS para avaliar a latência e a precisão dos drivers.
O comparativo de mercado da NNAPI pode ser encontrado em dois projetos no AOSP:
platform/test/mlts/benchmark
(app de comparação)platform/test/mlts/models
(modelos e conjuntos de dados)
Modelos e conjuntos de dados
O comparativo de mercado da NNAPI usa os modelos e conjuntos de dados a seguir.
- O float MobileNetV1 e o u8 quantizados em tamanhos diferentes são executados em um pequeno subconjunto (1.500 imagens) do Open Images Dataset v4.
- Os pontos flutuantes MobileNetV2 e u8 quantizados em tamanhos diferentes, são executados em um pequeno subconjunto (1.500 imagens) de Open Images Dataset v4.
- Modelo acústico baseado em memória de curto prazo (LSTM, na sigla em inglês) para conversão de texto em fala, executado em um pequeno subconjunto do conjunto CMU Arctic.
- Modelo acústico baseado em LSTM para reconhecimento automático de fala, executado em um pequeno subconjunto do conjunto de dados LibriSpeech.
Para saber mais, consulte
platform/test/mlts/models
.
Teste de estresse
O Android Machine Learning Test Suite inclui uma série de testes de falhas para validar a resiliência dos drivers em condições intensas de uso ou em casos de esquina do comportamento dos clientes.
Todos os testes de falha oferecem os seguintes recursos:
- Detecção de suspensão:se o cliente NNAPI trava durante um teste, ele
falha com o motivo da falha
HANG
, e o pacote de testes é movido para o próximo teste. - Detecção de falha do cliente NNAPI: os testes sobrevivem a falhas do cliente e falham
com o motivo da falha
CRASH
. - Detecção de falha do driver:os testes podem detectar uma falha do driver
que causa uma falha em uma chamada da NNAPI. Pode haver falhas nos
processos do driver que não causam uma falha da NNAPI e não causam falha no teste. Para cobrir esse tipo de falha, é recomendável executar o comando
tail
no registro do sistema para encontrar erros ou falhas relacionadas ao driver. - Segmentação de todos os aceleradores disponíveis: os testes são executados com base em todos os drivers disponíveis.
Todos os testes de colisão têm os quatro resultados possíveis a seguir:
SUCCESS
: a execução foi concluída sem erros.FAILURE
: falha na execução. Geralmente causado por uma falha ao testar um modelo, indicando que o driver falhou ao compilar ou executar o modelo.HANG
: o processo de teste parou de responder.CRASH
: o processo de teste falhou.
Para mais informações sobre testes de estresse e uma lista completa de testes de falha, consulte
platform/test/mlts/benchmark/README.txt
.
Usar MLTS
Para usar o MLTS:
- Conecte um dispositivo de destino à estação de trabalho e verifique se ele
pode ser acessado pelo
adb.
Exporte a variável de ambiente
ANDROID_SERIAL
do dispositivo de destino se mais de um dispositivo estiver conectado. cd
no diretório de origem de nível superior do Android.source build/envsetup.sh lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available. ./test/mlts/benchmark/build_and_run_benchmark.sh
No final de uma execução de comparativo de mercado, os resultados são apresentados como uma página HTML e transmitidos para
xdg-open
.
Para saber mais, consulte
platform/test/mlts/benchmark/README.txt
.
Versões da HAL de redes neurais
Esta seção descreve as mudanças introduzidas nas versões da HAL de redes neurais e Android.
Android 11
O Android 11 apresenta a HAL de redes neurais 1.3, que inclui as seguintes mudanças importantes.
- Suporte para quantização assinada de 8 bits na NNAPI. Adiciona o tipo de operando
TENSOR_QUANT8_ASYMM_SIGNED
. Os drivers com HAL 1.3 da NN que oferecem suporte a operações com quantização não assinada também precisam oferecer suporte às variantes assinadas dessas operações. Ao executar versões assinadas e não assinadas da maioria das operações quantizadas, os drivers precisam produzir os mesmos resultados até um deslocamento de 128. Há cinco exceções a esse requisito:CAST
,HASHTABLE_LOOKUP
,LSH_PROJECTION
,PAD_V2
eQUANTIZED_16BIT_LSTM
. A operaçãoQUANTIZED_16BIT_LSTM
não oferece suporte a operandos assinados, e as outras quatro operações são compatíveis com a quantização assinada, mas não exigem que os resultados sejam os mesmos. - Suporte a execuções protegidas em que o framework chama o método
IPreparedModel::executeFenced
para iniciar uma execução assíncrona e protegida em um modelo preparado com um vetor de barreiras de sincronização para aguardar. Para mais informações, consulte Execução limitada. - Suporte para fluxo de controle. Adiciona as operações
IF
eWHILE
, que usam outros modelos como argumentos e os executam condicionalmente (IF
) ou repetidamente (WHILE
). Para mais informações, consulte Fluxo de controle. - Melhoria na qualidade de serviço (QoS), já que os apps podem indicar as prioridades relativas dos modelos, a quantidade máxima de tempo esperada para um modelo ser preparado e o tempo máximo esperado para uma execução ser concluída. Para mais informações, consulte Qualidade de serviço.
- Suporte a domínios de memória que fornecem interfaces de alocador para buffers gerenciados pelo driver. Isso permite transmitir as memórias nativas do dispositivo entre as execuções ao suprimir a cópia e a transformação de dados desnecessários entre execuções consecutivas no mesmo driver. Para mais informações, consulte Domínios de memória.
Android 10
O Android 10 apresenta a NN HAL 1.2, que inclui as seguintes mudanças importantes.
- A estrutura
Capabilities
inclui todos os tipos de dados, incluindo tipos de dados vetoriais, e representa desempenho não relaxado usando um vetor em vez de campos nomeados. - Os métodos
getVersionString
egetType
permitem que o framework extraia informações de tipo de dispositivo (DeviceType
) e de versão. Consulte Descoberta e atribuição de dispositivos. - O método
executeSynchronously
é chamado por padrão para realizar uma execução de forma síncrona. O métodoexecute_1_2
instrui a framework a realizar uma execução de forma assíncrona. Consulte Execução. - O parâmetro
MeasureTiming
paraexecuteSynchronously
,execute_1_2
e execução de burst especifica se o driver vai medir a duração da execução. Os resultados são informados na estruturaTiming
. Consulte Tempo. - Suporte a execuções em que um ou mais operandos de saída têm uma dimensão ou classificação desconhecida. Consulte Forma de saída.
- Suporte a extensões do fornecedor, que são coleções de operações e tipos de dados definidos pelo fornecedor. O driver informa as extensões compatíveis pelo
método
IDevice::getSupportedExtensions
. Consulte Extensões do fornecedor. - Capacidade de um objeto de pico para controlar um conjunto de execuções de pico usando filas de mensagens rápidas (FMQs, na sigla em inglês) para se comunicar entre os processos do app e do driver, reduzindo a latência. Consulte Execuções de burst e filas rápidas de mensagens.
- Suporte a AHardwareBuffer para permitir que o driver execute execuções sem copiar dados. Consulte AHardwareBuffer.
- Melhoria no suporte ao armazenamento em cache de artefatos de compilação para reduzir o tempo usado na compilação quando um app é iniciado. Consulte Armazenamento de compilação em cache.
O Android 10 introduz os seguintes tipos e operações de operandos.
-
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
O Android 10 introduz atualizações para muitas das operações existentes. As atualizações estão relacionadas principalmente ao seguinte:
- Suporte para o layout de memória NCHW
- Suporte para tensores com classificação diferente de 4 em operações de softmax e normalização
- Suporte para convoluções dilatadas
- Suporte a entradas com quantização mista em
ANEURALNETWORKS_CONCATENATION
.
A lista abaixo mostra as operações que são modificadas no Android 10. Para conferir todos os detalhes das mudanças, consulte OperationCode na documentação de referência da 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
A NN HAL 1.1 foi introduzida no Android 9 e inclui as mudanças importantes abaixo.
IDevice::prepareModel_1_1
inclui um parâmetroExecutionPreference
. Um driver pode usar isso para ajustar a preparação, sabendo que o app prefere economizar bateria ou que vai executar o modelo em chamadas rápidas sucessivas.- Foram adicionadas nove operações novas:
BATCH_TO_SPACE_ND
,DIV
,MEAN
,PAD
,SPACE_TO_BATCH_ND
,SQUEEZE
,STRIDED_SLICE
,SUB
,TRANSPOSE
. - Um app pode especificar que cálculos de ponto flutuante de 32 bits podem ser executados
usando intervalo flutuante de 16 bits e/ou precisão, definindo
Model.relaxComputationFloat32toFloat16
comotrue
. O structCapabilities
tem o campo extrarelaxedFloat32toFloat16Performance
para que o driver possa informar o desempenho otimizado ao framework.
Android 8.1
A HAL de redes neurais inicial (1.0) foi lançada no Android 8.1. Para mais
informações, consulte
/neuralnetworks/1.0/
.