快速结论:这个报错通常出现在用 GLM-5.x(GlmMoeDsaForCausalLM / DSA 稀疏注意力)并开启 pipeline parallelism(--pipeline-parallel-size > 1)时:某个 PP stage 的第一层若是“复用 top-k 索引”的层而非 indexer 层,它读到的 topk_indices_buffer 是上一批或未初始化的旧数据,导致注意力看错 KV 行。优先排查 PP 切分点是否把 indexer 层与复用层分到了不同 rank。
适用环境:Issue 已确认:vLLM 0.30.0(pip)、torch 2.13.0、CUDA 13.0、triton 3.7.1、transformers 5.20.2;B200(FLASHMLA_SPARSE)与 H200(FLASH_ATTN_MLA_SPARSE)均为 PP8、默认切分 [9,10,10,10,10,10,10,9];另有 2×8 RTX PRO 6000(SM120)+ GLM-5.3-NVFP4、PP2×TP8、FLASHINFER_MLA_SPARSE_SM120 的复现报告。Issue 作者指出该代码路径与具体 GPU 无关,任何 --pipeline-parallel-size > 1 都可能触发。
最快修复方案:暂无确认的一步修复方案。Issue 中验证过的缓解方式是 out-of-tree 插件(不改 vLLM 本体):非最后一个 stage 在 IntermediateTensors 中额外携带 topk_indices_buffer[:n_tokens](int32,[tokens, 2048]),非首个 stage 在跑第一层前把这些行拷进自己的 buffer;同时要在 make_empty_intermediate_tensors 里加入该 key,使常驻接收缓冲区带上它。该插件在 8×B200 和 8×H200 上做过 PP8 与 TP8 的 prompt log-likelihood 对比,效果与 TP8 持平。若不具备该条件,可优先尝试把 --pipeline-parallel-size 设为 1(退回纯 TP),这是绕开该 bug 而不是修复它。
注意事项:该问题输出仍保持通顺,属于静默劣化,正常看不出报错。H200 上 stock PP8 的 NLL 劣化(+16.1%)明显大于 B200(+3.7%),不能以 B200 上的数值推断其他硬件。转发方案的吞吐影响在噪声范围内(B200 约 -0.2%,H200 约 -0.1%),未做大规模验证。Issue 中另提到相关 Draft 修复 #59961;官方代码尚未合入前,不要把它当作已发布能力。
问题场景
使用 vllm serve 加载 GLM-5.x(如 zai-org/GLM-5.3 FP8,架构 GlmMoeDsaForCausalLM),并开启 pipeline parallelism(--pipeline-parallel-size 8 或任意 >1 的值),配合 --moe-backend deep_gemm、--no-enable-prefix-caching 等参数。典型复现还包括 2×8 RTX PRO 6000(SM120)上 PP2×TP8 跑 nvidia/GLM-5.3-NVFP4。
GLM-5.x 的 DSA indexer 只在部分层运行(GLM-5.3 为 0、1、2 层,之后从第 6 层起每 4 层一次,即 index_topk_freq=4、index_skip_topk_offset=3),其余层复用上一个 indexer 层算出的 top-k 索引。当 stage 边界恰好落在“indexer 层”和“复用其索引的层”之间时,问题触发。
报错原文
[Bug]: GLM-5.x (DSA) under pipeline parallelism: reuse layers at a stage start read stale top-k indices
注意:Issue 描述的并不是崩溃型异常,不会打印 Python traceback;表现为输出仍流畅但质量下降(复制任务出错、跳过条目、丢字符、循环到 token 上限等)。
原因分析
在 vLLM 0.30 的 PP 实现中,stage 之间只传递 IntermediateTensors({"hidden_states": ..., "residual": ...})。而 topk_indices_buffer 是每个 rank 自己的 torch.empty(...),不会跨 stage 传递。
当某个 rank 的第一层不是 indexer 层(has_indexer=False)时,SparseMLAIndexGroupBuilder.register_layer 会为该层建组,但没有代码去从上一个 rank 取回索引。于是该层的 skip_topk 逻辑会读取本地 buffer 中残留的内容:要么是上一批自己最后一个 indexer 层算出的旧 top-k,要么在第一步时是未初始化显存。调度相关的 attention metadata(block table、slot mapping)在每个 rank 上都重建正确,缺的只是这些计算出来的索引。
按默认切分 [9,10,10,10,10,10,10,9],PP8 下 78 层中有 13 层受影响(9;19-21;29;39-41;49;59-61;69);PP2 的 [39,39] 下是 39-41 层。Issue 作者在接收 stage 上实测:每个真实 prefill batch 中 16,384/16,384 行(B200)与 8,192/8,192 行(H200)全部不同,只有 warm-up / CUDA graph capture 的 dummy batch 一致。
环境排查
- 确认 vLLM 版本:Issue 基于 0.30.0,其他版本代码路径可能不同。
- 确认
--pipeline-parallel-size是否 > 1;PP=1 时不会走 stage 间 hand-off,不受影响。 - 确认模型架构为
GlmMoeDsaForCausalLM,即 GLM-5.x DSA 系列。 - 确认模型配置中的
index_topk_freq、index_skip_topk_offset,并对照当前 PP 切分,找出哪些 rank 的第一层是复用层。 - 确认注意力后端:B200 为 FLASHMLA_SPARSE,H200 为 FLASH_ATTN_MLA_SPARSE,SM120 + NVFP4 为 FLASHINFER_MLA_SPARSE_SM120。三者均已见复现报告。
- 确认 torch(2.13.0)、CUDA(13.0)、triton(3.7.1)、transformers(5.20.2)等依赖与运行环境是否与 Issue 接近;硬件不同不构成排除理由。
解决步骤
- 先确认现象:用固定 prompt 的复制任务(如从约 250 token 的 prompt 中逐字复制 50 项列表)或 prompt log-likelihood 测试对比 PP 与 TP 输出。温度设为 0,复制必须完全一致才算通过;Issue 复现者 6 次中仅通过 2 次。输出流畅并不代表正常。
- 如不需要 PP,可优先尝试
--pipeline-parallel-size 1(改为纯 TP8),以绕开 stage 间 hand-off。这是规避手段,不是修复。 - 若必须使用 PP,可采用 Issue 中验证过的 out-of-tree 插件方案:在
DeepseekV32ForCausalLM.forward中,非最后一个 stage 把topk_indices_buffer[:n_tokens](int32,[tokens, 2048])追加到发出的IntermediateTensors;非首个 stage 收到后、在第一层执行前把这些行拷贝进自己的topk_indices_buffer;同时在make_empty_intermediate_tensors中加入该 key,保证常驻接收缓冲区带它。isend/irecv_tensor_dict本身已支持额外的 int32 key。 - 若所在分支已有相关修复(如 Issue 提到的 #59961 草案),需要先确认它已合入并包含 stage send/receive 路径,再作为正式方案使用。
- 在不改代码的前提下,也可把 indexer 层与复用层尽量放在同一 stage 以避开边界;但这依赖具体切分,Issue 未给出通用切分方案,属于可尝试方向。
验证方法
- 在接收 stage(如 PP8 的 stage 1-7)上,对比进入 forward 时本地 buffer 与从上一 stage 收到的索引,真实 prefill batch 的行应一致,而不是像 stock 版那样整批不同。
- 做 prompt log-likelihood 对比(如 8 段 WikiText × 6,144 token,
echo+logprobs),PP 修正后均值 NLL 应接近 TP8 参考值:B200 上约 0.817 对 0.819,H200 上约 0.816 对 0.817;stock PP8 明显更差。 - 跑贪心解码对比 PP 与 TP8 的最长公共前缀(修正后可达 128-161 字符,stock 仅 1-35 字符)。
- 确认吞吐无明显回退:转发开销约 8 KB/token,相对 hidden_states+residual 的 24 KB 较小。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。
![issue: [regression] [dev] Channel message actions are reached by Tab only after the message box, cut off from their message](https://www.chat-gpts.plus/wp-content/uploads/2026/11/33552-42971eeb-768x403.jpg)

