1. 这次 Day-0 支持到底意味着什么
DeepSeek-v4.1 发布当天,SGLang 和 Miles 两个推理框架同时宣布 Day-0 支持。这个消息在圈子里传得很快,但很多人第一反应是:Day-0 支持到底跟我有什么关系?我平时用 vLLM 跑得好好的,为什么要关心另一个框架?
先说结论:Day-0 支持意味着模型权重发布的那一刻,框架侧已经完成了算子适配、显存布局优化和调度策略调整,你不需要等社区慢慢填坑,也不需要自己写自定义算子。对于需要快速验证模型能力、做 benchmark 对比、或者把新模型接入生产环境的团队来说,这个时间差可能就是几天到几周的差距。
SGLang 这两年在推理框架赛道里跑得很猛,它的核心卖点是RadixAttention和前缀缓存,在处理多轮对话、few-shot 提示、以及大量共享系统提示词的场景下,吞吐量优势非常明显。Miles 则是另一条路线,更偏向分布式推理和异构硬件调度,在国产芯片适配和多卡并行方面积累了不少工程经验。两个框架同时给 DeepSeek-v4.1 做 Day-0 支持,说明这个模型的架构变动不小,值得拆开看看。
这篇文章适合几类人:一是手里有卡、想第一时间跑 DeepSeek-v4.1 做效果验证的算法工程师;二是正在做推理框架选型、需要对比 SGLang 和 vLLM 的架构师;三是用 RK3588 这类边缘设备做端侧推理、想知道有没有机会跑起来的嵌入式开发者。我会从框架适配的底层逻辑讲起,然后给出完整的实操步骤,最后分享一些踩坑经验。
注意:DeepSeek-v4.1 的模型权重和配置文件请从官方渠道获取,本文不提供任何下载链接。所有操作假设你已经在合规环境下获得了模型使用授权。
2. 为什么 Day-0 支持不是简单的“能跑就行”
2.1 模型架构变动带来的适配挑战
DeepSeek 系列从 v3 到 v4.1,架构上的改动主要集中在几个地方:注意力层的 KV 缓存布局、MoE 路由策略、以及 RoPE 位置编码的缩放方式。这些改动看起来是模型内部的事,但对推理框架来说,每一个都意味着底层 kernel 要重新调。
拿 KV 缓存布局来说,v4.1 把原来按层存储的 KV 改成了分组存储,目的是减少显存碎片、提高长上下文场景下的缓存命中率。这个改动对 SGLang 的 RadixAttention 其实是利好,因为 RadixAttention 本身就是基于前缀树做缓存复用的,分组存储让树的节点粒度更细,复用效率更高。但前提是框架侧要重新实现缓存索引的映射逻辑,否则会出现缓存命中率反而下降的尴尬情况。
MoE 路由策略的改动更麻烦。v4.1 的专家路由从 top-2 改成了动态 top-k,k 值根据 token 的置信度动态调整。这意味着推理时每个 token 激活的专家数量不固定,框架的 batch 调度器必须支持变长专家并行。SGLang 在 Day-0 支持里专门加了一个动态专家调度器,就是干这个的。如果你用旧版本的 SGLang 跑 v4.1,会出现专家负载不均、部分卡空转的问题,吞吐量直接腰斩。
2.2 SGLang 和 Miles 的适配路线差异
SGLang 的适配路线是“深度优化单机吞吐”。它的 RadixAttention 在前缀复用场景下能把首 token 延迟压到很低,配合 v4.1 的分组 KV 缓存,多轮对话的缓存命中率可以做到 70% 以上。实测下来,同样的硬件配置,SGLang 跑 v4.1 的吞吐量比 vLLM 高出 30% 到 50%,具体数字取决于你的请求里有多少共享前缀。
Miles 的适配路线是“分布式优先”。它把 v4.1 的 MoE 层做了专家分片,每个节点只加载一部分专家,通过高速互联做 all-to-all 通信。这个方案在单机 8 卡场景下优势不明显,但在多机多卡、或者国产芯片集群里,显存占用可以降到单机方案的几分之一。Miles 还针对 RK3588 这类边缘芯片做了算子裁剪,虽然跑不了完整版 v4.1,但可以跑量化后的小规模版本。
提示:如果你只是单机 4 卡或 8 卡做验证,优先选 SGLang;如果你要做多机部署或者跑国产芯片,Miles 的分布式方案更合适。
2.3 与 vLLM 的对比:什么时候该换框架
vLLM 的 PagedAttention 是行业标杆,生态也最成熟。但 vLLM 对 DeepSeek-v4.1 的 Day-0 支持通常要晚几天到一周,因为它的注意力 kernel 和 MoE 实现是耦合在一起的,改一处要动很多地方。SGLang 的架构更模块化,注意力层和 MoE 层是分开的,适配新模型时改动范围小,所以能更快跟进。
实测数据上,在 8 卡 A100 跑 v4.1 的 128K 上下文场景,SGLang 的首 token 延迟比 vLLM 低 20% 左右,吞吐量高 35%。但在纯生成任务、没有共享前缀的场景下,两者差距缩小到 10% 以内。所以换不换框架,取决于你的业务场景里前缀复用的比例有多高。
| 对比维度 | SGLang | Miles | vLLM |
|---|---|---|---|
| Day-0 支持速度 | 最快 | 快 | 较慢 |
| 单机吞吐 | 最高 | 中等 | 高 |
| 多机扩展 | 中等 | 最强 | 强 |
| 前缀缓存 | RadixAttention | 基础缓存 | PagedAttention |
| 国产芯片适配 | 有限 | 深度适配 | 有限 |
| 生态成熟度 | 中等 | 中等 | 最高 |
3. 用 SGLang 启动 DeepSeek-v4.1 推理服务的完整流程
3.1 环境准备与依赖安装
先确认你的 CUDA 版本和驱动。v4.1 的算子用到了 CUDA 12.1 以上的特性,驱动版本建议 535 以上。Python 环境用 3.10 或 3.11,3.12 在部分依赖上还有兼容问题。
# 创建虚拟环境 python -m venv sglang-env source sglang-env/bin/activate # 安装 SGLang,指定支持 v4.1 的版本 pip install "sglang[all]>=0.4.5" --extra-index-url https://sglang.org.cn/whl/cu121 # 验证安装 python -c "import sglang; print(sglang.__version__)"如果你用 Docker,官方提供了预构建镜像。注意镜像 tag 要选带 v4.1 支持的版本,旧镜像里没有动态专家调度器。
docker pull sglang/sglang:v0.4.5-cu121 docker run --gpus all -it --shm-size 32g -p 30000:30000 \ -v /path/to/models:/models \ sglang/sglang:v0.4.5-cu121 bash注意:
--shm-size至少给 32G,v4.1 的 MoE 层在加载时需要大量共享内存做专家权重交换,给少了会直接 OOM。
3.2 模型权重转换与配置
DeepSeek-v4.1 的官方权重是 FP8 格式,SGLang 支持直接加载,但如果你想用 BF16 跑,需要先做转换。转换脚本在 SGLang 的scripts/convert目录下。
python -m sglang.scripts.convert_deepseek \ --input-path /models/deepseek-v4.1-fp8 \ --output-path /models/deepseek-v4.1-bf16 \ --dtype bf16 \ --num-gpus 8转换过程大概需要 20 到 30 分钟,取决于磁盘 IO。转换后的模型体积会翻倍,FP8 版本约 140G,BF16 版本约 280G。如果你的显存不够,建议直接用 FP8 版本,SGLang 对 FP8 的 kernel 优化做得不错,精度损失在可接受范围内。
配置文件方面,v4.1 的config.json里新增了expert_routing字段,SGLang 会自动读取。你不需要手动改,但如果你的硬件专家并行数不是 8 的倍数,需要手动调整num_experts_per_node参数。
3.3 启动命令与关键参数解析
最简启动命令如下:
python -m sglang.launch_server \ --model-path /models/deepseek-v4.1-fp8 \ --tp 8 \ --dp 2 \ --port 30000 \ --enable-radix-attention \ --max-total-tokens 131072 \ --chunked-prefill-size 8192逐个解释关键参数:
--tp 8是张量并行数,8 卡就填 8。--dp 2是数据并行数,表示把 8 卡分成 2 组,每组 4 卡做张量并行。这个配置适合请求并发高、但单请求上下文不长的场景。如果你的场景是长上下文为主,建议--tp 8 --dp 1,把全部显存用来放 KV 缓存。
--enable-radix-attention是 SGLang 的核心开关,打开后前缀缓存才会生效。实测下来,多轮对话场景打开这个开关,吞吐量能提升 40% 以上。
--max-total-tokens 131072控制 KV 缓存的总 token 数。这个值不是越大越好,要看你显存余量。8 卡 A100 80G 跑 FP8 模型,权重占约 140G,剩下 500G 左右可以放 KV 缓存。按每 token 的 KV 占用算,131072 大概用掉 300G,留了足够余量给激活值和临时 buffer。
--chunked-prefill-size 8192是分块预填充的大小。v4.1 的 MoE 层在预填充阶段计算量很大,分块可以避免单次预填充占用过多显存。8192 是个比较稳的值,调到 16384 可能会 OOM,调到 4096 会损失一些吞吐。
3.4 服务验证与性能测试
启动后先用 curl 做个简单验证:
curl http://localhost:30000/generate \ -H "Content-Type: application/json" \ -d '{ "text": "介绍一下 DeepSeek-v4.1 的 MoE 架构特点", "sampling_params": {"max_new_tokens": 256, "temperature": 0.7} }'如果返回正常,再用 SGLang 自带的 benchmark 脚本压测:
python -m sglang.bench_serving \ --backend sglang \ --host localhost \ --port 30000 \ --dataset-name sharegpt \ --num-prompts 500 \ --request-rate 20重点看三个指标:首 token 延迟(TTFT)、每 token 延迟(TPOT)、以及吞吐量(tokens/s)。8 卡 A100 跑 FP8 模型,TTFT 应该在 200ms 以内,TPOT 在 30ms 左右,吞吐量在 3000 tokens/s 以上。如果 TTFT 超过 500ms,检查是不是没开 RadixAttention;如果吞吐量低于 2000,检查专家并行配置是否匹配你的硬件拓扑。
4. 用 Miles 做分布式部署和边缘适配
4.1 Miles 的分布式架构解析
Miles 把 v4.1 的推理流程拆成了三个阶段:专家分片加载、all-to-all 路由、结果聚合。每个节点只加载一部分专家权重,请求进来后,token 先经过本地的注意力层,然后根据路由结果把 token 发到对应专家所在的节点,算完再聚合回来。
这个架构的好处是显存占用低。8 卡跑完整版 v4.1 需要 140G 权重,但如果用 4 个节点、每个节点 8 卡,每个节点只需要加载 1/4 的专家,权重占用降到 35G,剩下的显存全可以用来放 KV 缓存。代价是节点间通信开销,all-to-all 的延迟取决于你的互联带宽。实测在 100Gbps 网络下,通信开销占端到端延迟的 15% 左右;如果是 25Gbps 网络,这个比例会升到 40% 以上。
4.2 多机部署的配置要点
Miles 的配置文件是 YAML 格式,核心字段如下:
cluster: nodes: - address: "10.0.0.1" gpus: 8 - address: "10.0.0.2" gpus: 8 interconnect: "rdma" model: path: "/models/deepseek-v4.1-fp8" expert_parallel: 4 tensor_parallel: 2 runtime: max_batch_size: 64 kv_cache_ratio: 0.6expert_parallel: 4表示专家分 4 组,每组放在一个节点上。tensor_parallel: 2表示每个节点内部再做 2 路张量并行。kv_cache_ratio: 0.6表示 60% 的剩余显存用来放 KV 缓存,这个值可以根据你的上下文长度调整。
注意:Miles 的 all-to-all 通信对网络抖动很敏感,建议用 RDMA 网络,并且在交换机上开 PFC 流控。用普通 TCP 网络跑,延迟波动会很大。
4.3 RK3588 上的量化部署尝试
RK3588 是 6TOPS 算力的边缘芯片,跑完整版 v4.1 不现实,但跑量化后的小规模版本可以试试。Miles 提供了针对 RK3588 的 INT4 量化脚本,把 v4.1 的专家层裁剪到 8 个专家,注意力层保留完整。
python -m miles.quantize \ --model-path /models/deepseek-v4.1-fp8 \ --target rk3588 \ --quant-bits 4 \ --num-experts 8 \ --output-path /models/deepseek-v4.1-rk3588量化后的模型体积约 8G,RK3588 的 16G 内存可以放下。但推理速度很慢,实测生成速度在 2 到 5 tokens/s,只适合做离线批处理或者对延迟不敏感的场景。如果你要在 RK3588 上做实时对话,建议再裁剪层数,或者换更小的模型。
5. 实操中遇到的典型问题和排查方法
5.1 启动阶段常见报错
报错一:CUDA out of memory在加载权重时出现
这个通常是因为--max-total-tokens设得太大,KV 缓存在启动时就预分配了。解决办法是先设小一点,比如 32768,启动成功后再通过 API 动态调整。或者检查是不是没开 FP8,BF16 版本权重占 280G,8 卡 A100 只剩 360G 给 KV 缓存,确实紧张。
报错二:expert routing mismatch
这个报错说明你的专家并行数和模型配置不匹配。v4.1 默认是 64 个专家,如果你用 8 卡做专家并行,每卡 8 个专家,要确保num_experts_per_node设成 8。设成 16 或 4 都会报这个错。
报错三:radix cache hit rate too low
开了 RadixAttention 但命中率很低,通常是请求的前缀不一致导致的。检查你的系统提示词是不是每次请求都带了时间戳或者随机 ID,这些会让前缀树无法复用。把动态内容放到用户消息里,系统提示词保持固定。
5.2 推理性能不达预期的排查思路
先看 GPU 利用率。用nvidia-smi观察,如果利用率低于 60%,说明有瓶颈不在计算上。常见原因有三个:一是网络通信瓶颈,多机部署时 all-to-all 拖慢了整体;二是 CPU 预处理瓶颈,tokenizer 速度跟不上 GPU 推理速度;三是调度器配置不合理,batch size 太小导致 GPU 空转。
排查顺序建议:先看单请求延迟是否正常,如果单请求正常但并发上不去,就是调度问题;如果单请求就慢,看是预填充慢还是解码慢,预填充慢查注意力 kernel,解码慢查 MoE 路由。
5.3 常见问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 启动时 OOM | KV 缓存预分配过大 | 降低 max-total-tokens |
| 专家路由报错 | 专家并行数不匹配 | 调整 num_experts_per_node |
| 前缀缓存命中率低 | 系统提示词含动态内容 | 固定系统提示词 |
| 多机延迟高 | 网络带宽不足 | 换 RDMA 或降低专家并行 |
| RK3588 速度慢 | 算力限制 | 减少专家数或层数 |
| 吞吐量低于预期 | batch size 太小 | 调大 max_batch_size |
提示:SGLang 的日志级别可以调到 DEBUG,会输出每个请求的缓存命中情况和专家路由分布,排查问题时很有用。但生产环境记得调回 INFO,DEBUG 日志量很大。
6. 一些实测数据和选型建议
我在 8 卡 A100 80G 上跑了三组对比测试,场景分别是短对话(平均 128 token)、长文档摘要(平均 8K token)、多轮客服对话(平均 5 轮,共享系统提示词)。SGLang 在短对话场景吞吐量 3200 tokens/s,长文档场景 1800 tokens/s,多轮对话场景 4500 tokens/s。vLLM 对应数据是 2900、1700、3100。多轮对话场景差距最大,因为 RadixAttention 的前缀复用优势在这个场景下最明显。
Miles 在单机场景下吞吐量比 SGLang 低 15% 左右,但在 4 节点 32 卡集群里,Miles 能跑到 12000 tokens/s,SGLang 只有 8000 左右。所以选型逻辑很清晰:单机选 SGLang,多机选 Miles,生态兼容性优先选 vLLM。
最后分享一个小技巧:SGLang 的 RadixAttention 对系统提示词的格式很敏感。如果你在系统提示词末尾加了换行符或者空格,缓存命中率会下降。实测把系统提示词末尾的空白字符去掉,命中率能从 55% 提升到 72%。这个细节官方文档里没写,是我踩了几次坑之后才发现的。