当前位置: 首页 > news >正文

ops-reduce:ReduceMax 与 ReduceMean 的并行优化

Transformer 推理中 Reduce 类算子无处不在:LayerNorm 需要算 mean 和 var(ReduceMean + 方差),Softmax 需要算 max(ReduceMax)和 sum(ReduceSum),Attention 的归一化因子需要跨序列维度做归约。

ops-reduce 是 CANN 管理所有归约算子的仓库——ReduceMax、ReduceMin、ReduceMean、ReduceProd。它们共享同一个核心问题:计算量极小但搬运量极大。


为什么 Reduce 类算子容易成为瓶颈

以 ReduceMax 为例——在一个[4096, 4096]的 Tensor 上沿行方向找最大值:

  • 数据量:32MB
  • 计算量:4096×4095 = 16M 次比较
  • 计算/搬运比:约 0.5 FLOPs/byte

对比 GEMM 的 52.5 FLOPs/byte——Reduce 的瓶颈非常明显:时间主要花在从 DDR 读数据上,Vector Unit 的比较运算只需要几微秒。


ReduceMax 与 ReduceMean 的典型场景

ReduceMax——Attention 中的 Softmax。Softmax 的第一步需要对 Score 矩阵的每一行找最大值,用于数值稳定性(减去最大值防止 exp 溢出)。这个 ReduceMax 在朴素 Attention 中需要对 32MB 的 Score 矩阵做一次完整扫描。

ReduceMean——LayerNorm。LayerNorm 的第一步mean = sum(x) / n需要对输入 Tensor 做 ReduceSum 再除以 n。LLaMA 的每个 Decoder Block 做两次 LayerNorm——每次都要对隐藏层的[B, n, d]Tensor 做 mean 和 var。


昇腾NPU如何做并行归约

ops-reduce 在 Vector Unit 上做并行归约。一个 Core 处理一部分数据,用 SIMD 指令同时比较多个元素:

// 昇腾 Vector Unit 上的 ReduceMax Kernel(伪代码)// 输入:x (GM 地址), n = 元素数// 输出:max_value (GM 地址)__vector__voidreduce_max_kernel(...){float16 local_max=-FLT_MAX;// 每次处理 128 个元素for(inti=0;i<n;i+=128){float16 vec[128]=load_gm_to_local(x+i);// DDR→L1local_max=vec_max(local_max,vec);// SIMD 比较}// 如果启动了多个 Core,做跨 Core 归约float16 global_max=warp_reduce_max(local_max);store_local_to_gm(global_max,max_value);// L1→DDR}

多 Core 场景中每个 Core 先算自己的局部最大值,然后通过一次跨 Core 的 reduce 操作合并为全局最大值。这个跨 Core reduce 在 Vector Unit 上用warp_reduce_max指令完成——比写 DDR 再读回来快两个数量级。


性能分析

在 Ascend 910 上对不同大小 Tensor 做 ReduceMax 的实测:

Tensor 形状元素数搬运量延迟带宽利用率
[1024]1K2KB3μs15%
[1,4096]4K8KB5μs28%
[4096,4096]16M32MB85μs72%
[8,4096,4096]128M256MB610μs78%

小 Tensor 的带宽利用率低是因为 DMA 启动开销占比大。大 Tensor 的利用率接近硬件上限。


Transformer 中的归约链路

LLaMA-7B 的两次 LayerNorm 的归约链路:

输入 [B, n, d] → ReduceMean → (x - mean)² → ReduceMean → var ↑ ↑ 一次归约 一次归约 mean 缓存 var 缓存

ops-reduce 在 LayerNorm 场景中的优化是:meanvar的归约 Kernel 共享同一个 Tensor 的搬运——mean归约时从 DDR 读一次 x,var归约时复用 L1 上的 x 数据,不需要重新搬运。优化后归约的搬运量从 2 次减到 1 次。

ReduceMean 的融合执行

ReduceMean 可以跟下游算子融合。LayerNorm 的(x - mean) / sqrt(var + eps)中,ReduceMean 和后面的计算共享同一个 x 的搬运——x 搬入 L1 后先做 ReduceMean,mean 的结果留存在 L1 中,后续的x - mean和 ReduceVar 直接使用——x 不需要重新搬运。

融合后 LayerNorm 的总搬运量从 2 次降到 1 次。实测中 LLaMA-7B 的 LayerNorm 延迟从 12μs 降到 7μs。

性能分析表的补充

Ascend 910 上不同 Tensor 大小的 ReduceMean(axis=-1)性能:

Tensor 形状元素数延迟瓶颈环节
[1, 4096]4K4μsDMA 启动
[4, 4096, 4096]64M210μsDDR 带宽
[8, 4096, 4096]128M395μsDDR 带宽
[1, 4096, 4096]16M56μsDDR 带宽

Batch 维度增加时延迟近线性增长——ops-reduce 在 Batch 维度上可以并行,每个 Batch 分给不同 Core 处理,Batch=8 时 4 个 Core 并行能把延迟从 395μs 降到 110μs。

参考仓库

ops-reduce 归约算子库

ops-math 数学算子库

http://www.zskr.cn/news/1351770.html

相关文章:

  • ESP8266玩转MicroPython:从固件烧录到第一个物联网项目(Thonny+点灯科技)
  • 什么,锐捷极简以太彩光一张网竟然有两幅面孔?
  • RK3588下位机程序无响应问题排查
  • GD32/STM32串口高效收数秘籍:巧用IDLE中断判断一帧数据收完
  • C语言标识符命名规则详解:从ZZULIOJ 1138题看新手常犯的5个错误
  • M1 Mac上搞定Tinker热修复:从7zip报错到成功生成补丁的完整踩坑实录
  • Maven依赖scope:从编译到打包,一张图理清生命周期与classpath
  • 观察不同时段调用 Taotoken 各类模型的延迟表现
  • pyasc:用 Python 调用 CANN 的推理能力
  • 6.1 TIM定时中断
  • RAG-外挂 “实时知识库”
  • 如何通过CircuitJS1 Desktop Mod实现零门槛电路仿真学习
  • 缓存一致性协议与事务内存的冲突检测机制
  • 样本量不足导致NotebookLM幻觉频发,如何用贝叶斯修正法72小时内精准重算?
  • 别再只测电压了!用STM32 HAL库的ADC+DMA,给你的移动设备做个精准电量计(附源码)
  • 5分钟搞定Windows 11区域语言模拟:Locale Remulator终极指南
  • 抖音下载神器:免费批量下载视频、图集、音乐和直播回放完整指南
  • Slumber:基于终端的 HTTP 客户端,兼具易用性与可配置性
  • 如何让AI Agent安全可控地工作?Markus治理体系深度解析
  • 80C166/C167芯片内部RAM执行代码技术详解
  • 终极指南:如何用Udeler轻松下载Udemy课程进行离线学习
  • Keil MDK FlexNet许可证服务器连接问题解决方案
  • 实时音视频ERTC方案概述
  • Claude Code 国内替代方案:基于百炼的配置与实践
  • 2026年鲜花店收银系统必备功能:节日高峰适配+线上预订同步
  • 评价高的四轴直驱电机厂家哪家靠谱
  • Antigravity IDE规则
  • DPO vs PPO:两种AI对齐技术到底选哪个?我全试了一遍
  • 全开源CRM客户关系管理系统源码完整部署指南附代码
  • Qwen3.5大模型入门:手把手教你构建多模态RAG智能问答系统(收藏版)