Prhub

#50060 [Bugfix] Only pad transformers backend `value` when it is narrower

原始 PR 作者 njhill 合并时间 2026-07-28 12:36 文件变更 1 提交数 1 评论 0 代码增减 +6 / -3

执行摘要

修复 transformers MLA pad 条件导致 QKV 投影崩溃

PR#49982 和 PR#49987 同时存在于 main 分支后,packed QKV 投影的 attention 模块因 value 被错误截断导致 RuntimeError: The size of tensor a (16) must match the size of tensor b (8)。PR body 指出两者单独测试均通过,交互后产生回归。

建议精读此 PR。它展示了两个独立正确的 PR 合并后产生交互回归的经典场景,以及如何通过严格化条件来修复。是代码审查和跨 PR 依赖分析的好案例。

讨论亮点

无 review 评论讨论。PR 仅被 AndreasKaratzas 批准。

实现拆解

在 vllm/model_executor/models/transformers/__init__.py 的 vllm_attention_forward 函数中:

  1. 将 padding 条件判断从 head_dim_v != head_dim_qk 改为 head_dim_v < head_dim_qk,并提取为变量 pad_value。
  2. 在后续 attn_output 反 padding 处复用同一 pad_value 变量,避免重复计算和逻辑不一致。
  3. 更新注释,说明更大的最后一维表示 value 未按 head 拆分(如 packed grouped/multi-query 投影),无需 padding。
文件 模块 状态 重要度
vllm/model_executor/models/transformers/__init__.py 注意力 modified 6.38

关键符号

vllm_attention_forward

关键源码片段

vllm/model_executor/models/transformers/__init__.py data-contract

唯一修改文件,包含 vllm_attention_forward 函数,修正了 value padding 条件以处理 packed grouped/multi-query QKV 投影场景。

# vllm/model_executor/models/transformers/__init__.py
​
def vllm_attention_forward(
    module: "torch.nn.Module",
    query: "torch.Tensor",
    key: "torch.Tensor",
    value: "torch.Tensor",
    attention_mask: "torch.Tensor",
    scaling: float | None = None,
    attention_instances: dict[int, "Attention"] | None = None,
    **kwargs,
):
    self_attn = attention_instances[module.layer_idx]
    if scaling is not None:
        self_attn.impl.scale = float(scaling)
    hidden = query.shape[-2]
    head_dim_qk = query.shape[-1]
    head_dim_v = value.shape[-1]
    query, key, value = (x.transpose(1, 2) for x in (query, key, value))
    query, key, value = (x.reshape(hidden, -1) for x in (query, key, value))
    # Pad `value` up to the query/key head size when it is smaller (expanded
    # MLA). A larger last dim just means `value` isn't split per head, e.g.
    # packed grouped/multi-query projections, and needs no padding.
    pad_value = head_dim_v < head_dim_qk
    if pad_value:
        value = F.pad(value.view(-1, head_dim_v), (0, head_dim_qk - head_dim_v))
        value = value.reshape(hidden, -1)
    attn_output = self_attn.forward(query, key, value)
    if pad_value:
        attn_output = attn_output.view(-1, head_dim_qk)[..., :head_dim_v]
        attn_output = attn_output.reshape(hidden, -1)
    return attn_output, None

评论区精华

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

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

风险与影响

低风险。更改仅调整 padding 条件,排除了错误的负 padding 情况;对正常 MLA(value 更窄)的路径保持完全相同的行为。可能的风险是如果未来有第三类场景(如 value 维度等于 head_dim_qk 但需要特殊处理),当前条件可能会漏掉,但可能性极低。

影响范围限于 transformers 后端中使用了 packed grouped/multi-query QKV 投影的模型,例如某些包含 kv_heads > 1 的多头注意力的模型。修复了这些模型在 vllm_attention_forward 中的崩溃。对其他模型(如标准多头注意力、MLA)无影响。

回归风险低 核心注意力路径

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论