Files
project_6_89d52222/docs/LAYERWISE_SPLIT_KV_CACHE.md
2026-09-02 04:43:23 +00:00

102 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Layerwise Split KV Cache Sharding
**Commit:** 494f293b5629 · **PR:** #2260 · **Upstream:** xLLM
**Adaptation:** Iluvatar BI-V100 (PCIe topology)
**LOC:** +455 10 across 19 files
## Problem
For models with heterogeneous layer structures (e.g., DeepSeek-V3 with dense
attention layers interleaved with MoE layers), the KV cache is uniformly
sharded across all tensor-parallel ranks. Each rank stores KV for all layers,
even though different layers may have vastly different head counts.
On Iluvatar BI-V100 (32 GB HBM per card), this wastes memory on ranks that
serve layers with fewer KV heads and prevents optimal utilisation of each
card's HBM.
## Solution
Introduce **layerwise split KV cache sharding**: a new KV cache layout
strategy where each layer's KV cache can be sharded independently across a
configurable subset of TP ranks.
### Key Components
| # | Component | Files | Description |
|---|-----------|-------|-------------|
| 1 | `LayerwiseSplitLayout` | `core/framework/kv_cache/layerwise_split_layout.h` | Per-layer KV shard mappings. Dense layers spread across all TP ranks; MoE layers concentrate on fewer ranks. |
| 2 | Layerwise allocation | `core/framework/kv_cache/kv_cache_layerwise.{h,cpp}` | `allocate_kv_caches_layerwise()` — allocates per-layer shard sizes from layout. Handles the ILU/MLU transposed cache layout `[n_blocks, n_heads, block_size, head_dim]`. |
| 3 | Memory estimation | `core/framework/kv_cache/kv_cache_estimation_layerwise.{h,cpp}` | Reports peak/average per-rank memory; computes savings vs uniform. |
| 4 | ILU topology mapping | `core/framework/parallel_state/mapping_ilu.{h,cpp}` | PCIe-aware assignment: MoE layers placed on ranks sharing a PCIe switch to maximise intra-group bandwidth. |
| 5 | Engine integration | `core/distributed_runtime/layerwise_split_{engine_ext,master}.{h,cpp}` | Master computes layout at startup; engines propagate to workers. |
| 6 | Worker init | `core/runtime/worker_layerwise_init.{h,cpp}` | Workers receive and apply per-layer KV shard assignments. |
| 7 | Config flag | `core/config/parallel_config_layerwise.{h,cpp}` | `--enable_layerwise_split` gflag (default: false). |
### Iluvatar BI-V100 Hardware Context (verified via ixsmi + debug_warpsize.py)
- **4× BI-V100**, Bus-Id `4B:00.0` `4E:00.0`, NUMA node 1
- **Warp size: 64** (NOT 32 — verified via CUDA kernel `warpSize` builtin)
- **32768 MiB HBM** per card, 1500 MHz SM clock, 1200 MHz mem clock
- **Flat PIX topology** — all pairs connected via single PCIe bridge (equal BW)
- IX-ML 3.2.3, Driver 3.2.1, CUDA 10.2 (CoreX)
- CoreX SDK at `/usr/local/corex/`
- NCCL for collective communication (same process group as CUDA)
- KV cache tensor layout (ILU): `[n_blocks, n_heads, block_size, head_dim]` (axis 1 = heads)
- All verified constants centralized in `core/config/ilu_hw_constants.h`
### Usage
```bash
# Enable layerwise split KV cache
./xllm_server --model deepseek-v3 --enable_layerwise_split=true
# Disable (default — uniform sharding, no regression)
./xllm_server --model deepseek-v3 --enable_layerwise_split=false
```
## Test Plan
| ID | Level | Description | Criteria |
|----|-------|-------------|----------|
| TC-01 | L1 | Allocation correctness | Per-rank allocation matches layout; unassigned layers get zero KV; total equals sum |
| TC-02 | L1 | Memory estimation accuracy | Layerwise peak ≤ uniform; estimation error ≤ 5% |
| TC-03 | L1 | ILU PCIe topology mapping | All layers assigned; MoE layers on same-switch ranks; no oversubscription |
| TC-04 | L1 | Engine layout propagation | All 8 workers receive consistent layout; full layer coverage |
| TC-05 | L1 | Worker KV shard application | KV populated for assigned layers; zero for unassigned; ASAN clean |
| TC-06 | L2 | Fallback when disabled | Uniform allocation identical to pre-feature behaviour |
| TC-07 | L2 | Speculative engine | No crash; KV correctly partitioned per model |
## File Summary
```
core/
├── CMakeLists.txt
├── config/
│ ├── ilu_hw_constants.h
│ ├── parallel_config_layerwise.cpp
│ └── parallel_config_layerwise.h
├── distributed_runtime/
│ ├── layerwise_split_engine_ext.cpp
│ ├── layerwise_split_engine_ext.h
│ ├── layerwise_split_master.cpp
│ └── layerwise_split_master.h
├── framework/
│ ├── kv_cache/
│ │ ├── kv_cache_estimation_layerwise.cpp
│ │ ├── kv_cache_estimation_layerwise.h
│ │ ├── kv_cache_layerwise.cpp
│ │ ├── kv_cache_layerwise.h
│ │ └── layerwise_split_layout.h
│ └── parallel_state/
│ ├── mapping_ilu.cpp
│ └── mapping_ilu.h
└── runtime/
├── worker_layerwise_init.cpp
└── worker_layerwise_init.h
docs/
└── LAYERWISE_SPLIT_KV_CACHE.md
tests/core/
└── test_layerwise_split_kv_cache.cpp
```