Skip to main content
BlogAI/ML

LMCache Multi-Process Mode: Shared KV Cache untuk MoE Serving

LMCache multi-process mode mengganti KV offload per rank dengan satu host-memory pool bersama untuk serving vLLM DP+EP. Telaah benchmark, config, dan batasnya.

Matthews Wong

Software Engineer

Oktober 202611 menit baca
LMCache Multi-Process Mode: Shared KV Cache untuk MoE Serving

Ringkasan Utama

LMCache multi-process mode menjalankan KV cache sebagai server terpisah yang dipakai bersama oleh semua rank data-parallel vLLM, menggantikan delapan offload pool terisolasi per rank dengan satu host-memory pool. Pada satu tes Qwen3-235B di 8x H100 milik LMCache, mean time-to-first-token turun dari 3,98 s ke 0,29 s, sedangkan angka 10x di judul adalah angka p99.

Angka yang membuat saya membuka post ini ada di judulnya: peningkatan 10x untuk inference mixture-of-experts. Angka sebulat itu biasanya menyembunyikan pembagi yang spesifik, jadi saya membaca tulisan LMCache, dokumentasi multi-process di baliknya, dan panduan data parallel vLLM secara berdampingan sebelum punya pendapat.

Saya tidak menjalankan setup ini; node 8x H100 tidak ada di meja saya. Semua yang ada di bawah adalah pembacaan dekat atas lima sumber primer, dengan hitungan diulang dan caveat yang dihilangkan headline. Setiap angka saya kaitkan ke halaman tempat saya membacanya, dan hal yang tidak disebut halaman itu saya tandai sebagai tidak diketahui, bukan ditebak.

Kenapa DP plus EP membuat tiap rank punya KV cache sendiri

Baseline di post ini adalah vLLM dengan data parallelism untuk attention dan expert parallelism untuk expert. Panduan data parallel vLLM menjelaskan setiap DP rank sebagai proses core engine terpisah yang berbicara dengan front end lewat ZMQ socket, dan menyatakan bahwa setiap DP engine punya KV cache yang independen. Bobot attention direplikasi per rank, sedangkan expert di-shard antar rank begitu expert parallelism aktif.

Layout itu bagus untuk throughput dan buruk untuk reuse. Post LMCache menyebut setiap request di-pin ke satu DP rank, sehingga percakapan multi-turn hanya diuntungkan oleh prefix yang ter-cache jika turn berikutnya mendarat di rank yang sama dengan turn sebelumnya. Panduan vLLM menyebut load balancer internalnya memakai antrean running dan waiting tiap engine, bahwa routing yang sadar KV cache belum diimplementasikan, dan bahwa manfaat prefix caching bergantung pada pengarahan prompt yang cerdas tanpa menjelaskan caranya.

Akibatnya adalah fragmentasi. Bahkan dengan CPU offload aktif, post menyebut cache tidak dibagi antar rank, sehingga prefix yang tumpang tindih di rank berbeda dihitung ulang. Untuk chat, agent, dan RAG, tempat tiap turn memperpanjang turn sebelumnya, itu adalah kerja prefill berulang yang Anda bayar dalam time-to-first-token. Catatan: ini klaim tentang mekanisme; post tidak melaporkan cache hit rate, jadi seberapa sering hal itu terjadi di tes tidak terukur.

Baseline: in-process offload, satu pool per rank

Baseline in-process memakai offloading bawaan vLLM dengan 50 GB host memory per rank. Di delapan rank totalnya 400 GB, dan launch-nya seperti ini.

# Baseline from the LMCache post: 8-way DP, experts sharded by EP,
# and one isolated 50 GB host-memory offload pool PER RANK (8 x 50 = 400 GB).
VLLM_USE_FLASHINFER_MOE_FP8=0 VLLM_USE_DEEP_GEMM=1 \
vllm serve Qwen/Qwen3-235B-A22B-Instruct-2507-FP8 \
  --data-parallel-size 8 \
  --enable-expert-parallel \
  --gpu-memory-utilization 0.8 \
  --max-num-batched-tokens 1024 \
  --kv-offloading-size 50 \
  --disable-hybrid-kv-cache-manager \
  --max-model-len auto

# Each rank can only reuse prefixes that rank itself has seen. A follow-up turn
# routed to a different rank than its first turn finds nothing and recomputes.

Dua detail penting nanti. Pertama, post mencatat bahwa flag disable-hybrid-kv-cache-manager diperlukan untuk model hybrid-memory-allocator dengan native offloading connector. Kedua, total 400 GB sama dengan pool tunggal yang dipakai run multi-process, jadi kedua sisi mendapat host memory yang sama. Yang berbeda adalah apakah memori itu satu pool atau delapan.

Apa yang diubah multi-process mode secara arsitektur

Di multi-process mode, LMCache berhenti menjadi library di dalam tiap proses vLLM dan menjadi service mandiri. Dokumentasi menyebut engine terhubung lewat transport request ZMQ atau gRPC, dan README menggambarkannya sebagai daemon yang berjalan terpisah dari inference engine. Perbandingan di bawah disusun dari post, dokumen multi-process, dan README.

AspekIn-process offloadLMCache multi-process mode
Lokasi cacheDi dalam tiap rank vLLM, process-local dan terfragmentasiSatu server per node, satu L1 host-memory pool bersama
Reuse prefix lintas rankTidak ada; tiap rank hanya melihat riwayatnya sendiriRank mana pun bisa memakai ulang yang disimpan rank lain
Kegagalan cacheSatu proses dengan engine, jadi senasibDokumen menyatakan kegagalan cache tidak menjatuhkan engine
Hashing dan manajemen memoriBersaing dengan thread vLLM di proses yang samaBerjalan di proses LMCache, di luar thread Python vLLM
Tier bawahHanya host memory offload pada baselineL1 adalah DRAM; backend L2 seperti local storage dan remote connector
JangkauanSatu rankSatu node saat ini; peer-to-peer lintas node masih roadmap

Di dalam server, dokumen menjelaskan StorageManager yang mengoordinasikan L1 pool dan adapter L2 opsional, dengan controller untuk menyimpan ke L2, mengeluarkan dari L1, dan prefetch hit L2 kembali ke L1. Kebijakan eviction yang tercantum adalah LRU, ARC, IsolatedLRU, dan noop. Run di post memakai LRU. L1 secara default adalah pinned CPU DRAM, dengan Device-DAX dan NVMe slab lewat GPUDirect Storage sebagai alternatif.

Konfigurasi yang menghasilkan angkanya

Post menerbitkan kedua baris launch, dan itulah yang membuatnya bisa diperiksa. Run MP menjalankan server dengan L1 pool 400 GB dan eviction LRU, lalu meluncurkan perintah vLLM DP plus EP yang sama dengan KV connector sebagai ganti flag offload.

# Terminal 1: the LMCache server owns ONE host-memory L1 pool for the node.
# 400 GB is the pool the post used on its 8x H100 box.
lmcache server --l1-size-gb 400 --eviction-policy LRU

# Terminal 2: the same vLLM DP+EP launch, with the connector instead of
# --kv-offloading-size. The post also drops --disable-hybrid-kv-cache-manager
# and does not say why, so treat that as a second variable.
VLLM_USE_FLASHINFER_MOE_FP8=0 VLLM_USE_DEEP_GEMM=1 \
vllm serve Qwen/Qwen3-235B-A22B-Instruct-2507-FP8 \
  --data-parallel-size 8 \
  --enable-expert-parallel \
  --gpu-memory-utilization 0.8 \
  --max-num-batched-tokens 1024 \
  --max-model-len auto \
  --kv-transfer-config '{"kv_connector":"LMCacheMPConnector","kv_role":"kv_both"}'

# The post's load generator: multi-round chat at 2.0 QPS for 120 seconds.
lmcache bench engine --engine-url http://localhost:8000 \
  --workload multi-round-chat --mrc-qps 2.0 --mrc-duration 120

Baca bedanya dengan teliti. Perintah MP tidak punya kv-offloading-size dan tidak punya disable-hybrid-kv-cache-manager, dan post tidak menjelaskan kedua penghilangan itu. Jadi kedua run berbeda lebih dari sekadar connector, dan selisih yang dipublikasikan tidak bisa dikaitkan hanya ke shared memory. Jika Anda mereproduksi, ubah satu hal pada satu waktu.

Jaga A/B Anda tetap jujur: jalankan baseline dan launch MP dengan semua flag vLLM lain identik, termasuk setelan hybrid KV cache manager, dan laporkan mean serta p99 time-to-first-token dari load generator yang sama.

Membaca benchmark: 10x itu sebenarnya apa

Tes memakai Qwen3-235B-A22B-Instruct-2507-FP8 di satu server dengan delapan GPU H100 80 GB, vLLM 0.18.1 dan LMCache 0.4.3-dev, digerakkan workload multi-round chat 2,0 QPS selama 120 detik. Berikut nilai tabel post dengan rasio yang saya hitung ulang.

MetrikIn-processLMCache MPRasio
TTFT mean3,98 s0,29 ssekitar 13,7x lebih rendah
TTFT p9913,55 s1,30 ssekitar 10,4x lebih rendah
Decode mean9,81 tok/s37,47 tok/ssekitar 3,8x lebih tinggi
Decode p9934,27 tok/s45,14 tok/ssekitar 1,3x lebih tinggi

Headline 10x cocok dengan rasio p99 time-to-first-token, bukan mean. Rasio mean lebih besar, dan bar chart di post memberi label 13,6x, dekat dengan 13,7x hitungan saya dari nilai tabel yang dibulatkan. Angka decode gain-nya lebih kecil, dan post tidak mendefinisikan apakah decode speed itu per request atau agregat, jadi saya tidak akan mengutip 3,8x tanpa caveat itu.

Post menyebut hit rate cache yang lebih tinggi, prefill redundan yang berkurang, dan fragmentasi yang berkurang, tetapi tidak menunjukkan data hit rate untuk memastikan pembagiannya. Ini satu model, satu mesin, satu workload, dan satu level QPS, tanpa pengulangan atau variansi, pada build development LMCache. Jumlah percakapan serta panjang prompt dan output tidak disebutkan. Anggap ini bukti keberadaan mekanisme yang kuat, bukan ramalan untuk cluster Anda.

Trade-off dan tempat ia bisa menggigit

Service cache bersama adalah satu bagian bergerak lagi di jalur panas setiap request. Dari dokumentasi, ini batasan yang akan saya rencanakan sebelum mengadopsinya.

  • Version lockstep: dokumen menyuruh upgrade server dan worker bersamaan, karena typed inline protocol tidak kompatibel dengan versi lama.
  • Sizing worker: setelan max-workers default-nya 1, dan max-gpu-workers sebaiknya minimal sebanyak instance vLLM yang berbagi server.
  • Isolated IPC mode hanya bekerja dengan vLLM MP connector, butuh package cuda-python di kedua sisi, dan tidak kompatibel dengan expandable_segments:True serta vLLM sleep mode.
  • Cakupan: sharing per node. Peer-to-peer sharing dan prefill-decode disaggregation untuk reuse seluruh cluster tercantum sebagai rencana, tanpa tanggal.

Benchmark memakai build development, LMCache 0.4.3-dev, dan dokumen meminta dev branch LMCache terbaru. Pin versi persis vLLM dan LMCache bersamaan, uji di release build, dan perlakukan server sebagai komponen yang kenaikan versinya dikoordinasikan dengan engine Anda.

Ada juga pertanyaan kapasitas yang tidak dijawab post. Satu pool berarti tekanan eviction dari semua rank jatuh ke memori yang sama, dan dokumen menyebut eviction dipicu di watermark 0,8 dan membebaskan 0,2 memori terisi per siklus secara default. Jika working set Anda lebih besar dari L1, pool bersama bisa membuang prefix berguna satu rank demi rank lain, perilaku yang perlu dipantau, bukan yang dilatih benchmark.

Menjalankannya: port, proses, dan bentuk Kubernetes

Halaman deployment memakai empat port. Port transport adalah yang harus disepakati connector engine, jadi ketidakcocokan antara port server dan nilai lmcache.mp.port di config connector adalah hal pertama yang dicek saat engine tidak menemukan cache.

PortFungsi menurut halaman deployment
6555Port transport LMCache, diatur lewat port di server dan lmcache.mp.port di connector
8080Varian HTTP server, dengan endpoint healthcheck untuk probe
9090Metrik Prometheus, aktif secara default
8000API vLLM pada tes contoh di halaman itu
# Server as the deployment page runs it (Docker, one node, 60 GB L1).
# --ipc host is what lets the engine and server share GPU memory handles;
# --isolated-ipc plus lmcache.mp.isolated_ipc on both sides removes that need.
docker run --runtime nvidia --gpus all --network host --ipc host \
  lmcache/standalone:nightly \
  /opt/venv/bin/lmcache server --l1-size-gb 60 --eviction-policy LRU \
  --max-workers 4 --port 6555

# vLLM side: the connector must point at the same transport port.
--kv-transfer-config '{"kv_connector":"LMCacheMPConnector","kv_role":"kv_both","kv_connector_extra_config":{"lmcache.mp.port":6555}}'

# Kubernetes: the server is a DaemonSet (one per GPU node), vLLM a Deployment.
kubectl create namespace multi-process
kubectl apply -f examples/multi_process/lmcache-daemonset.yaml
kubectl apply -f examples/multi_process/vllm-deployment.yaml

Di Kubernetes, halaman itu men-deploy server sebagai DaemonSet sehingga tiap node GPU menjalankan satu, dengan host networking dan transport terikat ke 127.0.0.1. DaemonSet tidak meminta GPU, pod vLLM yang memegangnya, dan pod LMCache yang terjadwal di node tanpa GPU crash dengan error inisialisasi CUDA. Halaman itu mencantumkan minimal 4 GPU per node dan NVIDIA GPU Operator sebagai syarat contohnya.

Yang dilakukan hari Senin

Jangan mulai dengan menginstalnya. Mulailah dengan mencari tahu apakah fragmentasi memang masalah Anda, lalu jalankan perbandingan terkontrol.

  1. Pastikan bentuknya: Anda menjalankan lebih dari satu DP rank dan traffic Anda multi-turn, agentic, atau RAG. Dengan satu rank tidak ada yang bisa dibagi.
  2. Catat baseline pada workload Anda sendiri: mean dan p99 time-to-first-token dari lmcache bench engine atau replay Anda sendiri, dengan flag offload yang sekarang.
  3. Jalankan satu server LMCache per node dengan ukuran L1 dari host memory yang tersisa setelah OS dan vLLM, lalu ganti hanya connector dan flag offload.
  4. Set max-gpu-workers minimal sebanyak engine di node, dan scrape port 9090 agar Anda melihat perilaku eviction dan hit, bukan menebaknya.
  5. Pin versi bersamaan, ulangi di lebih dari satu level QPS dengan pengulangan, baru putuskan; hasil yang dipublikasikan hanyalah satu titik.

Jika routing layer Anda sudah mengirim percakapan ke rank yang sama setiap kali, pool bersama memberi lebih sedikit dari yang disiratkan post, karena fragmentasi yang dihilangkannya adalah biaya salah routing. Dalam kasus itu, memperbaiki routing bisa jadi eksperimen pertama yang lebih murah.

Pelajaran yang saya ambil dari post ini: di serving DP plus EP, lokalitas KV cache adalah sifat topologi deployment Anda, bukan hanya kebijakan cache. Memindahkan cache dari rank ke service node-level bersama menghilangkan sumber recomputation yang nyata, dan mean 0,29 s masuk akal karena itu, tetapi headline 10x adalah angka p99 dari satu run build dev. Ukur workload Anda sendiri sebelum percaya salah satu angka.

FAQ

Pertanyaan Umum

Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.

Apa itu LMCache multi-process mode?

Mode ini menjalankan LMCache sebagai service mandiri, bukan library di dalam tiap proses vLLM. Engine terhubung lewat transport ZMQ atau gRPC, dan pod di node yang sama berbagi satu L1 cache. Dokumen menyebut kegagalan cache tidak menjatuhkan inference engine.

Kenapa data parallel serving memfragmentasi KV cache?

Setiap rank data-parallel di vLLM adalah engine terpisah dengan KV cache independen, dan setiap request di-pin ke satu rank. Turn lanjutan yang mendarat di rank lain tidak bisa memakai ulang prefix dan menghitungnya lagi. CPU offload saja tidak membagi cache antar rank.

Apakah peningkatan 10x LMCache untuk inference MoE itu nyata?

Itu pengukuran nyata tetapi sempit. Angka 10x cocok dengan p99 time-to-first-token, dari 13,55 s ke 1,30 s, pada satu model, satu server 8x H100 dan satu workload di build development. Rasio mean TTFT sekitar 13,7x, dan kedua config launch juga berbeda selain connector.

Bagaimana cara menjalankan server LMCache untuk vLLM?

Jalankan lmcache server dengan ukuran L1 dan kebijakan eviction, misalnya lmcache server --l1-size-gb 400 --eviction-policy LRU. Lalu luncurkan vLLM dengan kv-transfer-config yang menyebut LMCacheMPConnector dengan role kv_both. Port connector harus sama dengan port transport server.

Apakah LMCache multi-process mode membagi cache lintas node?

Belum. Sharing saat ini bersifat node-level: beberapa DP rank dan instance di satu node berbagi L1 host-memory pool. Peer-to-peer sharing dan prefill-decode disaggregation untuk reuse seluruh cluster tercantum sebagai rencana, tanpa tanggal.