Controladores de API de redes neuronales

Esta página proporciona una descripción general de cómo implementar un controlador de API de redes neuronales (NNAPI). Para obtener más detalles, consulte la documentación que se encuentra en los archivos de definición de HAL en hardware/interfaces/neuralnetworks . Una implementación de controlador de muestra se encuentra en frameworks/ml/nn/driver/sample .

Para obtener más información sobre la API de redes neuronales, consulte API de redes neuronales .

Redes neuronales HAL

La HAL de redes neuronales (NN) define una abstracción de los diversos dispositivos , como unidades de procesamiento de gráficos (GPU) y procesadores de señales digitales (DSP), que se encuentran en un producto (por ejemplo, un teléfono o una tableta). Los controladores para estos dispositivos deben cumplir con NN HAL. La interfaz se especifica en los archivos de definición de HAL en hardware/interfaces/neuralnetworks .

El flujo general de la interfaz entre el marco y un controlador se muestra en la figura 1.

Flujo de redes neuronales

Figura 1. Flujo de redes neuronales

Inicialización

En la inicialización, el marco consulta al controlador por sus capacidades usando IDevice::getCapabilities_1_3 . La estructura @1.3::Capabilities incluye todos los tipos de datos y representa el rendimiento no relajado mediante un vector.

Para determinar cómo asignar los cálculos a los dispositivos disponibles, el marco utiliza las capacidades para comprender qué tan rápido y con qué eficiencia energética cada controlador puede realizar una ejecución. Para proporcionar esta información, el conductor debe proporcionar números de rendimiento estandarizados basados ​​en la ejecución de cargas de trabajo de referencia.

Para determinar los valores que devuelve el controlador en respuesta a IDevice::getCapabilities_1_3 , use la aplicación comparativa NNAPI para medir el rendimiento de los tipos de datos correspondientes. Los modelos MobileNet v1 y v2, asr_float y tts_float se recomiendan para medir el rendimiento de valores de punto flotante de 32 bits y los modelos cuantificados MobileNet v1 y v2 se recomiendan para valores cuantificados de 8 bits. Para obtener más información, consulte Conjunto de pruebas de aprendizaje automático de Android .

En Android 9 y versiones anteriores, la estructura Capabilities incluye información de rendimiento del controlador solo para tensores cuantizados y de punto flotante, y no incluye tipos de datos escalares.

Como parte del proceso de inicialización, el marco puede consultar más información mediante IDevice::getType , IDevice::getVersionString , IDevice:getSupportedExtensions e IDevice::getNumberOfCacheFilesNeeded .

Entre reinicios del producto, el marco espera que todas las consultas descritas en esta sección siempre informen los mismos valores para un controlador determinado. De lo contrario, una aplicación que use ese controlador puede mostrar un rendimiento reducido o un comportamiento incorrecto.

Compilacion

El marco determina qué dispositivos usar cuando recibe una solicitud de una aplicación. En Android 10, las aplicaciones pueden descubrir y especificar los dispositivos que selecciona el marco. Para obtener más información, consulte Detección y asignación de dispositivos .

En el momento de la compilación del modelo, el marco envía el modelo a cada controlador candidato llamando a IDevice::getSupportedOperations_1_3 . Cada controlador devuelve una matriz de valores booleanos que indican qué operaciones del modelo se admiten. Un controlador puede determinar que no puede admitir una operación determinada por varias razones. Por ejemplo:

  • El controlador no admite el tipo de datos.
  • El controlador solo admite operaciones con parámetros de entrada específicos. Por ejemplo, un controlador puede admitir operaciones de convolución 3x3 y 5x5, pero no 7x7.
  • El controlador tiene restricciones de memoria que le impiden manejar gráficos o entradas grandes.

Durante la compilación, los operandos internos, de entrada y de salida del modelo, como se describe en OperandLifeTime , pueden tener dimensiones o rangos desconocidos. Para obtener más información, consulte Forma de salida .

El marco indica a cada controlador seleccionado que se prepare para ejecutar un subconjunto del modelo llamando a IDevice::prepareModel_1_3 . Luego, cada controlador compila su subconjunto. Por ejemplo, un controlador podría generar código o crear una copia reordenada de los pesos. Debido a que puede haber una cantidad significativa de tiempo entre la compilación del modelo y la ejecución de las solicitudes, no se deben asignar recursos como grandes porciones de memoria del dispositivo durante la compilación.

En caso de éxito, el controlador devuelve un @1.3::IPreparedModel . Si el controlador devuelve un código de error al preparar su subconjunto del modelo, el marco ejecuta todo el modelo en la CPU.

Para reducir el tiempo utilizado para la compilación cuando se inicia una aplicación, un controlador puede almacenar en caché los artefactos de compilación. Para obtener más información, consulte Caché de compilación .

Ejecución

Cuando una aplicación le pide al marco que ejecute una solicitud, el marco llama al método HAL IPreparedModel::executeSynchronously_1_3 de forma predeterminada para realizar una ejecución síncrona en un modelo preparado. Una solicitud también se puede ejecutar de forma asincrónica mediante el método execute_1_3 , el método executeFenced (consulte Ejecución delimitada) o mediante una ejecución en ráfaga .

Las llamadas de ejecución síncrona mejoran el rendimiento y reducen la sobrecarga de subprocesos en comparación con las llamadas asíncronas porque el control se devuelve al proceso de la aplicación solo después de que se completa la ejecución. Esto significa que el controlador no necesita un mecanismo separado para notificar al proceso de la aplicación que se completó una ejecución.

Con el método asíncrono execute_1_3 , el control vuelve al proceso de la aplicación una vez que se ha iniciado la ejecución, y el controlador debe notificar al marco cuando se completa la ejecución, mediante @1.3::IExecutionCallback .

El parámetro Request pasado al método de ejecución enumera los operandos de entrada y salida utilizados para la ejecución. La memoria que almacena los datos del operando debe usar el orden de fila principal con la primera dimensión iterando más lentamente y sin relleno al final de ninguna fila. Para obtener más información sobre los tipos de operandos, consulte Operandos .

Para controladores NN HAL 1.2 o superiores, cuando se completa una solicitud, el estado de error, la forma de salida y la información de tiempo se devuelven al marco. Durante la ejecución, los operandos internos o de salida del modelo pueden tener una o más dimensiones desconocidas o un rango desconocido. Cuando al menos un operando de salida tiene una dimensión o rango desconocido, el controlador debe devolver información de salida de tamaño dinámico.

Para controladores con NN HAL 1.1 o anterior, solo se devuelve el estado de error cuando se completa una solicitud. Las dimensiones de los operandos de entrada y salida deben especificarse por completo para que la ejecución se complete correctamente. Los operandos internos pueden tener una o más dimensiones desconocidas, pero deben tener un rango especificado.

Para las solicitudes de los usuarios que abarcan varios controladores, el marco es responsable de reservar la memoria intermedia y secuenciar las llamadas a cada controlador.

Se pueden iniciar varias solicitudes en paralelo en el mismo @1.3::IPreparedModel . El controlador puede ejecutar solicitudes en paralelo o serializar las ejecuciones.

El marco puede pedirle a un controlador que mantenga más de un modelo preparado. Por ejemplo, prepare el modelo m1 , prepare m2 , ejecute la solicitud r1 en m1 , ejecute r2 en m2 , ejecute r3 en m1 , ejecute r4 en m2 , libere (descrito en Limpieza ) m1 y libere m2 .

Para evitar una primera ejecución lenta que podría resultar en una experiencia de usuario deficiente (por ejemplo, un primer cuadro entrecortado), el controlador debe realizar la mayoría de las inicializaciones en la fase de compilación. La inicialización en la primera ejecución debe limitarse a las acciones que afectan negativamente el estado del sistema cuando se realizan antes, como reservar grandes búferes temporales o aumentar la velocidad del reloj de un dispositivo. Los controladores que pueden preparar solo un número limitado de modelos simultáneos pueden tener que inicializarse en la primera ejecución.

En Android 10 o versiones posteriores, en los casos en que se ejecutan varias ejecuciones con el mismo modelo preparado en rápida sucesión, el cliente puede optar por usar un objeto de ráfaga de ejecución para comunicarse entre la aplicación y los procesos del controlador. Para obtener más información, consulte Ejecuciones en ráfaga y Colas de mensajes rápidas .

Para mejorar el rendimiento de múltiples ejecuciones en rápida sucesión, el controlador puede conservar búferes temporales o aumentar la velocidad del reloj. Se recomienda crear un subproceso de vigilancia para liberar recursos si no se crean nuevas solicitudes después de un período de tiempo fijo.

Forma de salida

Para solicitudes donde uno o más operandos de salida no tienen todas las dimensiones especificadas, el controlador debe proporcionar una lista de formas de salida que contengan la información de dimensión para cada operando de salida después de la ejecución. Para obtener más información sobre las dimensiones, consulte OutputShape .

Si una ejecución falla debido a un búfer de salida de tamaño insuficiente, el controlador debe indicar qué operandos de salida tienen un tamaño de búfer insuficiente en la lista de formas de salida y debe informar tanta información dimensional como sea posible, usando cero para las dimensiones desconocidas.

Momento

En Android 10, una aplicación puede solicitar el tiempo de ejecución si la aplicación ha especificado un solo dispositivo para usar durante el proceso de compilación. Para obtener más información, consulte MeasureTiming y detección y asignación de dispositivos . En este caso, un controlador NN HAL 1.2 debe medir la duración de la ejecución o informar UINT64_MAX (para indicar que la duración no está disponible) al ejecutar una solicitud. El controlador debe minimizar cualquier penalización de rendimiento resultante de medir la duración de la ejecución.

El controlador informa las siguientes duraciones en microsegundos en la estructura de Timing :

  • Tiempo de ejecución en el dispositivo: no incluye el tiempo de ejecución en el controlador, que se ejecuta en el procesador host.
  • Tiempo de ejecución en el controlador: incluye el tiempo de ejecución en el dispositivo.

Estas duraciones deben incluir el momento en que se suspende la ejecución, por ejemplo, cuando la ejecución ha sido reemplazada por otras tareas o cuando está esperando que un recurso esté disponible.

Cuando no se le ha pedido al controlador que mida la duración de la ejecución, o cuando hay un error de ejecución, el controlador debe informar las duraciones como UINT64_MAX . Incluso cuando se le ha pedido al controlador que mida la duración de la ejecución, puede informar UINT64_MAX para el tiempo en el dispositivo, el tiempo en el controlador o ambos. Cuando el controlador notifica ambas duraciones como un valor distinto de UINT64_MAX , el tiempo de ejecución en el controlador debe ser igual o superior al tiempo en el dispositivo.

ejecución vallada

En Android 11, NNAPI permite que las ejecuciones esperen una lista de controladores sync_fence y, opcionalmente, devuelven un objeto sync_fence , que se señala cuando se completa la ejecución. Esto reduce la sobrecarga para modelos de secuencias pequeñas y casos de uso de transmisión. La ejecución vallada también permite una interoperabilidad más eficiente con otros componentes que pueden señalar o esperar a sync_fence . Para obtener más información sobre sync_fence , consulte Marco de sincronización .

En una ejecución delimitada, el marco llama al método IPreparedModel::executeFenced para iniciar una ejecución asíncrona delimitada en un modelo preparado con un vector de delimitaciones de sincronización que esperar. Si la tarea asíncrona finaliza antes de que regrese la llamada, se puede devolver un identificador vacío para sync_fence . También se debe devolver un objeto IFencedExecutionCallback para permitir que el marco consulte el estado del error y la información de duración.

Una vez completada una ejecución, se pueden consultar los siguientes dos valores de tiempo que miden la duración de la ejecución a través IFencedExecutionCallback::getExecutionInfo .

  • timingLaunched : duración desde que se llama a executeFenced hasta que executeFenced señala el syncFence devuelto.
  • timingFenced : duración desde que se señalan todas las vallas de sincronización que espera la ejecución hasta que executeFenced señala la syncFence de sincronización devuelta.

Flujo de control

Para los dispositivos que ejecutan Android 11 o superior, la NNAPI incluye dos operaciones de flujo de control, IF y WHILE , que toman otros modelos como argumentos y los ejecutan de forma condicional ( IF ) o repetidamente ( WHILE ). Para obtener más información sobre cómo implementar esto, consulte Flujo de control .

Calidad de servicio

En Android 11, la NNAPI incluye una calidad de servicio (QoS) mejorada al permitir que una aplicación indique las prioridades relativas de sus modelos, la cantidad máxima de tiempo que se espera para preparar un modelo y la cantidad máxima de tiempo que se espera para una ejecución. a completar. Para obtener más información, consulte Calidad de servicio .

Limpiar

Cuando una aplicación termina de usar un modelo preparado, el marco libera su referencia al objeto @1.3::IPreparedModel . Cuando ya no se hace referencia al objeto IPreparedModel , se destruye automáticamente en el servicio de controlador que lo creó. Los recursos específicos del modelo se pueden reclamar en este momento en la implementación del controlador del destructor. Si el servicio de controlador desea que el objeto IPreparedModel se destruya automáticamente cuando el cliente ya no lo necesite, no debe contener ninguna referencia al objeto IPreparedModel después de que el objeto IPreparedeModel se haya devuelto a través IPreparedModelCallback::notify_1_3 .

uso de CPU

Se espera que los controladores utilicen la CPU para configurar los cálculos. Los controladores no deben usar la CPU para realizar cálculos gráficos porque eso interfiere con la capacidad del marco para asignar correctamente el trabajo. El controlador debe informar las partes que no puede manejar al marco y dejar que el marco maneje el resto.

El marco proporciona una implementación de CPU para todas las operaciones NNAPI excepto para las operaciones definidas por el proveedor. Para obtener más información, consulte Extensiones de proveedores .

Las operaciones introducidas en Android 10 (API nivel 29) solo tienen una implementación de CPU de referencia para verificar que las pruebas CTS y VTS son correctas. Las implementaciones optimizadas incluidas en los marcos de trabajo de aprendizaje automático móvil son preferibles a la implementación de CPU de NNAPI.

Funciones de utilidad

El código base de NNAPI incluye funciones de utilidad que pueden usar los servicios de controlador.

El archivo frameworks/ml/nn/common/include/Utils.h contiene una variedad de funciones de utilidad, como las que se usan para registrar y convertir entre diferentes versiones de NN HAL.

  • VLogging: VLOG es una macro contenedora del LOG de Android que solo registra el mensaje si se establece la etiqueta adecuada en la propiedad debug.nn.vlog . initVLogMask() debe llamarse antes de cualquier llamada a VLOG . La macro VLOG_IS_ON se puede usar para verificar si VLOG está habilitado actualmente, lo que permite omitir el código de registro complicado si no es necesario. El valor de la propiedad debe ser uno de los siguientes:

    • Una cadena vacía, que indica que no se debe realizar ningún registro.
    • El token 1 o all , que indica que se debe realizar todo el registro.
    • Una lista de etiquetas, delimitadas por espacios, comas o dos puntos, que indican qué registro se debe realizar. Las etiquetas son compilation , cpuexe , driver , execution , manager y model .
  • compliantWithV1_* : devuelve true si un objeto NN HAL se puede convertir al mismo tipo de una versión HAL diferente sin perder información. Por ejemplo, llamar a compliantWithV1_0 en un V1_2::Model devuelve false si el modelo incluye tipos de operación introducidos en NN HAL 1.1 o NN HAL 1.2.

  • convertToV1_* : Convierte un objeto NN HAL de una versión a otra. Se registra una advertencia si la conversión da como resultado una pérdida de información (es decir, si la nueva versión del tipo no puede representar completamente el valor).

  • Capacidades: las funciones nonExtensionOperandPerformance y de update se pueden usar para ayudar a crear el campo Capabilities::operandPerformance .

  • Consulta de propiedades de tipos: isExtensionOperandType , isExtensionOperationType , nonExtensionSizeOfData , nonExtensionOperandSizeOfData , nonExtensionOperandTypeIsScalar , tensorHasUnspecifiedDimensions .

El archivo frameworks/ml/nn/common/include/ValidateHal.h contiene funciones de utilidad para validar que un objeto NN HAL es válido según la especificación de su versión HAL.

  • validate* : Devuelve true si el objeto NN HAL es válido de acuerdo con la especificación de su versión HAL. Los tipos de OEM y los tipos de extensión no están validados. Por ejemplo, validateModel devuelve false si el modelo contiene una operación que hace referencia a un índice de operandos que no existe o una operación que no se admite en esa versión de HAL.

El archivo frameworks/ml/nn/common/include/Tracing.h contiene macros para simplificar la adición de información de seguimiento del sistema al código de redes neuronales. Para ver un ejemplo, consulte las invocaciones de macro NNTRACE_* en el controlador de ejemplo .

El archivo frameworks/ml/nn/common/include/GraphDump.h contiene una función de utilidad para volcar el contenido de un Model en forma gráfica con fines de depuración.

  • graphDump : escribe una representación del modelo en formato Graphviz ( .dot ) en la secuencia especificada (si se proporciona) o en logcat (si no se proporciona ninguna secuencia).

Validación

Para probar su implementación de NNAPI, use las pruebas VTS y CTS incluidas en el marco de trabajo de Android. VTS ejercita sus controladores directamente (sin usar el marco), mientras que CTS los ejercita indirectamente a través del marco. Estos prueban cada método API y verifican que todas las operaciones admitidas por los controladores funcionen correctamente y brinden resultados que cumplan con los requisitos de precisión.

Los requisitos de precisión en CTS y VTS para la NNAPI son los siguientes:

  • Punto flotante: abs(esperado - real) <= atol + rtol * abs(esperado); dónde:

    • Para fp32, atol = 1e-5f, rtol = 5.0f * 1.1920928955078125e-7
    • Para fp16, atol = rtol = 5.0f * 0.0009765625f
  • Quantized: off-by-one (excepto mobilenet_quantized , que tiene off-by-tres)

  • Booleano: coincidencia exacta

Una forma en que CTS prueba NNAPI es mediante la generación de gráficos pseudoaleatorios fijos que se usan para probar y comparar los resultados de ejecución de cada controlador con la implementación de referencia de NNAPI. Para controladores con NN HAL 1.2 o superior, si los resultados no cumplen con los criterios de precisión, CTS informa un error y descarga un archivo de especificación para el modelo fallido en /data/local/tmp para la depuración. Para obtener más detalles sobre los criterios de precisión, consulte TestRandomGraph.cpp y TestHarness.h .

Pruebas de fuzz

El propósito de las pruebas de fuzz es encontrar fallas, aserciones, violaciones de memoria o comportamiento general indefinido en el código bajo prueba debido a factores como entradas inesperadas. Para las pruebas de fuzzing de NNAPI, Android usa pruebas basadas en libFuzzer , que son eficientes en la fuzzing porque utilizan la cobertura de línea de casos de prueba anteriores para generar nuevas entradas aleatorias. Por ejemplo, libFuzzer favorece los casos de prueba que se ejecutan en nuevas líneas de código. Esto reduce en gran medida la cantidad de tiempo que tardan las pruebas en encontrar el código problemático.

Para realizar pruebas de fuzz para validar la implementación de su controlador, modifique frameworks/ml/nn/runtime/test/android_fuzzing/DriverFuzzTest.cpp en la utilidad de prueba libneuralnetworks_driver_fuzzer que se encuentra en AOSP para incluir su código de controlador. Para obtener más información sobre las pruebas de fuzz de NNAPI, consulte frameworks/ml/nn/runtime/test/android_fuzzing/README.md .

Seguridad

Debido a que los procesos de la aplicación se comunican directamente con el proceso de un conductor, los conductores deben validar los argumentos de las llamadas que reciben. Esta validación es verificada por VTS. El código de validación está en frameworks/ml/nn/common/include/ValidateHal.h .

Los conductores también deben asegurarse de que las aplicaciones no puedan interferir con otras aplicaciones cuando usan el mismo dispositivo.

Conjunto de pruebas de aprendizaje automático de Android

Android Machine Learning Test Suite (MLTS) es un punto de referencia NNAPI incluido en CTS y VTS para validar la precisión de modelos reales en dispositivos de proveedores. El punto de referencia evalúa la latencia y la precisión, y compara los resultados de los controladores con los resultados utilizando TF Lite ejecutándose en la CPU, para el mismo modelo y conjuntos de datos. Esto garantiza que la precisión de un controlador no sea peor que la implementación de referencia de la CPU.

Los desarrolladores de la plataforma Android también usan MLTS para evaluar la latencia y la precisión de los controladores.

El punto de referencia NNAPI se puede encontrar en dos proyectos en AOSP:

Modelos y conjuntos de datos

El benchmark NNAPI utiliza los siguientes modelos y conjuntos de datos.

  • MobileNetV1 float y u8 cuantificados en diferentes tamaños, se ejecutan en un pequeño subconjunto (1500 imágenes) de Open Images Dataset v4.
  • MobileNetV2 float y u8 cuantificados en diferentes tamaños, se ejecutan en un pequeño subconjunto (1500 imágenes) de Open Images Dataset v4.
  • Modelo acústico basado en memoria a largo plazo (LSTM) para texto a voz, ejecutado en un pequeño subconjunto del conjunto CMU Arctic.
  • Modelo acústico basado en LSTM para reconocimiento de voz automático, ejecutado en un pequeño subconjunto del conjunto de datos de LibriSpeech.

Para obtener más información, consulte platform/test/mlts/models .

Pruebas de estrés

Android Machine Learning Test Suite incluye una serie de pruebas de choque para validar la resiliencia de los controladores en condiciones de uso intensivo o en casos extremos de comportamiento de los clientes.

Todas las pruebas de choque proporcionan las siguientes características:

  • Detección de bloqueo: si el cliente NNAPI se bloquea durante una prueba, la prueba falla con el motivo de falla HANG y el conjunto de pruebas pasa a la siguiente prueba.
  • Detección de fallas del cliente NNAPI: las pruebas sobreviven a las fallas del cliente y las pruebas fallan con el motivo de falla CRASH .
  • Detección de fallas del controlador: las pruebas pueden detectar una falla del controlador que provoque una falla en una llamada NNAPI. Tenga en cuenta que puede haber bloqueos en los procesos del controlador que no provoquen una falla de NNAPI y que no provoquen que la prueba falle. Para cubrir este tipo de falla, se recomienda ejecutar el comando tail en el registro del sistema para errores o bloqueos relacionados con el controlador.
  • Orientación de todos los aceleradores disponibles: las pruebas se ejecutan en todos los controladores disponibles.

Todas las pruebas de choque tienen los siguientes cuatro resultados posibles:

  • SUCCESS : ​​Ejecución completada sin error.
  • FAILURE : Ejecución fallida. Por lo general, causado por una falla al probar un modelo, lo que indica que el controlador no pudo compilar o ejecutar el modelo.
  • HANG : el proceso de prueba dejó de responder.
  • CRASH : el proceso de prueba se estrelló.

Para obtener más información sobre las pruebas de estrés y una lista completa de las pruebas de choque, consulte platform/test/mlts/benchmark/README.txt .

Uso de MLTS

Para usar el MLTS:

  1. Conecte un dispositivo de destino a su estación de trabajo y asegúrese de que sea accesible a través de adb . Exporte la variable de entorno ANDROID_SERIAL del dispositivo de destino si hay más de un dispositivo conectado.
  2. cd en el directorio fuente de nivel superior de Android.

    source build/envsetup.sh
    lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available.
    ./test/mlts/benchmark/build_and_run_benchmark.sh
    

    Al final de una ejecución comparativa, los resultados se presentan como una página HTML y se pasan a xdg-open .

Para obtener más información, consulte platform/test/mlts/benchmark/README.txt .

Versiones HAL de redes neuronales

Esta sección describe los cambios introducidos en las versiones HAL de Android y Neural Networks.

androide 11

Android 11 presenta NN HAL 1.3, que incluye los siguientes cambios notables.

  • Compatibilidad con cuantificación firmada de 8 bits en NNAPI. Agrega el tipo de operando TENSOR_QUANT8_ASYMM_SIGNED . Los controladores con NN HAL 1.3 que admiten operaciones con cuantificación sin firmar también deben admitir las variantes firmadas de esas operaciones. Cuando se ejecutan versiones firmadas y no firmadas de la mayoría de las operaciones cuantificadas, los controladores deben producir los mismos resultados hasta un desplazamiento de 128. Hay cinco excepciones a este requisito: CAST , HASHTABLE_LOOKUP , LSH_PROJECTION , PAD_V2 y QUANTIZED_16BIT_LSTM . La operación QUANTIZED_16BIT_LSTM no admite operandos firmados y las otras cuatro operaciones admiten la cuantificación firmada pero no requieren que los resultados sean los mismos.
  • Compatibilidad con ejecuciones delimitadas en las que el marco de trabajo llama al método IPreparedModel::executeFenced para iniciar una ejecución asíncrona delimitada en un modelo preparado con un vector de delimitaciones de sincronización a la espera. Para obtener más información, consulte Ejecución delimitada .
  • Soporte para control de flujo. Agrega las operaciones IF y WHILE , que toman otros modelos como argumentos y los ejecutan condicionalmente ( IF ) o repetidamente ( WHILE ). Para obtener más información, consulte Flujo de control .
  • Calidad de servicio (QoS) mejorada, ya que las aplicaciones pueden indicar las prioridades relativas de sus modelos, la cantidad máxima de tiempo que se espera para preparar un modelo y la cantidad máxima de tiempo que se espera para que se complete una ejecución. Para obtener más información, consulte Calidad de servicio .
  • Compatibilidad con dominios de memoria que proporcionan interfaces de asignador para búferes administrados por controladores. Esto permite pasar memorias nativas del dispositivo a través de ejecuciones, suprimiendo la copia y transformación innecesaria de datos entre ejecuciones consecutivas en el mismo controlador. Para obtener más información, consulte Dominios de memoria .

androide 10

Android 10 presenta NN HAL 1.2, que incluye los siguientes cambios notables.

  • La estructura Capabilities incluye todos los tipos de datos, incluidos los tipos de datos escalares, y representa el rendimiento no relajado mediante un vector en lugar de campos con nombre.
  • Los métodos getVersionString y getType permiten que el marco recupere el tipo de dispositivo ( DeviceType ) y la información de la versión. Consulte Detección y asignación de dispositivos .
  • El método executeSynchronously se llama de forma predeterminada para realizar una ejecución de forma síncrona. El método execute_1_2 le dice al marco que realice una ejecución de forma asíncrona. Ver Ejecución .
  • El parámetro MeasureTiming para executeSynchronously de forma sincronizada, execute_1_2 y ejecutar en ráfaga especifica si el controlador medirá la duración de la ejecución. Los resultados se informan en la estructura de Timing . Consulte Temporización .
  • Soporte para ejecuciones donde uno o más operandos de salida tienen una dimensión o rango desconocido. Consulte Forma de salida .
  • Compatibilidad con extensiones de proveedores, que son colecciones de operaciones y tipos de datos definidos por proveedores. El controlador informa de las extensiones admitidas a través del método IDevice::getSupportedExtensions . Consulte Extensiones de proveedor .
  • Capacidad de un objeto de ráfaga para controlar un conjunto de ejecuciones de ráfaga mediante colas de mensajes rápidos (FMQ) para comunicarse entre la aplicación y los procesos del controlador, lo que reduce la latencia. Consulte Ejecuciones en ráfaga y colas de mensajes rápidas .
  • Compatibilidad con AHardwareBuffer para permitir que el controlador realice ejecuciones sin copiar datos. Consulte AHardwareBuffer .
  • Compatibilidad mejorada para el almacenamiento en caché de artefactos de compilación para reducir el tiempo utilizado para la compilación cuando se inicia una aplicación. Consulte Almacenamiento en caché de compilación .

Android 10 presenta los siguientes tipos de operandos y operaciones.

  • Tipos 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
  • Operaciones

    • 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 presenta actualizaciones para muchas de las operaciones existentes. Las actualizaciones están relacionadas principalmente con lo siguiente:

  • Compatibilidad con el diseño de memoria NCHW
  • Soporte para tensores con rango diferente a 4 en operaciones de normalización y softmax
  • Soporte para circunvoluciones dilatadas
  • Soporte para entradas con cuantificación mixta en ANEURALNETWORKS_CONCATENATION

La siguiente lista muestra las operaciones que se modifican en Android 10. Para obtener detalles completos de los cambios, consulte OperationCode en la documentación de referencia de 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

androide 9

NN HAL 1.1 se presenta en Android 9 e incluye los siguientes cambios notables.

  • IDevice::prepareModel_1_1 incluye un parámetro ExecutionPreference . Un conductor puede usar esto para ajustar su preparación, sabiendo que la aplicación prefiere ahorrar batería o ejecutará el modelo en llamadas sucesivas rápidas.
  • Se agregaron nueve operaciones nuevas: BATCH_TO_SPACE_ND , DIV , MEAN , PAD , SPACE_TO_BATCH_ND , SQUEEZE , STRIDED_SLICE , SUB , TRANSPOSE .
  • Una aplicación puede especificar que los cálculos flotantes de 32 bits se pueden ejecutar con precisión o rango flotante de 16 bits configurando Model.relaxComputationFloat32toFloat16 en true . La estructura Capabilities tiene el campo adicional relaxedFloat32toFloat16Performance para que el controlador pueda informar su rendimiento relajado al sistema.

androide 8.1

El Neural Networks HAL inicial (1.0) se lanzó en Android 8.1. Para obtener más información, consulte /neuralnetworks/1.0/ .