Prhub

#40451 [Hardware][Power]Add Power VSX Attention Backend and fix l2 Cache Crash

原始 PR 作者 Akashcodes732 合并时间 2026-05-05 11:51 文件变更 8 提交数 11 评论 19 代码增减 +399 / -9

执行摘要

新增 Power VSX 注意力后端并修复 L2 缓存初始化崩溃

来自 PR 描述:目的是为 PowerPC 架构添加原生 VSX 支持,避免回退到标量代码,并解决初始化时 IndexError: unordered_map::at 造成的崩溃。测试用例为 ibm-granite/granite-3.3-8b-instruct 模型,在 ppc64le 上验证。

该 PR 值得关注硬件加速相关的设计模式:如何为不同 ISA 实现微内核并融入统一 dispatch 框架。特别需阅读 cpu_attn_vsx.hpp 中的 BF16 加载技巧和 generate_cpu_attn_dispatch.py 的条件编译方式。建议在合并后补充 VSX 内核的单元测试和基准对比。对于实现的技术细节,可参考最终合并版本是否修正了讨论中的合并方向问题。

讨论亮点

Review 中最关键的讨论:

  1. BFloat16 合并方向错误(gemini-code-assist[bot]):在 ppc64le 小端下,vec_mergeh/vec_mergel 的选择导致 8 元素行数据高低半部分互换,若未修正将导致 GEMM 结果错误。目前 PR 中代码仍保持此写法,需关注最终合并版本是否已修复。
  2. Half 类型指针算术错误(gemini-code-assist[bot]):copy_q_heads_tile 中使用 (float*)curr_src + d 对于 c10::Half 类型地址计算错误。
  3. FP16 性能瓶颈(gemini-code-assist[bot]):load_row8_B_as_f32c10::Half 特化使用标量循环,建议使用 xvcvhpsp 向量化。
  4. L2 缓存修复范围讨论(bigPYJ1151 与 gemini):bigPYJ1151 认为 #if 分支不应移除 x86/ARM,而应为 POWER 单独添加安全分支;gemini 建议全局应用安全模式以提高健壮性。
  5. FP8 KV cache 编译问题(bigPYJ1151 与 Akashcodes732):bigPYJ1151 建议在 cpu_types_vsx.hpp 中添加空结构体 stub 而非修改 cpu_attn_vec.hpp 的 guard,作者接受并采用。

实现拆解

实现分为四步:

  1. 新增 VSX 注意力内核文件csrc/cpu/cpu_attn_vsx.hpp):实现基于 Power VSX 指令的微内核 gemm_micro_ppc64le_Mx8_Ku4load_row8_B_as_f32 特化,支持 floatbfloat16 类型加载,并通过模板类 AttentionImpl 与现有框架对接。
  2. 扩展 ISA 枚举与分发脚本:在 csrc/cpu/cpu_attn_impl.hppcpu_attention::ISA 中新增 VSX 枚举值;在 csrc/cpu/generate_cpu_attn_dispatch.py 中注册 VSX 类型并添加到 ISA_FOR_32,生成条件编译宏 #ifdef __powerpc__ 包含新头文件并生成 dispatch case。
  3. Python 后端架构感知:在 vllm/v1/attention/backends/cpu_attn.py 中的 _CPU_ARCH_PREFER_MIXED_BATCH 元组加入 CpuArchEnum.POWERPC,使 Power 架构优先使用混合批次;在 _get_attn_isa() 函数中检测 arch == CpuArchEnum.POWERPC 返回 "vsx",从而选择 VSX 内核。
  4. L2 缓存大小修复:在 csrc/cpu/utils.hpp 中,将本用于 __s390x__ 的安全 L2 缓存检测(使用 find 而非 at)扩展到 __powerpc__,避免 unordered_map::at 因键缺失崩溃;同时提供默认回退 256KB。
  5. 配套调整:修改 csrc/cpu/cpu_attn.cpp 以识别 "vsx" ISA 提示;修改 csrc/cpu/cpu_attn_vec.hpp 添加注释说明 VSX 不支持 FP8 KV cache 并调整 load_b_pair_vec 返回语句;修改 csrc/cpu/cpu_types_vsx.hpp 添加 FP8 标记的 stub 以通过编译。注意:本次未包含直接测试文件变更。
文件 模块 状态 重要度
csrc/cpu/cpu_attn_vsx.hpp VSX 内核 added 8.63
csrc/cpu/generate_cpu_attn_dispatch.py 分发生成 modified 6.35
vllm/v1/attention/backends/cpu_attn.py 后端路由 modified 6.04
csrc/cpu/cpu_attn_impl.hpp ISA 枚举 modified 5.53
csrc/cpu/cpu_attn.cpp 调度入口 modified 5.15
csrc/cpu/cpu_attn_vec.hpp 向量加载 modified 4.87
csrc/cpu/cpu_types_vsx.hpp 类型支撑 modified 4.5
csrc/cpu/utils.hpp L2 检测 modified 5.09

关键符号

load_row8_B_as_f32 gemm_micro_ppc64le_Mx8_Ku4 get_available_l2_size _get_attn_isa copy_q_heads_tile

关键源码片段

csrc/cpu/cpu_attn_vsx.hpp core-logic

新增文件,实现 Power VSX 注意力微内核,包含 BF16/FP32 加载和 GEMM 微块,是 PR 的核心变更。

// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright contributors to the vLLM project
// 以下展示 BFloat16 特化的 load_row8_B_as_f32 函数
// 利用 vec_mergeh/mergel 将 BF16 扩展为 float32,实现内存加载
// 注意:在 ppc64le 小端下,vec_mergeh 取高半部分,vec_mergel 取低半部分
// 若方向错误将导致 GEMM 结果错误(参见 review #1)
template <>
FORCE_INLINE void load_row8_B_as_f32<c10::BFloat16>(const c10::BFloat16* p,
                                                    __vector float& b0,
                                                    __vector float& b1) {
  __vector unsigned short raw = vec_xl(
      0, reinterpret_cast<unsigned short*>(const_cast<c10::BFloat16*>(p)));
  __vector unsigned short zeros = vec_splat_u16(0);
  // LE: zeros 填入低 16 位,raw 填入高 16 位,得到 (bf16_bits << 16) 等价 float32
  b0 = (__vector float)vec_mergeh(zeros, raw);
  b1 = (__vector float)vec_mergel(zeros, raw);
}
// Note: c10::Half (FP16) is not supported on PowerPC architecture
csrc/cpu/generate_cpu_attn_dispatch.py dependency-wiring

修改分发脚本,注册 VSX ISA 类型、加入 ISA_FOR_32 列表,并生成 __powerpc__ 条件编译分支,将新内核集成到 dispatch 中。

# 在 ISA_TYPES 中增加 VSX 类型
ISA_TYPES = {
    "AMX": 0,
    "VEC": 1,
    "VEC16": 2,
    "NEON": 3,
    "VXE": 4,
    "VSX": 5, # 新增 Power VSX
}# 在 ISA_FOR_32 中加入 VSX,表示 head_dim 可被 32 整除时支持
ISA_FOR_32 = ["AMX", "NEON", "VEC", "VEC16", "VXE", "VSX"]# 在 generate_header_file 中添加条件包含
#ifdef __powerpc__
  #include "cpu_attn_vsx.hpp"
#endif# 添加 __powerpc__ 宏块,包含 VSX、VEC、VEC16(不带 FP8)
header += _macro_block(
    "#elif defined(__powerpc__)",
    ["VSX", "VEC", "VEC16"],
    fp8=False,
)
vllm/v1/attention/backends/cpu_attn.py core-logic

修改 Python 后端,在 _get_attn_isa 中检测 POWERPC 架构并返回 'vsx',同时在 _CPU_ARCH_PREFER_MIXED_BATCH 中加入 POWERPC。

def _get_attn_isa(dtype, block_size, head_size=None, kv_cache_dtype=None):
    # ... 前面部分 ...
    supports_amx = torch.cpu._is_amx_tile_supported()
    arch = current_platform.get_cpu_architecture()
    supports_arm = arch == CpuArchEnum.ARM
    supports_vxe = arch == CpuArchEnum.S390X
    supports_vsx = arch == CpuArchEnum.POWERPC # 新增 Power 检测
    # ...
    if supports_amx and dtype in (torch.bfloat16,) and block_size % 32 == 0:
        return "amx"
    elif block_size % 32 == 0:
        if supports_arm:
            return "neon"
        elif supports_vxe:
            return "vxe"
        elif supports_vsx:
            return "vsx" # 返回 VSX ISA 名称
        else:
            return "vec"
    else:
        return "vec16"# 同时将 POWERPC 加入混合批次偏好的架构列表
_CPU_ARCH_PREFER_MIXED_BATCH = (
    CpuArchEnum.X86, CpuArchEnum.ARM, CpuArchEnum.S390X, CpuArchEnum.POWERPC,
)

评论区精华

BFloat16 合并方向错误 正确性

gemini-code-assist[bot] 指出在 ppc64le 小端下,vec_mergeh/vec_mergel 的行半部分分配与 float 特化相反,可能导致 GEMM 结果错误。

结论:未在 PR 中看到修正,需确认合并状态。 · unresolved

Half 类型指针错误 正确性

gemini-code-assist[bot] 指出 copy_q_heads_tile 中对 c10::Half 的指针算术和加载使用 (float*) 转换,导致地址计算错误。

结论:建议使用 load_row8_B_as_f32 替代,未确认是否采用。 · unresolved

FP16 性能瓶颈 性能

gemini-code-assist[bot] 指出 load_row8_B_as_f32 的 c10::Half 特化使用标量循环,建议使用 xvcvhpsp 向量化。

结论:未在 PR 中改进,可能是后续优化。 · unresolved

L2 缓存修复范围 设计

bigPYJ1151 要求保留 x86/ARM 分支,为 POWER 单独添加;gemini 建议全局安全模式。作者扩展到 __powerpc__ 但未全局改动。

结论:折中处理:仅对 s390x 和 powerpc 使用安全查找,其他架构保持原样。 · 已解决

FP8 KV cache 编译问题 测试

bigPYJ1151 建议在 cpu_types_vsx.hpp 中添加空结构体 stub 代替修改 guard,作者接受。

结论:采用 stub 方案,已在 cpu_types_vsx.hpp 中添加。 · 已解决

风险与影响

  1. BFloat16 合并方向风险:若未按 ppc64le 字节序正确取高低半部分,VSX 后端 BFloat16 输入将产生错误计算结果,影响所有使用 BFloat16 的模型(如测试的 Granite)。此风险为实际正确性错误,必须确认已修复。
  2. Half 类型指针和加载风险copy_q_heads_tile 中对 c10::Half 的不当加载可能导致数据错乱或崩溃,虽 c10::Half 在 Power 上支持可能有限,但仍需修复。
  3. FP16 性能风险:当前 c10::Half 使用标量循环,在 FP16 模型推理时将成为严重瓶颈,建议后续优化。
  4. L2 缓存修复不足风险#else 分支仍直接调用 at,在其他架构上若键缺失仍会崩溃;本次仅扩展了 __powerpc__ 到条件中,未做全局改进。
  5. 缺少测试覆盖:未提供直接对 VSX 内核或 dispatch 的单元测试,回归风险较高。

用户影响:PowerPC(ppc64le)用户获得官方 VSX 注意力加速,可在 bf16 精度下运行如 granite-3.3-8b-instruct 等模型;之前因 L2 崩溃无法初始化的场景得到修复。
系统影响:构建系统条件编译增加 __powerpc__ 分支,不影响 x86/ARM 等现有平台。
团队影响:增加对 Power 后端的维护责任,需持续跟进 Power 特有的 ABI 和向量化兼容性。review 中发现的潜在正确性问题需要密切跟踪。

BF16 合并方向风险 Half 加载性能风险 L2 修复范围不足 缺少测试覆盖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论