2 puntos por darjeeling 1 시간 전 | 1 comentarios | Compartir por WhatsApp

Comparten el proceso de reproducción y corrección de dos bugs de race condition en el KV Cache encontrados al operar un Coding Agent basado en GLM-5 a escala de cientos de millones de solicitudes, junto con optimizaciones para mejorar el throughput.

Contexto

Las leyes de escalado (Scaling Laws) no solo han impulsado innovaciones en los parámetros de los modelos y en la escala de los datos, también están llevando la ingeniería de infraestructura hasta sus límites. Z.ai llama a los efectos secundarios que surgen en este proceso Scaling Pain.

Mientras procesaban cientos de millones de cargas de trabajo complejas de Coding Agent al día con la serie GLM-5, algunos usuarios reportaron anomalías como salida corrupta (garbled output), generación repetitiva y aparición de caracteres raros. Estos problemas no se reproducían en absoluto en entornos de inferencia estándar, y solo aparecían en entornos de alta concurrencia y contexto largo.


Resumen de resultados clave

Ítem Cifra
Tasa de salidas anómalas tras aplicar Bug Fix #1 0.1% → menos de 0.03%
Mejora de throughput con LayerSplit (40K~120K tokens) +10% ~ +132%
El fix de HiCache se aportó como SGLang PR #22811

Detección de anomalías: uso de métricas de Speculative Decoding

Detectar automáticamente estas anomalías ya era, por sí mismo, un reto. Las heurísticas como expresiones regulares producían muchos falsos positivos y falsos negativos, y los clasificadores basados en modelos resultaban demasiado costosos para experimentos a gran escala.

La clave estuvo en las métricas de Speculative Decoding.

  • Salida corrupta / caracteres raros: spec_accept_length extremadamente bajo → señal de inconsistencia del estado del KV Cache entre el modelo draft y el modelo target
  • Generación repetitiva: spec_accept_rate extremadamente alto → señal de que, por un KV Cache dañado, el patrón de atención converge en un bucle repetitivo

Con base en esto implementaron una estrategia de monitoreo en línea. Si, al superar los 128 tokens generados, spec_accept_length < 1.4 o spec_accept_rate > 0.96, la generación se detiene de inmediato y el balanceador de carga delega el reintento. En otras palabras, Speculative Decoding se amplió de herramienta de optimización de rendimiento a herramienta de monitoreo en tiempo real de la calidad de salida.


Bug Fix #1: race condition del KV Cache en la arquitectura separada PD

Causa

En la arquitectura separada PD (Prefill-Decode), se opera un mecanismo de interrupción de solicitudes basado en timeout para controlar la tail latency. Si Prefill no termina dentro del tiempo establecido, el lado Decode aborta esa solicitud y recupera el KV Cache.

El problema era que la señal de abort no se transmitía correctamente al lado Prefill. Incluso después de que Decode recuperaba el KV Cache y lo reasignaba a una nueva solicitud (Req2), el RDMA write y la operación Prefill de la solicitud anterior (Req1) seguían ejecutándose, lo que provocaba que sobrescribieran el KV Cache de Req2.

Corrección

Después de emitir el abort, Decode ahora envía una notificación al lado Prefill, y Prefill fue modificado para devolver una señal de "seguro para recuperar" solo cuando se cumple una de las dos condiciones siguientes.

  1. El RDMA write aún no ha comenzado
  2. Todos los writes ya emitidos se han completado

Decode reutiliza el KV Cache solo después de recibir esta confirmación. Como resultado de la aplicación, la tasa de salidas anómalas se redujo de 0.1% → menos de 0.03%.


Bug Fix #2: falta de garantía del orden Load-Use en HiCache

Causa

La carga de trabajo del Coding Agent tiene una longitud promedio de entrada superior a 70K tokens y una alta tasa de reutilización de prefijos. Para esto operan HiCache (KV Cache jerárquico), con una estructura donde el swap-in asíncrono del KV Cache desde la memoria de CPU se superpone con la ejecución de Load Stream y Forward Stream.

El problema era que el kernel Indexer no especificaba una restricción de sincronización con la finalización de la carga del indexer cache. Si Forward Stream comenzaba a ejecutarse antes que Load Stream, se producía un patrón de read-before-ready, leyendo un KV Cache que aún no había sido cargado, lo que llevaba a salidas anómalas.

Corrección

Antes de ejecutar el kernel Indexer, se insertó un punto de sincronización explícito con Load Stream, de modo que Forward Stream solo avance con el cálculo una vez que los datos estén listos. Esta corrección fue aportada a la comunidad de SGLang como el PR #22811.


Optimización: LayerSplit (almacenamiento distribuido del KV Cache por capa)

El cuello de botella común de ambos bugs era la carga de la etapa Prefill en sí. Para mejorarlo de raíz, diseñaron e implementaron LayerSplit.

Antes, en un entorno de Context Parallelism (CP), cada GPU almacenaba de forma redundante el KV Cache de todas las capas. Con LayerSplit, cada GPU almacena de forma distribuida solo una parte de las capas, lo que reduce de manera significativa el uso de memoria por GPU.

Durante la ejecución, el CP rank que posee el KV Cache de esa capa hace broadcast del caché antes de la operación de atención. Se superpusieron el broadcast y la operación del indexer para ocultar el overhead de comunicación, y como los datos de comunicación adicionales son solo el indexer cache (aproximadamente 1/8 del tamaño del KV Cache), el overhead total es prácticamente despreciable.

Con una tasa de cache hit del 90%, el throughput para solicitudes de 40K~120K tokens mejoró entre 10% y 132%, y cuanto mayor es la longitud del contexto, mayor es la mejora.


Conclusión

> "El throughput, la latencia y la disponibilidad no son suficientes. El sistema también debe garantizar la exactitud del estado del modelo detrás de cada solicitud de generación. Las leyes de escalado empujan la capacidad, pero lo único que puede hacer que esa capacidad sea confiable a gran escala es una ingeniería de sistemas rigurosa."


Fuente: Z.ai Research Blog (2026-04-30)

1 comentarios