chore: import upstream snapshot with attribution
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,427 @@
|
||||
# FlexKV ↔ sglang integration
|
||||
|
||||
A `RadixCache` subclass that routes sglang's host-tier KV cache through a
|
||||
FlexKV [`KVManager`](https://github.com/taco-project/FlexKV) (CPU / SSD /
|
||||
Remote offload). Same integration pattern as
|
||||
[`LMCRadixCache`](../lmcache/README.md): `FlexKVRadixCache` overrides
|
||||
`match_prefix` / `init_load_back` / `cache_finished_req` / `evict`; a
|
||||
`FlexKVConnector` façade talks to `KVManager`, `KVTPClient`, and a
|
||||
3-axis (PP × CP × TP) sync context.
|
||||
|
||||
---
|
||||
|
||||
## Quick start (single H20, single GPU, Qwen3-8B)
|
||||
|
||||
This walks through everything the verification on H20-GPU-11 actually
|
||||
exercised. Adjust paths / model / GPU as needed.
|
||||
|
||||
### 1. Prereqs
|
||||
|
||||
* `lmsysorg/sglang:dev` (or any sglang container with CUDA 12.x + torch 2.10+).
|
||||
* This sglang fork (branch `feat/flexkv-main-connector`) and FlexKV
|
||||
(branch `main`) checked out somewhere reachable from the container
|
||||
— e.g. `/raid/fly/sglang-connector-dir/{sglang,FlexKV}`. Verified
|
||||
against FlexKV main at `aa74e39` (PR #184); older commits down to
|
||||
the layerwise integration also work.
|
||||
|
||||
### 2. Start a container with both repos mounted
|
||||
|
||||
```bash
|
||||
docker run -d --name flexkv-sglang \
|
||||
--gpus all --ipc=host --network host \
|
||||
--shm-size=32g --cap-add SYS_NICE --cap-add IPC_LOCK \
|
||||
-v /raid/fly:/raid/fly \
|
||||
--workdir /raid/fly/sglang-connector-dir \
|
||||
--entrypoint "" \
|
||||
lmsysorg/sglang:dev sleep infinity
|
||||
|
||||
docker exec flexkv-sglang bash -c "
|
||||
apt-get update -qq &&
|
||||
apt-get install -y numactl libnuma-dev libxxhash-dev liburing-dev cmake ninja-build
|
||||
"
|
||||
```
|
||||
|
||||
### 3. Install sglang fork (editable) + FlexKV
|
||||
|
||||
```bash
|
||||
docker exec flexkv-sglang bash -c '
|
||||
set -e
|
||||
git config --global --add safe.directory "*"
|
||||
|
||||
# sglang fork: install in editable mode, replacing the prebuilt sglang
|
||||
cd /raid/fly/sglang-connector-dir/sglang
|
||||
pip install --no-deps -e python
|
||||
|
||||
# FlexKV: pin to main, init the xxHash submodule, debug C++ build.
|
||||
cd /raid/fly/sglang-connector-dir/FlexKV
|
||||
git checkout main && git pull --ff-only
|
||||
git submodule update --init third_party/xxHash
|
||||
pip install -q cython ninja pybind11
|
||||
FLEXKV_ENABLE_METRICS=0 bash build.sh --debug
|
||||
|
||||
# Smoke check
|
||||
python3 -c "
|
||||
import sglang, flexkv
|
||||
from flexkv.kvmanager import KVManager
|
||||
from sglang.srt.mem_cache.storage.flexkv import flexkv_comm
|
||||
from sglang.srt.mem_cache.registry import registered_radix_cache_backends
|
||||
import sglang.srt.mem_cache.storage.flexkv # registers
|
||||
print(\"flexkv ok\", flexkv.__file__)
|
||||
print(\"sglang ok\", sglang.__file__)
|
||||
print(\"registered backends:\", registered_radix_cache_backends())
|
||||
"
|
||||
'
|
||||
```
|
||||
|
||||
If the build hangs on `pip install sglang-kernel`, see
|
||||
[Troubleshooting](#troubleshooting).
|
||||
|
||||
### 4. Minimal FlexKV YAML
|
||||
|
||||
```yaml
|
||||
# /raid/fly/sglang-connector-dir/flexkv_min.yaml
|
||||
cpu_cache_gb: 16
|
||||
```
|
||||
|
||||
That's enough to enable a 16 GiB CPU offload pool. See
|
||||
[`example_config_mp.yaml`](example_config_mp.yaml) for SSD / remote /
|
||||
distributed knobs.
|
||||
|
||||
### 5. Launch the server (MP / synchronous mode)
|
||||
|
||||
```bash
|
||||
docker exec -d flexkv-sglang bash -c '
|
||||
cd /raid/fly/sglang-connector-dir
|
||||
CUDA_VISIBLE_DEVICES=0 \
|
||||
SGLANG_SKIP_SGL_KERNEL_VERSION_CHECK=1 \
|
||||
python3 -m sglang.launch_server \
|
||||
--model-path /raid/fly/model/Qwen3-8B \
|
||||
--port 30000 --tp-size 1 \
|
||||
--enable-flexkv \
|
||||
--flexkv-config-file /raid/fly/sglang-connector-dir/flexkv_min.yaml \
|
||||
--mem-fraction-static 0.45 --max-running-requests 8 \
|
||||
> /tmp/sglang.log 2>&1
|
||||
'
|
||||
```
|
||||
|
||||
`SGLANG_SKIP_SGL_KERNEL_VERSION_CHECK=1` bypasses the prebuilt
|
||||
`sglang-kernel` version assertion (the `lmsysorg/sglang:dev` image ships
|
||||
0.4.2.post2; main expects ≥ 0.4.3). Not a FlexKV-specific issue;
|
||||
remove when the container image is refreshed.
|
||||
|
||||
Wait ~2 min for the model load + CUDA graph capture. Confirm with:
|
||||
|
||||
```bash
|
||||
docker exec flexkv-sglang bash -c '
|
||||
grep -E "fired up|Connector ready" /tmp/sglang.log | tail -2
|
||||
'
|
||||
```
|
||||
|
||||
Expected (key lines):
|
||||
|
||||
```
|
||||
[FlexKV] Connector ready ...: layerwise=False, prefetch=False
|
||||
The server is fired up and ready to roll!
|
||||
```
|
||||
|
||||
### 6. Send a request and observe a cache hit
|
||||
|
||||
```bash
|
||||
# First call: priming — fresh prefill, FlexKV stores the prefix.
|
||||
docker exec flexkv-sglang bash -c '
|
||||
curl -s http://127.0.0.1:30000/generate -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"text\": \"The capital of France is\",
|
||||
\"sampling_params\": {\"max_new_tokens\": 5, \"temperature\": 0}}"
|
||||
'
|
||||
|
||||
# Flush the GPU radix (FlexKV CPU pool keeps the data) and re-send.
|
||||
docker exec flexkv-sglang bash -c '
|
||||
curl -s http://127.0.0.1:30000/flush_cache -X POST
|
||||
curl -s http://127.0.0.1:30000/generate -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"text\": \"The capital of France is\",
|
||||
\"sampling_params\": {\"max_new_tokens\": 5, \"temperature\": 0}}"
|
||||
'
|
||||
```
|
||||
|
||||
Look at the second response's `meta_info`:
|
||||
|
||||
```json
|
||||
"cached_tokens": 4,
|
||||
"cached_tokens_details": { "device": 0, "host": 4 },
|
||||
```
|
||||
|
||||
`host: 4` confirms the bytes came back from FlexKV's CPU pool. The
|
||||
server log should also show a matching D2H/H2D bandwidth line:
|
||||
|
||||
```
|
||||
[FLEXKV] ... H2D transfer request: N finished transfer data size: 0.0xx GB ... 30+ GB/s
|
||||
```
|
||||
|
||||
### 7. Layerwise mode
|
||||
|
||||
Add `FLEXKV_ENABLE_LAYERWISE_TRANSFER=1` before `python3 -m
|
||||
sglang.launch_server`. Everything else is identical. On the second
|
||||
request you'll see `cached_tokens_details: {"device": N, "host": 0}`
|
||||
(in IP mode the load happens inside `match_prefix` so sglang accounts
|
||||
for it as device-side) and a log line `LAYERWISE transfer request: N
|
||||
finished ...`. The startup log will also include
|
||||
`[FlexKV] Eventfd handshake complete ... counters=3 layers=<N>`.
|
||||
|
||||
---
|
||||
|
||||
## Correctness verification
|
||||
|
||||
Numerical match against a no-FlexKV baseline (greedy decoding,
|
||||
deterministic). Scripts are in this repo's testing notes; the canonical
|
||||
two are reproduced below.
|
||||
|
||||
```bash
|
||||
# Phase 1: capture the no-FlexKV baseline.
|
||||
docker exec -d flexkv-sglang bash -c '
|
||||
CUDA_VISIBLE_DEVICES=0 SGLANG_SKIP_SGL_KERNEL_VERSION_CHECK=1 \
|
||||
python3 -m sglang.launch_server \
|
||||
--model-path /raid/fly/model/Qwen3-8B --port 30000 --tp-size 1 \
|
||||
--mem-fraction-static 0.45 > /tmp/sglang.log 2>&1
|
||||
'
|
||||
# ... wait until ready ...
|
||||
docker exec flexkv-sglang python3 /raid/fly/sglang-connector-dir/sglang/python/sglang/srt/mem_cache/storage/flexkv/verify_outputs.py --phase baseline
|
||||
docker exec flexkv-sglang bash -c "pkill -9 -f launch_server; sleep 3"
|
||||
|
||||
# Phase 2: relaunch with --enable-flexkv and compare.
|
||||
docker exec -d flexkv-sglang bash -c '
|
||||
CUDA_VISIBLE_DEVICES=0 SGLANG_SKIP_SGL_KERNEL_VERSION_CHECK=1 \
|
||||
python3 -m sglang.launch_server \
|
||||
--model-path /raid/fly/model/Qwen3-8B --port 30000 --tp-size 1 \
|
||||
--enable-flexkv --flexkv-config-file /raid/fly/sglang-connector-dir/flexkv_min.yaml \
|
||||
--mem-fraction-static 0.45 > /tmp/sglang.log 2>&1
|
||||
'
|
||||
# ... wait until ready ...
|
||||
docker exec flexkv-sglang python3 /raid/fly/sglang-connector-dir/sglang/python/sglang/srt/mem_cache/storage/flexkv/verify_outputs.py --phase test
|
||||
```
|
||||
|
||||
Expected last line: `Total mismatches: 0`. Each prompt is run twice
|
||||
(R1 fresh / R2 after `flush_cache`); both R1 and R2 outputs must
|
||||
byte-equal the baseline.
|
||||
|
||||
Repeat the Phase-2 launch with `FLEXKV_ENABLE_LAYERWISE_TRANSFER=1`
|
||||
to validate the layerwise path.
|
||||
|
||||
---
|
||||
|
||||
## Selecting the backend
|
||||
|
||||
Two equivalent CLI flags:
|
||||
|
||||
```bash
|
||||
# Auto-selection chain (matches --enable-lmcache style)
|
||||
python3 -m sglang.launch_server --enable-flexkv \
|
||||
--flexkv-config-file /path/to/flexkv_config.yaml ...
|
||||
|
||||
# Explicit registry path
|
||||
python3 -m sglang.launch_server --radix-cache-backend flexkv \
|
||||
--flexkv-config-file /path/to/flexkv_config.yaml ...
|
||||
```
|
||||
|
||||
Either flag also sets `FLEXKV_CONFIG_PATH` so you can omit
|
||||
`--flexkv-config-file` and configure FlexKV purely through env vars.
|
||||
|
||||
---
|
||||
|
||||
## Modes
|
||||
|
||||
### MP (synchronous, default)
|
||||
|
||||
* `match_prefix` calls `FlexKVConnector.lookup_kv` only.
|
||||
* When `host_hit_length > 0`, the scheduler later calls
|
||||
`init_load_back`, which allocates the uncached slots and fires
|
||||
`retrieve_kv` (FlexKV `launch` + `wait`).
|
||||
* `cache_finished_req` runs `put_match` + `launch` and stashes the
|
||||
in-flight FlexKV task id. Source-node lock is held until
|
||||
`check_completed_stores` (called from `check_hicache_events` /
|
||||
`evict`) signals completion.
|
||||
|
||||
This is the path you'll use under any non-trivial deployment topology
|
||||
(DP > 1, multi-instance, multi-node, ...).
|
||||
|
||||
### IP / layerwise (`FLEXKV_ENABLE_LAYERWISE_TRANSFER=1`)
|
||||
|
||||
* `match_prefix` allocates the uncached slots and fires
|
||||
`start_load_kv_layerwise` immediately.
|
||||
* A `FlexKVLayerDoneCounter` is registered onto sglang's KV pool via
|
||||
`register_layer_transfer_counter`; the per-layer hook blocks each
|
||||
forward layer on its own eventfd until the FlexKV transfer worker
|
||||
signals the layer is staged.
|
||||
* Layerwise mode requires the FlexKV transfer worker's UDS socket
|
||||
(`/tmp/flexkv_layerwise_eventfd.sock` by default) to be reachable —
|
||||
the connector handshakes with it at startup. The socket path is
|
||||
computed by FlexKV's `build_layerwise_eventfd_socket_path` from the
|
||||
same dp/pp/instance settings, so configuration is taken care of as
|
||||
long as you launch FlexKV consistently.
|
||||
|
||||
---
|
||||
|
||||
## Files
|
||||
|
||||
* `flexkv_radix_cache.py` — `FlexKVRadixCache(RadixCache)`. Overrides
|
||||
`match_prefix`, `init_load_back`, `cache_finished_req`, `evict`,
|
||||
`check_hicache_events`, `reset`.
|
||||
* `flexkv_connector.py` — `FlexKVConnector`. Owns the `KVManager`,
|
||||
`KVTPClient`, and the cross-rank sync context. Public methods:
|
||||
`lookup_kv`, `retrieve_kv`, `start_load_kv_layerwise`, `store_kv`,
|
||||
`check_completed_stores`, `prefetch_async`, …
|
||||
* `flexkv_comm.py` — `FlexKVComm` (3-axis PP × CP × TP sync built on
|
||||
torch.distributed) + the eventfd / `SCM_RIGHTS` shims used by the
|
||||
layerwise transfer UDS handshake. **`FlexKVLayerLoadingEvent` here
|
||||
carries the layerwise correctness fix** (drain stale eventfd
|
||||
signals on reset, switch `wait` to `select.select` to keep blocking
|
||||
semantics on a NONBLOCK fd).
|
||||
* `__init__.py` — registers the `"flexkv"` factory with
|
||||
`sglang.srt.mem_cache.registry`.
|
||||
|
||||
---
|
||||
|
||||
## TP / PP / CP / DP
|
||||
|
||||
FlexKV runs one `KVManager` per DP route (=
|
||||
`instance_id * dp_size + dp_rank`). Every other rank in the same
|
||||
fan-out is the "sync follower" — `FlexKVComm` broadcasts the
|
||||
leader's lookup / store decisions via gloo CPU groups so non-leader
|
||||
ranks know which task ids and slot mappings to use.
|
||||
|
||||
Supported:
|
||||
|
||||
* **TP** (any size) — typical sglang topology.
|
||||
* **DP** (`dp_size > 1`) and multi-instance — FlexKV automatically
|
||||
switches its `KVManager` to server-client mode.
|
||||
* **PP** (`pp_size > 1`) — including cross-node PP. The PP receiver
|
||||
forwards its slot mappings back to FlexKV's
|
||||
`TransferManagerOnRemote` via the same ZMQ channel used for GPU
|
||||
registration.
|
||||
* **CP** (`attn_cp_size > 1`) — sync handled symmetrically with TP.
|
||||
* **DP attention** (`enable_dp_attention=True`) — the inner
|
||||
`attn_tp_size` is what FlexKV uses for register-side routing.
|
||||
|
||||
---
|
||||
|
||||
## Environment variables
|
||||
|
||||
* `FLEXKV_CONFIG_PATH` — full FlexKV YAML / JSON config (also set
|
||||
automatically by `--flexkv-config-file`).
|
||||
* `FLEXKV_ENABLE_LAYERWISE_TRANSFER` — `1` to enable layerwise mode.
|
||||
* `FLEXKV_LAYERWISE_EVENTFD_SOCKET` — UDS socket path (default
|
||||
`/tmp/flexkv_layerwise_eventfd.sock`); auto-suffixed per
|
||||
`(pp_rank, dp_client_id)` when those dims are > 1.
|
||||
* `FLEXKV_MASTER_HOST` / `FLEXKV_MASTER_PORTS` — multi-node master
|
||||
endpoint for `TransferManagerOnRemote`. Default
|
||||
`localhost:5556,5557,5558`. With `nnodes > 1` we also fall back to
|
||||
`server_args.dist_init_addr`'s host.
|
||||
* `FLEXKV_KV_CACHE_DTYPE` — override KV dtype when sglang uses
|
||||
`--kv-cache-dtype auto`.
|
||||
* `SGLANG_SKIP_SGL_KERNEL_VERSION_CHECK` — bypass the prebuilt
|
||||
`sglang-kernel` version assertion (not FlexKV-specific).
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* **`fatal: not a git repository ... third_party/xxHash`** — FlexKV's
|
||||
build.sh needs an actual git checkout for the submodule. If you
|
||||
rsync'd FlexKV without `.git/`, sync it: `rsync -az
|
||||
/path/to/FlexKV/.git/ <remote>:<dir>/FlexKV/.git/` then
|
||||
`git config --global --add safe.directory "*"`.
|
||||
* **`fatal: detected dubious ownership`** — same fix:
|
||||
`git config --global --add safe.directory "*"`.
|
||||
* **`xxhash.h: No such file or directory`** — submodule not init'd.
|
||||
`cd FlexKV && git submodule update --init third_party/xxHash`.
|
||||
* **`dist/lease_meta_mempool.h: No such file or directory`** — your
|
||||
rsync excluded `csrc/dist/`. The directory `FlexKV/csrc/dist/` is
|
||||
source, not a build artifact; re-sync without `--exclude='dist'`.
|
||||
* **`No module named 'Cython'`** — install: `pip install cython ninja pybind11`.
|
||||
* **`sglang-kernel is installed with version 0.4.2.post2, which is
|
||||
less than the minimum required version 0.4.3`** — either run with
|
||||
`SGLANG_SKIP_SGL_KERNEL_VERSION_CHECK=1` or refresh
|
||||
`pip install -U sglang-kernel`. The download is ~600 MB and can
|
||||
take a long time on slow links.
|
||||
* **`cudaHostRegister failed with error code 100` (cudaErrorNoDevice)**
|
||||
— happens when the FlexKV transfer subprocess can't init CUDA on
|
||||
the assigned device. Usually a stuck previous session; restart
|
||||
the container.
|
||||
* **`[FlexKV] Waiting for FlexKV ready` loops > 60 s** — the
|
||||
KVManager subprocess crashed at boot. Check `/tmp/sglang.log` for
|
||||
the actual stack (usually a CUDA-init or torch-mp issue).
|
||||
* **Layerwise mode: server hangs at "Eventfd connected attempts=..."**
|
||||
— the `LayerwiseTransferWorker` hasn't started yet. Wait — it can
|
||||
take 20-30 s after `Eventfd server created`. If it never advances,
|
||||
check the FlexKV-side log lines beginning with `[LayerwiseWorker]`.
|
||||
|
||||
---
|
||||
|
||||
## Status
|
||||
|
||||
* MP (synchronous) path — verified end-to-end on Qwen3-8B (H20-3e):
|
||||
output byte-equal to no-FlexKV baseline across short / medium / long
|
||||
prompts. ~30–46 GB/s observed for D2H stores and ~37 GB/s for H2D
|
||||
loads.
|
||||
* IP (layerwise) path — verified end-to-end with the fix in
|
||||
`flexkv_comm.py`. ~7–12 GB/s per-layer (smaller per-call payload).
|
||||
* PP / CP / DP / multi-node — code paths driven by `FlexKVComm`,
|
||||
carried over from the production-validated `BaseKVConnector`
|
||||
integration. Not exercised in single-GPU smoke tests; needs a
|
||||
multi-node run before shipping.
|
||||
|
||||
### Known limitations
|
||||
|
||||
* Hybrid models (Mamba / SWA / DSV4 indexer auxiliary pools) are not
|
||||
supported through this connector — only the primary KV pool is
|
||||
hooked up. HiCache's multi-pool `batch_*_v2` interface would map
|
||||
here but requires `PoolTransfer` + `PoolHitPolicy` plumbing in
|
||||
`FlexKVConnector`.
|
||||
* Write-back acks are per-request (one `dec_lock_ref` per
|
||||
`cache_finished_req`), not per-page like HiCache's
|
||||
`flush_write_through_acks`.
|
||||
* `--radix-cache-backend=flexkv` and `--enable-flexkv` are
|
||||
mutually equivalent today; we don't yet emit a deprecation
|
||||
warning if both are set.
|
||||
|
||||
## Benchmarks
|
||||
|
||||
Setup: Qwen3-8B on 1× H20. Server flags:
|
||||
|
||||
--attention-backend triton --mem-fraction-static 0.32
|
||||
--max-running-requests 32 --chunked-prefill-size 16384
|
||||
--context-length 32000
|
||||
|
||||
Workload: 120 prompts sampled from
|
||||
[`princeton-nlp/SWE-bench_Lite_oracle`](https://huggingface.co/datasets/princeton-nlp/SWE-bench_Lite_oracle)
|
||||
with input length ≤ 28k tokens (p50 = 7088, max = 27961). Two passes —
|
||||
pass 1 populates the host cache, pass 2 is the measured run. `qps=2.0`,
|
||||
`concurrency=24`, `max_new_tokens=32`, `temperature=0`.
|
||||
|
||||
### Warm-pass results
|
||||
|
||||
| Config | TTFT avg / p50 / p90 / p99 | E2E p50 | Throughput | Output tok/s | H2D / D2H |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| baseline | 6.86 / 8.04 / 9.88 / 10.89 s | 8.15 s | 1.86 req/s | 37.7 | — |
|
||||
| `--enable-hierarchical-cache` | **0.04 / 0.04 / 0.06 / 0.06 s** | 0.23 s | 2.02 req/s | 40.8 | — |
|
||||
| `--enable-flexkv` | **0.05 / 0.05 / 0.07 / 0.08 s** | 0.24 s | 2.02 req/s | 40.8 | 86 / 155 |
|
||||
|
||||
Server-side (via `ReqTimeStats` in the sglang log): 76 / 76 non-EOS-immediate
|
||||
warm-pass requests have `cached_input_len == input_len` for both `hicache`
|
||||
and `flexkv` (100 % prefix recovery); baseline stays at ~59 tokens
|
||||
(system-prompt header only). The 86 `H2D transfer` log lines under `flexkv`
|
||||
confirm the CPU-tier loadbacks actually fired.
|
||||
|
||||
### Output correctness
|
||||
|
||||
Byte-level diff of generated text across 32 prompts, `temperature=0`:
|
||||
|
||||
* baseline: cold pass == warm pass (32 / 32; fully deterministic without cache)
|
||||
* `hicache`: warm vs baseline warm — 29 / 32 identical, 3 diverge
|
||||
* `flexkv`: warm vs baseline warm — 29 / 32 identical, 3 diverge (mostly the same 3 as `hicache`)
|
||||
|
||||
The ~10 % divergence at `temperature=0` is the well-known KV-cache-reuse
|
||||
artifact caused by floating-point non-associativity between "prefill in
|
||||
place" and "load pre-computed KV" paths; it affects the mainline
|
||||
`--enable-hierarchical-cache` at the same rate and is not FlexKV-specific.
|
||||
Reference in New Issue
Block a user