Tenemos que diseñar hardware/algoritmo ‘consciente de SW/algoritmo’ eficiente, de modo que puedan entrelazarse estrechamente para exprimir cada parte de nuestros recursos informáticos limitados. ¿Cómo deberíamos hacerlo? A continuación se muestra una metodología en evolución que puede usarse como referencia si está diseñando nuevas funciones de HW/SW para IA.
1. Identificar cargas de trabajo de IA proxy.
Para iniciar el análisis, necesitamos modelos proxy de IA y definir una lista de prioridades para investigar más a fondo. Hay varios recursos a los que puede consultar, incluidos los últimos trabajos de investigación (CVPR, Siggraph, laboratorios de investigación de grandes tecnologías) con código de fuente abierta, comentarios o solicitudes de los clientes, tendencias de la industria, etc. Filtre varios modelos representativos según su experto juicio. Este paso es crucial ya que los utilizará para diseñar su “arquitectura futura”.
2. Análisis exhaustivo de la arquitectura del modelo.
Asegúrese de investigar exhaustivamente la arquitectura del modelo para comprender su funcionalidad e innovación y dividirla en partes detalladas tanto como pueda. ¿Hay nuevos operadores que no son compatibles con la pila tecnológica actual? ¿Dónde están las capas de computación intensiva? ¿Es un modelo con mucha transferencia de datos (memoria)? ¿Cuál es el tipo de datos requerido y qué tipo de técnicas de cuantificación se pueden aplicar sin sacrificar la precisión? ¿Qué parte del modelo se puede acelerar por hardware y dónde están las posibles optimizaciones de rendimiento?
Por ejemplo, en el renderizado neuronal, el modelo requiere que tanto el renderizado como la computación (multiplicación de matrices) funcionen en paralelo; es necesario verificar si la pila de software actual admite renderizado/cómputo simultáneamente. En los LLM, el tamaño de la caché de valor clave (KV) aumenta la longitud de la secuencia de entrada, es fundamental comprender los requisitos de memoria y la posible optimización de la jerarquía de memoria/transferencia de datos para manejar una caché KV grande.
3. Habilitación de SW y creación de prototipos
Descargue el código de fuente abierta para el modelo identificado en el Paso 2 y ejecútelo en el marco de software/HW ‘destino’. Este paso no es sencillo, especialmente para modelos nuevos/disruptivos. Como el objetivo es habilitar una solución viable para el análisis de rendimiento, no es necesario entregar un código de calidad del producto en esta etapa. Es aceptable realizar una corrección sucia en SW sin ajustar el rendimiento para continuar con el Paso 4. Un paso importante es convertir el modelo previamente entrenado en el marco de desarrollo (Pytorch) a un nuevo formato requerido por el nuevo marco de destino.
torch.onnx.export(model,
dummy_input,
"resnet50.onnx",
verbose=False,
input_names=input_names,
outputnames=output_names,
export_params=True)
Sin embargo, a menudo hay casos en los que se requiere un importante esfuerzo de apoyo. Por ejemplo, para ejecutar modelos de renderizado diferenciables, es necesario admitir la autograduación. Es muy probable que esta característica no esté lista en el nuevo marco y requiera meses de esfuerzo por parte del equipo de desarrollo. Otro ejemplo es la cuantificación GPTQ para LLM, que inicialmente podría no ser compatible con el marco de inferencia. En lugar de esperar al equipo de ingeniería, los arquitectos pueden ejecutar la carga de trabajo en el sistema Nvidia para realizar análisis de rendimiento, ya que Nvidia es el hardware elegido para el desarrollo académico. Esto permite desarrollar una lista de requisitos de SW basada en las brechas observadas durante la habilitación de SW.
4. Análisis de prestaciones e innovación arquitectónica.
Existen numerosas métricas para juzgar el rendimiento de un modelo de IA. A continuación se detallan los principales que debemos considerar.
4.1 fracasos (Operaciones de coma flotante) y MAC (Operaciones Multiplicar-Acumular).
Estas métricas se utilizan comúnmente para calcular la complejidad computacional de los modelos de aprendizaje profundo. Proporcionan una forma rápida y sencilla de comprender la cantidad de operaciones aritméticas necesarias. Los FLOP se pueden calcular mediante métodos como análisis en papel, informes de Vtune o herramientas como flops-counter.pytorch y pytorch-OpCounter.
4.2 Huella de memoria y ancho de banda (BW)
La huella de memoria consiste principalmente en pesos (parámetros de red) y datos de entrada. Por ejemplo, un modelo Llama con parámetros 13B en FP16 consume alrededor de 13*2 (FP16=2 bytes) = 26 GB de memoria (la entrada es insignificante ya que el peso ocupa mucho más espacio). Otro factor clave para los LLM es el tamaño de la caché de KV. La caché KV ocupa hasta el 30% de la memoria total y es dinámica (consulte la imagen en el Paso 2). Los modelos grandes suelen estar vinculados a la memoria, ya que la velocidad depende de la rapidez con la que se mueven los datos de la memoria del sistema a la memoria local, o de la memoria local a los cachés/registros locales. La memoria disponible BW es mucho mejor para predecir la latencia de inferencia (tiempo de generación de tokens para LLM) que los TOPS de cálculo máximo. Un indicador de rendimiento es la utilización del ancho de banda de la memoria (MBU), que se define como BW real/BW máximo. Idealmente, una MBU cercana al 100% indica que la memoria BW está totalmente utilizada.
¡Suficiente memoria no es suficiente!
Como la memoria es un cuello de botella, se requiere exploración en tecnologías avanzadas de compresión de modelos y memoria/almacenamiento en caché. A continuación se enumeran algunos trabajos pioneros:
- MemGPT: utiliza recursos de jerarquía de memoria de diferentes niveles, como una combinación de RAM rápida y pequeña, y memoria de almacenamiento grande y lenta. La información debe transferirse explícitamente entre ellos. [2]
- Cuantización de baja precisión (GPTQ, AWQ, GGML) para reducir la huella de memoria de los modelos
- Computación en memoria (PIM): reduzca la energía y mejore el rendimiento al eliminar la necesidad de movimiento de datos.
4.3 Latencia/rendimiento.
En visión por computadora, la latencia es el tiempo para generar un cuadro. En el contexto de los LLM, es el tiempo entre el primer token y la siguiente generación del token. El rendimiento es la cantidad de tokens/cuadros por segundo. La latencia es una métrica crítica para medir el rendimiento del sistema de IA y es un factor compuesto del rendimiento tanto del SW como del HW. Hay varias estrategias de optimización a considerar, por nombrar algunas a continuación:
- Optimización de operaciones con ancho de banda restringido, como normalizaciones, operaciones puntuales, SoftMax y ReLU. Se estima que la normalización y las operaciones puntuales consumen casi un 40% más de tiempo de ejecución que las multiplicaciones de matrices, mientras que solo logran 250 y 700 veces menos FLOPS que las multiplicaciones de matrices, respectivamente. Para resolver el problema, se puede utilizar la fusión del kernel para fusionar múltiples operadores y ahorrar costos de transferencia de datos o reemplazar operadores costosos (softmax) por operadores livianos (ReLU).
- Arquitectura HW especializada. La integración de hardware especializado (AVX, GPU, TPU, NPU) puede generar importantes aceleraciones y ahorros de energía, lo cual es particularmente importante para aplicaciones que requieren procesamiento en tiempo real en dispositivos con recursos limitados. Por ejemplo, las instrucciones Intel AVX pueden generar hasta 60.000 veces más velocidad que el código Python nativo.
Los núcleos tensoriales en gráficos Nvidia (V100, A100, H100, etc.) pueden multiplicar y sumar dos matrices FP16 y/o FP32 en un ciclo de reloj, en comparación con los núcleos Cuda que solo pueden realizar 1 operación por ciclo. Sin embargo, la utilización del núcleo tensorial es muy baja (3% – 9% para el entrenamiento de un extremo a otro), lo que genera un alto costo de energía y un bajo rendimiento. Existe una investigación activa sobre cómo mejorar la utilización de la matriz sistólica (FlexSA, SA multidireccional, etc.) que escribiré en la próxima serie de publicaciones.
Además, como la memoria y el tráfico de datos son siempre un cuello de botella para los grandes modelos de IA, es crucial explorar una arquitectura avanzada que considere una memoria en chip más grande y más eficiente. Un ejemplo es el diseño de memoria central de Cerebras, donde la memoria se direcciona de forma independiente por núcleo.
- Hay muchas otras optimizaciones: paralelismo, cuantificación de caché KV para LLM, activación dispersa y optimización de extremo a extremo. Explicaré más en próximas publicaciones.
4.4 Potencia y eficiencia energética
El poder es otra bestia que debemos considerar, especialmente para escenarios de usuarios de bajo consumo. Siempre es una compensación entre rendimiento y potencia. Como se ilustra a continuación, la operación de acceso a la memoria requiere un par de órdenes de magnitud más de energía que las operaciones de cálculo. Es muy necesaria la reducción de la transferencia de memoria para ahorrar energía.