Prácticas recomendadas: Inferencia de IA en Cloud Run con GPU

En esta página, se proporcionan prácticas recomendadas para optimizar el rendimiento cuando se usa un servicio de Cloud Run con una GPU para la inferencia de IA, con enfoque en los modelos de lenguaje grande (LLM).

Debes compilar e implementar un servicio de Cloud Run que pueda responder en tiempo real a los eventos de escalamiento. Esto significa que debes hacer lo siguiente:

  • Usa modelos que se carguen rápido y requieran una transformación mínima en estructuras preparadas para GPU, y optimiza la forma en que se cargan.
  • Usa configuraciones que permitan una ejecución máxima, eficiente y simultánea para reducir la cantidad de GPUs necesarias para entregar una solicitud objetivo por segundo y, al mismo tiempo, mantener bajos los costos.

Formas recomendadas de cargar modelos de AA grandes en Cloud Run

Google recomienda almacenar los modelos de IA dentro de imágenes de contenedores o optimizar su carga desde Cloud Storage.

Ventajas y desventajas de almacenar y cargar modelos de AA

Esta es una comparación de las opciones:

Ubicación del modelo Tiempo de implementación Experiencia de desarrollo Tiempo de inicio del contenedor Costo de almacenamiento
Imagen de contenedor Lenta Una imagen que contiene un modelo grande tardará más en importarse a Cloud Run. Los cambios en la imagen del contenedor requerirán una nueva implementación, que puede ser lenta para las imágenes grandes. Depende del tamaño del modelo. Para modelos muy grandes, usa Cloud Storage para obtener un rendimiento más predecible, pero más lento. Es posible que haya varias copias en Artifact Registry.
Cloud Storage, cargado con la activación de volumen de Cloud Storage FUSE Rápido. Se descargó el modelo durante el inicio del contenedor. No es difícil de configurar y no requiere cambios en la imagen de Docker. Es rápida cuando se realizan optimizaciones de red. No paraleliza la descarga. Una copia en Cloud Storage
Cloud Storage, descargado de forma simultánea con el comando gcloud storage cp de Google Cloud CLI o la API de Cloud Storage, como se muestra en el muestra de código de descarga simultánea del administrador de transferencias Rápido. Se descargó el modelo durante el inicio del contenedor. Es un poco más difícil de configurar, ya que deberás instalar Google Cloud CLI en la imagen o actualizar tu código para usar la API de Cloud Storage. Es rápida cuando se realizan optimizaciones de red. Google Cloud CLI descarga el archivo del modelo en paralelo, lo que lo hace más rápido que la activación de FUSE. Una copia en Cloud Storage
Internet Rápido. Se descargó el modelo durante el inicio del contenedor. Por lo general, son más simples (muchos frameworks descargan modelos de repositorios centrales). Por lo general, es deficiente y poco predecible:
  • Los frameworks pueden aplicar transformaciones de modelos durante la inicialización. (debes hacerlo en el tiempo de compilación).
  • Es posible que el host y las bibliotecas del modelo para descargarlo no sean eficientes.
  • Existe un riesgo de confiabilidad asociado con la descarga de Internet. Es posible que tu servicio no se inicie si el destino de descarga no está disponible y que el modelo subyacente que se descargó cambie, lo que disminuirá la calidad. Te recomendamos que lo alojes en tu propio bucket de Cloud Storage.
Depende del proveedor de hosting de modelos.

Almacena modelos en imágenes de contenedor

El almacenamiento de modelos de AA en imágenes de contenedor implementadas en Cloud Run se beneficia de las optimizaciones integradas de transmisión de imágenes de contenedor de Cloud Run, lo que maximiza el tiempo de carga de archivos sin optimizaciones de red adicionales.

La compilación de contenedores que incluyen modelos de AA puede tardar un poco. Si usas Cloud Build, puedes configurarlo para que use máquinas más grandes para compilaciones más rápidas. Para ello, compila una imagen con un archivo de configuración de compilación que tenga los siguientes pasos:

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'IMAGE', '.']
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'IMAGE']
images:
- IMAGE
options:
 machineType: 'E2_HIGHCPU_32'
 diskSizeGb: '500'
 

Puede crear una copia de modelo por imagen si la capa que contiene el modelo es distinta entre las imágenes (hash diferente). Podría haber un costo adicional de Artifact Registry, ya que podría haber una copia del modelo por imagen si la capa del modelo es única en cada imagen.

Almacena modelos en Cloud Storage

Para optimizar la carga de modelos de IA cuando se cargan desde Cloud Storage, ya sea con activaciones de volumen de Cloud Storage o directamente con la API de Cloud Storage o la línea de comandos, debes usar VPC directa con el valor de configuración de salida establecido en all-traffic, junto con Private Service Connect.

Consideraciones de diseño del sistema, compilación, implementación y entorno de ejecución

En las siguientes secciones, se describen las consideraciones para la compilación, la implementación, el entorno de ejecución y el diseño del sistema.

En el tiempo de compilación

En la siguiente lista, se muestran las consideraciones que debes tener en cuenta cuando planifiques tu compilación:

  • Elige una buena imagen base. Debes comenzar con una imagen de los contenedores de aprendizaje profundo o del registro de contenedores de NVIDIA para el framework de IA que usas. Estas imágenes tienen instalados los paquetes relacionados con el rendimiento más recientes. No recomendamos crear una imagen personalizada.
  • Elige modelos cuantificados de 4 bits para maximizar la simultaneidad, a menos que puedas demostrar que afectan la calidad de los resultados. La cuantificación produce modelos más pequeños y rápidos, lo que reduce la cantidad de memoria de GPU necesaria para entregar el modelo y puede aumentar el paralelismo durante el tiempo de ejecución. Idealmente, los modelos deberían entrenarse en la profundidad de bits objetivo en lugar de cuantificarse hasta ella.
  • Elige un formato de modelo con tiempos de carga rápidos para minimizar el tiempo de inicio del contenedor, como GGUF. Estos formatos reflejan con mayor precisión el tipo de cuantificación objetivo y requieren menos transformaciones cuando se cargan en la GPU. Por motivos de seguridad, no uses puntos de control en formato pickle.
  • Crea y activa las cachés de LLM en el tiempo de compilación. Inicia el LLM en la máquina de compilación mientras compilas la imagen de Docker. Habilita el almacenamiento en caché de instrucciones y alimenta instrucciones comunes o de ejemplo para ayudar a activar la caché para el uso real. Guarda los resultados que genera para que se carguen durante el tiempo de ejecución.
  • Guarda tu propio modelo de inferencia que generas durante el tiempo de compilación. Esto ahorra tiempo significativo en comparación con la carga de modelos almacenados de manera menos eficiente y la aplicación de transformaciones, como la cuantificación, al inicio del contenedor.

Durante la implementación

  1. Asegúrate de configurar la simultaneidad del servicio con precisión en Cloud Run.
  2. Ajusta los sondeos de inicio según tu configuración.

Los sondeos de inicio determinan si el contenedor se inició y está listo para aceptar tráfico. Ten en cuenta estos puntos clave cuando configures sondeos de inicio:

  • Tiempo de inicio adecuado: Permite que el contenedor, incluidos los modelos, tenga tiempo suficiente para inicializarse y cargarse por completo.
  • Verificación de preparación del modelo: Configura el sondeo para que se apruebe solo cuando la aplicación esté lista para entregar solicitudes. La mayoría de los motores de entrega logran esto automáticamente cuando el modelo se carga en la memoria de la GPU, lo que evita solicitudes prematuras.

Ten en cuenta que Ollama puede abrir un puerto TCP antes de que se cargue un modelo. Para solucionar este problema, siga estos pasos:

  • Carga previa de modelos: Consulta la documentación de Ollama para obtener orientación sobre cómo cargar previamente tu modelo durante el inicio.

En el tiempo de ejecución.

  • Administra de forma activa la longitud de contexto compatible. Cuanto más pequeña sea la ventana de contexto que admitas, más consultas podrás ejecutar en paralelo. Los detalles para hacerlo dependen del framework.
  • Usa las cachés de LLM que generaste en el tiempo de compilación. Proporciona las mismas marcas que usaste durante el tiempo de compilación cuando generaste la consigna y la caché de prefijos.
  • Carga desde el modelo guardado que acabas de escribir. Consulta Comparación entre el almacenamiento y la carga de modelos para ver cómo cargar el modelo.
  • Considera usar una caché de pares clave-valor cuantificada si tu framework la admite. Esto puede reducir los requisitos de memoria por consulta y permite configurar más paralelismo. Sin embargo, también puede afectar la calidad.
  • Ajusta la cantidad de memoria de la GPU que se reservará para los pesos del modelo, las activaciones y las cachés de par clave-valor. Establece el valor lo más alto posible sin obtener un error de memoria insuficiente.
  • Configura la simultaneidad correctamente en el código de tu servicio. Asegúrate de que el código del servicio esté configurado para funcionar con la configuración de simultaneidad de tu servicio de Cloud Run.
  • Verifica si tu framework tiene alguna opción para mejorar el rendimiento de inicio del contenedor (por ejemplo, usando la paralelización de carga de modelos).

A nivel del diseño del sistema

  • Agrega cachés semánticas cuando corresponda. En algunos casos, almacenar en caché consultas y respuestas completas puede ser una excelente manera de limitar el costo de las consultas comunes.
  • Controla la variación en tus preámbulos. Las cachés de instrucciones solo son útiles cuando contienen las instrucciones en secuencia. Las cachés se almacenan en caché de prefijo de manera efectiva. Las inserciones o ediciones en la secuencia significan que no están almacenadas en caché o solo están presentes de forma parcial.

Ajuste de escala automático y GPUs

Cloud Run escala automáticamente la cantidad de instancias de cada revisión en función de factores como el uso de CPU y la simultaneidad de solicitudes. Sin embargo, Cloud Run no escala automáticamente la cantidad de instancias según la utilización de GPU.

En el caso de una revisión con una GPU, si no tiene un uso significativo de la CPU, Cloud Run escala horizontalmente para la simultaneidad de solicitudes. Para lograr un escalamiento óptimo de la simultaneidad de solicitudes, debes establecer una cantidad máxima óptima de solicitudes simultáneas por instancia, como se describe en la siguiente sección.

Cantidad máxima de solicitudes simultáneas por instancia

La configuración de solicitudes simultáneas máximas por instancia controla la cantidad máxima de solicitudes que Cloud Run envía a una sola instancia a la vez. Debes ajustar la simultaneidad para que coincida con la simultaneidad máxima que el código dentro de cada instancia puede controlar con un buen rendimiento.

Cargas de trabajo de IA y simultaneidad máxima

Cuando se ejecuta una carga de trabajo de inferencia de IA en una GPU en cada instancia, la simultaneidad máxima que el código puede controlar con un buen rendimiento depende de detalles específicos del framework y la implementación. La siguiente información afecta la forma en que estableces la configuración óptima de solicitudes simultáneas máximas:

  • Cantidad de instancias de modelos cargadas en la GPU
  • Cantidad de consultas paralelas por modelo
  • Uso de lotes
  • Parámetros de configuración específicos de lotes
  • Cantidad de trabajo que no es de GPU

Si la cantidad máxima de solicitudes simultáneas se establece demasiado alta, es posible que las solicitudes terminen esperando dentro de la instancia para acceder a la GPU, lo que aumenta la latencia. Si la cantidad máxima de solicitudes simultáneas se establece demasiado baja, es posible que la GPU no se use por completo, lo que provocará que Cloud Run escale horizontalmente más instancias de las necesarias.

Una regla general para configurar la cantidad máxima de solicitudes simultáneas para las cargas de trabajo de IA es la siguiente:

(Number of model instances * parallel queries per model) + (number of model instances * ideal batch size)

Por ejemplo, supongamos que una instancia carga 3 instancias de modelo en la GPU y cada instancia de modelo puede controlar 4 consultas en paralelo. El tamaño de lote ideal también es 4 porque esa es la cantidad de consultas en paralelo que puede controlar cada instancia de modelo. Siguiendo la regla general, establecerías el máximo de solicitudes simultáneas 24: (3 * 4) + (3 * 4).

Ten en cuenta que esta fórmula es solo una regla general. La configuración ideal de solicitudes simultáneas máximas depende de los detalles específicos de tu implementación. Para lograr el rendimiento óptimo real, te recomendamos que realices una prueba de carga de tu servicio con diferentes parámetros de configuración de solicitudes simultáneas máximas para evaluar qué opción tiene el mejor rendimiento.

Equilibrio entre la capacidad de procesamiento, la latencia y el costo

Consulta Comparación entre la capacidad de procesamiento, la latencia y los costos para conocer el impacto de la cantidad máxima de solicitudes simultáneas en la capacidad de procesamiento, la latencia y el costo. Ten en cuenta que todos los servicios de Cloud Run que usan GPUs siempre tienen CPU asignada.