Usar unidades de procesamiento gráfico (GPU) para ejecutar tus modelos de aprendizaje automático (AA) puede mejorar drásticamente el rendimiento del modelo y la experiencia del usuario de tus aplicaciones habilitadas para AA. LiteRT permite el uso de GPU y otros procesadores especializados a través de un controlador de hardware llamado delegados. Habilita el uso de GPU con tu AA de LiteRT aplicaciones puede proporcionar los siguientes beneficios:
- Velocidad: Las GPU están diseñadas para una alta capacidad de procesamiento de procesamiento paralelo masivo de las cargas de trabajo. Este diseño los hace muy adecuados para redes neuronales profundas, consta de una gran cantidad de operadores, cada uno de los cuales trabaja en tensores de entrada que pueden procesarse en paralelo, lo que suele dar como resultado una menor latencia. En la mejor situación, ejecutar tu modelo en una GPU puede ejecutarse lo suficientemente rápido como para habilitar aplicaciones en tiempo real que antes no eran posibles.
- Eficiencia de energía: las GPU realizan cálculos de AA de un modo muy eficiente y optimizada, generalmente se consume menos energía y genera menos que la misma tarea que se ejecuta en CPU.
En este documento, se proporciona una descripción general de la compatibilidad de las GPU con LiteRT, y algunas usos avanzados de los procesadores de GPU. Para obtener información más específica sobre para implementar la compatibilidad con GPU en plataformas específicas, consulta las siguientes guías:
Asistencia de operaciones de AA de GPU
Existen algunas limitaciones a lo que las ops o operaciones del AA de TensorFlow pueden ser que acelera el delegado de GPU de LiteRT. El delegado admite el las siguientes operaciones con precisión de número de punto 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 son compatibles con la versión 1. Habilitar la cuantización support habilita las versiones adecuadas, por ejemplo, ADD versión 2.
Solución de problemas de compatibilidad con GPU
Si el delegado de la GPU no admite algunas operaciones, el framework ejecutar solo una parte del grafo en la GPU y la parte restante en la CPU. Venc. con el alto costo de la sincronización de CPU/GPU, un modo de ejecución dividida como este suele generar un rendimiento más lento que cuando se ejecuta toda la red en la CPU sola. En este caso, la aplicación genera una advertencia, como la siguiente:
WARNING: op code #42 cannot be handled by this delegate.
No se realiza ninguna devolución de llamada para fallas de este tipo, ya que no se trata de una operación una falla en el entorno de ejecución. Cuando pruebes la ejecución de tu modelo con el delegado de GPU, debes estar atento a estas advertencias. Un alto número de estas advertencias puede Indicar que tu modelo no es la mejor opción para la aceleración de GPU puede requerir la refactorización del modelo.
Modelos de ejemplo
Los siguientes modelos de ejemplo están diseñados para aprovechar la aceleración de GPU con LiteRT y se proporcionan como referencia y pruebas:
- Imagen de MobileNet v1 (224 x 224)
y la clasificación,
- Un modelo de clasificación de imágenes diseñado para dispositivos móviles e incorporados de visión de la nube. (modelo)
- Segmentación de DeepLab
(257 × 257)
- de segmentación de imágenes que asigna etiquetas semánticas, como un perro, gato o auto, a cada píxel de la imagen de entrada. (modelo)
- Objeto SSD de MobileNet
detección
- Un modelo de clasificación de imágenes que detecta varios objetos con cuadros delimitadores. (modelo)
- PoseNet para posar
estimada
- Un modelo de visión que estima las poses de las personas en imágenes o video. (modelo)
Optimización para GPU
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 un costo elevado para la GPU en dispositivos móviles. Las operaciones de cambio de forma son particularmente costosos de ejecutar, incluidos
BATCH_TO_SPACE
,SPACE_TO_BATCH
,SPACE_TO_DEPTH
, etcétera. Debes examinar minuciosamente el uso del redimensionamiento las operaciones y considerar que puede haberse aplicado solo para la exploración de datos o para las primeras iteraciones de tu modelo. Quitarlas puede afectar significativamente mejorar el rendimiento.Canales de datos de imágenes: 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]
realiza un cálculo mismo en un tensor de forma[B,H,W,8]
, pero mucho peor que[B,H,W,4]
Si el hardware de cámara que estás utilizando admite marcos de imagen en RGBA, ingresar esa entrada de 4 canales es mucho 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, se recomienda considerar volver a entrenar tu 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 consumo de energía mediante las funciones de hardware móvil.
Compatibilidad avanzada con GPU
Puedes usar técnicas adicionales y avanzadas con el procesamiento de GPU para permitir incluso un mejor rendimiento de los modelos, incluidas la cuantizació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 la GPU acelera los modelos cuantificados 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 completos posterior al entrenamiento
Para optimizar el rendimiento, usa modelos que tengan entrada de punto flotante y tensores de salida.
¿Cómo funciona?
Dado que el backend de la GPU solo es compatible con la ejecución de punto flotante, ejecutamos modelos mediante una "vista de punto flotante" del modelo original. En un alto nivel, esto implica los siguientes pasos:
Los tensores constantes (como los pesos o sesgos) se descuantizan una vez en la Memoria de GPU. Esta operación ocurre cuando el delegado se habilita para LiteRT.
Las entradas y salidas del programa de la GPU, si están cuantificadas en 8 bits, son descuantizar y cuantificar (respectivamente) para cada inferencia. Esta operación se realiza en la CPU con kernels optimizados de LiteRT.
Los simuladores de cuantización se insertan entre las operaciones para imitar los modelos cuantizados el comportamiento de los usuarios. Este enfoque es necesario para los modelos en los que las operaciones esperan activaciones. para seguir los límites aprendidos durante la cuantización.
Para obtener información sobre cómo habilitar esta función con el delegado de la GPU, consulta la lo siguiente:
Reduce el tiempo de inicialización con la serialización
La función de delegado de GPU te permite realizar cargas desde código de kernel compilado previamente y datos del modelo serializados y guardados en un disco a partir de ejecuciones anteriores. Con este enfoque, se evita volver a compilar y puede reducir el tiempo de inicio hasta en un 90%. Esta mejora es Se logra intercambiando espacio en el disco por un 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 de implementación:
- Almacena los datos de serialización en un directorio al que no puedan acceder
de Google Chat. En dispositivos Android, usa
getCodeCacheDir()
que apunta a una ubicación privada para la aplicación actual. - El token de modelo debe ser único para el dispositivo correspondiente al modelo específico. Puedes
procesar un token de modelo generando una huella digital a partir de los datos del modelo usando
bibliotecas como
farmhash::Fingerprint64