Delegados de GPU para TensorFlow Lite

El uso de 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 compatibles con el AA. TensorFlow Lite permite el uso de GPU y otros procesadores especializados a través de controladores de hardware llamados delegados. Habilitar el uso de GPU con tus aplicaciones de AA de TensorFlow Lite puede brindar los siguientes beneficios:

  • Velocidad: Las GPU están diseñadas para una alta capacidad de procesamiento de cargas de trabajo masivamente paralelas. Este diseño las hace muy adecuadas para 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 dar como resultado una latencia más baja. En el mejor de los casos, ejecutar tu modelo en una GPU podría 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 una manera muy eficiente y optimizada, por lo general consumiendo menos energía y generando menos calor que la misma tarea que se ejecuta en CPU.

En este documento, se proporciona una descripción general de la compatibilidad de las GPU en TensorFlow Lite 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:

Asistencia de operaciones de AA de GPU

Existen algunas limitaciones en relación con las operaciones, o las operaciones del AA de TensorFlow, que se pueden acelerar con el delegado de la GPU de TensorFlow Lite. El delegado admite 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 compatibilidad con la cuantización habilita las versiones adecuadas, por ejemplo, ADD v2.

Solución de problemas de compatibilidad con GPU

Si el delegado de la GPU no admite algunas 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 dividida como este a menudo genera 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 la siguiente:

WARNING: op code #42 cannot be handled by this delegate.

No hay devolución de llamada para fallas de este tipo, ya que no es una falla real en el entorno de ejecución. Cuando pruebes la ejecución de tu modelo con el delegado de GPU, deberías recibir estas advertencias. Una gran cantidad de estas advertencias puede indicar que tu modelo no es la mejor opción para su uso en la aceleración de GPU y puede requerir la refactorización del modelo.

Modelos de ejemplo

Los siguientes modelos de ejemplo se crearon para aprovechar la aceleración de GPU con TensorFlow Lite y se proporcionan como referencia y pruebas:

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 TensorFlow Lite:

  • 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 con detenimiento el uso de las operaciones de cambio de forma y considerar que puede haberse aplicado solo con el objetivo de explorar datos o para las primeras iteraciones del modelo. Quitarlas puede mejorar significativamente 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] tiene un rendimiento similar en un tensor con la forma [B,H,W,8], pero mucho peor que [B,H,W,4]. Si el hardware de cámara que usas admite marcos de imagen en RGBA, ingresar esa entrada de 4 canales es mucho más rápido, ya que se evita una copia en la memoria de RGB de 3 canales a RGBX de 4 canales.

  • Modelos optimizados para dispositivos móviles: Para obtener el mejor rendimiento, considera 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 el consumo de energía gracias a las funciones de hardware móvil.

Compatibilidad avanzada con GPU

Puedes usar técnicas adicionales y avanzadas con el procesamiento de GPU para habilitar un rendimiento aún mejor para tus 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 cuantizados de 8 bits, incluidos los siguientes:

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 punto flotante, ejecutamos modelos cuantizados con una "vista de punto flotante" del modelo original. En un nivel alto, esto implica los siguientes pasos:

  • Los tensores constantes (como los pesos o sesgos) se descuantizan una vez en la memoria de la GPU. Esta operación ocurre cuando el delegado se habilita para TensorFlow Lite.

  • Las entradas y salidas del programa de GPU, si se cuantizó 8 bits, se descuantizan y cuantifican (respectivamente) para cada inferencia. Esta operación se realiza en la CPU con kernels optimizados de TensorFlow Lite.

  • 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 las operaciones esperan que las activaciones sigan 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 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ódigos de kernel precompilados y datos de modelos serializados y guardados en el disco de ejecuciones anteriores. Este enfoque evita la nueva compilación y puede reducir el tiempo de inicio hasta en un 90%. Esta mejora se logra mediante el intercambio de espacio en el 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 de modelo debe ser único para el dispositivo correspondiente al modelo específico. Para procesar un token de modelo, genera una huella digital a partir de los datos del modelo mediante bibliotecas como farmhash::Fingerprint64.