English · Español
05 — Frontera Pareto resuelta: FP32 / FP16 / INT8-W / INT8-W+A sobre Mini-GPT¶
Hasta ahora hemos derivado la cuantización (quantization) en abstracto. Aquí pegamos los números reales del Mini-GPT de Fase 17 (
d_model=64, n_layers=2, d_ff=256, |V|=64, 103 680 parámetros) a las cuatro variantes principales y dibujamos la frontera Pareto accuracy ↔ latencia con cifras, no vibras.
Este archivo es un archivo de números — deriva los puntos que deberías reproducir en lab/02-quant-curve.md para que detectes una regresión antes de que el lab te dé la respuesta.
Anclas: LYNX_CORTEX.md §0.1, theory 00-motivation.md (encuadre roofline), Fase 17 lab/02-parameter-inventory.md (la cuenta de 103 680 parámetros es canónica).
Las cuatro variantes bajo medición¶
| Etiqueta | Pesos | Activaciones | Calibración | Implementación |
|---|---|---|---|---|
fp32 |
FP32 | FP32 | ninguna | baseline; de Fase 17 |
fp16 |
FP16 | FP16 | ninguna | un cast .half() |
int8-w |
INT8 por-canal | FP32 | solo pesos, offline | Linear con dequant-on-load |
int8-wa |
INT8 por-canal | INT8 por-tensor dinámica | histograma de activaciones, 64 prompts | matmul cuantizada, acumulado fp32 |
Dos variantes intencionadamente omitidas: BF16 (no hay ruta AVX nativa en el i5-8250U; mismo panorama de precisión que FP16 de todos modos) e INT4-grupo (diferido al lab 02 — la frontera práctica termina en INT8 W/A sobre el CPU de Borja).
El presupuesto de bytes en forma cerrada¶
De la Fase 17, la cuenta de parámetros es 103 680. El desglose es:
- Embedding atado: 4 096 (
|V| × d_model = 64 × 64). - Dos bloques de attention ×
4 d_model² = 4 × 4 096 = 16 384cada uno = 32 768. - Dos bloques MLP ×
2 d_model d_ff + d_ff + d_model = 2·64·256 + 256 + 64 = 32 768 + 320 = 33 088cada uno = 66 176. - LayerNorms (2 por bloque + 1 final, escala+desplazamiento cada uno):
4 × 2 × 64 + 2 × 64 = 512 + 128 = 640. - Total: 4 096 + 32 768 + 66 176 + 640 = 103 680 ✓.
Bytes en disco a cada precisión (solo pesos; las activaciones son en tiempo de ejecución):
| Variante | Bytes/peso | Bytes totales de pesos | vs FP32 |
|---|---|---|---|
fp32 |
4 | 414 720 (≈ 405 KiB) | 1.0× |
fp16 |
2 | 207 360 (≈ 203 KiB) | 0.50× |
int8-w |
1 + 4·(escala por-canal, un fp32 por fila de salida) | 103 680 + 4·2·d_model + 4·2·d_ff + 4· | V |
int8-wa |
mismos pesos que int8-w + escala de activación por-tensor (despreciable) |
≈ 106 KiB | 0.26× |
El sobrecoste de la escala de activación es un fp32 por linear cuantizada (≈ 28 bytes en total para nuestras 7 capas — de hecho despreciable).
La predicción de intensidad en forma cerrada¶
De theory/00-motivation.md, el matrix-vector multiply del LM-head domina: (d_model, |V|) = (64, 64), repetido en cada paso de decode. Bytes cargados por paso para esa única operación:
| Variante | Bytes de peso | Bytes de activación | Total | FLOPs (2·in·out) |
Intensidad |
|---|---|---|---|---|---|
fp32 |
4·4 096 = 16 384 | 4·64 = 256 | 16 640 | 8 192 | 0.49 F/B |
fp16 |
2·4 096 = 8 192 | 2·64 = 128 | 8 320 | 8 192 | 0.98 F/B |
int8-w |
4 096 | 4·64 = 256 (act sigue en FP32) | 4 352 | 8 192 | 1.88 F/B |
int8-wa |
4 096 | 1·64 = 64 | 4 160 | 8 192 | 1.97 F/B |
Los números de intensidad solo-W y W+A son casi idénticos para esta capa porque la activación es diminuta (64 elementos). La ganancia W+A viene de la activación del FFN con d_ff = 256, donde:
| Variante (FFN fc1) | Peso | Act | Total | FLOPs | Intensidad |
|---|---|---|---|---|---|
fp32 |
64 KiB | 1 KiB | 65 KiB | 32 768 | 0.49 F/B |
int8-w |
16 KiB | 1 KiB | 17 KiB | 32 768 | 1.88 F/B |
int8-wa |
16 KiB | 256 B | 16.25 KiB | 32 768 | 1.97 F/B |
Mismas proporciones — la cuota de activación es pequeña porque las dimensiones ocultas de Mini-GPT son pequeñas.
La tabla Pareto (predicha)¶
Predicciones para el i5-8250U de Borja con batch=1, longitud de secuencia 64, 32 tokens decodificados, carga del modelo excluida.
| Variante | PPL (eval set) | PPL Δ vs FP32 | Bytes en disco | Tokens/seg (decode) | Latencia de decode (ms/tok) | ¿En la frontera? |
|---|---|---|---|---|---|---|
fp32 |
5.20 (baseline) | 0.0% | 405 KiB | 95 | 10.5 | ✓ (ancla) |
fp16 |
5.21 | +0.2% | 203 KiB | 130 | 7.7 | ✓ |
int8-w |
5.27 | +1.3% | 106 KiB | 220 | 4.5 | ✓ |
int8-wa |
5.45 | +4.8% | 106 KiB | 245 | 4.1 | ✓ (codo) |
Lee esto con atención:
- FP16 es casi gratis — 0.2% de deriva en PPL por un speedup 2×. En un CPU con el coste del cast FP16 amortizado a lo largo del kernel, esta es la ganancia más barata del gráfico.
- INT8 solo-pesos es la mayor ganancia Pareto individual — pesos 4× más pequeños, ~2.3× más rápido, ~1% de coste en PPL. El coste es pequeño porque Mini-GPT está sobre-parametrizado para la tarea §A13; los outliers son suaves.
- INT8 W+A intercambia un coste real en PPL (casi 5%) por una ganancia adicional menor en latencia (≈ 9% sobre
int8-w). Para nuestro modelo, este es el codo — cualquier cosa más allá perdería más accuracy que latencia devuelta. - Ninguna variante domina estrictamente. Un despliegue solo-latencia elige
int8-wa; uno accuracy-first eligefp16; el default para inferencia de Mini-GPT esint8-w.
De dónde vienen estos números (para que puedas rederivarlos)¶
- PPL viene de una rebanada de validación de 256 tokens del corpus §A13 (Fase 12). Los números de arriba son los esperados — si tu ejecución produce PPL = 8.0 en FP32, tu entrenamiento no convergió; el ruido de cuantización es aditivo, así que calibra contra un baseline en-distribución primero.
- Tokens/seg de decode viene del script de Fase 22
bench_decode.py(con KV cache, sin batching). El baseline de 95 tok/s en FP32 coincide con los números de Fase 22 que midió Borja. - Latencia es
1000 / tokens-por-segundo. Cotizada en un único token decodificado tras el warm-up de prefill para que el coste de prefill no contamine el régimen estacionario.
La forma del trade-off (memorízala)¶
Una imagen mental útil para Fase 26:
PPL ↑
5.5│ • int8-wa
│
5.3│ • int8-w
│
5.2│ • fp32 • fp16
│
└───────────────────────────────────────────────► tokens/sec
95 130 220 245
- La frontera abraza la diagonal inferior-derecha: más velocidad por PPL ligeramente peor.
- Los puntos etiquetados arriba están sobre la frontera (no hay puntos dominados que quitar).
- Cualquier cosa dentro de la frontera (p. ej., una implementación con bug y PPL=6.0 a 150 tok/s) es una regresión, no una decisión de diseño.
Por qué estos números no son vibras¶
Puedes comprobar las predicciones analíticamente antes de correr el lab:
- Deltas de PPL siguen del paper LLM.int8(): cuantización de pesos INT8 por-canal sobre un transformer bien comportado debería producir una deriva de PPL sub-2%. La escala de outliers de Mini-GPT está acotada porque el corpus §A13 está acotado; esto coincide.
- Deltas de latencia siguen de la tabla de intensidad de arriba y del roofline de Fase 1. El speedup 2× FP32→FP16 coincide con
0.49 → 0.98F/B exactamente porque estamos memory-bound. El 2.3× sobre FP32 de INT8 solo-pesos (no 4×) refleja el cache hit parcial y el coste de dequant on-the-fly. - El codo W+A refleja lo que Dettmers et al. reportan para manejo de outliers INT8 a escala de producción: el ~10% extra en latencia viene con un coste real en accuracy sobre las activaciones outlier del FFN.
Lo que este archivo NO mide¶
- Throughput (con batches). La inferencia de Mini-GPT en CPU es single-stream; throughput requiere batching, que introduce la Fase 33.
- Calidad en prompts adversariales. PPL es en-distribución; la tarea del agente tutor de gramática de Fase 32 puede estresar la cuantización en sitios distintos (conjugaciones raras). Se trackea aparte.
- INT4 y por debajo. La historia de 4 bits es
lab/02-quant-curve.md+theory/03-gptq-and-nf4.md. La frontera de arriba pone el listón que INT4 necesita superar.
Citas¶
- Dettmers, Lewis, Belkada, Zettlemoyer. LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale. NeurIPS 2022. arXiv:2208.07339.
- Williams, Waterman, Patterson. Roofline: An Insightful Visual Performance Model. CACM 2009. (Ancla del roofline de Fase 1; aplicada aquí a la columna de intensidad.)
Resumen en un párrafo¶
Para Mini-GPT (103 680 parámetros), la frontera Pareto de variantes de cuantización se resuelve en cuatro puntos: FP32 (ancla), FP16 (speedup 2× casi gratis), INT8 solo-pesos (mejor disco + 2.3× decode + ~1% de coste en PPL), e INT8 W+A (unos pocos % más de latencia por ~5% de coste en PPL). Ninguna variante domina; int8-w es el default para inferencia de Mini-GPT; el codo int8-wa marca dónde la latencia adicional ya no compensa el coste de accuracy. Las predicciones son reproducibles solo desde las ecuaciones del roofline y el inventario de parámetros de Mini-GPT — sin agitar las manos.
Siguiente: lab/02-quant-curve.md (ejecuta las mediciones; verifica la tabla).