Usar unidades de procesamiento de gráficos (GPU) para ejecutar tus modelos de aprendizaje automático (AA) puede mejorar drásticamente el rendimiento de tu modelo y la experiencia del usuario de tus aplicaciones habilitadas para AA. LiteRT permite el uso de GPUs y otros procesadores especializados a través de un controlador de hardware llamado delegado. Habilitar el uso de GPUs con tus aplicaciones de AA de LiteRT puede proporcionar los siguientes beneficios:
- Velocidad: Las GPUs están diseñadas para un alto rendimiento de cargas de trabajo masivamente paralelas. Este diseño los hace adecuados para las redes neuronales profundas, que constan de una gran cantidad de operadores, cada uno de los cuales trabaja en tensores de entrada que se pueden procesar en paralelo, lo que suele generar una latencia más baja. En el mejor de los casos, ejecutar tu modelo en una GPU puede ser lo suficientemente rápido como para habilitar aplicaciones en tiempo real que antes no eran posibles.
- Eficiencia energética: Las GPUs realizan cálculos de AA de manera muy eficiente y optimizada, y suelen consumir menos energía y generar menos calor que la misma tarea que se ejecuta en las CPUs.
En este documento, se proporciona una descripción general de la compatibilidad con las GPUs en LiteRT y algunos usos avanzados de los procesadores de GPU. Para obtener información más específica sobre la implementación de la compatibilidad con GPU en plataformas específicas, consulta las siguientes guías:
Compatibilidad con operaciones de AA en la GPU
Existen algunas limitaciones en cuanto a qué operaciones de AA de TensorFlow, o ops, pueden acelerarse con el delegado de GPU de LiteRT. El delegado admite las siguientes operaciones con una precisión de punto flotante de 16 y 32 bits:
ADDAVERAGE_POOL_2DCONCATENATIONCONV_2DDEPTHWISE_CONV_2D v1-2EXPFULLY_CONNECTEDLOGICAL_ANDLOGISTICLSTM v2 (Basic LSTM only)MAX_POOL_2DMAXIMUMMINIMUMMULPADPRELURELURELU6RESHAPERESIZE_BILINEAR v1-3SOFTMAXSTRIDED_SLICESUBTRANSPOSE_CONV
De forma predeterminada, todas las operaciones solo se admiten en la versión 1. Habilitar la compatibilidad con la cuantificación habilita las versiones adecuadas, por ejemplo, ADD v2.
Soluciona problemas de compatibilidad con la GPU
Si el delegado de GPU no admite algunas de las operaciones, el framework solo ejecutará una parte del grafo en la GPU y la parte restante en la CPU. Debido al alto costo de la sincronización de CPU/GPU, un modo de ejecución dividido como este suele generar un rendimiento más lento que cuando toda la red se ejecuta solo en la CPU. En este caso, la aplicación genera advertencias, como las siguientes:
WARNING: op code #42 cannot be handled by this delegate.
No hay devolución de llamada para las fallas de este tipo, ya que no se trata de una falla real del tiempo de ejecución. Cuando pruebes la ejecución de tu modelo con el delegado de GPU, debes estar atento a estas advertencias. Una gran cantidad de estas advertencias puede indicar que tu modelo no es el más adecuado para usar la aceleración por GPU y es posible que requiera una refactorización.
Modelos de ejemplo
Los siguientes modelos de ejemplo se compilan para aprovechar la aceleración por GPU con LiteRT y se proporcionan como referencia y para pruebas:
- Clasificación de imágenes de MobileNet v1 (224 x 224)
- Es un modelo de clasificación de imágenes diseñado para aplicaciones de visión integradas y para dispositivos móviles.
(model)
* Segmentación de DeepLab (257 x 257)
- Modelo de segmentación de imágenes que asigna etiquetas semánticas, como perro, gato o automóvil, a cada píxel de la imagen de entrada.
(modelo)
* Detección de objetos con MobileNet SSD
- Un modelo de clasificación de imágenes que detecta múltiples objetos con cuadros de límite.
(model)
* PoseNet para la estimación de la pose
- Es un modelo de visión que estima las poses de las personas en imágenes o videos. (modelo)
- Un modelo de clasificación de imágenes que detecta múltiples objetos con cuadros de límite.
(model)
* PoseNet para la estimación de la pose
- Modelo de segmentación de imágenes que asigna etiquetas semánticas, como perro, gato o automóvil, a cada píxel de la imagen de entrada.
(modelo)
* Detección de objetos con MobileNet SSD
- Es un modelo de clasificación de imágenes diseñado para aplicaciones de visión integradas y para dispositivos móviles.
(model)
* Segmentación de DeepLab (257 x 257)
Optimización para GPUs
Las siguientes técnicas pueden ayudarte a obtener un mejor rendimiento cuando ejecutas modelos en hardware de GPU con el delegado de GPU de LiteRT:
Operaciones de cambio de forma: Algunas operaciones que son rápidas en una CPU pueden tener un costo alto para la GPU en dispositivos móviles. Las operaciones de cambio de forma son particularmente costosas de ejecutar, incluidas
BATCH_TO_SPACE,SPACE_TO_BATCH,SPACE_TO_DEPTH, etcétera. Debes examinar detenidamente el uso de las operaciones de cambio de forma y tener en cuenta que es posible que se hayan aplicado solo para explorar los datos o para las primeras iteraciones de tu modelo. Si los quitas, puedes mejorar significativamente el rendimiento.Canales de datos de imágenes: En la GPU, los datos de tensores se segmentan en 4 canales, por lo que un cálculo en un tensor con la forma
[B,H,W,5]se realiza casi igual en un tensor de forma[B,H,W,8], pero significativamente peor que[B,H,W,4]. Si el hardware de la cámara que usas admite fotogramas de imagen en RGBA, proporcionar 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, debes considerar volver a entrenar tu clasificador con una arquitectura de red optimizada para dispositivos móviles. La optimización para la inferencia en el dispositivo puede reducir drásticamente la latencia y el consumo de energía, ya que aprovecha las funciones de hardware para dispositivos móviles.
Compatibilidad avanzada con GPU
Puedes usar técnicas avanzadas adicionales con el procesamiento de GPU para lograr un rendimiento aún mejor en tus modelos, incluidas la cuantificación y la serialización. En las siguientes secciones, se describen estas técnicas con más detalle.
Usa modelos cuantizados
En esta sección, se explica cómo el delegado de GPU acelera los modelos cuantizados de 8 bits, incluidos los siguientes:
- Modelos entrenados con entrenamiento con cuantización
- Cuantización de rango dinámico posterior al entrenamiento
- Cuantización de números enteros completa posterior al entrenamiento
Para optimizar el rendimiento, usa modelos que tengan tensores de entrada y salida de punto flotante.
¿Cómo funciona?
Dado que el backend de la GPU solo admite la ejecución de números de punto flotante, ejecutamos modelos cuantificados proporcionándole una "vista de punto flotante" del modelo original. En un nivel alto, esto implica los siguientes pasos:
Los tensores constantes (como los pesos o las polarizaciones) se cuantifican una vez en la memoria de la GPU. Esta operación se realiza cuando se habilita el delegado para LiteRT.
Las entradas y salidas del programa de la GPU, si se cuantifican en 8 bits, se des cuantifican y cuantifican (respectivamente) para cada inferencia. Esta operación se realiza en la CPU con los kernels optimizados de LiteRT.
Los simuladores de cuantización se insertan entre las operaciones para imitar el comportamiento cuantizado. Este enfoque es necesario para los 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, consulta lo siguiente:
- Cómo usar modelos cuantificados con GPU en Android
- Cómo usar modelos cuantificados con GPU en iOS
Cómo reducir el tiempo de inicialización con la serialización
La función de delegado de GPU te permite cargar código de kernel precompilado y datos del modelo serializados y guardados en el 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. Puedes habilitar esta función 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 uses la función de serialización, asegúrate de que tu código cumpla con estas reglas de implementación:
- Almacena los datos de serialización en un directorio al que no puedan acceder otras apps. En dispositivos Android, usa
getCodeCacheDir(), que apunta a una ubicación privada para la aplicación actual. - El token del modelo debe ser único para el dispositivo en el modelo específico. Puedes calcular un token del modelo generando una huella digital a partir de los datos del modelo con bibliotecas como
farmhash::Fingerprint64.