Por Simon Gonzalez de Cruz (el build en público en X @KyaniteLabs_), con GLM-5.3. Noche 1 de un cadence diario: qué corrió, qué se rompió, y qué dijeron los números.
El número primero: un tope de thinking de 512 tokens compró la misma accuracy medida que el thinking sin límite — a 7,5× más rápido. Su número sombra: sin tope, el mismo modelo se pensó hasta morirse en 26 de 50 problemas, razonando hasta que el techo de output mató la respuesta. Los dos salieron de una corrida pareada. Ninguno era la historia real de la noche. La historia real es que la primera versión de este experimento no midió nada.
El setup
La caja: un mini-PC GMKtec EVO-X2 de $1.400 (Ryzen AI Max+ 395, 96GB de memoria unificada) sirviendo Qwen3.8-27B, un denso de 27B, a su contexto nativo completo de 262.144 tokens. La pregunta de la noche del veredicto es la que todo el que sirve modelos local tarde o temprano se hace: si le pongo techo a cuánto puede pensar, ¿cuánto me cuesta en accuracy?
El instrumento
Diseño pareado. Cada problema se pregunta bajo los tres presupuestos de thinking — sin tope, 1024 tokens, 512 tokens — con el orden de celdas rotado por problema para que cualquier drift le pegue a todos los brazos igual. Cincuenta problemas, cargados hacia lo difícil (25 hard / 15 mid / 10 easy), temperature 0, traces de reasoning completos en cada fila. La estadística es McNemar exacto sobre los pares discordantes: no «cuál promedio es más alto», sino «donde los brazos no coincidieron, ¿uno ganó de forma sistemática?». Condiciones todo el rato: Q4 dynamic quant, cache KV q8_0 a 262k, build ROCm de llama.cpp, el package aguantando 90-92 °C a 120W.
El twist: el primer experimento era inválido
El brazo de control — «sin tope» — no existía. El server campeón carga un default a nivel de server, --reasoning-budget 2048, con el mensaje «Reasoning budget reached. Answer now.» Cualquier request que no manda un presupuesto explícito lo hereda callado. El primer runner no lo mandó. La celda de «no cap» era una celda 2048 con sticker de «none».
La prueba fue vergonzosamente limpia: seis largos de thinking idénticos byte a byte entre las celdas «none» y 2048; el máximo idéntico en las dos (9.361 caracteres); el mismo problema difícil cortando a 7.955 caracteres en un brazo y 7.937 en el otro. La curva archivada nunca fue {none, 2048, 4096, 8192} — era {2048, 2048, 4096, 8192}, y su «none vs 2048: cero discordantes» era una celda comparándose consigo misma.
Fixes antes del rerun: los brazos sin tope ahora mandan un override explícito de un millón de tokens; el techo de output subió de 6.000 a 12.000 tokens (el techo viejo mataba respuestas mid-think en el brazo que se llamaba uncapped — un confound de output-cap); y cada fila ahora carga su trace completo, para que la próxima autopsia lea texto en vez de inferir de conteos.
El veredicto
| Presupuesto de thinking | Accuracy (n=50) | Wall mediano por problema |
|---|---|---|
| Sin tope (override 106) | 44% | 367 s |
| 1024 tokens | 40% | — |
| 512 tokens | 40% | 49 s |
Los tres McNemar exactos pairwise no son significativos: p = 0,73 para sin-tope-vs-512, con 0,63 y 1,0 en los otros contrastes. En este benchmark, esta noche, los caps son estadísticamente gratis.
Y protectivos. La mediana de completion del brazo sin tope pegó el techo de 12.000 tokens, y en 26 de 50 problemas el thinking nunca terminó — el modelo razonó más allá del cap de output y no emitió respuesta. Esas cuentan mal (sin respuesta en caja = mal, sin excepciones). El cap no solo ahorra tiempo; fuerza una conclusión que el modelo sin tope a veces no puede alcanzar solo.
Las dos polaridades, claro: esto es un benchmark (un subset de Omni-MATH), una noche, n=50 problemas pareados. Una celda capeada mide accuracy bajo corte temprano forzado — la rodilla que vimos queda en o por encima de la rodilla real del modelo, así que léela conservadora. Y en la banda más dura (difficulty ≥ 5.0), todas las celdas marcaron 16% plano: esos problemas están atados a capacidad, no a presupuesto. Un cap no te puede quitar lo que el modelo nunca tuvo.
El sobre en el que corrió
La corrida sostuvo la caja en su filo térmico medido — 90-92 °C de package a 120W, fans al 100% — por horas de generación sostenida sin throttle. Eso ya es doctrina: este es el sobre del chasis, no un mal setting; no hay descansos rituales de cooldown (caliente-estable le gana a ciclar calor); y el lane de producto 24/7 va a llevar power cap, no el full tilt del lane de experimento.
Qué se lleva el harness
El default que ya shipped el harness — presupuesto de thinking de 1024 por margen, 512 donde importa la velocidad — se ganó su número esta noche: el gap nominal 44% vs 40% cabe dentro de lo que este diseño puede detectar, y 512 convirtió problemas de 367 segundos en problemas de 49 al mismo score. La metodología y los datos crudos están públicos al lado de este post: METHODOLOGY.md (tamaños de n, gates, reglas de grading — las filas que las tablas de bench nunca imprimen) y el JSONL pareado completo, traces en la fila, bajo results/ en el repo qwen38-27b-strix-halo.
Esta noche
La window 2 corre el lane que la comunidad ya corroboró: cache KV q4_0 a 262k de contexto. Cada fila de 262k en el mapa de hardware que minamos corre q4-KV; nosotros servimos q8 — así que esta noche es el A/B de calidad pareado que nos faltaba, más el headroom de KV que libere. Notas de lab mañana.
Condiciones: GMKtec EVO-X2 (Ryzen AI Max+ 395, 96GB unificados), Qwen3.8-27B Q4 dynamic quant, llama.cpp ROCm, contexto 262.144 tokens, cache KV q8_0, temperature 0, subset Omni-MATH cargado a dificultad (25/15/10), n=50 problemas pareados por brazo, McNemar exacto en discordantes, medido 2026-08-17/18. Un benchmark, una noche, n=50 — un datapoint, no una ley.