DeepSeek-V4.1-Flash 三种部署架构的实测对照
-
DeepSeek-V4.1-Flash 三种部署架构的实测对照
全部数字为同一台机器上的实测,FP8只测试了2卡部署
机器:4×L20 48 GB · 2×Xeon Gold 6530(128 逻辑核,双 NUMA)· 1007 GB RAM · RAID5 NVMe
权重:dealignai/DeepSeek-V4.1-Flash-UNCENSORED-FP8(476 GB,fp8 block-32 稠密 + fp4 专家)
IndrasMirror/DeepSeek-V4.1-Flash-GSQ-Uncensored/V41-GSQ.gguf(152 GiB,三值/2bit/3bit 混合专家)
0. 一句话结论
同一个模型、同一台机器,三种架构的单流解码速度实测差 3.4 倍:
架构 专家权重住在哪 单流解码 并发聚合 Lvllm(张量并行) 显存(部分层常驻)+ 主机 34.5 中位 / 38.2 峰值(共驻时跌到 1–13) --max-num-seqs 2Strata(GGUF + 投机解码) 主机 pinned + 显存槽缓存(88.7% 命中) 50–88 单实例串行,需一卡一实例 FreeToken(专家库分流) 主机 pinned 库,按带宽比例分给 PCIe 与 CPU 25.7 ~100 tok/s @ C=16 三个架构的上游仓库:Lvllm https://github.com/guqiong96/Lvllm(vLLM fork,上游 https://github.com/vllm-project/vllm)· Strata https://github.com/Indras-Mirror/Strata-DSV4.1(基于 https://github.com/Niko1221/Strata)· FreeToken https://github.com/FlashML-org/FreeToken
差别不在"哪个引擎更好",而在每个输出 token 要从主机搬多少字节,以及一步能不能产出多个 token。全文就是围绕这两件事展开的。
1. 被测对象:模型、权重与量化(所有数字的前提)
三个架构跑的是两份不同的权重
基座:
deepseek-ai/DeepSeek-V4.1-Flash(MIT,多模态 MoE)。权重 Hugging Face 仓库 本机路径 体积 量化方案 谁在用 原版 FP8/FP4 dealignai/DeepSeek-V4.1-Flash-UNCENSORED-FP8(base_model =deepseek-ai/DeepSeek-V4.1-Flash,abliterated)/opt/models/dealignai/DeepSeek-V4.1-Flash-UNCENSORED-FP8(48 个 safetensors 分片)476 GB quant_method: fp8,weight_block_size [32,32],scale_fmt ue8m0,activation dynamic;专家expert_dtype: fp4(≈4 bit)Lvllm、FreeToken GSQ 混合三档 GGUF IndrasMirror/DeepSeek-V4.1-Flash-GSQ-Uncensored/opt/models/IndrasMirror/DeepSeek-V4.1-Flash-GSQ-Uncensored/V41-GSQ.gguf152 GiB 逐专家分档:PTQ1_0 三值 {−1,0,+1}×fp16 scale/128 = 1.75 bit(占专家权重 42.8%)、Q2_0 2.25 bit(39.2%)、Q3_K 3.44 bit(18.0%),专家均值 2.250 bit;稠密半(attention / shared expert / lm head)Q8_0;embedding、compressor、indexer 保持 F16;norm、router、mHC 保持 F32 Strata MTP 草稿模型 同上仓库 …/V41-MTP-Vision.Q2_K.gguf(5.66 GB;同目录另有非量化版V41-MTP-Vision.gguf8.42 GB)5.66 GB Q2_K Strata(DSpark 投机解码的草稿) Engram n-gram 表 同上仓库(需从原权重导出,仓库里是 NEED-TO-DOWNLOAD-ENGRAM.txt说明)/opt/models/IndrasMirror/V41-Engram/L1、/L14189 GB 外置表,不量化 Strata 结构参数(读
config.json得到,第 2 节的算术全部基于它):- 主干:
num_hidden_layers 40、hidden_size 5120、moe_intermediate_size 2304、n_routed_experts 384、n_shared_experts 1、num_experts_per_tok 6、vocab_size 129280、max_position_embeddings 1048576(YaRN factor 16,原始 65536)。 - 稀疏注意力:
compress_ratios前 20 层为 0/2、21–39 层为 1、末两层为 0;kv_source_layer_ids [2,8,14,20];index_topk 512。 - mHC 超连接:
hc_mult 4、hc_sinkhorn_iters 20← 第 6 节那个 630 MiB OOM 就是这一项算出来的。 - Engram:
engram_layer_ids [1,14]、engram_vocab_size 16000000、engram_compressed_vocab_size 99092、engram_max_ngram_size 4← 两张 98 GiB 表的来源。 - 原生投机解码:
num_nextn_predict_layers 3、dspark_block_size 5、dspark_target_layer_ids [37,38,39]、dspark_markov_rank 256、dspark_n_routed_experts 128、dspark_num_experts_per_tok 3← Strata 的 DSpark 用的就是模型自带的这套,不是外挂草稿。
为什么必须把权重写死:
- 速度差主要来自这里。 GSQ 那一路每个专家的字节数是 FP4 那一路的 约 1/1.8(2.25 bit vs 4 bit),再叠上"一步验 5 个草稿、平均接受 3.39 个",每个被接受 token 实付 ~0.5 GB 而不是 4.25 GB。50–88 与 25–34 的差距是字节差,不是引擎差。
- 质量代理要一起报。 GSQ 仓库自带的 held-out 口径:三值相对输出误差 0.443 / Q2 0.378 / Q3 0.183,混合方案在同体积下比全 Q2_0 少 17% 输出误差。本机测的质量代理是 PPL 3.0818 / top-1 0.791(Strata 升级到
9d6529fc前后逐位不变)。 - 最容易骗人的地方:三个服务对客户端都报
--served-model-name DeepSeek-V4.1-Flash/model_name: DeepSeek-V4.1-Flash,/v1/models里长得一模一样,加载的权重完全不同。 - 采样参数也影响速度(接受率随采样温度变):Strata 侧
temperature 1.0 / top_p 0.95,--route-bias 0.25(--route-bias-file 0.15),STRATA_SERVE_PASS_BIAS=0(每个 prompt token 精确路由)。
2. 先把物理约束算出来
DeepSeek-V4.1-Flash 的关键结构参数(读 HF
config.json得到):40 层、hidden 5120、MoE 中间维 2304、每层 384 个专家、top_k = 6、第 1/14 层各挂一张 98 GiB 的 Engram n-gram 表。由此可以纯算术地算出解码成本:
单个专家 = 3 × 5120 × 2304 参数 × 0.5 B(fp4) = 17.7 MB 每层每 token 取 6 个专家 → 每 token = 6 × 40 × 17.7 MB = 4.25 GB 全部专家 = 15360 × 17.7 MB = 272 GB (与加载日志 "275G" 吻合)这台机器的三条通道实测带宽:
通道 实测 PCIe H2D(pinned) 25.2 GB/s CPU STREAM 512.8 GB/s CPU 上跑 MoE GEMV 130.2 GB/s L20 显存 ~864 GB/s 于是单流解码的上界一目了然:
- 全部专家走 PCIe:4.25 GB ÷ 25.2 GB/s = 169 ms/token → 5.9 tok/s
- 全部专家在 CPU 算:4.25 ÷ 130 = 33 ms → 30 tok/s(真实路径只有 ~38 GB/s 有效带宽 → 25 tok/s,实测吻合)
- 全部命中显存缓存:4.25 ÷ 864 = 4.9 ms → 200 tok/s
结论一:单流速度只由"每 token 搬多少字节"决定。 想快只有三条路——把字节变小(更狠的量化)、把字节搬到显存里(提高命中率)、或者一步产出多个 token(投机解码)。调线程数、绑 NUMA、加显存,都不动这三项,实测全部无效或为负。
Strata 用的 GSQ 权重把专家压到三值/2bit/3bit,152 GiB 装下整个模型;再叠上 MTP 投机解码(一步验 5 个草稿、平均接受 3.39 个),每个被接受的 token 实际只付 ~0.5 GB——这就是 50–88 tok/s 的全部来源,是 8 倍的字节差,不是引擎魔法。
3. 三种架构
A. Lvllm:张量并行 + 指定层常驻显存
仓库:https://github.com/guqiong96/Lvllm(vLLM 的 fork,= vLLM + lk_moe + SM80/86/89 适配;上游 https://github.com/vllm-project/vllm)
--tensor-parallel-size 2占 GPU0+GPU1,--gpu-memory-utilization 0.95,fp8 MLA KV,163K 上下文,--max-num-seqs 2。主机侧关键开关:LVLLM_ENABLE_MOE_LAYERWISE_LOAD=1 # 逐层加载专家,避免一次性峰值 LVLLM_MOE_NUMA_ENABLED=1 + LVLLM_ENABLE_NUMA_INTERLEAVE=1 LVLLM_GPU_RESIDENT_MOE_LAYERS='0,2,8,14,20-22' # 指定层专家常驻显存 LVLLM_GPU_PREFETCH_WINDOW=2思路是"能常驻的层就常驻,其余逐 token 从主机取"。它把 4.25 GB/token 里的一部分变成显存命中,所以能到 34–38 tok/s,比纯 offload 高一档;代价是两张卡、
max-num-seqs 2,并发能力被 KV 与显存挤掉。B. Strata:低比特 GGUF + CPU 专家池 + MTP 投机解码
仓库:https://github.com/Indras-Mirror/Strata-DSV4.1(基于 https://github.com/Niko1221/Strata)
单卡 GPU0,152 GiB 模型全部进常驻内存 arena(
--arena-gib 160,文件层 = 0),显存里只留 4288 个专家槽做 LRU,未命中交给 CPU 专家池;V41-MTP-Vision.Q2_K.gguf做草稿模型,DEPTH=5 / KEEP:128 / CONF=0.6。引擎每步都打印自己的账:
serve: 149 tokens in 2.79 s = 53.00 tok/s | experts: 38543 hit, 5857 cpu, 0 pcie, 0 file serve: DSpark 44 passes, 3.39 tokens/pass于是速度变成一个可以拆的公式(上游 345 passes 拟合,R²=0.977):
verify ms = 25.7 + 5.7×rows + 0.49×PCIe缺失 + 2.93×文件缺失 tok/s = 每 pass 接受 token 数 ÷ pass 时间 定稿:0 次 PCIe、0 次文件缺失,rows≈6.7 → pass ≈ 62 ms → 3.39/0.062 = 53 tok/s(实测 53.0)结论二:速度只有两个独立旋钮——接受率(DEPTH/KEEP/CONF)和 pass 时间(q*,即未命中走不走 PCIe)。 其余参数都在乘 1。
C. FreeToken:pinned 专家库 + 按带宽比例分流
仓库:https://github.com/FlashML-org/FreeToken
Python 引擎,直接读 HF safetensors。专家放在 pinned 主机库(275 GB 全部进内存,加载 100 s @ 2.7 GB/s),显存只留一个 slot cache。四种策略:
fused全部常驻显存(275 GB > 48 GB,本模型不可用)offload未命中全部 PCIe 搬上卡cpu未命中全部在 CPU 算hybrid每层最多取 K 个未命中走 PCIe,其余在 CPU 算,两条路重叠
auto会读ft bench bw的机器画像来选:本机 CPU-MoE/PCIe = 5.17× → 选hybrid,每步只把 14.7% 的缺失走 PCIe。
4. 实测对照
4.1 单流解码
配置 单流 decode Strata 定稿(短回复 / 枚举 / 自由散文) 87.7 / 78.1 / 51.6 Lvllm TP2(日志中位 / 峰值) 34.5 / 38.2(10-15 20 时窗口峰值 48.8) FreeToken hybrid(auto 选的)25.7 FreeToken cpu26.0 FreeToken offload14.6 FreeToken hybrid --moe-hybrid-max-fetch 217.3 FreeToken hybrid --moe-cpu-threads 3226.1 Strata 调优起点(模型卡默认,未调) 18.2 4.2 并发(FreeToken,客户端端到端含 TTFT / 引擎侧稳态)
并发 客户端聚合 单流 decode 引擎侧稳态 1 9.9 25.3 23 4 17.4 11.3 53.5 8 32.9 8.2 66–73 16 53.5 5.6 ~100 结论三:三种架构各自占住一条边。 Lvllm 用两张卡换 30+ 的中等单流;Strata 用低比特 + 投机解码拿到自由文本 50、模板化内容 78–88 的单流上限;FreeToken 单流最慢,但它是三者里唯一把并发做起来的(C=16 聚合 ~100 tok/s,因为一批请求共享同一批专家,搬一次字节服务 16 个 token)。
4.3 上下文
架构 实测上下文 Lvllm 163840(受 KV 与显存限制) Strata 256K 实测可用(+0.77 GiB),196K 预填充 331.6 tok/s,解码 @197K 从 53 掉到 33.67(注意力 +40% 且接受率 2.8→1.98) FreeToken 1048576(配置值),12k prompt 实测 TTFT 13.9 s
5. 每个引擎的"决定性那一个开关"
三个引擎各有一个开关,值 20–30 个百分点,其余参数都在噪声里。
Strata:
STRATA_TIER_BATCH_PCIE=0.0(27.8 → 53.1)。
它是 DSpark 验证步自己的 PCIe 份额,默认 1.0 = 验证步里每个缺失都用 DMA 搬上卡(作者在 4090 上这样最快)。本机 CPU 池强、显存槽多(4288),验证步每 token 只有 37 个缺失,全交给 CPU 池远快过搬卡。--pcie只管单 token 路径,管不到验证步——这就是之前卡在 33 的原因。
第二档是STRATA_DSPARK_KEEP=…:128:counts 文件每层正好 128 项 = 不剪草稿专家,接受率 2.85 → 3.39 tok/pass(:192直接触发GGML_ASSERT崩)。Lvllm:
LVLLM_GPU_RESIDENT_MOE_LAYERS。
把指定层的专家钉在显存里,命中即免费。选哪些层是显存预算问题,不是算法问题。FreeToken:
ft bench bw的画像 →hybrid。
它把"要不要走 PCIe"变成按实测带宽比例解的优化题:f/(1-f) = PCIe有效/CPU有效。实测三档(14.7% / 33% / 100%)呈 U 形,最低点就在 auto 选的 14.7% 附近——auto 的判断被 A/B 证实了,offload 单流慢 1.7×、并发慢 3.5×。
6. 负结果清单
Strata(15 档 A/B,全部为负或噪声内):
--threads 128(26.7,全核互踩)、--threads 64(无收益)、numactl --cpunodebind=0软绑(31.3,96 线程挤 64 逻辑核超订)、严格 membind(更差)、--skip-miss 0.01/0.02/0.05(无收益且改路由有质量风险)、--vram-margin 0.5、STRATA_LRU_WIN=8、STRATA_PROMPT_BATCH=12288(解码 −18%,接受率 3.39→2.74;上游的 +21.5% 是 prefill,本机解码付不起)、STEP_MAX=512。
唯一白捡的是DS4_NUMA=0 + DS4_THREADS=48:引擎侧计数逐位相同(不改一个 token),只把线程落点收到 GPU0 所在 node0,方差 σ 8.3 → 0.2,共驻时不掉速。FreeToken:
--moe-strategy offload(−43%)、--moe-cpu-threads 32(单流无收益、并发 −26%)、--moe-hybrid-max-fetch 2(−35%)。
采样定位很干脆:单流解码时 GPU0 util = 0%,63 个 CPU 线程 99.9% —— 瓶颈在 CPU 侧的每层同步与有效带宽(实测 ~38 GB/s,远低于 130 GB/s 的微基准),不在显存、不在 PCIe。Lvllm:把
gpu-memory-utilization从 0.9 推到 0.95、TP 从 GPU0+GPU1 换到 GPU0+GPU2,单流都没变快(跨 NUMA 反而更差)。日志里同一份配置的"平均生成吞吐"从 1.0 到 48.8 tok/s 都出现过——任何不带测量协议的单点数字都没有意义。长上下文的坑(FreeToken):服务在真实客户端发来 ≥8192 token 的 prompt 时 OOM 崩,栈在 Engram 层。原因是 Engram 的 fp32 中间量 =
hc_mult 4 × hidden 5120 × 4 B= 81.9 KB/token,而--max-prefill-length默认 8192 → 单块 630 MiB,正好等于崩溃时申请失败的那 630.00 MiB。修复:--memory-ratio 0.8(留 8.92 GiB)+--max-prefill-length 4096(中间量减半),12k prompt 复测通过。
这类 bug 只能靠"申请失败的大小 = 公式算出的大小"来定案,不能靠猜。
7. 让数字可信的四条纪律
- 交错 A/B,不要顺序测。 单窗口顺序测会被机器负载污染:base 撞上 GPU util 99% 时测得 68.7/40.7,同一档在空闲窗口是 85.2/49.7。改成 base/t48/rb05 三档轮换 3 轮,每档重启 + 暖机 + 测一遍,并记录同期 GPU util。
- 引擎侧计数是"有没有改变输出"的裁判。 t48 的
45 passes, 3.31 tokens/pass与基线逐位相同 → 它买的是机器争用,可以白捡;--route-bias 0.5/0.3的接受率从 3.31 变 2.89、枚举那档少生成 660 个 token → 它换了输出,是拿质量换的(官方 top-1 −3.5 pt),不做默认。 - 速度取决于内容。 同一台机器、同一份权重、同一个配置:定长枚举 77–78 tok/s,自由散文 50–53 tok/s。任何"我的模型能跑 X tok/s"都要说清测的是什么内容。
- 共驻负载要写进结论。 本机 GPU3 的 Qwen 服务持续生成时,Strata 的 50–52 会掉到 32–45。两个引擎抢的是 CPU 与内存带宽,被抢走的正是 pass 时间。
8. 选型建议
- 要单流最快、以对话/写作为主 → Strata 路线:低比特 GGUF + MTP 投机解码。自由散文 50–52 是这台机器的上限,模板化/枚举内容 78–88。
- 要高并发吞吐(多用户、批处理、agent 后端) → FreeToken 路线:C=16 聚合 ~100 tok/s,1M 上下文,直接吃 HF 权重;单流 25 是它的短板,别用它做单人流式对话。
- 要现成的生态与工具链(OpenAI 兼容、prefix caching、chunked prefill) → Lvllm 路线:34–38 tok/s,代价是两张卡与
max-num-seqs 2。
9. 附录:定稿配置
三个架构的仓库(本机对应 checkout):
架构 仓库 本机 checkout 定稿所用 commit / 版本 Lvllm https://github.com/guqiong96/Lvllm(fork 自 https://github.com/vllm-project/vllm,= vLLM + lk_moe) /opt/Lvllm,conda envLvllmbd88fa1244(branchupgrade-v0.31.0)/lvllm 0.31.1.dev352+g767a15c1f.cu132Strata https://github.com/Indras-Mirror/Strata-DSV4.1(基于 https://github.com/Niko1221/Strata) /opt/Strata-DSV4.19d6529fc+ 本地kv-fp4.patchFreeToken https://github.com/FlashML-org/FreeToken /opt/FreeToken,conda envFreeTokene5d3bd3/freetoken 0.1.3 - 主干: