Prhub

#42686 [torch.compile] Add patch for fullgraph compilation

原始 PR 作者 ProExpertProg 合并时间 2026-05-18 03:49 文件变更 1 提交数 1 评论 6 代码增减 +62 / -0

执行摘要

为 torch.compile 全图模式添加 Inductor 物化启发式补丁

根据Issue #27828,Inductor分区性能不如Dynamo分区,主要原因之一是物化启发式不够智能,导致Transformer模型中残差连接等多次使用的张量被重复融合进入后续内核,造成计算量线性增长。此补丁通过成本模型决定是否物化,从而降低内存流量。

值得阅读其成本模型的设计思路(简洁有效),但注意该PR已被回滚。建议直接使用PyTorch 2.12(已包含上游官方修复),或等待vllm团队重新评估后修复已知问题并重新合入。

讨论亮点

Review中gemini-code-assist[bot]指出了三个实现错误:

1) Vconfig的导入路径不准确(但最终代码已修正);
2) StorageBox没有has_large_inner_fn方法,应使用self.data.has_large_inner_fn()
3) StorageBox没有num_reads方法,应使用len(self.get_reads())

PR作者在Issue评论中确认了高batch size下约1.6%的延迟增加,归因于fp32残差读写,但认为这是独立问题,决定合并。最终PR合并后因CI失败被回滚(#42913)。

实现拆解

  1. vllm/env_override.py末尾新增函数_patch_should_realize_on_reuse
  2. 函数首先检查torch版本是否为2.11.0,否则直接返回,避免重复应用。
  3. 定义内部函数should_realize_on_reuse_patched,接收selfStorageBox实例)和users参数。
  4. 补丁逻辑:若users > 1且底层数据是PointwiseReduction,则依次考虑CPU重操作、大inner_fn,最后基于总读取字节和输出字节的成本模型判断是否物化(total_read_bytes * (users - 1) >= output_bytes * (1 + users))。
  5. 如果成本模型无法计算(如size hint未知),则回退到config.realize_reads_threshold阈值判断。
  6. 最后将StorageBox.should_realize_on_reuse替换为新的补丁函数,并在模块加载时调用_patch_should_realize_on_reuse()
  7. 无测试或配置改动。
文件 模块 状态 重要度
vllm/env_override.py 环境配置 modified 7.43

关键符号

_patch_should_realize_on_reuse should_realize_on_reuse_patched

关键源码片段

vllm/env_override.py core-logic

添加了完整的 Inductor 物化补丁,包括版本检查、成本模型实现和运行时 hook

# 对应文件 : vllm/env_override.py
# 该补丁在模块加载时自动应用,仅对 PyTorch 2.11.0 生效def _patch_should_realize_on_reuse():
    """
    为 Inductor 的物化启发式添加补丁。
    该补丁从 PyTorch 2.12 上游向后移植而来,解决全图编译中
    多次使用张量(如残差连接)的冗余重计算问题。
    """
    # 仅 PyTorch 2.11 需要,2.12 已包含上游修复
    if not is_torch_equal("2.11.0"):
        return
​
    def should_realize_on_reuse_patched(self, users: int) -> bool:
        """
        基于总内存流量的成本模型,决定是否物化一个多次使用的张量。        Inline:   total_read_bytes * users (每个用户都需重读所有输入)
        Materialize: total_read_bytes + output_bytes * (1 + users) (一次写 + 每个用户读一次)
        当 Inline 成本 >= Materialize 成本时,选择物化。
        """
        from torch._inductor import config
        from torch._inductor.ir import Pointwise, Reduction, is_cpu
        from torch._inductor.virtualized import V
​
        if users > 1 and isinstance(self.data, (Pointwise, Reduction)):
            if is_cpu(self.data):
                # CPU 上对重操作(如 exp, sigmoid)的结果应尽早物化
                opcount = self.data.inner_fn_opcount()
                heavy_ops = ["exp", "sigmoid"]
                if any(x in opcount.used_ops for x in heavy_ops):
                    return True
            if self.has_large_inner_fn(): # 注意 : 应为 self.data.has_large_inner_fn(),原始 PR 存在此 bug
                return True
            # 基于内存带宽的成本模型
            total_read_bytes = sum(
                V.graph.get_dep_size_hint(dep) for dep in self.get_reads()
            )
            output_bytes = (
                V.graph.sizevars.optimization_hint(self.data.get_numel(), fallback=0)
                * self.data.dtype.itemsize
            )
            if total_read_bytes > 0 and output_bytes > 0:
                return total_read_bytes * (users - 1) >= output_bytes * (1 + users)
            # 回退到原有的读取次数阈值
            return self.num_reads() > config.realize_reads_threshold # 注意 : 应为 len(self.get_reads()),原始 PR 存在此 bug
        return False
​
    from torch._inductor.ir import StorageBox
    # 猴子替换 StorageBox 的方法
    StorageBox.should_realize_on_reuse = should_realize_on_reuse_patched# 在模块加载时立即调用
_patch_should_realize_on_reuse()

评论区精华

Import paths and method existence in patch 正确性

gemini-code-assist[bot] 指出 V 和 config 的导入路径错误,并且 StorageBox 没有 has_large_inner_fn 和 num_reads 方法,应使用 self.data.has_large_inner_fn() 和 len(self.get_reads())。

结论:PR 作者未回应,但最终合并的代码中导入路径已正确,而方法调用错误仍然存在,构成潜在运行时风险。 · unresolved

Performance regression at high batch size 性能

ProExpertProg 在 Issue 评论中指出在高 num_tokens 下 Inductor 分区有约 1.6% 的延迟增加,并归因于残差读 / 写使用 fp32 而非 bf16。

结论:PR 作者认为这是独立问题,决定先合并。 · 已解决

Approval and CI failure other

BoyuanFeng 批准了 PR,但后续因 CI 失败被回滚(#42913),表明存在未暴露的稳定性问题。

结论:PR 合并后导致 CI 失败,被回滚。 · 已解决

风险与影响

1) 方法调用错误风险has_large_inner_fnnum_readsStorageBox实例上不存在,可能导致运行时AttributeError(尽管未在测试中触发,但可能因环境差异暴露)。
2) 版本兼容性:仅针对torch 2.11.0,其他版本无影响。
3) 已回滚记录:该PR因在CI中引入失败被回滚,说明存在未识别的稳定性问题。

对使用torch 2.11及vllm的fullgraph编译用户,理论上可提升Inductor分区的性能(约0.5-1.6%)。但补丁未经过充分测试,且存在未解决的正确性风险,可能影响生产环境稳定性。已回滚历史表明该变更需要更仔细的验证。

编译路径变更 缺少测试覆盖 方法存在性错误 已回滚历史

关联 Issue

#176994 [Inductor] Improve materialization heuristic for a chain of computations
#27828 [Performance][torch.compile]: Inductor partition performance issues

完整报告

参与讨论