Qualidade de serviço

A partir do Android 11, a NNAPI oferece uma melhor qualidade de serviço (QoS) ao permitir que um app indique 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. Além disso, o Android 11 apresenta outros valores de erro da NNAPI que permitem que um serviço indique com mais precisão o que deu errado quando ocorre uma falha, para que o app cliente possa reagir e se recuperar melhor.

Prioridade

No Android 11 ou mais recente, os modelos são preparados com uma prioridade na NN HAL 1.3. Essa prioridade é relativa a outros modelos preparados pertencentes ao mesmo app. As execuções de maior prioridade podem usar mais recursos de computação do que as de menor prioridade e podem impedir ou impedir as execuções de menor prioridade.

A chamada de NN HAL 1.3 que inclui Priority como argumento explícito é IDevice::prepareModel_1_3. IDevice::prepareModelFromCache_1_3 inclui implicitamente Priority nos argumentos do cache.

Há muitas estratégias possíveis para oferecer suporte a prioridades, dependendo dos recursos do driver e do acelerador. Confira algumas estratégias:

  • Para drivers com suporte integrado à prioridade, transmita diretamente o campo Priority para o acelerador.
  • Use uma fila de prioridade por app para oferecer suporte a prioridades diferentes, mesmo antes de uma execução chegar ao acelerador.
  • Pause ou cancele modelos de baixa prioridade que estão sendo executados para liberar o acelerador para executar modelos de alta prioridade. Para isso, insira pontos de verificação em modelos de baixa prioridade que, quando alcançados, consultam uma flag para determinar se a execução atual precisa ser interrompida antes do tempo ou particione o modelo em submodelos e consulte a flag entre as execuções de submodelos. O uso de pontos de verificação ou submodelos em modelos preparados com uma prioridade pode introduzir um overhead adicional que não está presente em modelos sem prioridade em versões anteriores ao NN HAL 1.3.

    • Para oferecer suporte à preempção, preserve o contexto de execução, incluindo a próxima operação ou submodelo a ser executado e todos os dados de operando intermediários relevantes. Use esse contexto de execução para reassumir a execução mais tarde.
    • O suporte à preempção total não é necessário, então o contexto de execução não precisa ser preservado. Como as execuções de modelo da NNAPI são determinísticas, elas podem ser reiniciadas do zero mais tarde.

O Android permite que os serviços diferenciem entre diferentes apps de chamada usando um AID (UID do Android). O HIDL tem mecanismos integrados para recuperar o UID do app de chamada pelo método ::android::hardware::IPCThreadState::getCallingUid. Uma lista de AIDs pode ser encontrada em libcutils/include/cutils/android_filesystem_config.h.

Prazos

A partir do Android 11, a preparação e as execuções de modelos podem ser iniciadas com um argumento de prazo OptionalTimePoint. Para drivers que podem estimar o tempo necessário para uma tarefa, esse prazo permite que o driver interrompa a tarefa antes do início, se ele estimar que a tarefa não pode ser concluída antes do prazo. Da mesma forma, o prazo permite que o driver interrompa uma tarefa em andamento que ele estima que não será concluída antes do prazo. O argumento de prazo não força um driver a abortar uma tarefa se ela não for concluída até o prazo ou se o prazo tiver passado. O argumento de prazo pode ser usado para liberar recursos de computação no driver e retornar o controle ao aplicativo mais rapidamente do que é possível sem o prazo.

As chamadas da HAL 1.3 de NN que incluem prazos OptionalTimePoint como argumento são:

  • IDevice::prepareModel_1_3
  • IDevice::prepareModelFromCache_1_3
  • IPreparedModel::execute_1_3
  • IPreparedModel::executeSynchronously_1_3
  • IPreparedModel::executeFenced

Para ver uma implementação de referência do recurso de prazo para cada um dos métodos acima, consulte o driver de amostra da NNAPI em frameworks/ml/nn/driver/sample/SampleDriver.cpp.

Códigos de erro

O Android 11 inclui quatro valores de código de erro na NN HAL 1.3 para melhorar a geração de relatórios de erros, permitindo que os drivers comuniquem melhor o estado e os apps para uma recuperação mais tranquila. Estes são os valores do código de erro em ErrorStatus.

  • MISSED_DEADLINE_TRANSIENT
  • MISSED_DEADLINE_PERSISTENT
  • RESOURCE_EXHAUSTED_TRANSIENT
  • RESOURCE_EXHAUSTED_PERSISTENT

No Android 10 ou versões anteriores, um driver só podia indicar uma falha pelo código de erro GENERAL_FAILURE. No Android 11, os dois códigos de erro MISSED_DEADLINE podem ser usados para indicar que a carga de trabalho foi abortada porque o prazo foi atingido ou porque o driver previu que a carga de trabalho não seria concluída até o prazo. Os dois códigos de erro RESOURCE_EXHAUSTED podem ser usados para indicar que a tarefa falhou devido a uma limitação de recurso no driver, como o driver não ter memória suficiente para a chamada.

A versão TRANSIENT de ambos os erros indica que o problema é temporário e que chamadas futuras para a mesma tarefa podem ser bem-sucedidas após um breve atraso. Por exemplo, esse código de erro precisa ser retornado quando o driver estiver ocupado com um trabalho de longa duração ou que consome muitos recursos, mas a nova tarefa seria concluída com sucesso se o driver não estivesse ocupado com o trabalho anterior. A versão PERSISTENT de ambos os erros indica que futuras chamadas para a mesma tarefa devem sempre falhar. Por exemplo, esse código de erro precisa ser retornado quando o motorista estima que a tarefa não será concluída dentro do prazo, mesmo em condições perfeitas, ou que o modelo é inerentemente muito grande e excede os recursos do driver.

Validação

A funcionalidade de qualidade de serviço é testada nos testes VTS da NNAPI (VtsHalNeuralnetworksV1_3Target). Isso inclui um conjunto de testes de validação (TestGenerated/ValidationTest#Test/) para garantir que o driver rejeite prioridades inválidas e um conjunto de testes chamados DeadlineTest (TestGenerated/DeadlineTest#Test/) para garantir que o driver processe os prazos corretamente.