Membagikan proses reproduksi dan perbaikan dua bug race condition pada KV Cache yang ditemui saat melayani Coding Agent berbasis GLM-5 dalam skala ratusan juta permintaan, beserta optimasi peningkatan throughput.
Latar belakang
Hukum penskalaan (Scaling Laws) bukan hanya mendorong terobosan pada parameter model dan skala data, tetapi juga memaksa rekayasa infrastruktur hingga ke batasnya. Z.ai menyebut efek samping yang muncul dalam proses ini sebagai Scaling Pain.
Saat memproses ratusan juta workload Coding Agent kompleks per hari dengan seri GLM-5, dilaporkan gejala anomali pada sebagian pengguna seperti output rusak (garbled output), generasi berulang, dan munculnya karakter langka. Masalah ini sama sekali tidak dapat direproduksi di lingkungan inferensi standar, dan hanya muncul pada lingkungan berkonteks panjang dengan konkurensi tinggi.
Ringkasan hasil utama
| Item | Angka |
|---|---|
| Rasio output anomali setelah Bug Fix #1 diterapkan | 0.1% → kurang dari 0.03% |
| Peningkatan throughput LayerSplit (40K~120K token) | +10% ~ +132% |
| Fix HiCache dikontribusikan sebagai SGLang PR #22811 | ✅ |
Deteksi anomali: memanfaatkan metrik Speculative Decoding
Mendeteksi anomali secara otomatis itu sendiri merupakan tantangan besar. Heuristik seperti regex menghasilkan banyak false positive dan false negative, sementara classifier berbasis model terlalu mahal untuk eksperimen skala besar.
Terobosan datang dari metrik Speculative Decoding.
- Output rusak / karakter langka:
spec_accept_lengthsangat rendah → sinyal ketidakcocokan status KV Cache antara model draft dan model target - Generasi berulang:
spec_accept_ratesangat tinggi → sinyal bahwa pola attention berkumpul ke loop berulang akibat KV Cache yang rusak
Berdasarkan hal ini, diterapkan strategi pemantauan online. Jika pada saat token yang dihasilkan melebihi 128, spec_accept_length < 1.4 atau spec_accept_rate > 0.96, maka generasi segera dihentikan dan retry diserahkan ke load balancer. Artinya, Speculative Decoding diperluas dari alat optimasi performa menjadi alat pemantauan kualitas output secara real-time.
Bug Fix #1: race condition KV Cache pada arsitektur pemisahan PD
Penyebab
Pada arsitektur pemisahan PD (Prefill-Decode), digunakan mekanisme penghentian permintaan berbasis timeout untuk mengendalikan tail latency. Jika Prefill tidak selesai dalam waktu yang ditentukan, sisi Decode akan meng-abort permintaan tersebut dan merebut kembali KV Cache.
Masalahnya adalah sinyal abort tidak tersampaikan dengan benar ke sisi Prefill. Bahkan setelah Decode merebut kembali KV Cache dan mengalokasikannya ulang ke permintaan baru (Req2), RDMA write dan operasi Prefill dari permintaan sebelumnya (Req1) tetap berjalan, sehingga terjadi kondisi menimpa KV Cache milik Req2.
Perbaikan
Setelah Decode mengeluarkan abort, sistem diubah agar notifikasi dikirim ke sisi Prefill, dan Prefill hanya mengembalikan sinyal "aman untuk direbut kembali" bila memenuhi salah satu dari dua kondisi berikut.
- RDMA write belum dimulai
- Semua write yang sudah diterbitkan telah selesai
Decode hanya akan menggunakan ulang KV Cache setelah menerima konfirmasi ini. Hasil penerapannya, rasio output anomali turun dari 0.1% → kurang dari 0.03%.
Bug Fix #2: tidak adanya jaminan urutan Load-Use pada HiCache
Penyebab
Workload Coding Agent memiliki panjang input rata-rata di atas 70K token dan tingkat reuse prefix yang tinggi. Untuk itu digunakan HiCache (KV Cache hierarkis), dengan struktur yang menjalankan Load Stream dan Forward Stream secara overlap sambil melakukan swap-in KV Cache dari memori CPU secara asinkron.
Masalahnya adalah kernel Indexer tidak menyatakan batasan sinkronisasi terhadap selesainya pemuatan cache Indexer. Jika Forward Stream mulai berjalan lebih dulu daripada Load Stream, maka muncul pola read-before-ready yang membaca KV Cache yang belum dimuat, dan ini berujung pada output anomali.
Perbaikan
Sebelum eksekusi kernel Indexer, ditambahkan titik sinkronisasi eksplisit dengan Load Stream, sehingga Forward Stream hanya melanjutkan komputasi setelah data dipastikan siap. Perbaikan ini dikontribusikan ke komunitas SGLang sebagai PR #22811.
Optimasi: LayerSplit (penyimpanan terdistribusi KV Cache per layer)
Bottleneck bersama dari kedua bug ini adalah beban pada tahap Prefill itu sendiri. Untuk memperbaikinya secara mendasar, dirancang dan diimplementasikan LayerSplit.
Sebelumnya, dalam lingkungan Context Parallelism (CP), setiap GPU menyimpan salinan duplikat KV Cache untuk semua layer. Pada LayerSplit, penyimpanan didistribusikan agar setiap GPU hanya menangani sebagian layer saja, sehingga penggunaan memori per GPU berkurang besar.
Saat dijalankan, CP rank yang memiliki KV Cache untuk layer terkait akan menyiarkan cache tersebut sebelum operasi attention. Broadcast dioverlap dengan operasi indexer untuk menyembunyikan overhead komunikasi, dan karena data komunikasi tambahan hanya berupa indexer cache (sekitar 1/8 ukuran KV Cache), total overhead-nya nyaris bisa diabaikan.
Dengan kondisi cache hit rate 90%, throughput untuk permintaan 40K~120K token meningkat sebesar 10%~132%, dan semakin panjang konteksnya, semakin besar pula peningkatannya.
Kesimpulan
> "Throughput, latensi, dan ketersediaan saja tidak cukup. Sistem juga harus menjamin ketepatan status model di balik setiap permintaan generasi. Hukum penskalaan memang mendorong kemampuan hingga batasnya, tetapi yang membuat kemampuan itu dapat dipercaya pada skala besar hanyalah rekayasa sistem yang benar-benar ketat."
Sumber: Z.ai Research Blog (2026-04-30)
1 komentar
TAUTAN PR https://github.com/sgl-project/sglang/pull/22811