PyTorch 2.14:NVGEMM 将 CuTeDSL 与 CUTLASS 内核带入 Inductor

2026-09-03 27 预计阅读时间: 1 分钟
来源: pytorch.org AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

PyTorch 2.14 的重点变化之一,是 NVGEMM 将由 CuTeDSL 生成的 CUTLASS 内核接入 Inductor,并支持 epilogue fusion(尾部算子融合)。这项改动面向的是编译器和 GPU 内核执行路径:模型中的矩阵乘法不再只是单独完成,后续的缩放、偏置或激活等操作也有机会融合进同一个 GPU 内核,从而减少中间张量写回和额外的内核启动。

对使用 PyTorch 编写模型的开发者来说,最值得关注的不是新增一个 Python API,而是 torch.compile 背后的生成代码和内核选择可能发生变化。升级后,应通过实际模型和目标 GPU 重新验证性能、显存占用与数值结果。

NVGEMM 改变了什么

GEMM,也就是通用矩阵乘法,是 Transformer、推荐模型和许多视觉网络中的核心计算。传统执行路径通常可以抽象为:

矩阵乘法 -> 写回显存 -> 加偏置 -> 激活函数 -> 再次写回显存

如果编译器能够识别这些连续操作,就可以尝试生成类似下面的路径:

矩阵乘法 + 偏置 + 激活函数 -> 一次性写回结果

PyTorch 2.14 摘要中提到的 NVGEMM,会把 CuTeDSL 生成的 CUTLASS 内核带入 Inductor。CuTeDSL 用于描述和生成 GPU 计算内核,CUTLASS 则提供了面向 NVIDIA GPU 的高性能矩阵运算组件。Inductor 位于 torch.compile 的编译后端中,负责把 PyTorch 图转换为更适合目标硬件执行的代码。

这几层组合起来,意味着高性能矩阵乘法内核可以更直接地参与 PyTorch 的图编译和算子融合流程。

Epilogue fusion 为什么重要

在 GEMM 中,epilogue 通常指矩阵乘法主计算完成之后的尾部处理,例如:

  • 加 bias;
  • 乘以缩放因子;
  • 应用 ReLU、GELU 等激活函数;
  • 完成某些类型转换或输出变换。

这些操作的计算量可能不大,但如果每个操作都单独启动 CUDA kernel,就会产生额外的启动开销,并需要在 kernel 之间读写显存。对于尺寸较小、调用频繁或对延迟敏感的模型,这些成本会比较明显。

尾部融合的价值通常来自两个方面:

  1. 减少 kernel launch 次数;
  2. 减少中间结果在显存中的往返读写。

不过,融合并不是所有场景都一定更快。矩阵尺寸、数据类型、GPU 架构、张量布局和动态形状都会影响最终内核选择。不能只根据算子图判断收益,应该在真实输入分布上进行基准测试。

可以这样验证 torch.compile

下面是一个最小示例。它使用一个带 bias 和 GELU 的线性模块,交给 torch.compile 编译。示例假设环境已经安装了 PyTorch 2.14,并且运行在支持 CUDA 的 NVIDIA GPU 上;具体的 NVGEMM 内核选择由 PyTorch、Inductor 和运行时硬件共同决定。

import time
import torch


def main() -> None:
    if not torch.cuda.is_available():
        raise SystemExit("This example requires a CUDA-enabled NVIDIA GPU.")

    device = "cuda"
    dtype = torch.float16

    model = torch.nn.Sequential(
        torch.nn.Linear(4096, 4096),
        torch.nn.GELU(),
    ).to(device=device, dtype=dtype).eval()

    # Inductor will compile the model graph and select suitable GPU kernels.
    compiled_model = torch.compile(model, backend="inductor")
    inputs = torch.randn(16, 4096, device=device, dtype=dtype)

    with torch.inference_mode():
        for _ in range(10):
            compiled_model(inputs)
        torch.cuda.synchronize()

        start = time.perf_counter()
        for _ in range(100):
            compiled_model(inputs)
        torch.cuda.synchronize()
        elapsed_ms = (time.perf_counter() - start) * 1000 / 100

    print(f"average latency: {elapsed_ms:.3f} ms")
    print(f"torch version: {torch.__version__}")
    print(f"GPU: {torch.cuda.get_device_name(0)}")


if __name__ == "__main__":
    main()

运行前建议先确认版本和 GPU:

python - <<'PY'
import torch
print("PyTorch:", torch.__version__)
print("CUDA available:", torch.cuda.is_available())
if torch.cuda.is_available():
    print("GPU:", torch.cuda.get_device_name(0))
PY

python benchmark_compile.py

测试时要把 eager 模式作为对照组,并分别统计首次编译时间和稳定运行时间。首次调用包含编译开销,不应与已经完成 warm-up 的 steady-state 延迟混在一起。

升级后的工程检查清单

升级到 PyTorch 2.14 时,可以按下面的顺序验证:

  • 固定输入形状、batch size、数据类型和 GPU 型号,比较升级前后的延迟;
  • 同时测试 eager 与 torch.compile,确认收益来自稳定执行而不是测量误差;
  • 检查模型输出的绝对误差和相对误差,特别是 FP16 或 BF16 路径;
  • 测试动态 batch、不同序列长度和不同矩阵尺寸;
  • 观察显存峰值、kernel 数量以及编译缓存行为;
  • 为无法编译或收益不稳定的模型保留回退路径。

还需要注意,NVGEMM 和相关 CUTLASS 内核的实际适用范围取决于硬件与算子形状。部署环境中的 NVIDIA GPU、CUDA 版本、PyTorch 构建方式和驱动版本应作为一个整体验证,不能只升级 Python 包后就假定所有模型都会自动获得相同收益。

采用建议

PyTorch 2.14 的这项变化更像是执行引擎升级,而不是需要大规模改写模型代码的 API 迁移。对于已经使用 torch.compile 的项目,重点是重新跑一轮基准测试,关注 GEMM 密集型模块以及带 bias、激活函数的线性层。对于仍以 eager 模式为主的项目,可以从单个推理模块开始试用,并把编译时间、稳定延迟、数值一致性和回退策略纳入验收标准。

最稳妥的判断方式是:在真实 GPU 和真实输入上测量,而不是仅凭 NVGEMM、CuTeDSL 或 CUTLASS 的名称推断性能结果。


相关推荐