El uso de unidades de procesamiento de gráficos (GPU) para ejecutar sus modelos de aprendizaje automático (ML) puede mejorar drásticamente el rendimiento de su modelo y la experiencia del usuario de sus aplicaciones habilitadas para ML. TensorFlow Lite permite el uso de GPU y otros procesadores especializados a través de un controlador de hardware llamado delegados . Habilitar el uso de GPU con sus aplicaciones TensorFlow Lite ML puede brindar los siguientes beneficios:
- Velocidad : las GPU están diseñadas para un alto rendimiento de cargas de trabajo masivamente paralelas. Este diseño los hace adecuados para redes neuronales profundas, que constan de una gran cantidad de operadores, cada uno de los cuales trabaja en tensores de entrada que pueden procesarse en paralelo, lo que generalmente resulta en una latencia más baja. En el mejor de los casos, ejecutar su modelo en una GPU puede ejecutarse lo suficientemente rápido como para habilitar aplicaciones en tiempo real que antes no eran posibles.
- Eficiencia energética : las GPU realizan cálculos de aprendizaje automático de una manera muy eficiente y optimizada, por lo general consumen menos energía y generan menos calor que la misma tarea que se ejecuta en las CPU.
Este documento proporciona una descripción general de la compatibilidad con GPU en TensorFlow Lite y algunos usos avanzados de los procesadores GPU. Para obtener información más específica sobre cómo implementar la compatibilidad con GPU en plataformas específicas, consulte las siguientes guías:
Soporte de operaciones GPU ML
Existen algunas limitaciones en cuanto a las operaciones u operaciones de TensorFlow ML que el delegado de GPU de TensorFlow Lite puede acelerar. El delegado admite las siguientes operaciones con precisión flotante de 16 y 32 bits:
-
ADD
-
AVERAGE_POOL_2D
-
CONCATENATION
-
CONV_2D
-
DEPTHWISE_CONV_2D v1-2
-
EXP
-
FULLY_CONNECTED
-
LOGICAL_AND
-
LOGISTIC
-
LSTM v2 (Basic LSTM only)
-
MAX_POOL_2D
-
MAXIMUM
-
MINIMUM
-
MUL
-
PAD
-
PRELU
-
RELU
-
RELU6
-
RESHAPE
-
RESIZE_BILINEAR v1-3
-
SOFTMAX
-
STRIDED_SLICE
-
SUB
-
TRANSPOSE_CONV
De forma predeterminada, todas las operaciones solo se admiten en la versión 1. Al habilitar el soporte de cuantificación se habilitan las versiones apropiadas, por ejemplo, ADD v2.
Solución de problemas de compatibilidad con GPU
Si algunas de las operaciones no son compatibles con el delegado de GPU, el marco solo ejecutará una parte del gráfico en la GPU y la parte restante en la CPU. Debido al alto costo de la sincronización CPU/GPU, un modo de ejecución dividida como este a menudo resulta en un rendimiento más lento que cuando toda la red se ejecuta solo en la CPU. En este caso, la aplicación genera una advertencia, como por ejemplo:
WARNING: op code #42 cannot be handled by this delegate.
No hay devolución de llamada para fallas de este tipo, ya que no se trata de una falla real en tiempo de ejecución. Al probar la ejecución de su modelo con el delegado de GPU, debe estar alerta a estas advertencias. Una gran cantidad de estas advertencias pueden indicar que su modelo no es el más adecuado para su uso con aceleración de GPU y puede requerir una refactorización del modelo.
Modelos de ejemplo
Los siguientes modelos de ejemplo están creados para aprovechar la aceleración de GPU con TensorFlow Lite y se proporcionan como referencia y prueba:
- Clasificación de imágenes MobileNet v1 (224x224) : un modelo de clasificación de imágenes diseñado para aplicaciones de visión móviles e integradas. ( modelo )
- Segmentación DeepLab (257x257) : modelo de segmentación de imágenes que asigna etiquetas semánticas, como perro, gato, automóvil, a cada píxel de la imagen de entrada. ( modelo )
- Detección de objetos MobileNet SSD : un modelo de clasificación de imágenes que detecta múltiples objetos con cuadros delimitadores. ( modelo )
- PoseNet para estimación de pose : un modelo de visión que estima las poses de personas en imágenes o videos. ( modelo )
Optimización para GPU
Las siguientes técnicas pueden ayudarle a obtener un mejor rendimiento al ejecutar modelos en hardware de GPU utilizando el delegado de GPU de TensorFlow Lite:
Operaciones de remodelación : algunas operaciones que son rápidas en una CPU pueden tener un costo elevado para la GPU en dispositivos móviles. Las operaciones de remodelación son particularmente costosas de ejecutar, incluidas
BATCH_TO_SPACE
,SPACE_TO_BATCH
,SPACE_TO_DEPTH
, etc. Debe examinar de cerca el uso de operaciones de remodelación y considerar que es posible que se hayan aplicado solo para explorar datos o para las primeras iteraciones de su modelo. Eliminarlos puede mejorar significativamente el rendimiento.Canales de datos de imagen : en la GPU, los datos del tensor se dividen en 4 canales, por lo que un cálculo en un tensor con la forma
[B,H,W,5]
se realiza aproximadamente de la misma manera en un tensor con la forma[B,H,W,8]
, pero significativamente peor que[B,H,W,4]
. Si el hardware de la cámara que está utilizando admite fotogramas de imagen en RGBA, alimentar esa entrada de 4 canales es significativamente más rápido, ya que evita una copia de memoria de RGB de 3 canales a RGBX de 4 canales.Modelos optimizados para dispositivos móviles : para obtener el mejor rendimiento, debería considerar volver a entrenar su clasificador con una arquitectura de red optimizada para dispositivos móviles. La optimización de la inferencia en el dispositivo puede reducir drásticamente la latencia y el consumo de energía aprovechando las funciones del hardware móvil.
Soporte avanzado de GPU
Puede utilizar técnicas avanzadas adicionales con el procesamiento de GPU para permitir un rendimiento aún mejor para sus modelos, incluidas la cuantificación y la serialización. Las siguientes secciones describen estas técnicas con más detalle.
Usando modelos cuantificados
Esta sección explica cómo el delegado de GPU acelera los modelos cuantificados de 8 bits, incluidos los siguientes:
- Modelos entrenados con entrenamiento consciente de la cuantificación
- Cuantización de rango dinámico posterior al entrenamiento
- Cuantización de enteros completos posterior al entrenamiento
Para optimizar el rendimiento, utilice modelos que tengan tensores de entrada y salida de punto flotante.
¿Cómo funciona esto?
Dado que el backend de la GPU solo admite la ejecución de punto flotante, ejecutamos modelos cuantificados dándole una "vista de punto flotante" del modelo original. A alto nivel, esto implica los siguientes pasos:
Los tensores constantes (como pesos/sesgos) se descuantizan una vez en la memoria de la GPU. Esta operación ocurre cuando el delegado está habilitado para TensorFlow Lite.
Las entradas y salidas del programa GPU, si están cuantificadas en 8 bits, se descuantizan y se cuantifican (respectivamente) para cada inferencia. Esta operación se realiza en la CPU utilizando los núcleos optimizados de TensorFlow Lite.
Se insertan simuladores de cuantificación entre operaciones para imitar el comportamiento cuantificado. Este enfoque es necesario para modelos en los que los operadores esperan que las activaciones sigan los límites aprendidos durante la cuantificación.
Para obtener información sobre cómo habilitar esta función con el delegado de GPU, consulte lo siguiente:
Reducir el tiempo de inicialización con serialización
La función de delegado de GPU le permite cargar desde código de kernel precompilado y datos de modelo serializados y guardados en disco de ejecuciones anteriores. Este enfoque evita la recompilación y puede reducir el tiempo de inicio hasta en un 90%. Esta mejora se logra intercambiando espacio en disco por ahorro de tiempo. Puede habilitar esta característica con algunas opciones de configuración, como se muestra en los siguientes ejemplos de código:
C++
TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default(); options.experimental_flags |= TFLITE_GPU_EXPERIMENTAL_FLAGS_ENABLE_SERIALIZATION; options.serialization_dir = kTmpDir; options.model_token = kModelToken; auto* delegate = TfLiteGpuDelegateV2Create(options); if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;
Java
GpuDelegate delegate = new GpuDelegate( new GpuDelegate.Options().setSerializationParams( /* serializationDir= */ serializationDir, /* modelToken= */ modelToken)); Interpreter.Options options = (new Interpreter.Options()).addDelegate(delegate);
Cuando utilice la función de serialización, asegúrese de que su código cumpla con estas reglas de implementación:
- Almacene los datos de serialización en un directorio al que no puedan acceder otras aplicaciones. En dispositivos Android, use
getCodeCacheDir()
que apunta a una ubicación privada para la aplicación actual. - El token del modelo debe ser exclusivo del dispositivo para el modelo específico. Puede calcular un token de modelo generando una huella digital a partir de los datos del modelo utilizando bibliotecas como
farmhash::Fingerprint64
.