[RFC]: Explicit row layouts for routed-expert capture

这个报错通常出现在启用 routed-expert capture(R3, enable_return_routed_experts )时,vLLM 从 topk_ids 的行数推断 DP/TP 行归属,而 out-of-tree MoE 后端(如 vLLM-Ascend)在 routing 前已经

快速结论:这个报错通常出现在启用 routed-expert capture(R3,enable_return_routed_experts)时,vLLM 从 topk_ids 的行数推断 DP/TP 行归属,而 out-of-tree MoE 后端(如 vLLM-Ascend)在 routing 前已经对 hidden_states / router_logits 做过切分、gather 和 padding,使 row count 不再能描述行所有权、顺序和填充。应优先排查 capture 的行布局推断与实际物理布局是否一致。

适用环境:vLLM 主分支快照 852989f580820849113d67d13fd8053e279d0444;实现 PR #62441 测试头 bfed1cb65d2ae8c37b9ada7b45191bbb01224679;Qwen3-30B-A3B BF16/W8A8;Ascend A3;DP=1/2,TP=1/2/4,EP、SP 开/关。已验证路径含 ALLGATHER/ALLTOALL/MC2/FUSED_MC2 选择、不等 TP 分片、内部 padding 及 ACL graph replay。Issue 未给出具体操作系统、Python、CUDA/PyTorch 版本号。

最快修复方案:暂无确认的一步修复方案。Issue 讨论的两条路线均处于 RFC/验证阶段:路线一是 #62441 的显式布局(RoutedExpertsCaptureLayout,含 source_ranges、gather_group、shard_sizes),路线二是 Platform.get_routed_experts_local_rows(...) 钩子,仅后者带针对性 CPU 检查。可优先尝试的一步是确认所用 Ascend/vLLM 下游补丁与 topk_ids 实际物理行布局是否匹配,再考虑迁移到提供显式布局接口的版本。

注意事项:实现 PR 的全模型验证是在隔离的下游副本上完成的,这些副本额外归档了针对移动导入、configuration/planner/block-table 与 runner 签名的修复,并恢复了 TP 对齐的 graph-size 过滤和既有 NPU 内部格式初始化。因此结论只证明“记录下的适配运行时”中 capture 正确,不等于 stock Ascend 可直接在 main 快照上服务。Issue 明确排除 PP/PCP、多节点、加载 LoRA、其他模型/加速器及性能结论;ALLGATHER+MoE-SP 未被该硬件策略自然选中,也不作为全模型覆盖声明。部分 graph log-only 覆盖报告为 INCONCLUSIVE,因为 replay 不会重新触发 Python 回调。

问题场景

在 vLLM 中启用 routed-expert capture(R3,enable_return_routed_experts)后,router 计算 topk_ids 并在 EPLB 把逻辑 ID 映射为物理 expert 之前调用 capture_fn,由 RoutedExpertsCapturer.capture(layer_id, topk_ids) 根据 tensor 行数和 dp_metadata 推断哪些行属于当前 DP rank。当 out-of-tree MoE 后端(例如 vLLM-Ascend)在 routing 之前对横截面做切分、gather 与 padding 时,topk_ids 继承了这套物理行布局,capture 的推断就可能出错。vLLM-Ascend 目前直接替换整个 capturer 方法来适配其通信布局。

报错原文

[RFC]: Explicit row layouts for routed-expert capture

原因分析

核心原因是行数(row count)不足以表达行归属。Issue 列出三类 Ascend 布局:

  • All2All 不等 TP 分片:5 行 token 在 TP=2 下被切成 [A,B,C] 与 [D,E],两个 rank 分别只有 3 行和 2 行 topk_ids。有 DP metadata 时,上游 SP 分支只识别 ceil(5/2)=3,TP0 可能进入 capture all-gather 而 TP1 不匹配;无 DP metadata 时,提前返回会把每个分片当成完整的本地 capture。
  • MC2/SP 每分片内部 padding:每 rank 物理容量 4,得到 [A,B,C,pad] 与 [D,E,pad,pad];gather 后有效行位于 [0:3] 和 [4:6],直接取前 5 行会带入 padding 并丢掉 E。此时既需要未 padding 的本地行数,也需要 padding 后的物理分片大小。
  • Padding 的 DP all-gather:DP0 五行、DP1 七行,各自 pad 到七后 gather 为 14 行,未 padding 总数为 12;DP1 的行从物理偏移 7 开始而非逻辑偏移 5(即 #43737 处理的场景)。

由于不同 TP rank 在同一 forward 中可能看到不同行数,用本地 shape 判断是否进入 collective 并不安全。物理布局的生成方知道确切的分片大小和有效行区间,而 capturer 不知道;在通用 capturer 中继续增加 n == ... 形状分支只能逐个补丁,比较脆弱。

环境排查

  • 确认 vLLM 版本或 commit;Issue 验证基于 main 快照 852989f580820849113d67d13fd8053e279d0444 和测试头 bfed1cb65d2ae8c37b9ada7b45191bbb01224679。
  • 确认是否使用 Ascend 后端,以及所用下游补丁的版本;stock Ascend checkout 不能直接对 main 快照启动服务。
  • 确认 enable_return_routed_experts(R3)是否开启,是否为 LoRA enable flag 之外的真实 LoRA 场景(Issue 中未加载 adapter)。
  • 确认并行配置:DP(1/2)、TP(1/2/4)、EP 开关、SP 开关,以及是否启用 ACL graph 与 graph replay。
  • 确认模型为 Qwen3-30B-A3B,精度 BF16/W8A8;其他模型与加速器不在验证范围内。
  • 确认下游副本是否具备移动导入、configuration/planner/block-table、runner 签名等适配修复,以及 TP 对齐 graph-size 过滤和 NPU 内部格式初始化。

解决步骤

  1. 先定位触发点:确认异常出现在 RoutedExpertsCapturer.capture 的行归属推断处,而不是 EPLB 映射或 expert dispatch 阶段。capture 记录的是逻辑 expert ID,发生在 EPLB 之前。
  2. 记录当前 forward 中各 rank 的 topk_ids 行数,与后端 prepare 阶段的物理布局(分片大小、padding、gather 顺序、有效行区间)逐一比对,判断属于哪一类布局。
  3. 若使用 Ascend:检查是否仍依赖 vLLM-Ascend 中对整个 capturer 方法的替换补丁;该补丁说明的是布局适配缺口,而非根治方案。
  4. 评估 #62441 的显式布局接口:让 capture 调用接收后端提供的可选 row layout(source_ranges、gather_group、shard_sizes),由知道物理布局的生产方直接告知分片与有效行区间。
  5. 或评估替代方案 Platform.get_routed_experts_local_rows(topk_ids, forward_context, dp_rank, tp_size):默认返回 None 以保留现有 DP/TP 恢复逻辑,平台覆盖时返回本地 token 行(可为空 tensor),由共享 capturer 负责边界检查与 buffer 写入。注意该方案只有针对性 CPU 检查,完整回归与下游加速器/graph 集成尚未完成。
  6. 若采用提供显式布局的版本,需在 Ascend 上重新跑全模型 serving/API 验证:逐元素比对 API 返回的 expert ID 与 worker buffer 中的 expert ID,覆盖不等 TP 分片与内部 padding 配置。

验证方法

在启用 capture 的完整 serving/API 链路上,用独立 oracle 记录 routing 前的原始逻辑 router ID,并让独立 DP/行标签流经真实的 prepare 通信,在 routing 前移除;参考实现依据这些标签重建 token 归属,且不读取 capture_layout / source_ranges / shard_sizes,再按请求 ID 校验每个 TP worker buffer 以及每个返回的 token/layer/top-k。Issue 报告的基线结果为 17/17 配置 PASS、144 个 HTTP 请求,16,048,896 个 API expert ID 与 31,912,320 个 worker-buffer expert ID 零差异。逐 forward 重置有效性并复制图内设备数据,可避免 warmup/replay 的旧值被当成当前数据。若只看到 graph log-only 报告为 INCONCLUSIVE,应结合原始 device/API 比对判断,而不能仅凭日志回调缺失判定失败。

参考来源

vllm-project/vllm #61539

相关实现 PR:#62441;相关历史修复:#43737。

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 33987

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注