Prhub

#36902 [Kernel][Helion][1/N] Add Helion kernel for per_token_group_fp8_quant

原始 PR 作者 xiaohongchen1991 合并时间 2026-06-11 23:59 文件变更 10 提交数 8 评论 12 代码增减 +4347 / -4

执行摘要

新增 per_token_group_fp8_quant Helion 核函数,性能提升 1.15-1.45x

性能优化:使用 Helion 自动调优框架为 per_token_group_fp8_quant 生成高性能 GPU 核函数。该操作是 FP8 量化中的关键步骤,原有 C 实现尚有优化空间。该 PR 是 Issue #32962 的子任务,旨在系统性替换性能敏感的线性/量化核函数。

该 PR 补充了一个重要的量化核函数,设计清晰、测试完善,建议所有使用 Helion 内核优化的开发者仔细阅读 register.py 中的 mutates_args 用法和 pick_config 选择策略。特别关注 review 中提出的 use_ue8m0 未调优风险以及测试环境覆盖度不足的问题,可在后续 PR 中提改进。

讨论亮点

在 review 中,gemini-code-assist 指出自动调优输入生成器 generate_inputsuse_ue8m0 硬编码为 False,但核函数内部支持 scale_ue8m0 路径,若启用该路径可能得到次优性能。建议将 use_ue8m0 纳入调优循环,确保两种模式均获得最优配置。作者未对此评论做出公开回应,PR 以 APPROVED 状态合并,该建议暂未处理。

实现拆解

  1. 核心核函数实现 (vllm/kernels/helion/ops/per_token_group_fp8_quant.py): 使用 Helion 的 Triton 方言实现 per_token_group_fp8_quant,包含 per_token_group_fp8_quant 装饰后的核函数、baseline 参考实现、generate_inputs 自动调优输入生成器及 pick_config 最佳配置选择器。
  2. 注册机制增强 (vllm/kernels/helion/register.py): 在 HelionKernelWrapperregister_kernel 装饰器中新增 mutates_args 参数,使 CustomOp 能够正确标记被修改的张量,满足 vLLM 的 Op 框架约束。
  3. 平台特定配置 (vllm/kernels/helion/configs/per_token_group_fp8_quant/): 新增针对 NVIDIA H100 (nvidia_h100.json) 和 B200 (nvidia_b200.json) 的自动调优配置,覆盖多种 hidden_size / group_size / num_tokens 组合。
  4. 测试体系 (tests/kernels/helion/test_per_token_group_fp8_quant.py): 提供基于 FakeTensor 的配置选择器测试(精确匹配、最近邻匹配、空配置回退、超范围回退)和正确性测试;tests/kernels/helion/utils.py 添加 skip_if_platform_unsupported 帮助函数,按当前 GPU 平台跳过不支持的核函数测试。
  5. 构建集成 (setup.py, .buildkite/): 更新 Helion 版本要求至 1.1.0,调整 CI 测试区域以包含新增核函数。
文件 模块 状态 重要度
vllm/kernels/helion/ops/per_token_group_fp8_quant.py 量化核函数 added 7.92
tests/kernels/helion/test_per_token_group_fp8_quant.py 测试 added 8.05
vllm/kernels/helion/register.py 注册框架 modified 5.59
tests/kernels/helion/utils.py 测试工具 added 5.67
vllm/kernels/helion/configs/per_token_group_fp8_quant/nvidia_h100.json 配置 added 6.05
vllm/kernels/helion/configs/per_token_group_fp8_quant/nvidia_b200.json 配置 added 6.05
setup.py 构建 modified 4.49
tests/kernels/helion/test_register.py 测试 modified 3.52
.buildkite/test-amd.yaml CI 配置 modified 2.5
.buildkite/test_areas/kernels.yaml CI 配置 modified 2.5

关键符号

per_token_group_fp8_quant pick_config generate_inputs baseline skip_if_platform_unsupported

关键源码片段

tests/kernels/helion/test_per_token_group_fp8_quant.py test-coverage

包含配置选择器单元测试和正确性测试,确保核函数行为正确。

# SPDX-License-Identifier: Apache-2.0
"""Tests for per_token_group_fp8_quant Helion kernel."""from typing import Any
import pytest
import torch
from torch._subclasses.fake_tensor import FakeTensorMode
from tests.kernels.helion.utils import skip_if_platform_unsupported
from tests.kernels.quant_utils import FP8_DTYPE
from vllm.kernels.helion.case_key import CaseKey
from vllm.kernels.helion.config_manager import ConfigManager
from vllm.kernels.helion.ops.per_token_group_fp8_quant import (
    _pick_cache, baseline, per_token_group_fp8_quant, pick_config,
)
from vllm.model_executor.layers.quantization.utils.quant_utils import get_fp8_min_max
from vllm.utils.import_utils import has_helionif not has_helion():
    pytest.skip("Helion is not installed. Install with: pip install vllm[helion]",
                allow_module_level=True)def _generate_fake_input(num_tokens: int, hidden_size: int, group_size: int) -> tuple[Any, ...]:
    """在 FakeTensorMode 下生成假输入,避免实际的 GPU 分配。"""
    with FakeTensorMode():
        input = torch.randn((num_tokens, hidden_size), device="cuda", dtype=torch.bfloat16)
        output_q = torch.empty(input.shape, device=input.device, dtype=FP8_DTYPE)
        output_s = torch.empty((num_tokens, hidden_size // group_size),
                               device=input.device, dtype=torch.float32)
        # ... 剩余参数
        return (input, output_q, output_s, group_size, 1e-10,
                *get_fp8_min_max(), False, False)@pytest.fixture(autouse=True)
def reset_config_manager_singleton():
    ConfigManager.reset_instance()
    ConfigManager()
    yield
    ConfigManager.reset_instance()class TestPerTokenGroupFp8QuantConfigPicker:
    def setup_method(self):
        _pick_cache.clear()
​
    def test_config_picker_exact_match(self):
        # 测试精确匹配:输入 shape (16,4096) group=128,应选择相同 key 的配置
        config_keys = [
            CaseKey({"hidden_size": 2048, "group_size": 64, "num_tokens": 16}),
            CaseKey({"hidden_size": 4096, "group_size": 128, "num_tokens": 16}),
        ]
        args = _generate_fake_input(16, 4096, 128)
        selected_key = pick_config(args, config_keys)
        assert selected_key == CaseKey({"hidden_size": 4096, "group_size": 128, "num_tokens": 16})
​
    def test_config_picker_closest_match(self):
        # 测试最近匹配:输入 shape (20,3000) group=70,无精确匹配,应选最接近的 config
        config_keys = [
            CaseKey({"hidden_size": 2048, "group_size": 64, "num_tokens": 16}),
            CaseKey({"hidden_size": 2048, "group_size": 64, "num_tokens": 32}),
            # ... 更多
        ]
        args = _generate_fake_input(20, 3000, 70)
        selected_key = pick_config(args, config_keys)
        assert selected_key == CaseKey({"hidden_size": 2048, "group_size": 64, "num_tokens": 32})
​
    def test_config_picker_no_configs(self):
        # 无配置时返回 None
        assert pick_config(_generate_fake_input(16, 4096, 128), []) is None
​
    def test_config_picker_fallback_to_largest(self):
        # 输入超出所有配置的范围,应回退到最大的配置
        config_keys = [
            CaseKey({"hidden_size": 4096, "group_size": 128, "num_tokens": 32}),
            # ...
        ]
        args = _generate_fake_input(64, 8192, 256)
        selected_key = pick_config(args, config_keys)
        assert selected_key == CaseKey({"hidden_size": 4096, "group_size": 128, "num_tokens": 32})

评论区精华

scale_ue8m0 参数未纳入自动调优 性能

gemini-code-assist 指出 generate_inputs 将 use_ue8m0 硬编码为 False,导致启用该分支时性能可能次优。建议遍历 use_ue8m0 值进行调优。

结论:作者未回复,PR 合并,该建议暂未处理。 · unresolved

风险与影响

  1. 配置覆盖不完整: 调优输入生成器只使用了 hidden_size = [2048, 4096, 5120]group_size = [128],未覆盖实际推理时的所有组合(如 group_size = 64、更大 hidden size),可能在高维或不常见大小上退化为次优配置。
  2. scale_ue8m0 分支未调优: 如 review 所提,use_ue8m0 分支未参与调优,启用后性能可能不及预期。
  3. 依赖升级: Helion 版本从 1.0.0 升至 1.1.0,若版本间 API 有 breaking changes 会影响其他 Helion 核函数。
  4. 硬编码精度: 输入生成器中 scale_dtype = float32,但 FP8 量化中 scale 可能是 fp16float32,若其他调用方使用不同 scale dtype 会导致意外行为。

直接影响使用 per_token_group_fp8_quant 的量化模型(如广泛部署的 FP8 推理),在 H100/B200 上可获 15-45% 量化阶段加速。对系统而言,该核函数作为 CustomOp 注册,不改变上层接口,兼容 V1/V2 引擎。测试通过新增 243+30 行测试用例和配置 picker 测试,确保前向正确性和配置选择逻辑。对 vLLM Helion 集成工程而言,该 PR 巩固了注册模式(mutates_args),为后续同类核函数提供了参考实现。

use_ue8m0 未调优 配置覆盖不完整 Helion 版本升级

关联 Issue

#32962 [Performance]: Custom Helion Kernels

完整报告

参与讨论