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

【算子】05. 性能调优:Bank Conflict、Repeat/DataBlock 与搬运优化

AI 辅助阅读官方代码生成的文档,纯理论分析,未上机验证

涉及用例清单

用例说明源码
matmul_high_performanceMatmul 高阶 API 9 级递进优化(单核→多核→MDL→Cache→常量Tiling→UnitFlag)04_best_practices/01_matrix_compute_practices/matmul_high_performance/
data_copyGM↔UB、GM↔L1 搬运效率对比(分块大小、非对齐、L2Cache、同地址冲突)04_best_practices/04_memory_access_practices/data_copy/
bank_conflict_nd2nzND→NZ 格式转换中 UB bank 冲突的 stride 规避04_best_practices/04_memory_access_practices/bank_conflict_nd2nz/

用例路径均在asc-devkit/examples/01_simd_cpp_api/下。


1. 三个用例概览

1.1 matmul_high_performance — 9 级递进优化

矩阵规格 M=N=K=8192,NPU 架构 2201(24核),通过SCENARIO_NUM编译宏切换 9 个优化级别:

Case优化策略说明
0单核基础单核完成全量计算,无 tiling
1单核 Tiling固定 baseM/baseN/baseK,tiling 分块
2多核 M:N=2:12 切分多核并行,M 分 2 份 N 分 12 份
3多核 M:N=4:6 切分平衡 M/N 方向的负载
4MDL (Matrix Data Layout)开启 MDL 模式,优化 L1→L0 数据搬运效率
5MDL + L1Cache增加 L1 缓存深度(depthA1=16, stepKa=8)
6MDL + L1Cache + L2CacheM 轴切分为 2 份循环计算,利用 L2 缓存复用 B 矩阵
7常量 Tiling编译期生成 MatmulApiStaticTiling,消除运行时 Scalar 开销
8常量 Tiling + UnitFlag使能 UnitFlag,减少 M/N 尾块处理的标量判断

关键代码结构(以 Case 6 L2Cache 为例):

// B 矩阵复用:A 矩阵沿 M 轴切 2 份,共享同一份 Bfor(inti=0;i<2;i++){matmulObj.SetTensorA(aGlobal[offsetA+i*(M>>1)*K]);matmulObj.SetTensorB(bGlobal[offsetB]);// B 复用matmulObj.IterateAll(cGlobal[offsetC+i*(M>>1)*N]);}

核心结论:Matmul 高阶 API 的调优不涉及手写 kernel 逻辑,而是通过调整 tiling 参数(split 比例、buffer 深度、cache 模式)和编译期常量化来优化。性能提升主要来自:减少 Scalar 计算开销(常量 Tiling)、提高数据复用率(L2 Cache 复用 B 矩阵)、减少尾块分支(UnitFlag)。

1.2 data_copy — 搬运效率对比

在 Vector Add 场景下对比 DataCopy 和 DataCopyPad 在不同参数下的效率:

内存搬运到 UB 的性能趋势(来自 README 的性能数据):

  • 分块粒度:单次搬运量越大效率越高,16KB+ 达到带宽峰值
  • 非对齐搬运:首地址非 32B 对齐时性能显著下降
  • L2Cache 复用:开启 L2 Cache 可提升 ~30%(GM↔L2 带宽远高于 GM↔HBM)
  • 同地址冲突:多个 DataCopy 同时访问相同 GM 地址时产生竞争,通过偏移起始地址规避

1.3 bank_conflict_nd2nz — ND→NZ 格式转换的 Bank 冲突规避

两个场景对比:默认 stride → 全冲突,调整 stride → 无冲突。详见第 3 节 bank conflict 原理分析。


2. Bank Conflict 深度解析

2.1 什么是 Bank Conflict

UB(Unified Buffer)不是一整块连续内存,而是被拆分成bank——每个 bank 是独立的存储体,可以独立读写。

910B (dav-2201) 的 UB 结构

UB 总大小 192KB ├── 16 个 bank group(每个 group 每拍最多 1 读或 1 写) │ └── 每个 bank group 含 3 个 bank │ └── 每个 bank = 4KB = 128 行 × 32B/行 总共 48 个 bank

Bank 地址映射规则:bank ID = (address / 32B) % 48
Bank group 划分:group k = banks {k, k+16, k+32}, k ∈ [0,15]

3510 的差异(用于对比理解):

  • UB 256KB,16 个 bank,8 个 bank group,每组 2 个 bank
  • 每个 bank group 有两组读写口(可 2 读 0 写 或 1 读 1 写,2201 只能 1 读或 1 写)

2.2 三种冲突类型

类型条件后果
读写冲突读和写同时访问同一个 bank排队串行
写写冲突多个写同时访问同一个 bank group排队串行
读读冲突多个读同时访问同一个 bank group排队串行(3510:2 读可并行,超过才冲突)

2.3 冲突发生的原因

Vector 计算单元每拍同时读/写 8 个 DataBlock(每个 32B,共 256B)。如果这 8 个 DataBlock 因地址 stride 对齐而全部落在同一个 bank group 上,本来 1 拍完成的操作需要排队 8 拍——性能直接除 8。

典型问题场景

Add(dst, src0, src1, repeatParams): src0 base=0x00000 (bank 0, group 0) src1 base=0x04000 (bank 32, group 0) ← 与 src0 同 group! dst base=0x08000 (bank 0, group 0) ← 与 src0 同 group! 同一 Repeat 内:读src0 + 读src1 → 读读冲突(同bank group不同bank) 读src0 + 写dst → 读写冲突(相同bank)

2.4 如何检测

使用msprof op工具跑算子后,生成ResourceConflictRatio.csv,其中展示 bank group conflict 在所有指令周期中的占比。

msprofop./your_kernel_executable# 输出目录下的 ResourceConflictRatio.csv 包含冲突占比数据

2.5 两种规避方法

方法一:调整访问 Stride

把"跳着读"改成"连续读",避免同一 Repeat 的 8 个 DataBlock 落入同 bank group:

// 反例:blkStride=16 → 8 DataBlock 全落在 bank group 0BinaryRepeatParams{1,16,16,8,8,8};// 正例:blkStride=1 → 8 DataBlock 均匀分散到 8 个不同 bank groupBinaryRepeatParams{1,1,1,8,8,8};
方法二:地址 Padding

多申请一点 UB 空间做偏移,让各 buffer 的起始地址落到不同 bank group:

// 反例:x起始bank0, y起始bank32(同group0) → 读读冲突常量pipe.InitBuffer(inQueueX,1,4096*sizeof(float));pipe.InitBuffer(inQueueY,1,4096*sizeof(float));// 正例:x 多申请 256B (8 DataBlock),y 地址偏移到 bank 8 (group 8)pipe.InitBuffer(inQueueX,1,4096*sizeof(float)+256);pipe.InitBuffer(inQueueY,1,4096*sizeof(float));// 效果:x 和 y 起始 bank group 不同,无读读冲突

2.6 文档索引

文档路径关键行
Bank冲突概述SIMD算子性能优化/内存访问/避免UB的bank冲突/概述.md第 7-32 行(结构总览+dav对比)
2201 规避指南避免bank冲突(NPU架构版本2201).md第 10-17, 261-361 行
3510 规避指南避免bank冲突(NPU架构版本3510).md第 3-10, 216-318 行
SIMT Bank冲突SIMT算子性能优化/内存访问/避免UB的Bank冲突.md第 55-91 行(Padding 优化 25.7%)
msprof 检测调试调优/性能调优.md第 47, 100 行(ResourceConflictRatio.csv)

3. Repeat / DataBlock 机制

3.1 硬件约束

Vector 计算单元每拍处理256 字节NPU架构版本3510.md第 55 行)。一个 DataBlock = 32B,所以每拍 = 8 个 DataBlock。这是硬件固定宽度,不可配置。

3.2 Repeat = 一拍的硬件执行

一次 Vector API 调用(AddMulExp等)的硬件行为等价于:

while (repeatTimes--) { 读取 8 个 DataBlock(256B) 执行计算 写回 8 个 DataBlock(256B) }

3.3 三个控制参数

Repeat0:[DB0][DB1][DB2][DB3][DB4][DB5][DB6][DB7]├── dataBlockStride ──┤ ← 同一 Repeat 内相邻 DB 的间隔(单位:DataBlock) Repeat0DB0 地址:base Repeat1DB0 地址:base+repeatStride ×32B ← 相邻 Repeat 起始地址间隔
参数范围默认值含义
repeatTimes≤255API 内部按 count 算执行多少次 Repeat
dataBlockStride(blkStride)≥01(连续)同一 Repeat 内 8 个 DB 的间隔。0=始终复用第一个 DB
repeatStride(repStride)≥08(连续)相邻 Repeat 起始地址的间隔。0=反复计算同一组 DB

3.4 与 Bank Conflict 的关系

dataBlockStride=1 → 8 DB 地址: 0,1,2,3,4,5,6,7 → 8 bank: 0,1,2,3,4,5,6,7 → 8 bank group: 0,1,2,3,4,5,6,7 → 全部不同 → 无冲突 ✓ dataBlockStride=16 → 8 DB 地址: 0,16,32,48,64,80,96,112 → 8 bank: 0,16,32,0,16,32,0,16 → 全部 bank group 0 → 全冲突 ✗ (8 拍完成)

根因dataBlockStride恰好匹配 bank group 映射周期时(每 16 个 bank 循环一次 bank group),所有 DB 落入同一 group。

3.5 文档索引

文档关键行内容
术语表第 148-156, 374-387 行DataBlock、Repeat/RepeatStride/RepeatTimes 定义
高维切分第 23-84 行8 DataBlock 机制、blkStride/repStride 四种场景详解+示意图
UnaryRepeatParams全文结构体字段定义与使用说明

4. 性能优化建议汇总

来自各文档的优化建议(优化建议总览表.md):

优先级优化项说明
多核拆分利用全部物理 core,确保负载均衡
Double Buffer使能 double buffer 实现搬运与计算的流水重叠
减少 Bank 冲突调整 stride 或地址 padding
设置合理的 L2 CacheMode默认使能 L2Cache,数据量不大时无需干预
L2 Cache 切分当数据总量超过 L2 容量时,手动切分 L2 复用窗口
使能 L1 CacheMatmul 场景中增加 L1 depth,提高数据复用
常量 Tiling编译期生成 tiling,消除运行时 Scalar 开销
数据搬运对齐保证 GM↔UB 搬运大小 = DataBlock 整数倍且 ≥16KB
避免同地址访问多个 DataCopy 同时访问相同 GM 地址时产生竞争
UnitFlag减少尾块处理标量判断(Matmul 高阶 API)
纯 Cube 模式跳过 KFC 消息框架开销(纯矩阵乘场景)

5. 附录:关键术语

术语含义
RepeatVector 计算单元的一拍:同时读 8 个 DataBlock(256B)→ 计算 → 写回
DataBlockVector 计算的基本单元,32B。UB 每行也是 32B
dataBlockStride同一 Repeat 内相邻 DataBlock 的间隔(单位=DataBlock)
repeatStride相邻 Repeat 起始 DataBlock 的间隔(单位=DataBlock)
BankUB 的独立存储体(2201: 4KB/个, 3510: 16KB/个)
Bank Group多个 bank 的逻辑组。2201: 3 bank/组, 3510: 2 bank/组
Bank Conflict多个并发访问撞到同一 bank group,排队串行
MDLMatrix Data Layout 模式,优化 L1→L0 搬运(Matmul 调优)
L2 Cache硬件自动管理的 GM 缓存(~7TB/s vs GM ~1.6TB/s)
常量 Tiling编译期生成 tiling 数据为constexpr,消除运行时标量计算
UnitFlag硬件自动处理 M/N 尾块,无需 kernel 侧SetTail
http://www.jsqmd.com/news/1020746/

相关文章:

  • 创业公司怎么省云钱:架构设计里的精算学
  • 混合储能驱动永磁同步电机全系统仿真模型(Simulink仿真实现)
  • 快速掌握Windows预览体验计划终极离线配置指南
  • Python机器学习模型服务化:从Flask到FastAPI生产实践
  • Ubuntu系统实战指南:从桌面开发到服务器部署的全面解析
  • 2026靠谱降AIGC工具怎么选?实测15款后这几个最实用
  • 软件著作权申请指南:高通过率说明文档撰写模板与全流程解析
  • 医院钢制门排名
  • Oracle异步描述符调整等待事件:原理、诊断与优化实战
  • AI 功能的用户体验设计:从技术演示到产品价值,智能功能的体验闭环
  • 红外显微镜的价格与品牌选择指南
  • 行测电子版教材|备考|刷题
  • Windows硬件信息深度伪装实战指南:EASY-HWID-SPOOFER内核级修改解决方案
  • XUnity.AutoTranslator:Unity游戏实时翻译引擎深度解析与实战指南
  • 文本预处理实战:面向机器学习任务的中文英文清洗与特征构建
  • 北欧路线老年旅行团哪家体验感好?2026口碑好的北欧路线暑期家庭旅行团推荐 - 品牌2026
  • FMQL:构建安全高效动态查询的声明式查询语言规范
  • 终极鼠标悬停翻译指南:如何在浏览器中实现一键多语言翻译
  • 小红书内容高效管理终极指南:3种方式实现作品批量下载完整解决方案
  • OpenRouter Fusion 搅动 AGI 格局:当「多模型协作」打平「单模型最强」,通往 AGI 的路可能不止一条 - 微元算力(weytoken)
  • 【CANdelaStudio-从入门到深入到实战】17 安全访问实战:从“种子-密钥”到“会话锁”的攻防博弈
  • 行测电子书下载|pdf版本|全套
  • Adabound优化器实战指南:工业级模型稳定收敛技巧
  • LLM、Token、RAG、Agent、MCP……普通人最容易卡住的8个AI概念,一篇讲明白
  • 3分钟掌握Silk音频转换:高效解码微信QQ语音的专业方案
  • 终极RustDesk服务器一键部署:10分钟搭建免费远程桌面平台
  • 大功率电力电子、生态环境多维传感、重型高端运动控制、全层级内核权限、全品类存储介质、天地全域通信、工业电气安全十五大顶级底层架构体系,全部采用标准C语言内嵌汇编双格式绝密源码编写,彻底销毁设备出厂预埋
  • 如何免费解锁Wand专业版:终极游戏修改指南
  • 简历改了8遍没回应?测试开发私教老师一顿操作,学员:“原来我写了个寂寞”
  • 2026年 广东TFT液晶屏源头厂家推荐榜单:高亮/宽温/工业级/医疗级/车载TFT屏,智能家电与超声诊断仪TFT,小尺寸2.4/2.8/3.5吋定制品牌评测 - 品牌发掘