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

📅 2026/6/16 3:12:41
【算子】05. 性能调优:Bank Conflict、Repeat/DataBlock 与搬运优化
AI 辅助阅读官方代码生成的文档纯理论分析未上机验证涉及用例清单用例说明源码matmul_high_performanceMatmul 高阶 API 9 级递进优化单核→多核→MDL→Cache→常量Tiling→UnitFlag04_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 级递进优化矩阵规格 MNK8192NPU 架构 220124核通过SCENARIO_NUM编译宏切换 9 个优化级别Case优化策略说明0单核基础单核完成全量计算无 tiling1单核 Tiling固定 baseM/baseN/baseKtiling 分块2多核 M:N2:12 切分多核并行M 分 2 份 N 分 12 份3多核 M:N4:6 切分平衡 M/N 方向的负载4MDL (Matrix Data Layout)开启 MDL 模式优化 L1→L0 数据搬运效率5MDL L1Cache增加 L1 缓存深度depthA116, stepKa86MDL L1Cache L2CacheM 轴切分为 2 份循环计算利用 L2 缓存复用 B 矩阵7常量 Tiling编译期生成 MatmulApiStaticTiling消除运行时 Scalar 开销8常量 Tiling UnitFlag使能 UnitFlag减少 M/N 尾块处理的标量判断关键代码结构以 Case 6 L2Cache 为例// B 矩阵复用A 矩阵沿 M 轴切 2 份共享同一份 Bfor(inti0;i2;i){matmulObj.SetTensorA(aGlobal[offsetAi*(M1)*K]);matmulObj.SetTensorB(bGlobal[offsetB]);// B 复用matmulObj.IterateAll(cGlobal[offsetCi*(M1)*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 ConflictUBUnified Buffer不是一整块连续内存而是被拆分成bank——每个 bank 是独立的存储体可以独立读写。910B (dav-2201) 的 UB 结构UB 总大小 192KB ├── 16 个 bank group每个 group 每拍最多 1 读或 1 写 │ └── 每个 bank group 含 3 个 bank │ └── 每个 bank 4KB 128 行 × 32B/行 总共 48 个 bankBank 地址映射规则bank ID (address / 32B) % 48Bank group 划分group k banks {k, k16, k32}, k ∈ [0,15]3510 的差异用于对比理解UB 256KB16 个 bank8 个 bank group每组 2 个 bank每个 bank group 有两组读写口可 2 读 0 写 或 1 读 1 写2201 只能 1 读或 1 写2.2 三种冲突类型类型条件后果读写冲突读和写同时访问同一个 bank排队串行写写冲突多个写同时访问同一个 bank group排队串行读读冲突多个读同时访问同一个 bank group排队串行35102 读可并行超过才冲突2.3 冲突发生的原因Vector 计算单元每拍同时读/写 8 个 DataBlock每个 32B共 256B。如果这 8 个 DataBlock 因地址 stride 对齐而全部落在同一个 bank group 上本来 1 拍完成的操作需要排队 8 拍——性能直接除 8。典型问题场景Add(dst, src0, src1, repeatParams): src0 base0x00000 (bank 0, group 0) src1 base0x04000 (bank 32, group 0) ← 与 src0 同 group! dst base0x08000 (bank 0, group 0) ← 与 src0 同 group! 同一 Repeat 内读src0 读src1 → 读读冲突同bank group不同bank 读src0 写dst → 读写冲突相同bank2.4 如何检测使用msprof op工具跑算子后生成ResourceConflictRatio.csv其中展示 bank group conflict 在所有指令周期中的占比。msprofop./your_kernel_executable# 输出目录下的 ResourceConflictRatio.csv 包含冲突占比数据2.5 两种规避方法方法一调整访问 Stride把跳着读改成连续读避免同一 Repeat 的 8 个 DataBlock 落入同 bank group// 反例blkStride16 → 8 DataBlock 全落在 bank group 0BinaryRepeatParams{1,16,16,8,8,8};// 正例blkStride1 → 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.csv3. Repeat / DataBlock 机制3.1 硬件约束Vector 计算单元每拍处理256 字节NPU架构版本3510.md第 55 行。一个 DataBlock 32B所以每拍 8 个 DataBlock。这是硬件固定宽度不可配置。3.2 Repeat 一拍的硬件执行一次 Vector API 调用Add、Mul、Exp等的硬件行为等价于while (repeatTimes--) { 读取 8 个 DataBlock256B 执行计算 写回 8 个 DataBlock256B }3.3 三个控制参数Repeat0:[DB0][DB1][DB2][DB3][DB4][DB5][DB6][DB7]├── dataBlockStride ──┤ ← 同一 Repeat 内相邻 DB 的间隔单位DataBlock Repeat0DB0 地址:base Repeat1DB0 地址:baserepeatStride ×32B ← 相邻 Repeat 起始地址间隔参数范围默认值含义repeatTimes≤255API 内部按 count 算执行多少次 RepeatdataBlockStride(blkStride)≥01连续同一 Repeat 内 8 个 DB 的间隔。0始终复用第一个 DBrepeatStride(repStride)≥08连续相邻 Repeat 起始地址的间隔。0反复计算同一组 DB3.4 与 Bank Conflict 的关系dataBlockStride1 → 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 → 全部不同 → 无冲突 ✓ dataBlockStride16 → 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 个 DataBlock256B→ 计算 → 写回DataBlockVector 计算的基本单元32B。UB 每行也是 32BdataBlockStride同一 Repeat 内相邻 DataBlock 的间隔单位DataBlockrepeatStride相邻 Repeat 起始 DataBlock 的间隔单位DataBlockBankUB 的独立存储体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