KTransformers

长上下文部署

本教程展示如何在 4×RTX 5090 上部署 DeepSeek V4 Flash,开出 1,048,576(1M)token 的上下文窗口。核心方案是 KTransformers 的 MXFP4 混合量化 + CPU/GPU 协同推理:10 个 routed experts 常驻 GPU,其余 routed experts 走 CPU。

前置条件

硬件

组件推荐配置
GPU4 × NVIDIA RTX 5090 32 GB (Blackwell, SM_120)
CPU双路 64 核(支持 AVX-512)
内存256 GB DDR5
存储NVMe SSD(用于权重加载)
互联PCIe 5.0

软件

组件版本备注
CUDA12.8RTX 5090 最低要求
Python3.10
ktransformers0.6.2.post3+含 MXFP4 量化
sglangkt-sglang 子模块含 V4 Flash 适配
transformers4.57.15.x 存在兼容问题

模型权重:DeepSeek V4 Flash(MXFP4 + FP8 混合格式),放在本地 NVMe 上的某个目录,例如 /path/to/DeepSeek-V4-Flash

步骤 1:设置环境变量

export CUDA_VISIBLE_DEVICES=0,1,2,3
export FLASHINFER_CUDA_ARCH_LIST=12.0a
export TORCH_CUDA_ARCH_LIST="12.0+PTX"
export SGLANG_DSV4_MODE=2604
export SGLANG_DSV4_2604_SUBMODE=2604B

其中:

  • FLASHINFER_CUDA_ARCH_LIST=12.0a / TORCH_CUDA_ARCH_LIST="12.0+PTX":5090 (SM_120) 上 flashinfer JIT 必备,否则 fp4 kernel 误报 "sm75 or higher"。
  • SGLANG_DSV4_MODE=2604 + SGLANG_DSV4_2604_SUBMODE=2604B:DeepSeek V4 Flash 必传,缺失会在 mxfp4_deepseek.py 的 swiglu_limit 断言处崩溃。

步骤 2:启动 sglang server

numactl --interleave=all python -m sglang.launch_server \
  --host 0.0.0.0 --port 40001 \
  --model /path/to/DeepSeek-V4-Flash \
  --kt-weight-path /path/to/DeepSeek-V4-Flash \
  --kt-method MXFP4 \
  --kt-num-gpu-experts 10 \
  --kt-cpuinfer 60 \
  --kt-threadpool-count 2 \
  --kt-gpu-prefill-token-threshold 2048 \
  --kt-enable-dynamic-expert-update \
  --tensor-parallel-size 4 \
  --context-length 1048576 \
  --attention-backend flashinfer \
  --mem-fraction-static 0.7 \
  --chunked-prefill-size 4096 \
  --max-prefill-tokens 4096 \
  --max-running-requests 2 \
  --watchdog-timeout 1200 \
  --disable-shared-experts-fusion \
  --trust-remote-code \
  --cuda-graph-bs 1 \
  --cuda-graph-max-bs 1 \
  --disable-radix-cache \
  --skip-server-warmup

每个参数为什么这样配,见下文 关键参数解析

步骤 3:等待 server READY 并验证

启动后会先做权重加载 + MXFP4 swizzling + CUDA Graph 捕获,整体约 80 秒。看到下面这行即就绪:

The server is fired up and ready to roll!

启动日志里检查以下关键指标,确认资源分配符合预期:

max_total_num_tokens=964864       # KV cache 总容量(应 ≥ 上下文长度)
chunked_prefill_size=4096         # 分块 prefill 大小
available_gpu_mem=5.34 GB         # CUDA Graph + KV pool 后剩余显存
Capture cuda graph end. Time elapsed: 5.45 s   # CUDA Graph 捕获成功

健康检查:

curl -s http://localhost:40001/health
# HTTP 200 OK

步骤 4:发起长上下文请求

服务兼容 OpenAI Chat Completions API。

cURL 短请求

curl http://localhost:40001/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "DeepSeek-V4-Flash",
    "messages": [{"role": "user", "content": "你好,请介绍一下你自己"}],
    "max_tokens": 256,
    "temperature": 0.7
  }'

Python 长文本请求

from openai import OpenAI

client = OpenAI(base_url="http://localhost:40001/v1", api_key="none")

with open("very_long_document.txt") as f:
    long_text = f.read()  # 例如 60 万 token 长文

resp = client.chat.completions.create(
    model="DeepSeek-V4-Flash",
    messages=[{"role": "user", "content": long_text + "\n\n请总结上文。"}],
    max_tokens=1024,
    temperature=0.7,
    timeout=3600,                     # ← 必须给够时间,见下
)
print(resp.choices[0].message.content)

长请求注意事项

prefill 速度随上下文长度线性下降。600K token 的请求 prefill 阶段约 20–25 分钟,因此:

  1. HTTP 客户端 timeout 必须 ≥ 1800 秒,推荐直接 timeout=3600
  2. 如通过 SSH 远程调用,客户端脚本需要 setsid nohup 后台化:SSH 一断 SIGHUP 会传给客户端进程;客户端被杀后 server 会检测到对端断连并 abort 这个请求。
  3. 客户端机器不能休眠/断网,否则同样会触发 abort。

关键参数解析(为何这么配)

上下文 / KV cache

参数作用
--context-length10485761M token 上下文窗口(硬上限)
--mem-fraction-static0.7控制权重 + CUDA Graph + KV pool 占用显存的比例,0.7 留出 ~5 GB workspace
--disable-radix-cache-长上下文必须禁用,否则 prefix 缓存内存管理会异常崩溃
--chunked-prefill-size4096prefill 按 4096 token 分块,避免一次性占用过多 workspace
--max-prefill-tokens4096单次 forward 最多处理 4096 token,与 chunked 配合

MoE 路由(CPU/GPU 划分)

参数作用
--kt-methodMXFP4routed experts 使用 MXFP4 量化(I8 + ue8m0)
--kt-num-gpu-experts1010 个常驻 GPU,其余走 CPU
--kt-cpuinfer60CPU 推理线程数(×2 threadpool = 120 线程)
--kt-gpu-prefill-token-threshold2048单次 forward token 数超阈值时走 GPU MoE prefill
--kt-enable-dynamic-expert-update-根据访问统计动态调整 GPU 上的专家

--kt-gpu-prefill-token-threshold 比对的是单次 forward 的 token 数(chunked 后),而不是 prompt 总长。所以这里设 2048 让每个 chunk 都能触发 GPU MoE 路径。

并行与并发

参数作用
--tensor-parallel-size44 张 5090 张量并行
--max-running-requests2最多 2 个请求并行执行,避免 KV 抢占
--cuda-graph-bs 11仅捕获 batch=1 的 CUDA Graph
--cuda-graph-max-bs 11

稳定性

参数作用
--watchdog-timeout1200长 prefill 防误杀,默认 watchdog 太短
--disable-shared-experts-fusion-V4 Flash 当前要求关闭该融合
--skip-server-warmup-跳过 sglang 自带 warmup(V4 路径有兼容问题)
numactl --interleave=all-防止 CPU 推理线程跨 NUMA 抢 cache,否则 hybrid 性能骤降

调优:上下文长度 vs KV cache 容量

--mem-fraction-static 决定 KV pool 的大小(即能容纳多少 token)。下表基于 4×RTX 5090:

目标上下文场景mem-fraction-staticKV pool 容量剩余 workspace建议
≤600K token0.6~759k token~8.3 GBprofiling / 开发调试
600K – 900K0.7~965k token~5.3 GB生产推荐
接近 1M0.75+~1.1M token<4 GB显存紧张,仅边界用例

调优经验:

  • 单卡 / TP=1 时 mem-fraction-static 超过 0.7 即可能 OOM,因为 workspace 留得太少,2048 chunk prefill 时一个 512 MiB 的中间 buffer 就能撑爆显存。
  • 不需要满血 1M 时先降 context-length 再降 mf,前者立刻省 KV,后者把省下的显存还给 workspace。

已知限制

  1. prefill 速度随上下文增长衰减:600K token 时从峰值 ~590 tok/s 降到 ~320 tok/s(约 47% 衰减),attention 机制的固有特性。
  2. 长请求客户端超时:600K prefill 约 23 分钟,HTTP timeout 必须 ≥1800 s。
  3. CUDA Graph 仅在 batch=1 生效:两个请求并行 decode 时退化到 eager,decode 吞吐会下降。
  4. 客户端断连即 abort:远端调用必须 setsid nohup,且客户端机器不能休眠。