Prhub

#48637 [CPU][Perf] INT8 Fused MoE Kernel for Arm CPUs

原始 PR 作者 fadara01 合并时间 2026-07-27 13:53 文件变更 12 提交数 9 评论 26 代码增减 +1742 / -216

执行摘要

ARM CPU INT8 融合 MoE 内核,性能提升约 1.9 倍

PR 目的:在 ARM CPU 上启用 W8A8 INT8 MoE 检查点(如 RedHatAI/Qwen3-30B-A3B-Thinking-2507-quantized.w8a8),实现比现有 BF16 内核更高的推理吞吐。PR body 明确提到性能目标为 ~1.9x。

值得精读,尤其是:微内核实现利用 smmla 指令,提取激活函数减少代码重复,以及 Python 层如何通过 _supports_current_device 控制后端选择。

讨论亮点
  1. 整数溢出风险:depthfirst-app[bot] 指出 cpu_fused_moe_int8.cpp 中多处使用 int32_t 计算缓冲区大小和指针偏移,在大量 token 或专家数下可能溢出,建议改用 int64_t。作者未直接回复是否修复,但 PR 已合并,代码片段仍可见 int32_t,风险未彻底解决。
  2. 后端枚举设计:aditew01 提问为何需要 ARM_CPU 枚举,bigPYJ1151 建议统一为 CPU 标签,通过 _supports_current_device 区分设备。作者采纳并修改。
  3. 测试参数化:aditew01 指出测试中直接调用 "neon" 硬编码,作者将其抽象为测试参数,便于未来扩展。

实现拆解

  1. 新增 C++ 微内核 (csrc/cpu/micro_gemm/cpu_micro_gemm_int8_neon.hpp):实现 MicroGemmINT8 模板类,利用 ARM AdvSIMD smmla 指令进行 INT8 矩阵乘法,设计 8x8 的 tile 循环和累加器。
  2. 提取激活函数 (csrc/cpu/cpu_fused_moe_activations.hpp):将原 cpu_fused_moe.cpp 中的 SiLU、GELU、Swiglu 等激活函数提取为独立头文件,供新旧内核共用。
  3. 新增 INT8 MoE 调度内核 (csrc/cpu/cpu_fused_moe_int8.cpp):实现 fused_moe_int8_impl 模板函数,负责 INT8 GEMM 的调度、量化/反量化、激活和加权组合,使用 ISA 分发宏兼容 NEON 和其他架构。
  4. Python 层适配 (vllm/model_executor/layers/fused_moe/experts/cpu_moe.py):新增 ArmCPUExpertsInt8 类,继承 FusedMoEExpertsMonolithic,通过 _supports_current_device 限制仅 ARM CPU,提供 prepare_int8_moe_layer_for_cpu 进行权重预打包。修改 CPUExpertsInt8 使其仅适用 x86。
  5. 测试补充 (tests/kernels/moe/test_cpu_fused_moe.py):新增 test_cpu_fused_moe_int8 测试函数,包含参考实现和量化辅助函数,仅在 ARM 平台运行。
文件 模块 状态 重要度
vllm/model_executor/layers/fused_moe/experts/cpu_moe.py MoE 专家层 modified 8.95
csrc/cpu/micro_gemm/cpu_micro_gemm_int8_neon.hpp 微内核 added 8.21
csrc/cpu/cpu_fused_moe_int8.cpp 调度内核 added 7.98
csrc/cpu/cpu_fused_moe_activations.hpp 激活函数 added 7.85
tests/kernels/moe/test_cpu_fused_moe.py 测试 modified 7.4

关键符号

prepare_int8_moe_layer_for_cpu ArmCPUExpertsInt8._supports_current_device fused_moe_int8_impl gemm_micro_smmla_8x8_packed_a silu_and_mul swigluoai_and_mul

分析完成后,这里会展示 LLM 生成的相对完整源码片段和详细注释。

评论区精华

整数溢出风险 安全

depthfirst-app[bot] 指出 cpu_fused_moe_int8.cpp 中使用 int32_t 计算缓冲区大小(第 131 行)和指针偏移(第 265 行),在大量 token 或专家数下可能溢出,导致堆溢出。

结论:作者未明确回复,PR 已合并,但代码中仍使用 int32_t,风险未彻底解决。 · unresolved

INT8 MoE 后端枚举名称 设计

aditew01 提问为何需要 ARM_CPU 枚举,bigPYJ1151 建议统一为 CPU,通过 _supports_current_device 区分。作者接受并修改。

结论:采用统一 CPU 枚举,设备区分移至专家类。 · 已解决

测试中硬编码 neon 测试

aditew01 质疑测试直接调用 "neon",作者解释目前仅 NEON 实现,但已参数化接口便于扩展。

结论:抽象为测试参数,实现可扩展。 · 已解决

风险与影响

  1. 整数溢出风险:核心缓冲区计算使用 int32_t,在批量 token 数较大时可能溢出,导致内存越界,建议升级到 int64_t。
  2. 仅 ARM 平台支持:INT8 内核仅实现 NEON 版本,其他 CPU 架构无法受益,但不会影响现有 BF16 内核。
  3. 精度损失:INT8 量化对称方案可能引入额外精度误差,但测试提供了参考对比。
  • 用户:ARM CPU 用户可直接使用 INT8 MoE 模型,获得约 1.9 倍性能提升。
  • 系统:CMake 构建新增源文件,需 ARM I8MM 和 BF16 指令集支持,否则回退 BF16。
  • 团队:代码可扩展,为未来 x86 INT8 或其他 ISA 预留了接口。
整数溢出风险 仅 ARM 平台 构建条件依赖 ARM I8MM

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论