Delegados de TensorFlow Lite

Introducción

Los delegados habilitan la aceleración de hardware de los modelos TensorFlow Lite aprovechando los aceleradores del dispositivo, como la GPU y el procesador de señal digital (DSP) .

De forma predeterminada, TensorFlow Lite utiliza núcleos de CPU optimizados para el conjunto de instrucciones ARM Neon . Sin embargo, la CPU es un procesador multipropósito que no está necesariamente optimizado para la aritmética pesada que normalmente se encuentra en los modelos de aprendizaje automático (por ejemplo, las matemáticas matriciales involucradas en la convolución y las capas densas).

Por otro lado, la mayoría de los teléfonos móviles modernos contienen chips que manejan mejor estas operaciones pesadas. Utilizarlos para operaciones de redes neuronales proporciona enormes beneficios en términos de latencia y eficiencia energética. Por ejemplo, las GPU pueden proporcionar una velocidad de latencia hasta 5 veces mayor , mientras que Qualcomm® Hexagon DSP ha demostrado reducir el consumo de energía hasta un 75 % en nuestros experimentos.

Cada uno de estos aceleradores tiene API asociadas que permiten cálculos personalizados, como OpenCL u OpenGL ES para GPU móviles y Qualcomm® Hexagon SDK para DSP. Normalmente, habría que escribir una gran cantidad de código personalizado para ejecutar una red neuronal a través de estas interfaces. Las cosas se complican aún más si se considera que cada acelerador tiene sus ventajas y desventajas y no puede ejecutar todas las operaciones en una red neuronal. La API Delegate de TensorFlow Lite resuelve este problema actuando como un puente entre el tiempo de ejecución de TFLite y estas API de nivel inferior.

tiempo de ejecución con delegados

Elegir un delegado

TensorFlow Lite admite múltiples delegados, cada uno de los cuales está optimizado para determinadas plataformas y tipos particulares de modelos. Por lo general, habrá varios delegados aplicables a su caso de uso, dependiendo de dos criterios principales: la plataforma (¿Android o iOS?) a la que se dirige y el tipo de modelo (¿punto flotante o cuantificado?) que está intentando acelerar. .

Delegados por plataforma

Multiplataforma (Android e iOS)

  • Delegado de GPU : el delegado de GPU se puede utilizar tanto en Android como en iOS. Está optimizado para ejecutar modelos basados ​​en flotantes de 32 y 16 bits donde hay una GPU disponible. También admite modelos cuantificados de 8 bits y proporciona un rendimiento de GPU a la par de sus versiones flotantes. Para obtener detalles sobre el delegado de GPU, consulte TensorFlow Lite en GPU . Para obtener tutoriales paso a paso sobre el uso del delegado de GPU con Android e iOS, consulte Tutorial del delegado de GPU de TensorFlow Lite .

Androide

  • Delegado NNAPI para dispositivos Android más nuevos : el delegado NNAPI se puede utilizar para acelerar modelos en dispositivos Android con GPU, DSP y/o NPU disponibles. Está disponible en Android 8.1 (API 27+) o superior. Para obtener una descripción general del delegado NNAPI, instrucciones paso a paso y mejores prácticas, consulte Delegado NNAPI de TensorFlow Lite .
  • Delegado de Hexagon para dispositivos Android más antiguos : el delegado de Hexagon se puede utilizar para acelerar modelos en dispositivos Android con Qualcomm Hexagon DSP. Se puede utilizar en dispositivos que ejecutan versiones anteriores de Android que no son compatibles con NNAPI. Consulte el delegado de TensorFlow Lite Hexagon para obtener más detalles.

iOS

  • Delegado de Core ML para iPhones y iPads más nuevos : para iPhones y iPads más nuevos donde Neural Engine está disponible, puede usar el delegado de Core ML para acelerar la inferencia para modelos de punto flotante de 32 o 16 bits. Neural Engine está disponible para dispositivos móviles Apple con SoC A12 o superior. Para obtener una descripción general del delegado de Core ML e instrucciones paso a paso, consulte Delegado de TensorFlow Lite Core ML .

Delegados por tipo de modelo

Cada acelerador está diseñado teniendo en cuenta un determinado ancho de bits de datos. Si proporciona un modelo de punto flotante a un delegado que solo admite operaciones cuantificadas de 8 bits (como el delegado Hexagon ), rechazará todas sus operaciones y el modelo se ejecutará completamente en la CPU. Para evitar este tipo de sorpresas, la siguiente tabla proporciona una descripción general del soporte de delegados según el tipo de modelo:

Tipo de modelo GPU NNAPI Hexágono CoreML
Punto flotante (32 bits) No
Cuantización float16 post-entrenamiento No No
Cuantización del rango dinámico post-entrenamiento No No
Cuantización de enteros post-entrenamiento No
Entrenamiento consciente de la cuantificación No

Validación del desempeño

La información de esta sección actúa como una guía aproximada para seleccionar a los delegados que podrían mejorar su solicitud. Sin embargo, es importante tener en cuenta que cada delegado tiene un conjunto predefinido de operaciones que admite y puede realizarlas de manera diferente según el modelo y el dispositivo; por ejemplo, el delegado de NNAPI puede optar por utilizar el Edge-TPU de Google en un teléfono Pixel mientras utiliza un DSP en otro dispositivo. Por lo tanto, normalmente se recomienda realizar algunas evaluaciones comparativas para evaluar qué tan útil es un delegado para sus necesidades. Esto también ayuda a justificar el aumento del tamaño binario asociado con adjuntar un delegado al tiempo de ejecución de TensorFlow Lite.

TensorFlow Lite cuenta con amplias herramientas de evaluación de precisión y rendimiento que pueden permitir a los desarrolladores tener confianza al utilizar delegados en su aplicación. Estas herramientas se analizan en la siguiente sección.

Herramientas para la evaluación

Latencia y huella de memoria

La herramienta de referencia de TensorFlow Lite se puede utilizar con parámetros adecuados para estimar el rendimiento del modelo, incluida la latencia de inferencia promedio, la sobrecarga de inicialización, la huella de memoria, etc. Esta herramienta admite múltiples indicadores para determinar la mejor configuración de delegados para su modelo. Por ejemplo, --gpu_backend=gl se puede especificar con --use_gpu para medir la ejecución de GPU con OpenGL. La lista completa de parámetros de delegados admitidos se define en la documentación detallada .

Aquí hay un ejemplo ejecutado para un modelo cuantificado con GPU a través de adb :

adb shell /data/local/tmp/benchmark_model \
  --graph=/data/local/tmp/mobilenet_v1_224_quant.tflite \
  --use_gpu=true

Puede descargar la versión prediseñadas de esta herramienta para Android, arquitectura ARM de 64 bits aquí ( más detalles ).

Precisión y corrección

Los delegados suelen realizar cálculos con una precisión diferente a la de sus homólogos de CPU. Como resultado, existe una compensación de precisión (generalmente menor) asociada con la utilización de un delegado para la aceleración de hardware. Tenga en cuenta que esto no siempre es cierto; por ejemplo, dado que la GPU utiliza precisión de punto flotante para ejecutar modelos cuantificados, podría haber una ligera mejora en la precisión (por ejemplo, <1% de mejora en el Top 5 en la clasificación de imágenes ILSVRC).

TensorFlow Lite tiene dos tipos de herramientas para medir con qué precisión se comporta un delegado para un modelo determinado: basado en tareas y independiente de tareas . Todas las herramientas descritas en esta sección admiten los parámetros de delegación avanzada utilizados por la herramienta de evaluación comparativa de la sección anterior. Tenga en cuenta que las subsecciones siguientes se centran en la evaluación del delegado (¿el delegado realiza lo mismo que la CPU?) en lugar de la evaluación del modelo (¿el modelo en sí es bueno para la tarea?).

Evaluación basada en tareas

TensorFlow Lite tiene herramientas para evaluar la corrección en dos tareas basadas en imágenes:

Los archivos binarios prediseñados de estas herramientas (Android, arquitectura ARM de 64 bits), junto con la documentación, se pueden encontrar aquí:

El siguiente ejemplo demuestra la evaluación de clasificación de imágenes con NNAPI utilizando Edge-TPU de Google en un Pixel 4:

adb shell /data/local/tmp/run_eval \
  --model_file=/data/local/tmp/mobilenet_quant_v1_224.tflite \
  --ground_truth_images_path=/data/local/tmp/ilsvrc_images \
  --ground_truth_labels=/data/local/tmp/ilsvrc_validation_labels.txt \
  --model_output_labels=/data/local/tmp/model_output_labels.txt \
  --output_file_path=/data/local/tmp/accuracy_output.txt \
  --num_images=0 # Run on all images. \
  --use_nnapi=true \
  --nnapi_accelerator_name=google-edgetpu

El resultado esperado es una lista de métricas Top-K del 1 al 10:

Top-1 Accuracy: 0.733333
Top-2 Accuracy: 0.826667
Top-3 Accuracy: 0.856667
Top-4 Accuracy: 0.87
Top-5 Accuracy: 0.89
Top-6 Accuracy: 0.903333
Top-7 Accuracy: 0.906667
Top-8 Accuracy: 0.913333
Top-9 Accuracy: 0.92
Top-10 Accuracy: 0.923333

Evaluación independiente de la tarea

Para tareas en las que no existe una herramienta de evaluación establecida en el dispositivo, o si está experimentando con modelos personalizados, TensorFlow Lite tiene la herramienta Inference Diff . (Android, arquitectura binaria ARM de 64 bits aquí )

Inference Diff compara la ejecución de TensorFlow Lite (en términos de latencia y desviación del valor de salida) en dos configuraciones:

  • Inferencia de CPU de un solo subproceso
  • Inferencia definida por el usuario: definida por estos parámetros

Para hacerlo, la herramienta genera datos gaussianos aleatorios y los pasa a través de dos intérpretes TFLite: uno que ejecuta núcleos de CPU de un solo subproceso y el otro está parametrizado por los argumentos del usuario.

Mide la latencia de ambos, así como la diferencia absoluta entre los tensores de salida de cada intérprete, por elemento.

Para un modelo con un único tensor de salida, la salida podría verse así:

Num evaluation runs: 50
Reference run latency: avg=84364.2(us), std_dev=12525(us)
Test run latency: avg=7281.64(us), std_dev=2089(us)
OutputDiff[0]: avg_error=1.96277e-05, std_dev=6.95767e-06

Lo que esto significa es que para el tensor de salida en el índice 0 , los elementos de la salida de la CPU difieren de la salida delegado en un promedio de 1.96e-05 .

Tenga en cuenta que interpretar estos números requiere un conocimiento más profundo del modelo y de lo que significa cada tensor de salida. Si se trata de una regresión simple que determina algún tipo de puntuación o incrustación, la diferencia debería ser baja (de lo contrario, es un error del delegado). Sin embargo, resultados como el de "clase de detección" de los modelos SSD son un poco más difíciles de interpretar. Por ejemplo, podría mostrar una diferencia al usar esta herramienta, pero eso puede no significar que haya algo realmente malo con el delegado: considere dos clases (falsas): "TV (ID: 10)", "Monitor (ID:20)" - Si un delegado está ligeramente fuera de la verdad dorada y muestra un monitor en lugar de un televisor, la diferencia de salida para este tensor podría ser tan alta como 20-10 = 10.