Prhub

#42730 [CPU][RISC-V] Add missing RVV cpu_types helpers for WNA16

原始 PR 作者 wcynb1023 合并时间 2026-06-01 14:56 文件变更 3 提交数 4 评论 8 代码增减 +59 / -1

执行摘要

为 RISC-V CPU 添加 WNA16 量化所需 RVV 向量辅助函数

填充了CPU WNA16路径所需的RISC-V RVV辅助函数缺失(PR body原话:"fills missing RISC-V RVV cpu_types helpers that are required by the CPU WNA16 path")。在此变更前,GPTQ量化模型无法在RISC-V服务器上成功运行;变更后,TinyLlama-1.1B-Chat-v0.3-GPTQ可以在RISC-V上加载并正常运行。

对于关注RISC-V后端或CPU量化路径的读者,本PR展示了如何扩展cpu_types以支持新ISA,特别是使用RVV vrgather优化LUT查表的模式值得学习。建议精读cpu_types_riscv_impl.hpp中的新构造函数和interleave_save实现。

讨论亮点
  1. FP32Vec16 LUT构造函数性能:gemini-code-assist指出原始实现使用标量循环和栈溢出,效率低下,建议使用RVV vrgather并行查表。作者采纳建议并重写为vrgather实现,审查者确认优化正确且高效。
  2. Dequantizer4b向量大小不匹配:gemini-code-assist潜在指出如果VecTypeTrait映射为8元素向量,输出保存会留下间隙(代码假设16元素)。该评论在本PR中未解决,作者未回应,可能需后续处理。

实现拆解

  1. 核心向量辅助函数csrc/cpu/cpu_types_riscv_impl.hpp):为FP16Vec16BF16Vec16添加从c10::Halfc10::BFloat16标量构造的构造函数;为FP32Vec16添加从int64_t和查找表构造的构造函数(使用RVV vrgather实现高效并行查表);添加模板函数interleave_save用于交织存储16位向量;添加FP8 KV cache存根以通过编译。
  2. 构建系统cmake/cpu_extension.cmake):当检测到RISC-V且RVV可用时,将csrc/cpu/cpu_wna16.cpp加入源文件列表。
  3. Torch绑定csrc/cpu/torch_bindings.cpp):将cpu_gemm_wna16操作的条件编译从__AVX512F__扩展为__AVX512F__ || defined(__riscv_v),允许在RISC-V上注册并实现该操作。
  4. 性能优化:根据审查反馈,将原始FP32Vec16 LUT构造函数中的标量循环替换为RVV vrgather指令,显著提升反量化路径性能。
文件 模块 状态 重要度
csrc/cpu/cpu_types_riscv_impl.hpp 向量类型层 modified 6.86
csrc/cpu/torch_bindings.cpp Torch 绑定 modified 4.89
cmake/cpu_extension.cmake 构建配置 modified 3.45

关键符号

FP16Vec16(c10::Half) BF16Vec16(c10::BFloat16) FP32Vec16(int64_t, const FP32Vec16&) interleave_save FP32Vec16(const BF16Vec32&, int)

关键源码片段

csrc/cpu/cpu_types_riscv_impl.hpp core-logic

核心文件,添加 RISC-V RVV 向量类型构造器和辅助函数,使 WNA16 路径能够在 RISC-V 上编译运行

// FP32Vec16 的 LUT 构造函数:使用 RVV vrgather 实现 4-bit 反量化查表
// 输入 : value 为 64 位 packed 4-bit 索引(16 个 4-bit 索引),lut 为 16 个浮点数值的查找表
// 输出 : 根据索引从 lut 中 gather 出 16 个 float 值
// 方法 : 先将标量广播为向量,通过 vid 获取 lane ID,移位提取每个 4-bit 索引,
// 然后用 vrgather 并行查表
FP32Vec16(int64_t value, const FP32Vec16& lut) {
  const uint64_t q_values = static_cast<uint64_t>(value);
  // 广播 pack 后的 4-bit 索引到所有元素
  auto packed = RVVI(__riscv_vmv_v_x_u64, LMUL_1024)(q_values, VEC_ELEM_NUM);
  // 生成 lane ID(0..15)并左移 2 位(每个索引占 4 bits)
  auto lane_ids = RVVI(__riscv_vid_v_u64, LMUL_1024)(VEC_ELEM_NUM);
  auto shifts = RVVI(__riscv_vsll_vx_u64, LMUL_1024)(lane_ids, 2, VEC_ELEM_NUM);
  // 右移提取所需索引
  auto shifted = RVVI(__riscv_vsrl_vv_u64, LMUL_1024)(packed, shifts, VEC_ELEM_NUM);
  // 掩码低 4 位得到 4-bit 索引
  auto idx64 = RVVI(__riscv_vand_vx_u64, LMUL_1024)(shifted, 0xF, VEC_ELEM_NUM);
  // 将 64 位索引转换为 32 位(vrgather 要求 32 位索引)
  auto idx32 = RVVI(__riscv_vnsrl_wx_u32, LMUL_512)(idx64, 0, VEC_ELEM_NUM);
  // 使用 vrgather 并行查表
  reg = RVVI(__riscv_vrgather_vv_f32, LMUL_512)(lut.reg, idx32, VEC_ELEM_NUM);
}// 模板函数 interleave_save:将两个 16 位向量交织存储为 32 位 packed 条目
// 用于 AMX 路径需要交织 K 元素的情况,这里为 RISC-V 提供通用实现
// 通过逐一 save 到临时缓冲区再交织写入,避免 AMX 专有路径
void interleave_save_16b(const VecT& vec0, const VecT& vec1, void* ptr) {
  alignas(64) uint16_t values0[VecT::VEC_ELEM_NUM];
  alignas(64) uint16_t values1[VecT::VEC_ELEM_NUM];
  vec0.save(values0);
  vec1.save(values1);
  auto* packed = reinterpret_cast<uint16_t*>(ptr);
  // 交织排列:s0[e], s1[e], s0[e+1], s1[e+1], ...
  for (int e = 0; e < VecT::VEC_ELEM_NUM; ++e) {
    packed[2 * e] = values0[e];
    packed[2 * e + 1] = values1[e];
  }
}

评论区精华

FP32Vec16 LUT 构造函数性能优化 性能

gemini-code-assist 指出原始实现使用标量循环和栈溢出,效率低下,建议使用 RVV vrgather 指令并行查表。

结论:作者使用 vrgather 替换了标量实现,性能提升,审查者确认优化正确且高效。 · 已解决

Dequantizer4b 中向量大小不匹配 正确性

gemini-code-assist 指出如果 VecTypeTrait 映射为 8 元素向量,Dequantizer4b 的输出保存会留下间隙,因为代码假设 16 元素。

结论:该评论未在本 PR 中解决,作者未回应,可能需后续处理。 · unresolved

风险与影响

  1. 平台依赖风险:新增RVV代码依赖于编译器对__riscv_v等宏的正确定义以及硬件VLEN兼容性,不同RISC-V实现(如VLEN=128/256/512)可能影响LMUL和元素数量的匹配,但现有实现已通过VEC_ELEM_NUM常量适配,基本安全。
  2. 测试覆盖不足:仅手动验证了TinyLlama-1.1B-Chat-v0.3-GPTQ一个模型,其他WNA16量化模型(如Marlin稀疏格式)可能仍存在未暴露的问题。缺少自动化单元测试。
  3. 回归风险:对x86后端无影响(条件编译限制),但RISC-V新增符号可能影响未来重构时的编译兼容性。

用户:RISC-V CPU用户现在可以运行GPTQ量化模型(如TinyLlama),扩展了vLLM的硬件兼容性。
系统:仅在RISC-V且RVV可用时生效,其他平台无影响。
团队:增加了RISC-V架构的维护成本,但代码量小且独立;后续W4A16优化将在此基础上进行。

仅手动测试一个模型 RVV VLEN 依赖

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论