Prhub

#30540 [Attention Backend] Add HPC-Ops attention backend

原始 PR 作者 BBuf 合并时间 2026-07-22 22:06 文件变更 6 提交数 19 评论 20 代码增减 +790 / -1

执行摘要

新增 HPC-Ops 注意力后端

添加一个可选的后端 hpc_ops,包装腾讯混元 AI Infra 团队的 HPC-Ops 库中的分页 MHA 内核,作为 HPC-Ops 与 SGLang 集成的第一步。启用方式:--attention-backend hpc_ops

该 PR 值得精读,特别是零拷贝 KV 池适配、图分割实现 FP8 路径、与现有元数据辅助函数的复用模式。后续 MoE 后端和融合算子的集成 PR 值得关注。建议在工厂函数中主动检查 has_hpc_ops() 并给出友好错误提示。

讨论亮点
  • 安装方式修正:thisjiang 指出文档中写的是 pip install,但 HPC-Ops 仅支持源码安装。BBuf 修正为 "requires installing from source",并更新了文档和测试跳过信息。
  • FP8 KV 缓存支持:thisjiang 询问文档中最初仅列 bf16,BBuf 确认后添加了 FP8 支持,更新了支持矩阵和 --kv-cache-dtype fp8_e4m3 示例,并说明 FP8 路径要求特定的 head 配置。
  • 推测解码支持:thisjiang 询问是否支持 MTP,BBuf 确认当前不支持,后端在工厂函数中显式拒绝推测解码场景,并列为合理后续工作。

实现拆解

  1. 新增后端文件:创建 python/sglang/srt/layers/attention/hpc_ops_backend.py,定义 HPCOpsAttnBackend 类继承 AttentionBackend。关键设计点:
    • 零拷贝读取 KVWriteLoc 中的桩池,通过 view 直接转换为 (num_pages, page_size, num_kv_heads, head_dim) 格式,避免数据拷贝。
    • 预填充调用 hpc.attention_with_kvcache_prefill_bf16,解码调用 hpc.attention_decode_bf16(split-K)。
    • 复用 build_trtllm_mha_page_tableupdate_trtllm_mha_graph_metadata 等设备端辅助函数,避免 CPU 同步。
    • 通过 needs_cpu_seq_lens = False 跳过 seq_lens_cpu 同步,支持纯 GPU 解码 CUDA graph。
    • 提供 fused_qk_rope_store_kv_fp8 接口,支持 FP8 KV 缓存路径。
  2. 后端注册和约束:在 attention_registry.py 中添加 create_hpc_ops_backend 工厂函数,通过 @register_attention_backend("hpc_ops") 注册。启动时检查是否使用 MLA、是否编码器-解码器模型、是否启用了推测解码,不符合条件时提前报错。在 server_args.pyATTENTION_BACKEND_CHOICES 中添加 "hpc_ops"
  3. 参数后处理:在 overrides.py_mla_backend_page_constraints 中添加块,检查 attention_backend 是否为 "hpc_ops",若是则自动将 page_size 设为 64。
  4. FP8 KV 缓存路径:在 hunyuan_v3.py 中,为 HYV3Attention 添加惰性解析标志 use_hpc_ops_fp8_attn 和 FP32 缓存变量。新增 _resolve_hpc_ops_fp8_attn 方法,在首次前向时判断后端是否为 HPCOpsAttnBackend 且启用了 FP8,若是则调用 fused_qk_rope_store_kv_fp8 完成 QKNorm + RoPE + FP8 量化 + StoreKV 融合操作,并跳过后续的 norm/rope/KV-write 步骤。该融合操作被注册为图分割操作,使得预填充 CUDA graph 可以捕获 attention 部分,同时保持 Python 端的 scale 传递。
  5. 文档更新:在 docs_new/docs/advanced_features/attention_backend.mdx 中更新支持矩阵和示例命令。
文件 模块 状态 重要度
python/sglang/srt/layers/attention/hpc_ops_backend.py 注意力后端 added 9.24
python/sglang/srt/models/hunyuan_v3.py 模型适配 modified 7.61
python/sglang/srt/layers/attention/attention_registry.py 注册中心 modified 6.71
python/sglang/srt/arg_groups/overrides.py 参数校验 modified 5.83
python/sglang/srt/server_args.py 服务配置 modified 4.3

关键符号

has_hpc_ops HPCOpsAttnBackend.__init__ HPCOpsAttnBackend.init_forward_metadata HPCOpsAttnBackend.init_cuda_graph_state HPCOpsAttnBackend.init_forward_metadata_out_graph HPCOpsAttnBackend.init_forward_metadata_in_graph HPCOpsAttnBackend.fused_qk_rope_store_kv_fp8 create_hpc_ops_backend HYV3Attention._resolve_hpc_ops_fp8_attn HYV3Attention.forward

关键源码片段

python/sglang/srt/models/hunyuan_v3.py data-contract

为 HunYuan V3 模型添加 FP8 KV 缓存路径,融合 QKNorm+RoPE+ 量化 +StoreKV。

# 在 __init__ 中新增的字段,惰性决议 FP8 路径是否可用
# 仅当 CUDA、head_dim 128、且 head 配置匹配时置 None,否则 False
self.use_hpc_ops_fp8_attn: Optional[bool] = (
    None
    if is_cuda()
    and self.head_dim == 128
    and (self.num_heads, self.num_kv_heads) in ((8, 1), (64, 8))
    else False
)
self._hpc_cos_sin_fp32: Optional[torch.Tensor] = None
self._hpc_q_norm_w_fp32: Optional[torch.Tensor] = None
self._hpc_k_norm_w_fp32: Optional[torch.Tensor] = None# 惰性决议:首次前向时检查后端类型并缓存 FP32 资源
def _resolve_hpc_ops_fp8_attn(self) -> bool:
    from sglang.srt.layers.attention.hpc_ops_backend import HPCOpsAttnBackend
    backend = get_attn_backend()
    use_fp8_path = isinstance(backend, HPCOpsAttnBackend) and backend.use_fp8
    if use_fp8_path:
        # fused 内核需要 fp32 精度的 cos / sin 表和 norm 权重
        self._hpc_cos_sin_fp32 = self.rotary_emb.cos_sin_cache.float()
        if self.use_qk_norm:
            self._hpc_q_norm_w_fp32 = self.q_norm.weight.detach().float()
            self._hpc_k_norm_w_fp32 = self.k_norm.weight.detach().float()
    return use_fp8_path# forward 方法中的 FP8 捷径(仅展示新增分支,省略原有逻辑)
def forward(
    self,
    positions: torch.Tensor,
    hidden_states: torch.Tensor,
    forward_batch: ForwardBatch,
) -> torch.Tensor:
    qkv, _ = self.qkv_proj(hidden_states)
​
    if self.use_hpc_ops_fp8_attn is None:
        self.use_hpc_ops_fp8_attn = self._resolve_hpc_ops_fp8_attn()
    if self.use_hpc_ops_fp8_attn and not forward_batch.forward_mode.is_idle():
        # 调用后端的 fused QKNorm + RoPE + FP8-quant + StoreKV
        q = get_attn_backend().fused_qk_rope_store_kv_fp8(
            layer=self.attn,
            forward_batch=forward_batch,
            qkv=qkv,
            cos_sin_cache=self._hpc_cos_sin_fp32,
            q_norm_weight=self._hpc_q_norm_w_fp32,
            k_norm_weight=self._hpc_k_norm_w_fp32,
            qk_norm_policy=2 if self.use_qk_norm else 0,
        )
        # q 是 FP8,RadixAttention.forward 输出 dtype 自动切换为 bf16
        attn_output = self.attn(
            q.view(-1, self.q_size), None, None, forward_batch, save_kv_cache=False
        )
        output, _ = self.o_proj(attn_output)
        return output
    # 标准路径:split q/k/v、norm、rope、attn(原有代码略)
    q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
    # ...
python/sglang/srt/layers/attention/attention_registry.py core-logic

注册 hpc_ops 后端,包含启动时约束检查。

# 注册 HPC-Ops 注意力后端,仅在显式指定 `--attention-backend hpc_ops` 时使用
@register_attention_backend("hpc_ops")
def create_hpc_ops_backend(runner):
    # 当前不支持 MLA ( Multi-head Latent Attention ) 模型,显式拒绝
    if runner.use_mla_backend:
        raise ValueError("hpc_ops backend can only be used with non-MLA models.")
    # 不支持编码器 - 解码器模型中的交叉注意力
    if runner.model_config.is_encoder_decoder:
        raise ValueError(
            "Cross attention is not supported in the hpc_ops attention backend."
        )
    # 暂不支持推测解码 ( MTP / EAGLE 等 ),后续可扩展
    if runner.server_args.speculative_algorithm is not None:
        raise ValueError(
            "hpc_ops backend does not support speculative decoding for now."
        )
    # 实际后端类在首次使用时延迟导入,降低启动开销
    from sglang.srt.layers.attention.hpc_ops_backend import HPCOpsAttnBackend
    return HPCOpsAttnBackend(runner)

评论区精华

HPC-Ops 安装方式 documentation

thisjiang 在 review 中指出文档中写的是 `pip install`,但 HPC-Ops 仅支持源码安装。

结论:BBuf 修正文档和测试跳过信息为 'requires installing from source'。 · 已解决

FP8 KV 缓存支持 question

thisjiang 询问文档中最初仅列 bf16,是否有 FP8 支持?

结论:BBuf 确认后添加了 FP8 支持,更新支持矩阵和 `--kv-cache-dtype fp8_e4m3` 示例,并说明 FP8 路径要求特定的 head 配置。 · 已解决

推测解码 (MTP) 支持 question

thisjiang 询问是否支持 MTP (multi-token prediction)。

结论:BBuf 确认当前不支持,后端在工厂函数中显式拒绝推测解码场景,并列为合理后续工作。 · 已解决

风险与影响

  • 依赖风险:HPC-Ops 为手动源码安装,若未安装则启动时因导入 hpc 失败而直接崩溃。建议在工厂函数中增加检测并给出清晰错误。
  • 性能风险:HPC-Ops 内核主要针对 H20 优化,在 H200 等 GPU 上部分场景有 -8% 性能回退。文档已明确注明,但仍可能被用户忽略。后端为 opt-in,影响可控。
  • 兼容性风险:仅支持 sm90+、head_dim=128、GQA 分组 4 或 8、固定 page size=64,若模型不满足则启动时报错,无静默降级。
  • FP8 路径约束:融合 RoPE+quant 内核仅支持 (64,8)(8,1) 两种 head 配置,非兼容模型启动时会被拒绝检查。
  • CUDA Graph 交互:FP8 prefill 路径使用图分割操作,需确保 fused 操作在重放时仍正确执行,已通过注册 register_split_op 处理。
  • 用户影响:仅显式指定 --attention-backend hpc_ops 的用户受影响,默认路径完全不变。现有工作流无需调整。文档已更新支持矩阵。
  • 系统影响:新增一个后端文件(674行),扩展了 server_args.pyoverrides.pyhunyuan_v3.py。无运行时性能开销除非启用。
  • 团队影响:开启了与腾讯混元团队的持续协作通道,后续 MoE、AllReduce 融合等算子将逐步接入。
缺少测试覆盖 第三方依赖风险 硬件平台差异 FP8 路径约束

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论