Prhub

#47832 [CI] Fix Transformers modeling backend LoRA test

原始 PR 作者 hmellor 合并时间 2026-07-07 19:40 文件变更 3 提交数 4 评论 0 代码增减 +8 / -18

执行摘要

修复 LoRA 下 QKV 融合因缺少 split_sizes 属性导致的崩溃

PR #47804 和 #47824 指出的 QA 测试失败根本原因是 #47187 新增的 split_sizes 属性未被 LoRA 包装类复制。作者选择从根本上消除冗余属性,降低维护成本。

值得精读,设计决策(用已有属性推导而非存储冗余)值得借鉴。

讨论亮点

无 review 讨论,仅 claude[bot] 自动评论说明分支来自 fork 未启用自动 review。

实现拆解

  1. 移除 split_sizes 属性:在 QKVParallelLinear.__init__ 中删除手动设置 split_sizes 的代码,改为直接使用已有的 output_sizestp_size 属性。
  2. 修改 QKVFuser 的 AST 模板:在 qkv.py 中将 split 调用从 self.qkv.split_sizes 改为 [s // self.qkv.tp_size for s in self.qkv.output_sizes],避免依赖新属性。
  3. 更新测试存根:在 test_linear.py 中将存根对象的 split_sizes 替换为 output_sizestp_size,并验证生成的代码包含 tp_size 引用。
文件 模块 状态 重要度
vllm/model_executor/models/transformers/fusers/qkv.py 融合器 modified 6.64
vllm/model_executor/layers/linear.py 线性层 modified 6.08
tests/models/transformers/fusers/test_linear.py 线性层 modified 4.72

关键符号

QKVParallelLinear.__init__ QKVFuser.update_forward QKVFuser.update_attrs _apply_qkv_fuser_with_stubs

关键源码片段

vllm/model_executor/models/transformers/fusers/qkv.py core-logic

核心 AST 模板变更,用 output_sizes/tp_size 替换 split_sizes

# vllm/model_executor/models/transformers/fusers/qkv.py
# 在 update_forward 中,字符串模板从 split_sizes 改为动态计算:
# 之前:self.qkv.split_sizes,依赖手动维护的属性
# 之后:自 output_sizes 和 tp_size 推导,彻底消除冗余
sections = f"[s // {merged}.tp_size for s in {merged}.output_sizes]"
template = f"{', '.join(temps)} = {merged}(__arg__).split({sections}, -1)"# 同时删除了 update_attrs 中设置 split_sizes 的代码块
# 因为 QKVParallelLinear 的 output_sizes 已包含所有必要信息
vllm/model_executor/layers/linear.py data-contract

QKVParallelLinear 初始化简化为无重复 output_size 计算

# vllm/model_executor/layers/linear.py
class QKVParallelLinear(RowParallelLinear):
    def __init__(self, ...):
        # ... 初始化属性 ...
        # 之前:手动计算 output_size + 设置 output_sizes
        # output_size = (num_heads * head_size + ...) * tp_size
        # self.output_sizes = [...]
​
        # 之后:先设置 output_sizes,再通过 sum 得到 output_size
        self.output_sizes = [
            self.num_heads * self.head_size * tp_size, # q_proj
            self.num_kv_heads * self.head_size * tp_size, # k_proj
            self.num_kv_heads * self.v_head_size * tp_size, # v_proj
        ]
        output_size = sum(self.output_sizes)
​
        super().__init__(...)
tests/models/transformers/fusers/test_linear.py test-coverage

测试存根和断言适配新方案

# tests/models/transformers/fusers/test_linear.py
# 之前:merged.split_sizes = [q.out_features, k.out_features, v.out_features]
# 之后:使用 output_sizes 和 tp_size 模拟真实类行为
merged.output_sizes = [q.out_features, k.out_features, v.out_features]
merged.tp_size = 1# 测试断言更新:验证编译后的代码包含 output_sizes 和 tp_size
names = code.co_names
assert "qkv_proj" in names and "output_sizes" in names and "o_proj" in names
assert "tp_size" in names

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

移除属性可能影响其他依赖 split_sizes 的代码(如需提前访问该属性的序列化或工具函数),但当前库内无其他使用者。性能方面,动态计算 tp_size 除法的开销在 eager 模式极小,且会被 torch.compile 消除。

直接修复 LoRA 测试回归,使 Transformers 后端融合功能正常可用。影响范围限于 QKVParallelLinearQKVFuser 使用方,无用户可见变更。

属性移除可能影响外部扩展

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论