Prhub

#39058 [Kernel] Implement CUDA kernel for ReLUSquaredActivation (relu^2)

原始 PR 作者 tanish-malekar 合并时间 2026-07-13 10:18 文件变更 7 提交数 13 评论 18 代码增减 +140 / -2

执行摘要

为 ReLUSquaredActivation 实现 CUDA kernel

原 ReLUSquaredActivation.forward_cuda 只包含 TODO: implement cuda kernels,直接委托 forward_native,导致 eager 模式下执行两次不融合的 kernel(relu + square)。通过实现融合 kernel 消除重复启动开销,并与其他激活保持一致。

值得精读,展示了如何为 CustomOp 添加 CUDA kernel 并设计带有正确性验证的 Benchmark。评审中关于 XPU/IR 的讨论对跨平台开发有参考价值。

讨论亮点
  • 输入连续性假设:gemini-code-assist 指出 forward_cuda 使用 torch.empty_like(x) 可能产生非连续张量导致 kernel 错误。作者回复这是故意的,与其它激活一致,且推理上下文中输入总是连续的,风险较低。
  • XPU 平台支持:tjtanaa 询问是否在 XPU 上验证,xinyu-intel 回复无对应 kernel,并提议迁移至 vLLM IR。作者修复移除 XPU 注册,保持回退 native。
  • vLLM IR 迁移:xinyu-intel 建议将 relu_squared 迁移至 vLLM IR,作者同意后续应统一迁移所有激活操作。

实现拆解

  1. csrc/libtorch_stable/activation_kernels.cu 中添加 CUDA kernel relu_squared_kernel<T>,使用已有的 LAUNCH_ACTIVATION_KERNEL 宏,输入逐元素计算 relu(x)^2
  2. csrc/libtorch_stable/ops.h(稳定版和非稳定版)和 csrc/ops.h 中声明 void relu_squared(...) 函数。
  3. csrc/libtorch_stable/torch_bindings.cpp 中注册 op relu_squaredops.defops.impl)。
  4. 修改 vllm/model_executor/layers/activation.py:添加 __init__ 方法,在 CUDA 平台时设置 self.op = torch.ops._C.relu_squared;重写 forward_cuda 使用 self.op;移除 forward_xpu,XPU/CPU 自动回退 forward_native
  5. 新增 benchmarks/kernels/benchmark_relu_squared.py 进行微基准测试,同时验证正确性;更新 tests/kernels/core/test_activation.py 增加 ReLUSquaredActivation 测试用例。
文件 模块 状态 重要度
benchmarks/kernels/benchmark_relu_squared.py 性能基准 added 8.27
vllm/model_executor/layers/activation.py 激活函数 modified 6.76
csrc/libtorch_stable/torch_bindings.cpp 操作注册 modified 4.83
csrc/libtorch_stable/ops.h 操作声明 modified 4.54
csrc/ops.h 操作声明 modified 4.54
tests/kernels/core/test_activation.py 内核测试 modified 3.77
csrc/libtorch_stable/activation_kernels.cu 内核实现 modified 3.45

关键符号

benchmark_relu_squared ReLUSquaredActivation.__init__ ReLUSquaredActivation.forward_cuda ReLUSquaredActivation.forward_native relu_squared_kernel

关键源码片段

vllm/model_executor/layers/activation.py data-contract

修改 ReLUSquaredActivation 类,添加 __init__ 以存储 op,重写 forward_cuda 调用自定义 kernel,移除错误 XPU/CPU 注册,是功能入口。

@CustomOp.register("relu2")
class ReLUSquaredActivation(CustomOp):
    """
    Applies the relu^2 activation introduced in https://arxiv.org/abs/2109.08668v2
    """
​
    def __init__(self):
        super().__init__()
        if current_platform.is_cuda_alike():
            # 仅在 CUDA 平台时注册自定义 op,XPU/CPU 自动回退至 forward_native
            self.op = torch.ops._C.relu_squared
​
    def forward_native(self, x: torch.Tensor) -> torch.Tensor:
        """PyTorch-native implementation equivalent to forward()."""
        return torch.square(F.relu(x))
​
    def forward_cuda(self, x: torch.Tensor) -> torch.Tensor:
        out = torch.empty_like(x)
        self.op(out, x) # 调用单次融合 kernel,与 gelu_new 等模式一致
        return out

评论区精华

输入张量连续性假设 正确性

gemini-code-assist 指出 forward_cuda 使用 torch.empty_like(x) 可能产生非连续张量,导致 CUDA kernel 结果错误。

结论:作者说明这是与其他激活类一致的做法,且 vLLM 推理输入始终连续,风险较低。 · 已解决

XPU 平台支持 测试

tjtanaa 询问是否在 XPU 上验证此 kernel,xinyu-intel 回复称无对应 XPU kernel,并提议迁移至 vLLM IR。

结论:作者移除了 XPU 注册,使 XPU 自动回退至 forward_native。 · 已解决

vLLM IR 迁移讨论 设计

xinyu-intel 建议将此操作迁移至 vLLM IR。作者回应称应统一迁移所有激活操作,不在本 PR 中处理。

结论:暂不处理,需后续统一迁移。 · 未关闭

风险与影响

  1. 连续性假设:CUDA kernel 假设 outinput 连续,否则结果错误;但 vLLM 的激活输入始终连续,风险低。
  2. XPU/CPU 回退:回退至 native 无性能提升,但正确性保证。
  3. 大张量溢出:元素数大于 2^32 时 32 位索引溢出(与其他 kernel 共享限制),实际推理尺寸远低于该阈值。
  4. 基准测试方法:使用 do_bench_cudagraph 排除启动开销,实际 eager 收益可能略低。

对用户:使用 relu^2 激活的模型在 eager 模式下性能提升,编译模式下无变化。对开发者:新增 kernel 遵循现有模式,易于扩展。对 CI:新增微基准仅手动运行,不增加 CI 负担。

contiguous 假设 XPU 无原生 kernel 大张量 32 位索引溢出

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论