viable/strict/1789752186: [MPS] Migrate `softplus` to Metal (#197000)
PyTorch 合并 PR #197000,将 softplus 与 softplus_backward 从 MPSGraph 迁移到 Metal 实现。这两个算子是基于 TensorIterator 的结构化算子,额外状态仅为两个标量,因此复用 elu 已使用的 unary/binary-with-params Metal harness:在 ActivationKernel.metal 中新增两个 functor 并注册 stub,替换约 150 行 MPSGraph 代码。beta 与 threshold 以 float 存入单个非模板 SoftplusParams,因为三种受支持 dtype 的 opmath 均为 float,与 CPU、CUDA 内核一致。mps::log1p 随图一并删除,softplus 是其最后一个调用者。
发展脉络
- 首次出现viable/strict/1789752186: [MPS] Migrate `softplus` to Metal (#197000)PyTorch Core
- 当前判断这条证据显示 PyTorch 的 MPS 后端正在把算子从 MPSGraph 逐步下沉到手写 Metal 内核,属于框架侧对 Apple 芯片后端的持续投入。收益结构也值得注意:小张量上启动开销下降明显,大张量受带宽限制几乎不变,说明这类迁移主要改善的是大量小算子场景,而非大张量吞吐。可验证的下一信号是后续 release note 中 MPS 迁移类 PR 的数量与覆盖算子范围。Agent Pulse · 分析
PyTorch PR #197000 把 MPS 后端的 softplus 前向与反向从 MPSGraph 迁移到 Metal 内核。实现方式是在 ActivationKernel.metal 中新增两个 functor,并复用 elu 已有的 unary/binary-with-params harness,替换约 150 行 MPSGraph 代码;beta 与 threshold 作为 float 存入单个非模板 SoftplusParams,与 CPU、CUDA 内核保持一致。mps::log1p 因失去最后一个调用者而被删除。作者给出的测量方式为每次 torch.mps.synchronize() 排队 200 个算子、取 3 次运行最优值:32x32 前向从 15.6us 降至 5.7us、反向从 15.5us 降至 3.0us;4096x4096 前向从 554us 降至 518us、反向从 793us 降至 773us。作者判断收益来自小张量上的启动开销,大张量两种实现都受带宽限制。该 PR 修复 #131736,并注明在 Claude Code 协助下完成。
从证据看,迁移的可行性来自算子形态:softplus 是结构化 TensorIterator 算子,额外状态只有两个标量,因此能直接套用已有 Metal harness,而不需要新的调度路径。参数用非模板 float 结构体承载,前提是三种受支持 dtype 的 opmath 都是 float,这与 CPU、CUDA 内核一致。可验证的下一信号是:其他同样只有少量标量状态的 MPSGraph 算子是否被批量迁移,以及 mps::log1p 删除后是否有其他调用方出现。
这条证据显示 PyTorch 的 MPS 后端正在把算子从 MPSGraph 逐步下沉到手写 Metal 内核,属于框架侧对 Apple 芯片后端的持续投入。收益结构也值得注意:小张量上启动开销下降明显,大张量受带宽限制几乎不变,说明这类迁移主要改善的是大量小算子场景,而非大张量吞吐。可验证的下一信号是后续 release note 中 MPS 迁移类 PR 的数量与覆盖算子范围。
对使用 Apple 芯片做 PyTorch 训练或推理的团队,这类改动可能降低小张量密集负载的算子启动开销,但证据只覆盖 softplus 单个算子,且大张量几乎无变化,因此不宜外推为整体性能提升。评估时应以自身负载的端到端耗时为标准,而非单算子微基准。
若该模式被复制,MPS 后端可能继续减少对 MPSGraph 的依赖,把更多结构化算子改为 Metal 实现。需要观察的是:迁移后是否出现数值或边界行为回归,以及小张量延迟收益在真实训练或推理负载中是否可复现。