移动后清理旧路径 BMM算子优化分析_Release/BMM算子优化分析_v0.7_讲解PPT.html

This commit is contained in:
2026-08-27 11:24:41 +00:00
parent 5717240f3c
commit 25439c407b

View File

@@ -1,263 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BMM算子优化分析 — 讲解PPT</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:"PingFang SC","Microsoft YaHei",sans-serif;background:#0f172a;color:#e2e8f0;overflow:hidden}
.slide{display:none;width:100vw;height:100vh;padding:60px 80px;flex-direction:column;justify-content:center}
.slide.active{display:flex}
.slide h1{font-size:42px;color:#38bdf8;margin-bottom:16px}
.slide h2{font-size:32px;color:#818cf8;margin-bottom:24px}
.slide h3{font-size:24px;color:#c4b5fd;margin:20px 0 12px}
.slide p{font-size:20px;line-height:1.7;margin:8px 0}
.slide ul,.slide ol{font-size:19px;line-height:1.8;margin-left:28px}
.slide li{margin:6px 0}
.slide .tag{display:inline-block;background:#1e293b;border:1px solid #334155;border-radius:6px;padding:2px 10px;font-size:16px;margin:3px;color:#94a3b8}
.slide .eq{font-family:monospace;font-size:18px;color:#fbbf24;background:#1e293b;padding:4px 10px;border-radius:6px}
.slide table{font-size:17px;border-collapse:collapse;margin:12px 0;width:100%}
.slide th,.slide td{border:1px solid #334155;padding:8px 14px;text-align:left}
.slide th{background:#1e293b;color:#818cf8}
.slide td{background:#0f172a}
.slide .hl{color:#fbbf24}
.slide .ct{color:#38bdf8}
.slide .sub{color:#94a3b8;font-size:16px}
.slide .note{color:#f87171;font-size:16px;margin-top:16px}
.nav{position:fixed;bottom:24px;right:32px;display:flex;gap:12px;z-index:100}
.nav button{background:#1e293b;color:#e2e8f0;border:1px solid #334155;border-radius:8px;padding:10px 20px;font-size:16px;cursor:pointer}
.nav button:hover{background:#334155}
.nav .pg{font-size:15px;color:#94a3b8;align-self:center;min-width:60px}
.code{font-family:monospace;font-size:16px;background:#1e293b;padding:12px 18px;border-radius:8px;margin:10px 0;white-space:pre;line-height:1.5;color:#e2e8f0}
.dot{color:#38bdf8;font-weight:bold}
</style>
</head>
<body>
<div class="nav">
<span class="pg" id="pg">1/14</span>
<button onclick="go(-1)"></button>
<button onclick="go(1)"></button>
</div>
<!-- Slide 1: Title -->
<div class="slide active" id="s1">
<h1>BMM 算子最优实现分析</h1>
<p style="font-size:28px;color:#c4b5fd">昇腾 950PR — BatchMatMulV3</p>
<p class="sub">v0.7|基于 CANN 源码 + 950PR 白皮书 + 架构规格的系统推导</p>
<p class="sub" style="margin-top:30px">这份分析靠谱吗?→ 最后一页有验证</p>
</div>
<!-- Slide 2: 问题引入 -->
<div class="slide" id="s2">
<h2>1. 什么是 BMM 算子?</h2>
<p>Batch MatMul对 batch 维的每个索引独立做一次矩阵乘</p>
<div class="eq">C[b, m, n] = Σₖ A[b, m, k] · B[b, k, n] + bias</div>
<p style="margin-top:16px">输入:左矩阵 <span class="hl">[BatchA, M, K]</span>、右矩阵 <span class="hl">[BatchB, K, N]</span></p>
<p>输出:<span class="hl">[BatchC, M, N]</span>batch 维支持广播</p>
<p style="margin-top:20px"><b>核心挑战</b>B、M、N、K 四个维度都可能很大或很小,必须在<span class="hl">32 个 AIC 核</span>上高效并行完成计算</p>
<p class="sub">一个 case 由 (B, M, N, K, dtype, 转置, 广播形态) 完全决定</p>
</div>
<!-- Slide 3: 硬件背景 -->
<div class="slide" id="s3">
<h2>2. 硬件基础:昇腾 950PR</h2>
<table>
<tr><th>规格</th><th>数值</th><th>对 tiling 的意义</th></tr>
<tr><td>AIC / AIV 核数</td><td class="hl">32 / 641:2</td><td>核间并行度上限 C=32</td></tr>
<tr><td>Cube 算力 BF16</td><td class="hl">486 TFLOPS</td><td>算存比分子</td></tr>
<tr><td>GM 带宽</td><td class="hl">1.6 TB/s读写共享</td><td>访存 Bound 分母</td></tr>
<tr><td>L2 Cache</td><td class="hl">128MB / 5.2 TB/s</td><td>重复读取的吸收层</td></tr>
<tr><td>L1 / L0A / L0B / L0C</td><td class="hl">512KB / 64KB / 64KB / 256KB</td><td>核内分块的容量约束</td></tr>
</table>
<p style="margin-top:16px"><b>关键关系</b>L25.2TB/s→ L1512KB→ L0A/B64KB→ Cube16×16×16 一拍)→ L0C256KB→ Fixpipe → GM</p>
<p class="sub">GM 带宽 1.6TB/s 相对 L2 的 5.2TB/s 是瓶颈——数据复用就是一切</p>
</div>
<!-- Slide 4: 性能模型 -->
<div class="slide" id="s4">
<h2>3. 什么叫"最优"</h2>
<div class="eq">T_total = max(T_MMAD, T_MTE2, T_MTE1, T_Fixpipe [, T_Reduce])</div>
<p style="margin-top:16px"><b>总时延 = 流水线最慢的一级</b></p>
<p>核内多级流水并行Cube 计算MMAD、GM→L1 搬移MTE2、L1→L0 搬移MTE1、L0C 写出Fixpipe</p>
<p style="margin-top:16px"><b class="hl">瓶颈交换</b>:搬移是瓶颈时,可牺牲算力换搬移效率;计算是瓶颈时,可牺牲搬移换计算效率</p>
<p style="margin-top:12px">算存比:<span class="eq">AI = 2MN/(M+N)</span> FLOP/元素</p>
<p>16bit 平衡点:<span class="eq">R₁₆ = 486 TFLOPS / (1.6TB/s ÷ 2B) ≈ 607.5</span> FLOP/元素</p>
<p>AI < R 访存 Bound瓶颈在搬移AI > R₁₆ → 计算 Bound瓶颈在 Cube</p>
</div>
<!-- Slide 5: 分块本质 -->
<div class="slide" id="s5">
<h2>4. 分块计算的本质4 维可切</h2>
<p>BMM 的实现 = 把数据按 B、M、N、K 切块,由 32 个 AIC 核并行 + 串行完成</p>
<p style="margin-top:16px"><b class="hl">核间怎么分这 4 个维度,就是分支划分的第一性问题</b></p>
<table>
<tr><th>切分维度</th><th>读入特征</th><th>计算特征</th><th>写出特征</th></tr>
<tr><td><span class="hl">切 B</span></td><td>核间零重复读</td><td>无核间依赖</td><td>无中间结果</td></tr>
<tr><td><span class="ct">切 M / 切 N</span></td><td>共享矩阵被多核重复读</td><td>无核间依赖</td><td>无中间结果</td></tr>
<tr><td><span class="note">切 K</span></td><td>零重复读</td><td>多核共同完成,有依赖</td><td>需核间归约</td></tr>
</table>
<p style="margin-top:16px">4 维任意非空子集共 <span class="hl">15 种</span>切分组合 → 完备枚举</p>
<p class="sub">为什么切 K 最贵L0C 累加机制:核内切 K 时多轮 mmad 在 L0C 原地累加不出核;切到核间,部分和必须写出 workspace 再归约</p>
</div>
<!-- Slide 6: 价格表 -->
<div class="slide" id="s6">
<h2>5. 切分维度的"价格表"</h2>
<div class="eq">cost(切 B) = 0 < cost( M/N) cost( K)</div>
<p style="margin-top:20px"><b class="hl">切 B 免费</b>零重复读、零依赖、零中间写出——BMM 语义就是逐 batch 独立</p>
<p><b class="ct">切 M/N 廉价</b>:共享矩阵被重复读,但 128MB L25.2TB/s吸收大部分代价</p>
<p><b class="note">切 K 昂贵</b>:归约流量 ∝ 切 K 份数 × 输出量,且引入核间同步——结构性代价</p>
<p style="margin-top:24px"><b>整条分支决策树就是一句话:</b></p>
<p style="font-size:26px;color:#fbbf24;text-align:center">按价格从低到高购买并行度,买不够才加价</p>
</div>
<!-- Slide 7: 分支推导 -->
<div class="slide" id="s7">
<h2>6. 从价格表到 7 大分支</h2>
<div class="code">第0层K=0/1 → AIV 向量通路Cube 无用)
BatchA=1 或 BatchB=1 → 折叠转普通 Matmul
第1层B ≥ 32切 B 可满核)
M×N 大 → IterBatch逐 batch 算)
M×N 小 → MergeBatch多 batch 合并成大 tile 算)
第2层B < 32P = B·MN·4B/L0C 32
ASW_Basic M/N 补并行重复读交 L2+swizzle 吸收
第3层P < 32B/M/N 都填不满核
K StreamK K付归约代价
K 降核 ASW只用 P 个核其余闲置</div>
<p style="margin-top:12px">7 大路径:<span class="tag">特殊(AIV)</span><span class="tag">转Matmul</span><span class="tag">IterBatch</span><span class="tag">MergeBatch</span><span class="tag">ASW_Basic</span><span class="tag">StreamK</span><span class="tag">降核ASW</span></p>
</div>
<!-- Slide 8: MergeBatch -->
<div class="slide" id="s8">
<h2>7. MergeBatch — 多 batch 合并计算</h2>
<p><b>思路</b>:单 batch M×N 太小时,把 b 个 batch 拼成 [bM,K]@[K,bN] 大矩阵,</p>
<p>算完取块对角线得各 batch 结果。交叉项被丢弃,浪费比例 (b1)/b</p>
<p style="margin-top:12px"><b class="hl">为什么允许浪费?</b> 进这个分支的 case 必然是访存 Bound瓶颈在搬移</p>
<p>不是在计算——浪费的算力被搬移时延掩盖,用闲置算力换搬移效率</p>
<p style="margin-top:16px"><b>进入条件精要</b></p>
<ul>
<li>每核 batch 数 ≥ 42 组 × 合并下限 b₀=2组间乒乓</li>
<li>合并块输出 ≤ L0Cb₀²·MN·4B·2 ≤ 256KB</li>
<li>单核搬移总量 ≥ 480KB保证 GM 带宽利用率)</li>
<li>搬移 tile ≥ 16KB单次搬移效率下限</li>
<li>2MN/(M+N) &lt; R₁₆/b₀访存 Bound保证浪费被掩盖</li>
</ul>
<p class="sub">为何不允许 b_core=2合并后每核仅 1 组,与 IterBatch(b_core=2) 总搬移时延相同,但多 50% 冗余计算——无收益</p>
<p class="sub">典型B=128, M=N=64, K=512 → MergeBatchK=256 → 单核搬移不够 480KB → IterBatch</p>
</div>
<!-- Slide 9: IterBatch -->
<div class="slide" id="s9">
<h2>8. IterBatch — 逐 batch 计算</h2>
<p><b>思路</b>:核间切 B核内逐个 batch 做标准 Matmul。无浪费、无跨 batch 依赖</p>
<p style="margin-top:12px"><b>进入条件精要</b>B ≥ 32负载均衡L1 四形态之一满足</p>
<p style="margin-top:10px"><b class="hl">关键:能否进 IterBatch 不由算存比判定</b></p>
<p>即使计算 BoundL1 放不下完整 M、N 维输入 → 单 batch 内部重复读 → 额外搬移可能把算子重新拖回访存 Bound</p>
<p style="margin-top:10px"><b>L1 四形态</b></p>
<ul>
<li>a) 单 batch 全驻留b_core=1 且 MK+KN ≤ L1</li>
<li>b) 双 batch 乒乓b_core>1 且 2(MK+KN) ≤ L1</li>
<li>c) 一侧驻留+对侧切 K预算 L1 或 L1/2b_core≥2 时半区预取下一 batch 驻留侧)</li>
<li>d) 两侧切 K无缝兜底驻留侧超 L1/2 时接管)</li>
</ul>
</div>
<!-- Slide 10: StreamK -->
<div class="slide" id="s10">
<h2>9. StreamK — K 维核间切分</h2>
<p><b>思路</b>B/M/N 都填不满核时,把 K 切给多个核各算一段,再归约</p>
<p style="margin-top:12px"><b>进入条件</b>P = B·MN·4B/L0C &lt; 16=C/2K/grid_K ≥ 128 元素dValue 256B</p>
<p class="sub">阈值取 C/2grid_K≥2 时每块需 2 核P×2 ≤ C 才放得下</p>
<p><b>归约代价</b>(按实现流程推导):</p>
<div class="code">第1步grid_K 个 AIC 各算 K/grid_K 段L0C 原地累加
第2步fixpipe 写部分和到 workspace驻留 L2走 5.2TB/s 写口)
第3步AIV 从 L2 读回各段部分和到 UB向量求和写回
AIV 独立硬件,数据流 GM/L2→UB→AIV→UB→L2/GM</div>
<p style="margin-top:10px">归约时延 = 写部分和 + AIV 读回 + AIV 求和 + 写回,四段之和</p>
<p>收益判据T_Reduce &lt; T_pipe(11/grid_K)T_pipe = max(T_MTE2, T_MMAD)</p>
<p>⟺ T_pipe &gt; grid_K/(grid_K1)·T_Reduceα=grid_K/(grid_K1)grid_K=2 时 α=2</p>
<p class="sub">StreamK case 多为访存 BoundAI &lt; R₁₆T_pipe = T_MTE2 是瓶颈</p>
<p style="margin-top:8px"><span class="eq">K &gt; grid_K²/(grid_K1) × 12</span> grid_K=2→K>494→K>668→K>112</p>
<p class="sub">源码 8192 = C×512B = dValue 推荐值在最大 grid_K=C 下的保障条件2非归约代价条件3阈值仅 ~50~400</p>
</div>
<!-- Slide 11: ASW 1 -->
<div class="slide" id="s11">
<h2>10. ASW_Basic — 通用框架swizzle</h2>
<p><b>思路</b>:不切 K切 B/M/N 任意组合。最常命中的分支35.2%</p>
<p style="margin-top:12px"><b class="hl">swizzle 滑窗蛇形</b>:编排输出块的执行顺序,压缩每一波核的活跃工作集</p>
<p><b>窗口怎么取</b>M 向每 W 块划窗W = C 的 ≤ √C 的最大因子32 核 → W=4</p>
<p>一波核的 L2 足迹 ≈ (W·M^t·K + C/W·K·N^t)·dtypeW=√C 时最小</p>
<p><b>蛇形只在窗口行边界</b>:奇数窗口行 N 方向反向,使上一窗口末尾的 B 列带延续到下一窗口LRU 热线),跨窗切换几乎零增量。窗内不蛇形——窗内 W 个 A 行块全程驻留 L2扫序无关。</p>
<p style="margin-top:10px"><b>对比</b>:朴素行优先(Ñ=16 时)一波足迹 18 单位;滑窗 12 单位 → 缩小 1/3</p>
</div>
<!-- Slide 12: ASW 2 -->
<div class="slide" id="s12">
<h2>11. ASW_Basic — L2 切分 & 写出策略</h2>
<p><b>切的是输出平面</b>:把 M×N 切成大矩形块,每块的输入工作集 ≤ L2 可用空间</p>
<p style="margin-top:12px"><b class="hl">L2 是读写共用的</b>:输出驻留 L2 会压缩读入空间 → 写与读要联合决策</p>
<p style="margin-top:8px"><b>写出 Bound 先判定</b>BW_out = C·Q₁₆·outB/(2K)K=256 时已超 GM 总线</p>
<p style="margin-top:8px"><b>三场景</b></p>
<ul>
<li><b>A</b>S_in+S_out ≤ L2 → 全驻留,输出走 L2 异步回写(削峰)</li>
<li><b>B</b>S_in ≤ L2 < S_in+S_out 输入驻留保住 r_in=1输出直写 GM不占 L2</li>
<li><b>C</b>S_in > L2 → 必须切分,输出直写 GM块内错位分核对角线同地址冲突 4→2</li>
</ul>
<p class="sub">r_in = 1 含义:每个输入从 GM 只读一遍,后续复用全在 L2 命中</p>
</div>
<!-- Slide 13: 遍历验证 -->
<div class="slide" id="s13">
<h2>12. case 遍历验证20736 个 case 全覆盖</h2>
<p>B∈[1,2048]、M,N,K∈[1,10240] 对数采样,按进入条件严格分类</p>
<table>
<tr><th>分支</th><th>占比</th><th>B 范围</th></tr>
<tr><td>ASW_Basic</td><td class="hl">35.2%</td><td>2~2048</td></tr>
<tr><td>IterBatch</td><td>21.9%</td><td>32~2048</td></tr>
<tr><td>降核 ASW</td><td>15.4%</td><td>2~128</td></tr>
<tr><td>特殊(AIV)</td><td>8.3%</td><td>任意</td></tr>
<tr><td>MergeBatch</td><td>8.1%</td><td>128~2048</td></tr>
<tr><td>转Matmul</td><td>7.6%</td><td>B=1</td></tr>
<tr><td>StreamK</td><td>3.5%</td><td>2~128</td></tr>
</table>
<p style="margin-top:12px"><b class="hl">7 个分支全部有真实 case 命中,无覆盖空洞</b></p>
<p class="sub">降核 ASW 是 P&lt;C 且 K 小区域的理性归宿:并行度凑不满,碎切反而不如少用核</p>
</div>
<!-- Slide 14: 靠谱吗? -->
<div class="slide" id="s14">
<h2>这份分析靠谱吗?</h2>
<h3>✅ 根基扎实</h3>
<ul>
<li><b>源码级验证</b>:分支条件与 CANN ops-nn batch_mat_mul_v3 源码逐条对照arch35 路径MergeBatch/IterBatch/StreamK/ASW 的 IsCapable 条件均能在源码中找到对应,差异处已标注并给出理由</li>
<li><b>硬件规格准确</b>950PR 架构白皮书表3-1/表4-2+ CANN 9.0 AscendC 编程文档054/056/192篇等为所有参数L1 512KB、L0C 256KB、dValue 256B、GM 1.6TB/s提供依据</li>
<li><b>数学推导闭环</b>15 种切分组合完备枚举 → 价格表(免费/廉价/昂贵)→ 7 分支体系,极小性有反例表格验证</li>
</ul>
<h3>⚠️ 需要注意</h3>
<ul>
<li><b>经验常数</b>min_TileSize=16KB、480KB、均衡率 0.8、CUBE_BOUND_RATIO 0.85 等)为该芯片档实测值,换芯片需重新标定</li>
<li><b>重叠区</b>MergeBatch vs IterBatch 在 M×N 中段)的归属由端到端时延模型 $T_{total}$ 精确仲裁,文档条件给出的是"主场"</li>
<li><b>StreamK θ≈12</b> 基于 L2 5.2TB/s 推导,若 workspace 落 GM 则升至 ~97源码 8192 门槛由 dValue 推荐值主导</li>
</ul>
<p style="margin-top:16px;font-size:24px;text-align:center;color:#38bdf8"><b>整体评价:逻辑体系完整,推导自洽,可指导工程实现</b></p>
</div>
<script>
let cur = 0;
const slides = document.querySelectorAll('.slide');
const N = slides.length;
function go(d) {
slides[cur].classList.remove('active');
cur = ((cur + d) % N + N) % N;
slides[cur].classList.add('active');
document.getElementById('pg').textContent = `${cur+1}/${N}`;
}
document.addEventListener('keydown', e => { if (e.key === 'ArrowRight') go(1); if (e.key === 'ArrowLeft') go(-1); });
</script>
</body>
</html>