Test-time quantization: cuantizar en caliente sin dataset de calibración
Este post es la continuación natural de Quantization para inferencia LLM, que conviene leer primero: allí están GPTQ, AWQ, el scale + zero-point y por qué los outliers de activación son el problema central. Aquí no discutimos cuántos bits usar, sino cuándo y con qué información se calculan las escalas: offline contra un corpus (PTQ) o en caliente contra el tráfico real (TTQ).
TL;DR
La cuantización activation-aware (AWQ, SmoothQuant) decide qué canales proteger midiendo la magnitud de las activaciones sobre un dataset de calibración en un pase offline, antes de desplegar. El supuesto implícito es que ese corpus representa el tráfico futuro. Pero los outliers de activación —los canales de magnitud 10-100× la mediana que dominan el error de cuantización— dependen del input: cambian con el dominio, el idioma y la distribución del cliente. Cuando el tráfico real se aleja de la calibración, las escalas fijas dejan de ser óptimas y la calidad cae. Test-time quantization (TTQ) elimina el corpus y el pase offline: deriva las escalas activation-aware en tiempo de inferencia, a partir de las activaciones que realmente se observan, por token o por batch. La contrapartida es honesta y no menor: introduce overhead en runtime —calcular estadísticas, detectar outliers, recomputar escalas en cada step— que compite directamente con el ahorro de cuantizar. En modelos pequeños ese overhead pesa proporcionalmente más, porque el forward es corto y los costes fijos por step dominan (el marco está en roofline invertido para SLM). TTQ es ortogonal al formato: no es un competidor de INT4 o FP8, es una forma distinta de derivar s. Compensa cuando no hay pipeline de calibración, cuando la distribución del tráfico es cambiante o desconocida, y en multitenant donde no existe un corpus representativo.
Estás aquí: DEPLOY
La analogía: el sastre que toma medidas frente a las tallas pre-confeccionadas
Una tienda de ropa tiene dos formas de vestir a un cliente.
La primera es vender tallas pre-confeccionadas. La fábrica midió en su día a un “cliente medio” —un maniquí promedio construido sobre una muestra de población— y cortó las prendas según esas medidas. Cuando entra un cliente, le das la talla que más se le acerca. Es rapidísimo: la prenda ya está cosida, solo se entrega. El problema aparece cuando el cliente no se parece al maniquí promedio: si tiene los hombros mucho más anchos que la media —su outlier particular—, la talla estándar le tira o le sobra tela, porque se cortó protegiendo otras zonas. Esto es la PTQ offline calibrada: AWQ midió la importancia de cada canal sobre un corpus y fijó las escalas de una vez; rápido en inferencia, pero ciego al cliente concreto.
La segunda es el sastre que toma medidas en el momento. Cuando entra el cliente, el sastre saca el metro, mide a ese cliente, detecta dónde está su volumen particular y ajusta el corte a su anatomía real. El resultado encaja mejor, sobre todo en los clientes que se salen del molde. Pero cada cliente cuesta tiempo: medir, marcar, decidir. Esto es TTQ: las escalas se derivan en caliente de las activaciones que ese input genera realmente.
La analogía se sostiene en tres detalles:
- El maniquí promedio = el dataset de calibración. Si la población que entra a la tienda se parece al maniquí, las tallas funcionan; si no, fallan en los extremos.
- Tomar medidas en cada cliente = calcular estadísticas de activación por token/batch. Mejor ajuste, pero un coste fijo que se paga en cada prenda.
- Los hombros anchos = los canales outlier de activación. Son precisamente las zonas donde el ajuste importa y donde la talla genérica más se equivoca.
El sastre gana cuando los clientes son variados o desconocidos. Pierde cuando tienes una población homogénea y un maniquí que la representa bien: ahí pagar la medición en cada cliente es tirar el tiempo.
El problema que TTQ resuelve: la calibración fija envejece con el tráfico
Recordemos del post de quantization qué hacen exactamente AWQ y SmoothQuant. No cuantizan todos los canales por igual: identifican el ~1 % de canales cuyas activaciones tienen magnitud grande —los salient channels— y los protegen escalándolos antes de cuantizar. Para medir esa importancia necesitan ver activaciones, y las ven sobre un dataset de calibración (128-512 muestras, típicamente WikiText o un slice del dominio) en un pase offline previo al despliegue.
El supuesto es fuerte: que la distribución de activaciones del corpus de calibración representa la del tráfico de producción. Dos razones por las que ese supuesto se rompe:
- Los outliers de activación dependen del input. No son una propiedad fija del modelo como los pesos. El canal que es outlier procesando código C++ puede no serlo procesando árabe conversacional o JSON de logs. La magnitud y la posición de los picos cambian con el dominio, el idioma y el formato de entrada.
- El tráfico real rara vez es el corpus. Calibras con WikiText en inglés y el cliente te manda tickets de soporte en español con tablas pegadas. La calibración protegió los canales que WikiText activaba, no los que activa el tráfico real. Las escalas son subóptimas justo donde el cliente vive.
El resultado es degradación dependiente de la distribución: el modelo cuantizado mantiene la calidad mientras el input se parece a la calibración y la pierde a medida que se aleja. El caso más incómodo es el multitenant: si sirves a clientes con dominios distintos desde el mismo modelo cuantizado, no existe un único corpus representativo; cualquier calibración fija favorece a unos tenants y penaliza a otros.
El mecanismo de TTQ: medir las activaciones reales y escalar en caliente
TTQ (arXiv:2603.19296, marzo 2026) propone derivar la cuantización activation-aware en tiempo de inferencia, sin pase offline ni dataset de calibración. La idea, en su forma desnuda y conceptual:
Paso 1 — Observar. Cuando llega el tensor de activaciones X a una capa lineal (por token o por batch), se calculan estadísticas baratas sobre los canales: una medida de tendencia central (mediana o media de magnitud) y una de dispersión por canal. Esto es el equivalente a que AWQ mirase su corpus, pero hecho sobre las activaciones que de verdad están entrando ahora.
Paso 2 — Detectar outliers en caliente. Con esas estadísticas se identifican los canales cuya magnitud se dispara respecto a la mediana del tensor —el criterio típico es un umbral del estilo “magnitud > k × mediana”. Son los canales que, si se cuantizan con la misma escala que el resto, disparan el error.
Paso 3 — Derivar escalas y segregar. Para los canales normales se calcula una escala que aprovecha el rango; para los outliers se aplica un tratamiento distinto —una escala propia, o mantenerlos en precisión más alta— al estilo mixed-precision en caliente. Es la misma filosofía que LLM.int8() (segregar outliers a FP16) o AWQ (escalar salient channels), pero con el umbral y las escalas recalculados sobre el input actual, no congelados desde la calibración.
Paso 4 — Cuantizar y multiplicar. Con las escalas frescas se cuantiza y se ejecuta el GEMM. Las activaciones que entran al siguiente layer compensan el reescalado, igual que en AWQ, para que la matemática se cancele.
La diferencia clave con AWQ no está en qué se hace (proteger outliers de activación) sino en cuándo y contra qué: AWQ lo decide una vez, offline, contra un corpus; TTQ lo decide en cada step, en caliente, contra el tráfico real. Es la traslación a inferencia de la idea de “test-time”: adaptar el cómputo a la muestra concreta que tienes delante en lugar de a un promedio precomputado.
Las matemáticas que importan
El error de cuantizar un outlier con la escala equivocada
Recordemos la cuantización uniforme afín del post base: un código entero q = round(x/s) - z con escala s y zero-point z, y reconstrucción x̂ = s·(q + z). Para un cuantizador de b bits con rango simétrico, la escala que cubre un tensor de magnitud máxima M es aproximadamente s = M / (2^{b-1} - 1). El error de redondeo de cada elemento está acotado por media escala: |x - x̂| ≤ s/2.
Aquí está el problema del outlier. La escala s se elige para cubrir el valor más grande del grupo. Si un canal tiene magnitud 30× la mediana y compartes una sola escala con el resto del tensor, esa magnitud manda: M es el outlier, así que s se infla 30× respecto a lo que necesitaría la mayoría. El error absoluto de redondeo de los valores normales sube proporcionalmente.
Cuenta concreta. Tomemos un grupo donde la mediana de magnitudes es 1.0 y un canal outlier vale 30.0, cuantizado a INT4 (b = 4, niveles ±7):
- Con escala compartida,
s = 30 / 7 ≈ 4.29. El error de redondeo de un valor típico (magnitud ~1) es de hastas/2 ≈ 2.14. Es decir, el error sobre los valores normales es del orden de su propio valor: el outlier ha destruido la resolución de todo lo demás. Error relativo de un valor de magnitud 1: hasta ~214 %. - Segregando el outlier (lo sacas a FP16 o le das su propia escala) y cuantizando el resto con
M = 1,s = 1/7 ≈ 0.143. El error de un valor típico baja as/2 ≈ 0.071, ~7 % relativo. Treinta veces menos error sobre la mayoría de los pesos del grupo.
Esa es toda la razón de ser de la cuantización activation-aware: detectar y tratar aparte el ~1 % de canales que, de no segregarse, secuestran la escala. AWQ lo hace contra el corpus; TTQ lo hace contra el input real. Y si el canal que es outlier en producción no era outlier en la calibración, AWQ no lo protegió: cuantizó el tráfico real con la escala inflada del caso de arriba. Ahí TTQ gana precisión.
El overhead: el coste de medir en cada step
El precio es simétrico. Calcular las estadísticas por token —magnitudes por canal, mediana o percentil, umbral de outlier, escalas— son reducciones sobre el tensor de activación que no existían en el forward con escalas congeladas. Llamemos:
T= tiempo del forward por token con escalas fijas (PTQ estática), en µs.Δ= coste extra por token de derivar las estadísticas y escalas en caliente, en µs.
El overhead relativo es simplemente:
$$\text{overhead} = \frac{\Delta}{T}$$
La clave es que Δ es relativamente fijo por step (depende del número de canales y capas, no de cuánto trabajo “útil” haga el modelo), mientras que T escala con el tamaño del modelo. Por eso el cociente se comporta de forma muy distinta según el modelo:
- Modelo grande (p. ej. 70B):
Tes grande —cada forward mueve decenas de GB de pesos desde HBM—. SiΔ ≈ 8 µsyT ≈ 800 µs, el overhead es8/800 = 1 %. Despreciable frente al ahorro de cuantizar. - SLM (p. ej. 1B):
Tes pequeño —el forward por token es corto—. Con el mismoΔ ≈ 8 µsyT ≈ 60 µs, el overhead es8/60 ≈ 13 %. Ya no es despreciable: se come buena parte de lo que ganaste cuantizando.
Esto conecta directamente con el roofline invertido para modelos pequeños: en SLM los costes fijos por step (lanzamiento de kernels, sincronizaciones, overheads que no escalan con el modelo) pesan proporcionalmente más, porque hay menos trabajo útil entre los que repartirlos. El Δ de TTQ es exactamente uno de esos costes fijos. Per-batch en lugar de per-token amortiza Δ entre todos los tokens del batch y baja el overhead relativo, a costa de escalas menos finas; es el primer parámetro a tocar.
La conclusión incómoda: TTQ regala robustez a la distribución pero gasta parte del presupuesto de aceleración en medir, y en el régimen donde la aceleración más escasea —los SLM, los que más se despliegan en el edge— es donde ese gasto más duele. No es gratis; es un cambio de moneda.
Nota de escepticismo metodológico: arXiv:2603.19296 es de marzo de 2026, muy reciente, y a la fecha de este post no hay reproducciones independientes amplias. Las cifras de speedup y de calidad que circulen conviene tomarlas con la misma cautela que cualquier número sin metodología publicada: ¿qué hardware, qué tamaño de batch, qué
Δreal medido, contra qué baseline (PTQ bien calibrada o mal calibrada), en qué dominio? El argumento conceptual —robustez a la distribución a cambio de overhead por step— es sólido; los multiplicadores concretos, pendientes de validación.
Qué NO es TTQ: deslindando del resto del zoo
TTQ se confunde fácilmente con técnicas vecinas. La distinción que importa es que TTQ es el cómo derivas las escalas, no el formato ni el momento del entrenamiento.
| Técnica | Cuándo se fijan las escalas | Necesita corpus calibración | Toca entrenamiento | Es un formato |
|---|---|---|---|---|
| PTQ estática (GPTQ, AWQ) | Offline, antes de desplegar | Sí | No | No (usa INT4/INT8) |
| QAT | Durante el entrenamiento | No (datos de train) | Sí (re-entrena) | No |
| FP8 end-to-end | En runtime, pero escalas simples por tensor | Mínimo / ninguno | No | Sí (E4M3/E5M2) |
| TTQ | En runtime, activation-aware por token/batch | No | No | No (ortogonal al formato) |
Las cuatro distinciones, una a una:
- Frente a PTQ estática (GPTQ/AWQ). Misma meta (proteger outliers), mismo formato posible (INT4), pero PTQ congela las decisiones offline contra un corpus y TTQ las recalcula en caliente. TTQ es, en cierto sentido, “AWQ sin la fase de calibración, pagada en runtime”.
- Frente a QAT. QAT mete la cuantización dentro del bucle de entrenamiento para que el modelo aprenda a ser robusto a ella; cuesta re-entrenar. TTQ no toca el entrenamiento: opera sobre un modelo ya entrenado, en inferencia. Son ataques en momentos opuestos del pipeline.
- Frente a FP8 end-to-end. FP8 es un formato con su propio rango logarítmico; su “dynamic scaling” calcula un escalar simple por tensor en runtime, pero no hace detección activation-aware de outliers por canal. TTQ podría, conceptualmente, derivar escalas en caliente para un cuantizador FP8 o INT4: es ortogonal al formato.
- TTQ es ortogonal al formato. Decide cómo obtener
s, no en cuántos bits guardasq. Puedes imaginar “TTQ sobre INT4” o “TTQ sobre FP8”. Lo que define a TTQ es la fuente de la escala —activaciones reales en caliente— no el ancho del código.
Cuándo compensa (y cuándo no)
TTQ no es un reemplazo universal de AWQ. Es una herramienta para un perfil concreto de despliegue. Compensa cuando:
- No tienes pipeline de calibración. Quieres desplegar un modelo cuantizado ya, sin montar el dataset de calibración, ejecutar el pase offline ni validar que el corpus representa el tráfico. TTQ recorta esa fase entera: cargas el modelo y sirves.
- La distribución del tráfico es cambiante o desconocida. Un asistente que un día recibe código y otro día contratos legales en otro idioma. Ninguna calibración fija cubre bien ambos; la adaptación en caliente sigue la distribución sin re-calibrar.
- Multitenant sin corpus representativo. Sirves el mismo modelo a clientes con dominios dispares. No existe un corpus único que represente a todos; cualquier calibración fija crea ganadores y perdedores entre tenants. TTQ ajusta a cada input, sea del tenant que sea.
No compensa cuando:
- Tienes un dominio estable y un buen corpus de calibración. Si tu tráfico es homogéneo y representativo, AWQ offline te da la misma calidad con cero overhead en runtime. Pagar
Δen cada token para reaprender lo que un corpus ya capturó es desperdicio. - Sirves SLM con SLA de latencia ajustado. Es justo el caso donde
Δ/Tes alto. Si el modelo es pequeño y el TPOT importa, el overhead de medir puede borrar la ganancia de cuantizar. Mide tuΔreal antes de asumir que sale a cuenta. - El batch es grande y compute-bound. Con concurrencia alta el forward ya no está memory-bound y el coste de las reducciones extra compite peor; conviene al menos amortizar
Δper-batch.
Implicaciones en hardware on-premise
En una RTX 4090 (24 GB, Ada Lovelace)
El caso natural de la 4090 es el SLM —Qwen 3 1.5B, Llama 3 8B AWQ-INT4— sirviendo a baja concurrencia. Es precisamente el régimen donde TTQ es más arriesgado: T por token es pequeño y la 4090 no tiene FP8 nativo acelerado (lo discutimos en el post de quantization), así que las reducciones extra de TTQ corren en CUDA cores compitiendo por el mismo tiempo. Aquí la pregunta no es “¿mejora la calidad?” sino “¿el overhead me deja un TPOT aceptable?”. Si el tráfico es homogéneo, AWQ offline gana por simplicidad y latencia. TTQ solo justifica su Δ si la distribución de inputs es genuinamente impredecible y la degradación de la calibración fija es medible.
En un cluster genérico 4×H100 SXM (320 GB, NVLink, FP8 nativo)
Aquí el cálculo se invierte parcialmente. Con modelos grandes T es alto y el Δ/T baja a la zona de pocos puntos porcentuales, así que el overhead de TTQ es más digerible. El caso de uso fuerte es el multitenant: un cluster que sirve un modelo grande a clientes con dominios heterogéneos, donde no hay un corpus de calibración que contente a todos. Ahí la robustez a la distribución de TTQ tiene valor real y el overhead se diluye en un forward grande. Aun así, sobre H100 con FP8 nativo, el baseline a batir es exigente: FP8 estático casi no pierde calidad (ver tabla del post de quantization) y no cuesta nada en runtime. TTQ tiene que demostrar que su ganancia de robustez en los tenants outlier supera lo que regala en overhead. Con un paper de marzo de 2026 y sin reproducciones, esa demostración está pendiente.
Lo que no hemos cubierto
- El coste de memoria de las estadísticas en caliente: buffers por canal, su impacto en el footprint y en la presión de cache.
- Interacción con continuous batching: cómo se derivan escalas cuando un batch mezcla requests de dominios distintos en el mismo step.
- TTQ + speculative decoding: si el draft y el target derivan escalas en caliente por separado, y cómo afecta eso a la tasa de aceptación.
- Estabilidad numérica: qué pasa cuando un batch tiene un outlier extremo puntual que infla la escala de todos los tokens de ese step.
Ver también
- Quantization para inferencia LLM — la base imprescindible: scale + zero-point, GPTQ, AWQ y por qué los outliers de activación son el problema; TTQ es AWQ con las escalas derivadas en caliente en vez de offline.
- Roofline invertido para modelos pequeños — por qué los costes fijos por step pesan más en SLM; explica directamente por qué el overhead
Δde TTQ duele más en modelos pequeños. - Cuantización agresiva sub-4-bit y ternario — la frontera estática por debajo de 4 bits; complementa a TTQ, que ataca el cómo de la escala en vez del cuántos bits.
- QLoRA y multi-LoRA agresivo en SLM — adapters sobre un base cuantizado; el base podría derivar escalas en caliente mientras los adapters van en BF16.
- FP8 end-to-end: pesos, KV y calidad — el formato del datacenter Hopper/Blackwell; TTQ es ortogonal y podría derivar escalas para un cuantizador FP8.
- KV cache: la memoria de trabajo de la inferencia LLM — el KV cache también se cuantiza; sus escalas son otro candidato a derivarse en caliente por la misma lógica.
- Knowledge distillation — la otra vía para servir modelos pequeños robustos; destilar reduce el modelo, TTQ ajusta su cuantización al tráfico.
- Optimizando el decode en vLLM — donde se materializan en parámetros las palancas de cuantización en runtime para exprimir una 4090.
Referencias
- TTQ: Activation-Aware Test-Time Quantization to Accelerate LLM Inference On The Fly (marzo 2026). https://arxiv.org/abs/2603.19296
- Lin, J., Tang, J., Tang, H., Yang, S., Dang, X., Han, S. AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration (MLSys 2024). https://arxiv.org/abs/2306.00978
- Frantar, E., Ashkboos, S., Hoefler, T., Alistarh, D. GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers (ICLR 2023). https://arxiv.org/abs/2210.17323
- Xiao, G., Lin, J., Seznec, M., Wu, H., Demouth, J., Han, S. SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models (ICML 2023). https://arxiv.org/abs/2211.10438
- Dettmers, T., Lewis, M., Belkada, Y., Zettlemoyer, L. LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale (NeurIPS 2022). https://arxiv.org/abs/2208.07339