Por Simon Gonzalez de Cruz (el build en público en X @KyaniteLabs_), con GLM-5.3. Noche 2 de las notas de lab. Anoche cerré con una promesa: correr el A/B pareado de q4_0-KV que nos faltaba. Esto es lo que volvió.
El número primero: el campeón ahora corre cache KV de 4 bits — como 47% menos memoria KV (4.3GB ahorrados) en la misma ventana de contexto — con cero costo medido de accuracy y cero flags de corrupción. El gate de promoción fue pareado, pre-registrado y auto-ejecutable: si el brazo q4 empataba los hits de aguja de q8 y no disparaba tripwires, el unit file voltea; si no, el campeón viejo se restaura solo.
La pila de evidencia
Tres capas, cada una pareada:
| Capa | Diseño | Resultado |
|---|---|---|
| Accuracy de tarea | GSM8K, n=60 estratificado, pareado | McNemar exacto p = 1.0; q4 un poco más rápido (18,78 s vs 19,47 s de media) |
| Integridad a contexto profundo | Agujas al 50%/90% de profundidad, misma pila de ~198k tokens, misma semilla, control en la misma sesión | q4: 0/2 hits, cero tripwires, stops limpios; q8: 0/2 hits, un trip |
| Frontera de retrieval | Aguja al 25% (donde q8 históricamente recupera) | FOUND, stop limpio — la frontera de la zona tonta no se movió |
El tripwire es el contador de anomalías de finish_reason que dejamos armado en cada hora de serving desde que corrió el reporte de corrupción de KV cuantizado en RDNA4. Un trip disparó en toda la noche — en el brazo q8 (una respuesta de 40 tokens que nunca paró; n=1, rambling de contexto profundo, anotado, no interpretado). El brazo que la regla de verdad gatea — q4 — salió limpio.
El miss que nos cachamos a nosotros
La pila del gate se armó con un estimado: 5.800 párrafos, ~45 tokens cada uno, dile 262k. El contador del server dijo 198.227 tokens. La comparación pareada no se toca — los dos brazos prefilleron la misma pila, que es todo el punto de parear — pero cada sitio donde habíamos escrito «agujas a 262k» estaba inflando el instrumento. El tweet de anuncio ya había salido con el estimado. La corrección salió de reply en menos de una hora, el README del repo ahora carga conteos del server, y la regla queda: etiqueta el instrumento con el contador de la fuente, no con el estimado del generador. Prefill frío medido por esa pared de aguja: 109,5 tok/s a ~198k (número clase aguja: prompt completo + respuesta, no un harness de bench).
Qué te compra medio cache
Aritmética, etiquetada como aritmética: q8_0 mete ~8,5 bits por valor KV, q4_0 ~4,5 — de ahí ~47% (4.3GB ahorrados) menos en la línea KV a contexto idéntico. El wall time medido en las sondas fue para el mismo lado que GSM8K: q4 un filo más rápido en lecturas de cache. Lo que se acumula viene después: la matemática del ensayo 35B (ahí el headroom de KV decide si cabe), y el lane de KV adaptativo, cuya barra se acaba de mover de «gana al q8 estático» a «gana al q4 estático».
Condiciones
GMKtec EVO-X2 (Ryzen AI Max+ 395, 96GB unificados), Qwen3.8-27B Q4 dynamic quant, llama.cpp ROCm, ventana 262.144 tokens, K+V q4_0 KV (campeón desde 2026-08-18 10:32Z), temperature 0. GSM8K n=60 pareado; aguja n=2 estaciones por brazo más una sonda de frontera; una caja, una noche; tripwire armado todo el tiempo. Datapoints, no leyes. Log del gate y unit de rollback en el repo: qwen38-27b-strix-halo.