GLM-5ベースのCoding Agentを数億件規模でサービス運用する中で直面した、KV Cacheのレースコンディションバグ2件の再現・修正過程と、スループット改善の最適化を共有する。
背景
スケーリング則(Scaling Laws)はモデルパラメータとデータ規模の革新をもたらしただけでなく、インフラエンジニアリングも限界まで押し進めている。Z.aiはこの過程で生じる副作用を Scaling Pain と呼ぶ。
GLM-5シリーズで複雑なCoding Agentワークロードを1日数億件処理していたところ、一部ユーザーから 壊れた出力(garbled output)、反復生成、希少文字の生成 などの異常現象が報告された。これらの問題は標準的な推論環境ではまったく再現せず、高同時実行・長文脈環境でのみ 現れた。
主要結果の要約
| 項目 | 数値 |
|---|---|
| Bug Fix #1適用後の異常出力率 | 0.1% → 0.03%未満 |
| LayerSplitのスループット改善(40K~120Kトークン) | +10% ~ +132% |
| HiCache fixはSGLang PR #22811として貢献 | ✅ |
異常現象の検知: Speculative Decoding指標の活用
異常現象を自動検知すること自体が難題だった。正規表現のようなヒューリスティックは誤検知・見逃しが多く、モデルベースの分類器は大規模実験にはコストが高すぎた。
突破口は Speculative Decodingメトリクス だった。
- 壊れた出力 / 希少文字:
spec_accept_lengthが極端に低い → draftモデルとtargetモデルのKV Cache状態不一致のシグナル - 反復生成:
spec_accept_rateが極端に高い → 破損したKV Cacheによりアテンションパターンが反復ループへ収束しているシグナル
これに基づいてオンライン監視戦略を実装した。生成トークンが128個を超えた時点で spec_accept_length < 1.4 または spec_accept_rate > 0.96 なら即座に生成を中断し、ロードバランサーにリトライを引き渡す。Speculative Decodingが 性能最適化ツールから出力品質のリアルタイム監視ツール へと拡張されたわけだ。
Bug Fix #1: PD分離アーキテクチャにおけるKV Cacheレースコンディション
原因
PD(Prefill-Decode)分離アーキテクチャでは、テールレイテンシ(tail latency)制御のためにタイムアウトベースのリクエスト中断メカニズムを運用している。Prefillが定められた時間内に完了しないと、Decode側が該当リクエストをabortしてKV Cacheを回収する。
問題は、abortシグナルがPrefill側に正しく伝わらない ことだ。DecodeがKV Cacheを回収して新しいリクエスト(Req2)に再割り当てした後も、以前のリクエスト(Req1)のRDMA writeとPrefill演算が継続し、Req2のKV Cacheを上書きする 現象が発生した。
修正
Decodeがabortを発行した後にPrefill側へ通知を送り、Prefillが次の2条件のいずれかを満たす場合にのみ 「回収安全」シグナル を返すよう変更した。
- RDMA writeがまだ開始されていない場合
- すでに発行されたwriteがすべて完了している場合
Decodeはこの確認を受けた後にのみKV Cacheを再利用する。適用の結果、異常出力率は 0.1% → 0.03%未満 に減少した。
Bug Fix #2: HiCacheにおけるLoad-Use順序保証の欠落
原因
Coding Agentワークロードは平均入力長が70Kトークンを超え、prefix再利用率が高い。これに対応するため HiCache(階層型KV Cache) を運用しており、CPUメモリからKV Cacheを非同期にswap-inしながら Load Stream と Forward Stream を重ねて実行する構造になっている。
問題は、Indexerカーネルが Indexer cacheのロード完了との同期制約を明示していなかった 点にある。Forward StreamがLoad Streamより先に実行を開始すると、まだロードされていないKV Cacheを読む read-before-ready パターンが発生し、異常出力につながった。
修正
Indexerカーネル実行前にLoad Streamとの 明示的な同期ポイント を挿入し、データ準備完了後にのみForward Streamが計算を進めるよう変更した。この修正は SGLangコミュニティにPR #22811として貢献 された。
最適化: LayerSplit(レイヤー単位のKV Cache分散保存)
2つのバグに共通するボトルネックはPrefill段階そのものの負荷だった。これを根本的に改善するため LayerSplit を設計・実装した。
従来はContext Parallelism(CP)環境で、各GPUがすべてのレイヤーのKV Cacheを重複保存していた。LayerSplitでは各GPUが レイヤーの一部だけ を担当するように分散保存し、GPUごとのメモリ使用量を大幅に削減する。
実行時には、該当レイヤーのKV Cacheを所有するCP rankがアテンション演算前にキャッシュをブロードキャストする。ブロードキャストとindexer演算を重ねて実行することで通信オーバーヘッドを隠し、追加通信データはindexer cache(KV Cacheの約1/8サイズ)のみなので、全体のオーバーヘッドは無視できる水準だ。
キャッシュヒット率90%条件で40K~120Kトークンのリクエストに対し、スループットは 10%~132%向上 し、コンテキスト長が長いほど改善幅が大きくなる。
結論
> 「スループット、レイテンシ、可用性だけでは不十分だ。システムはすべての生成リクエストの背後で、モデル状態の 正確性 も保証しなければならない。スケーリング則が能力を押し広げるとしても、その能力を大規模で信頼できるものにするのは、徹底したシステムエンジニアリングしかない。」
出典: Z.ai Research Blog (2026-04-30)
1件のコメント
PR LINK https://github.com/sgl-project/sglang/pull/22811