总览
只需要一句 model.compile(),就可以加速 PyTorch 模型的推理和训练速度。
若想进一步细调模型编译行为,就需要传入参数了。
torch.compile 大致的过程
为了编译模型的推理和训练过程,PyTorch 需要先提取模型代码的计算图 computation graph。这个计算图只涉及 Tensor 的运算,不包含任何 Python 方法和对象(例如 print pandas.DataFrame)。
PyTorch 使用 Dynamo 将用户代码分离为两部分:Python 侧代码和 Tensor 侧代码。然后将 Tensor 侧代码发送给后端 backend 来优化计算图。
默认的 backend 是 inductor,会将已知的所有优化技术应用到计算图中。若不想进行任何优化,可以把 backend 设为 eager。
各个参数
fullgraph 参数
如果有不能编译的代码,torch.compile 会将计算图切分,保留这部分代码为未优化状态。
传入 fullgraph=True 可以确保计算图不会发生断裂。
dynamic 参数
模型的输入 Tensor 维度不一定是一成不变,但编译后的模型更喜欢维度固定的输入。
使用 dynamic=True 编译的模型可以接受动态维度的输入。通常比 dynamic=True 编译的模型慢,但可以避免重新编译的成本。
默认情况下 torch.compile 会自动检测是否发生动态变化,然后编译出更动态的模型。
backend 参数
确定编译后端。关于 backend 所处地位,请看上文的 “torch.compile 的过程” 一节。
backend 的可选项可通过 torch._dynamo.list_backends() 查看。
以下是我的测试结果,仅供参考:
- cudagraphs
- 编译较慢,训练较快
- inductor(默认)
- 编译较慢,训练最快
- eager,不进行额外优化
- 编译最快,训练最慢
mode 参数
若使用了非 eager 的编译后端,就可以传入 mode 参数来控制一些编译行为。
mode 的可选项可通过 torch._inductor.list_mode_options() 查看。
在 backend=indutor 的情况下,给出测试结果,仅供参考:
- default(默认)
- 编译较快,训练最慢
- reduce-overhead
- 编译很慢,训练最快
- max-autotune-no-cudagraphs
- 编译最快,训练较慢
- 途中警告 SM 单元数不足以开启 max_autotune_gemm 模式
- max-autotune
- 编译最慢,训练很快
参考来源
- pytorch.org/docs/stable…
- “A Walk Through Example of torch.compile”,depyf.readthedocs.io/en/latest/w…
- “Speed up models by compiling them”,lightning.ai/docs/pytorc…